forked from dinstein/fabric
/
db_opt.go
171 lines (137 loc) · 4.01 KB
/
db_opt.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package db
import (
"github.com/spf13/viper"
"github.com/tecbot/gorocksdb"
)
type baseOpt struct {
conf *viper.Viper
}
func (o baseOpt) Inited() bool { return o.conf != nil }
func (o baseOpt) Options() (opts *gorocksdb.Options) {
//most common options
opts = gorocksdb.NewDefaultOptions()
opts.SetCreateIfMissing(true)
opts.SetCreateIfMissingColumnFamilies(true)
if !o.Inited() {
return
}
vp := o.conf
maxLogFileSize := vp.GetInt("maxLogFileSize")
if maxLogFileSize > 0 {
dbLogger.Infof("Setting rocksdb maxLogFileSize to %d", maxLogFileSize)
opts.SetMaxLogFileSize(maxLogFileSize)
}
keepLogFileNum := vp.GetInt("keepLogFileNum")
if keepLogFileNum > 0 {
dbLogger.Infof("Setting rocksdb keepLogFileNum to %d", keepLogFileNum)
opts.SetKeepLogFileNum(keepLogFileNum)
}
logLevelStr := vp.GetString("loglevel")
logLevel, ok := rocksDBLogLevelMap[logLevelStr]
if ok {
dbLogger.Infof("Setting rocks db InfoLogLevel to %d", logLevel)
opts.SetInfoLogLevel(logLevel)
}
return
}
// basically it was just a fixed-length prefix extractor
type indexCFPrefixGen struct{}
func (*indexCFPrefixGen) Transform(src []byte) []byte {
return src[:1]
}
func (*indexCFPrefixGen) InDomain(src []byte) bool {
//skip "lastIndexedBlockKey"
return len(src) > 0 && int(src[0]) > 0
}
func (s *indexCFPrefixGen) Name() string {
return "indexPrefixGen\x00"
}
// method has been deprecated
func (*indexCFPrefixGen) InRange(src []byte) bool {
return false
}
//define options for db
func (openchainDB *OpenchainDB) buildOpenDBOptions(base baseOpt) (*gorocksdb.Options,
[]*gorocksdb.Options) {
if openchainDB.baseOpt == nil {
openchainDB.baseOpt = base.Options()
}
//cache opts for indexesCF
if openchainDB.indexesCFOpt == nil {
iopt := base.Options()
if globalDataDB.GetDBVersion() > 1 {
/*
It seems gorocksdb has no way to completely release a go object
used in opitons, so the leaking of memory can not be avoided
when a Stop() is called
we have to reused the option in most case to mitigate the leaking
*/
iopt.SetPrefixExtractor(&indexCFPrefixGen{})
openchainDB.indexesCFOpt = iopt
}
}
return openchainDB.openDBOptions()
}
func (openchainDB *OpenchainDB) openDBOptions() (*gorocksdb.Options,
[]*gorocksdb.Options) {
//sanity check
if openchainDB.baseOpt == nil {
panic("Called before buildOpenDBOptions is invoked")
}
var dbOpts = make([]*gorocksdb.Options, len(columnfamilies))
for i, cf := range columnfamilies {
switch cf {
case IndexesCF:
dbOpts[i] = openchainDB.indexesCFOpt
default:
dbOpts[i] = openchainDB.baseOpt
}
}
return openchainDB.baseOpt, dbOpts
}
func (openchainDB *OpenchainDB) cleanDBOptions() {
if openchainDB.indexesCFOpt != nil {
/* problem and hacking:
rocksdb crashs if the option with prefix extractor is destroy
the possible cause may be:
https://github.com/facebook/rocksdb/issues/1095
whatever we have no way to resolve it but just reset the handle to nil
before destory the option
(it was weired that cmo (merge operator) is not release in gorocksdb)
*/
openchainDB.indexesCFOpt.SetPrefixExtractor(gorocksdb.NewNativeSliceTransform(nil))
openchainDB.indexesCFOpt.Destroy()
openchainDB.indexesCFOpt = nil
}
if openchainDB.baseOpt != nil {
openchainDB.baseOpt.Destroy()
openchainDB.baseOpt = nil
}
}
//open of txdb is ensured to be Once
func (txdb *GlobalDataDB) buildOpenDBOptions(base baseOpt) (*gorocksdb.Options,
[]*gorocksdb.Options) {
sOpt := base.Options()
sOpt.SetMergeOperator(&globalstatusMO{})
txOpts := make([]*gorocksdb.Options, len(txDbColumnfamilies))
for i, cf := range txDbColumnfamilies {
switch cf {
case GlobalCF:
if txdb.globalStateOpt == nil {
sOpt := base.Options()
sOpt.SetMergeOperator(&globalstatusMO{})
txdb.globalStateOpt = sOpt
}
txOpts[i] = txdb.globalStateOpt
default:
txOpts[i] = sOpt
}
}
return sOpt, txOpts
}
func (txdb *GlobalDataDB) cleanDBOptions() {
if txdb.globalStateOpt != nil {
txdb.globalStateOpt.Destroy()
txdb.globalStateOpt = nil
}
}