forked from 0xPolygonID/c-polygonid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cache.go
118 lines (96 loc) · 1.9 KB
/
cache.go
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package c_polygonid
import (
"log/slog"
"os"
"path"
"sync"
"github.com/dgraph-io/badger/v4"
)
var badgerLogger badger.Logger = nil
var globalDB *badger.DB
var dbCnt int
var dbCond = sync.NewCond(&sync.Mutex{})
func CleanCache() (err error) {
dbCond.L.Lock()
for dbCnt != 0 {
dbCond.Wait()
}
defer dbCond.L.Unlock()
db, err := openDB()
if err != nil {
return err
}
defer func() {
err2 := db.Close()
if err2 != nil {
if err == nil {
err = err2
} else {
slog.Error("failed to close db", "err", err2)
}
}
}()
return db.DropAll()
}
func getCacheDB() (*badger.DB, func(), error) {
dbCond.L.Lock()
defer dbCond.L.Unlock()
err := maybeOpenDB()
if err != nil {
return nil, nil, err
}
// Close the DB only once per calling getCacheDB().
var once sync.Once
releaseDB := func() {
once.Do(func() {
dbCond.L.Lock()
defer dbCond.L.Unlock()
dbCnt--
if dbCnt == 0 {
err2 := globalDB.Close()
if err2 != nil {
slog.Error("failed to close db", "err", err2)
}
globalDB = nil
}
dbCond.Broadcast()
})
}
return globalDB, releaseDB, nil
}
// If globalDB is nil, open a new DB, assign it to globalDB.
// Also increment dbCnt.
// DANGER: This function is not thread-safe and should be called only when
// dbCond.L is locked. Use getCacheDB() instead.
func maybeOpenDB() error {
if globalDB != nil {
dbCnt++
return nil
}
db, err := openDB()
if err != nil {
return err
}
globalDB = db
dbCnt = 1
return nil
}
func openDB() (*badger.DB, error) {
badgerPath, err := getBadgerPath()
if err != nil {
return nil, err
}
opts := badger.DefaultOptions(badgerPath)
if badgerLogger != nil {
opts.Logger = badgerLogger
}
return badger.Open(opts)
}
func getBadgerPath() (string, error) {
cachePath, err := os.UserCacheDir()
if err != nil {
return "", err
}
cachePath = path.Join(cachePath, "c-polygonid-cache")
return cachePath, nil
}