~emersion/drmdb

ref: 09fb82de3ecc5a42a61fbb6bf71029d6a45c8e8a drmdb/database/db.go -rw-r--r-- 1.4 KiB
09fb82deSimon Ser Fix format/modifier pretty-printing 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package database

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) {
	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) {
	k, err := store(n)
	if err == nil {
		db.storeCache(k, n)
	}
	return k, err
}

func (db *DB) Load(k string) (*drmtree.Node, error) {
	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(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
}