diff --git a/store.go b/store.go index d8ccd44..2d57e60 100644 --- a/store.go +++ b/store.go @@ -59,6 +59,9 @@ type Store struct { refs int footer *Footer nextFNameSeq int64 + + totPersists uint64 + totCompactions uint64 } // StoreOptions are provided to OpenStore(). @@ -377,6 +380,7 @@ func (s *Store) Persist(higher Snapshot, persistOptions StorePersistOptions) ( footer.prevFooter = s.footer prevFooter := s.footer s.footer = footer + s.totPersists++ s.m.Unlock() if prevFooter != nil { diff --git a/store_compact.go b/store_compact.go index e0d81ba..210367c 100644 --- a/store_compact.go +++ b/store_compact.go @@ -206,6 +206,7 @@ func (s *Store) compact(footer *Footer, higher Snapshot, s.m.Lock() footerPrev := s.footer s.footer = footerReady // Owns the frefCompact ref-count. + s.totCompactions++ s.m.Unlock() if footerPrev != nil { diff --git a/store_stats.go b/store_stats.go new file mode 100644 index 0000000..6e6c6be --- /dev/null +++ b/store_stats.go @@ -0,0 +1,42 @@ +// Copyright (c) 2016 Couchbase, Inc. +// 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 moss + +import ( + "io/ioutil" +) + +// Stats returns a map of stats. +func (s *Store) Stats() (map[string]interface{}, error) { + finfos, err := ioutil.ReadDir(s.dir) + if err != nil { + return nil, err + } + + var numBytesUsedDisk uint64 + for _, finfo := range finfos { + if !finfo.IsDir() { + numBytesUsedDisk += uint64(finfo.Size()) + } + } + + s.m.Lock() + totPersists := s.totPersists + totCompactions := s.totCompactions + s.m.Unlock() + + return map[string]interface{}{ + "num_bytes_used_disk": numBytesUsedDisk, + "total_persists": totPersists, + "total_compactions": totCompactions, + }, nil +} diff --git a/store_test.go b/store_test.go index 382f1ac..74cf59a 100644 --- a/store_test.go +++ b/store_test.go @@ -80,6 +80,23 @@ func TestOpenEmptyStore(t *testing.T) { s.Options() // It should not panic. + sstats, err := s.Stats() + if err != nil { + t.Errorf("expected no stats err") + } + if sstats == nil { + t.Errorf("expected non-nil stats") + } + if sstats["num_bytes_used_disk"].(uint64) != 0 { + t.Errorf("expected 0 stats to start") + } + if sstats["total_persists"].(uint64) != 0 { + t.Errorf("expected 0 stats to start") + } + if sstats["total_compactions"].(uint64) != 0 { + t.Errorf("expected 0 stats to start") + } + ss, err := s.Snapshot() if err != nil || ss == nil { t.Errorf("expected snapshot, no err") @@ -242,6 +259,20 @@ func testSimpleStore(t *testing.T, sync bool) { t.Errorf("expected llss close to work") } + sstats, err := store.Stats() + if err != nil { + t.Errorf("expected no stats err") + } + if sstats == nil { + t.Errorf("expected non-nil stats") + } + if sstats["num_bytes_used_disk"].(uint64) <= 0 { + t.Errorf("expected >0 num_bytes_used_disk") + } + if sstats["total_persists"].(uint64) <= 0 { + t.Errorf("expected >0 total_persists") + } + if store.Close() != nil { t.Errorf("expected store close to work") }