veyron/lib/stats: Add Delete function
The new Delete function is used to delete a stats object from the tree,
along with any children below it.
Use this function to clean up the ipc server stats when the server is
stopped.
Change-Id: I84eec2a015ad7affead9d73dbbcbc8536ee98ccc
diff --git a/lib/stats/stats.go b/lib/stats/stats.go
index 335098c..e55947c 100644
--- a/lib/stats/stats.go
+++ b/lib/stats/stats.go
@@ -67,6 +67,24 @@
return obj.Value(), nil
}
+// Delete deletes a StatsObject and all its children, if any.
+func Delete(name string) error {
+ if name == "" {
+ return ErrNotFound
+ }
+ elems := strings.Split(name, "/")
+ last := len(elems) - 1
+ dirname, basename := strings.Join(elems[:last], "/"), elems[last]
+ lock.Lock()
+ defer lock.Unlock()
+ parent := findNodeLocked(dirname, false)
+ if parent == nil {
+ return ErrNotFound
+ }
+ delete(parent.children, basename)
+ return nil
+}
+
func newNode() *node {
return &node{children: make(map[string]*node)}
}
diff --git a/lib/stats/stats_test.go b/lib/stats/stats_test.go
index 17e0f61..dc2c8c6 100644
--- a/lib/stats/stats_test.go
+++ b/lib/stats/stats_test.go
@@ -272,3 +272,25 @@
t.Errorf("unexpected result. Got %#v, want %#v", result, expected)
}
}
+
+func TestDelete(t *testing.T) {
+ _ = libstats.NewInteger("a/b/c/d")
+ if _, err := libstats.GetStatsObject("a/b/c/d"); err != nil {
+ t.Errorf("unexpected error value: %v", err)
+ }
+ if err := libstats.Delete("a/b/c/d"); err != nil {
+ t.Errorf("unexpected error value: %v", err)
+ }
+ if _, err := libstats.GetStatsObject("a/b/c/d"); err != libstats.ErrNotFound {
+ t.Errorf("unexpected error value: Got %v, want %v", err, libstats.ErrNotFound)
+ }
+ if err := libstats.Delete("a/b"); err != nil {
+ t.Errorf("unexpected error value: %v", err)
+ }
+ if _, err := libstats.GetStatsObject("a/b"); err != libstats.ErrNotFound {
+ t.Errorf("unexpected error value: Got %v, want %v", err, libstats.ErrNotFound)
+ }
+ if _, err := libstats.GetStatsObject("a/b/c"); err != libstats.ErrNotFound {
+ t.Errorf("unexpected error value: Got %v, want %v", err, libstats.ErrNotFound)
+ }
+}
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 7665b83..a8ff3b3 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -499,6 +499,9 @@
close(s.stoppedChan)
s.Unlock()
+ // Delete the stats object.
+ s.stats.stop()
+
// Note, It's safe to Stop/WaitForStop on the publisher outside of the
// server lock, since publisher is safe for concurrent access.
diff --git a/runtimes/google/ipc/stats.go b/runtimes/google/ipc/stats.go
index a04e932..5f6f2ed 100644
--- a/runtimes/google/ipc/stats.go
+++ b/runtimes/google/ipc/stats.go
@@ -24,6 +24,10 @@
latency *histogram.Histogram
}
+func (s *ipcStats) stop() {
+ stats.Delete(s.prefix)
+}
+
func (s *ipcStats) record(method string, latency time.Duration) {
// Try first with a read lock. This will succeed in the most common
// case. If it fails, try again with a write lock and create the stats