|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- /*
- Copyright 2015 Google LLC
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
- package bigtable
-
- import (
- "fmt"
- "strings"
- "time"
-
- durpb "github.com/golang/protobuf/ptypes/duration"
- bttdpb "google.golang.org/genproto/googleapis/bigtable/admin/v2"
- )
-
- // A GCPolicy represents a rule that determines which cells are eligible for garbage collection.
- type GCPolicy interface {
- String() string
- proto() *bttdpb.GcRule
- }
-
- // IntersectionPolicy returns a GC policy that only applies when all its sub-policies apply.
- func IntersectionPolicy(sub ...GCPolicy) GCPolicy { return intersectionPolicy{sub} }
-
- type intersectionPolicy struct {
- sub []GCPolicy
- }
-
- func (ip intersectionPolicy) String() string {
- var ss []string
- for _, sp := range ip.sub {
- ss = append(ss, sp.String())
- }
- return "(" + strings.Join(ss, " && ") + ")"
- }
-
- func (ip intersectionPolicy) proto() *bttdpb.GcRule {
- inter := &bttdpb.GcRule_Intersection{}
- for _, sp := range ip.sub {
- inter.Rules = append(inter.Rules, sp.proto())
- }
- return &bttdpb.GcRule{
- Rule: &bttdpb.GcRule_Intersection_{Intersection: inter},
- }
- }
-
- // UnionPolicy returns a GC policy that applies when any of its sub-policies apply.
- func UnionPolicy(sub ...GCPolicy) GCPolicy { return unionPolicy{sub} }
-
- type unionPolicy struct {
- sub []GCPolicy
- }
-
- func (up unionPolicy) String() string {
- var ss []string
- for _, sp := range up.sub {
- ss = append(ss, sp.String())
- }
- return "(" + strings.Join(ss, " || ") + ")"
- }
-
- func (up unionPolicy) proto() *bttdpb.GcRule {
- union := &bttdpb.GcRule_Union{}
- for _, sp := range up.sub {
- union.Rules = append(union.Rules, sp.proto())
- }
- return &bttdpb.GcRule{
- Rule: &bttdpb.GcRule_Union_{Union: union},
- }
- }
-
- // MaxVersionsPolicy returns a GC policy that applies to all versions of a cell
- // except for the most recent n.
- func MaxVersionsPolicy(n int) GCPolicy { return maxVersionsPolicy(n) }
-
- type maxVersionsPolicy int
-
- func (mvp maxVersionsPolicy) String() string { return fmt.Sprintf("versions() > %d", int(mvp)) }
-
- func (mvp maxVersionsPolicy) proto() *bttdpb.GcRule {
- return &bttdpb.GcRule{Rule: &bttdpb.GcRule_MaxNumVersions{MaxNumVersions: int32(mvp)}}
- }
-
- // MaxAgePolicy returns a GC policy that applies to all cells
- // older than the given age.
- func MaxAgePolicy(d time.Duration) GCPolicy { return maxAgePolicy(d) }
-
- type maxAgePolicy time.Duration
-
- var units = []struct {
- d time.Duration
- suffix string
- }{
- {24 * time.Hour, "d"},
- {time.Hour, "h"},
- {time.Minute, "m"},
- }
-
- func (ma maxAgePolicy) String() string {
- d := time.Duration(ma)
- for _, u := range units {
- if d%u.d == 0 {
- return fmt.Sprintf("age() > %d%s", d/u.d, u.suffix)
- }
- }
- return fmt.Sprintf("age() > %d", d/time.Microsecond)
- }
-
- func (ma maxAgePolicy) proto() *bttdpb.GcRule {
- // This doesn't handle overflows, etc.
- // Fix this if people care about GC policies over 290 years.
- ns := time.Duration(ma).Nanoseconds()
- return &bttdpb.GcRule{
- Rule: &bttdpb.GcRule_MaxAge{MaxAge: &durpb.Duration{
- Seconds: ns / 1e9,
- Nanos: int32(ns % 1e9),
- }},
- }
- }
-
- // GCRuleToString converts the given GcRule proto to a user-visible string.
- func GCRuleToString(rule *bttdpb.GcRule) string {
- if rule == nil {
- return "<default>"
- }
- switch r := rule.Rule.(type) {
- case *bttdpb.GcRule_MaxNumVersions:
- return MaxVersionsPolicy(int(r.MaxNumVersions)).String()
- case *bttdpb.GcRule_MaxAge:
- return MaxAgePolicy(time.Duration(r.MaxAge.Seconds) * time.Second).String()
- case *bttdpb.GcRule_Intersection_:
- return joinRules(r.Intersection.Rules, " && ")
- case *bttdpb.GcRule_Union_:
- return joinRules(r.Union.Rules, " || ")
- default:
- return ""
- }
- }
-
- func joinRules(rules []*bttdpb.GcRule, sep string) string {
- var chunks []string
- for _, r := range rules {
- chunks = append(chunks, GCRuleToString(r))
- }
- return "(" + strings.Join(chunks, sep) + ")"
- }
|