M database/db.go => database/db.go +55 -4
@@ 4,25 4,76 @@ import (
"git.sr.ht/~emersion/drmdb/drmtree"
)
+const cacheSize = 1000
+
+type cacheEntry struct {
+ key string
+ node *drmtree.Node
+}
+
type DB struct {
+ cache []cacheEntry // ring buffer
+ indexes map[string]int // key → cache index
+ cur int
}
func Open() (*DB, error) {
- return &DB{}, initDB()
+ if err := initDB(); err != nil {
+ return nil, err
+ }
+ return &DB{
+ cache: make([]cacheEntry, cacheSize),
+ indexes: make(map[string]int, cacheSize),
+ }, nil
+}
+
+func (db *DB) storeCache(k string, n *drmtree.Node) {
+ prev := db.cache[db.cur]
+ delete(db.indexes, prev.key)
+ db.cache[db.cur] = cacheEntry{key: k, node: n}
+ db.indexes[k] = db.cur
+ db.cur = (db.cur + 1) % len(db.cache)
+}
+
+func (db *DB) loadCache(k string) *drmtree.Node {
+ i, ok := db.indexes[k]
+ if !ok {
+ return nil
+ }
+ return db.cache[i].node
}
func (db *DB) Store(n *drmtree.Node) (string, error) {
- return store(n)
+ k, err := store(n)
+ if err == nil {
+ db.storeCache(k, n)
+ }
+ return k, err
}
func (db *DB) Load(k string) (*drmtree.Node, error) {
- return load(k)
+ if n := db.loadCache(k); n != nil {
+ return n, nil
+ }
+ n, err := load(k)
+ if err == nil {
+ db.storeCache(k, n)
+ }
+ return n, err
}
func (db *DB) Walk(fn func(k string, n *drmtree.Node) error) error {
- return walk(fn)
+ return walk(func(k string) error {
+ n, err := db.Load(k)
+ if err != nil {
+ return err
+ }
+ return fn(k, n)
+ })
}
func (db *DB) Close() error {
+ db.cache = nil
+ db.indexes = nil
return nil
}
M database/fs.go => database/fs.go +2 -7
@@ 99,7 99,7 @@ func load(k string) (*drmtree.Node, error) {
return &n, f.Close()
}
-func walk(fn func(k string, n *drmtree.Node) error) error {
+func walk(fn func(k string) error) error {
files, err := ioutil.ReadDir(Dir)
if err != nil {
return err
@@ 111,12 111,7 @@ func walk(fn func(k string, n *drmtree.Node) error) error {
}
k := strings.TrimSuffix(fi.Name(), ".json")
- n, err := load(k)
- if err != nil {
- return err
- }
-
- if err := fn(k, n); err == ErrStop {
+ if err := fn(k); err == ErrStop {
return nil
} else if err != nil {
return err
M server.go => server.go +1 -1
@@ 76,7 76,7 @@ func New() *echo.Echo {
e.GET("/", func(c echo.Context) error {
data := struct {
- Host string
+ Host string
NumSnapshots int
NumDevices int
NumDrivers int