services/mounttable/btmtd: Add GC grace period
Add a grace period before garbage collecting newly created nodes. It
defaults to 1 minute, but is set to 0 for the tests.
Also, only create new rows if they don't already exist. If they exist,
return a concurrent access error.
Change-Id: I65850adcf96a3ac76e32b18d68658169b77ecd56
diff --git a/services/mounttable/btmtd/internal/bt.go b/services/mounttable/btmtd/internal/bt.go
index 64ec5e7..86cb9ce 100644
--- a/services/mounttable/btmtd/internal/bt.go
+++ b/services/mounttable/btmtd/internal/bt.go
@@ -27,6 +27,7 @@
"v.io/v23/security"
"v.io/v23/security/access"
v23mt "v.io/v23/services/mounttable"
+ "v.io/v23/verror"
"v.io/x/ref/lib/timekeeper"
)
@@ -207,7 +208,7 @@
defer cancel()
clock := timekeeper.RealTime()
- return b.nodeTbl.ReadRows(bctx, bigtable.InfiniteRange(""),
+ if err := b.nodeTbl.ReadRows(bctx, bigtable.InfiniteRange(""),
func(row bigtable.Row) bool {
n := nodeFromRow(ctx, b, row, clock)
if n.name == "" {
@@ -233,7 +234,19 @@
return true
},
bigtable.RowFilter(bigtable.LatestNFilter(1)),
- )
+ ); err != nil {
+ return err
+ }
+
+ c, err := b.Counters(ctx)
+ if err != nil {
+ return err
+ }
+ fmt.Printf("Counters:\n")
+ for k, v := range c {
+ fmt.Printf("%s=%d\n", k, v)
+ }
+ return nil
}
func (b *BigTable) CountRows(ctx *context.T) (int, error) {
@@ -341,8 +354,15 @@
mut.Set(metadataFamily, creatorColumn, ts, []byte(creator))
mut.Set(metadataFamily, permissionsColumn, bigtable.ServerTime, jsonPerms)
mut.Set(metadataFamily, versionColumn, bigtable.ServerTime, []byte(strconv.FormatUint(uint64(rand.Uint32()), 10)))
- if err := b.apply(ctx, rowKey(name), mut); err != nil {
+
+ filter := bigtable.ChainFilters(bigtable.FamilyFilter(metadataFamily), bigtable.ColumnFilter(creatorColumn))
+ condMut := bigtable.NewCondMutation(filter, nil, mut)
+ var exists bool
+ if err := b.apply(ctx, rowKey(name), condMut, bigtable.GetCondMutationResult(&exists)); err != nil {
return err
}
+ if exists {
+ return verror.New(errConcurrentAccess, ctx, name)
+ }
return incrementCreatorNodeCount(ctx, b, creator, 1)
}
diff --git a/services/mounttable/btmtd/internal/mounttable_test.go b/services/mounttable/btmtd/internal/mounttable_test.go
index aed1b76..b59784c 100644
--- a/services/mounttable/btmtd/internal/mounttable_test.go
+++ b/services/mounttable/btmtd/internal/mounttable_test.go
@@ -196,6 +196,7 @@
}
// Add mount table service.
internal.SetClock(clock)
+ internal.SetGcGracePeriod(0)
mt := internal.NewDispatcher(bt, nil)
// Start serving on a loopback address.
diff --git a/services/mounttable/btmtd/internal/node.go b/services/mounttable/btmtd/internal/node.go
index 3bc477a..efd3ae9 100644
--- a/services/mounttable/btmtd/internal/node.go
+++ b/services/mounttable/btmtd/internal/node.go
@@ -27,6 +27,15 @@
"v.io/x/ref/lib/timekeeper"
)
+var gcGracePeriod = time.Minute
+
+// SetGcGracePeriod sets the grace period for garbage collecting newly created
+// nodes. Nodes are not eligible for garbage collection until after this time
+// has passed. This function exists only for testing purposes.
+func SetGcGracePeriod(p time.Duration) {
+ gcGracePeriod = p
+}
+
type mtNode struct {
bt *BigTable
name string
@@ -231,6 +240,9 @@
if n.sticky || len(n.children) > 0 || len(n.servers) > 0 {
break
}
+ if time.Since(n.creationTime.Time()) < gcGracePeriod {
+ break
+ }
if err = n.delete(ctx, false); err != nil {
break
}