github.com/evdatsion/aphelion-dpos-bft@v0.32.1/libs/db/go_level_db.go (about) 1 package db 2 3 import ( 4 "bytes" 5 "fmt" 6 "path/filepath" 7 8 "github.com/syndtr/goleveldb/leveldb" 9 "github.com/syndtr/goleveldb/leveldb/errors" 10 "github.com/syndtr/goleveldb/leveldb/iterator" 11 "github.com/syndtr/goleveldb/leveldb/opt" 12 ) 13 14 func init() { 15 dbCreator := func(name string, dir string) (DB, error) { 16 return NewGoLevelDB(name, dir) 17 } 18 registerDBCreator(GoLevelDBBackend, dbCreator, false) 19 } 20 21 var _ DB = (*GoLevelDB)(nil) 22 23 type GoLevelDB struct { 24 db *leveldb.DB 25 } 26 27 func NewGoLevelDB(name string, dir string) (*GoLevelDB, error) { 28 return NewGoLevelDBWithOpts(name, dir, nil) 29 } 30 31 func NewGoLevelDBWithOpts(name string, dir string, o *opt.Options) (*GoLevelDB, error) { 32 dbPath := filepath.Join(dir, name+".db") 33 db, err := leveldb.OpenFile(dbPath, o) 34 if err != nil { 35 return nil, err 36 } 37 database := &GoLevelDB{ 38 db: db, 39 } 40 return database, nil 41 } 42 43 // Implements DB. 44 func (db *GoLevelDB) Get(key []byte) []byte { 45 key = nonNilBytes(key) 46 res, err := db.db.Get(key, nil) 47 if err != nil { 48 if err == errors.ErrNotFound { 49 return nil 50 } 51 panic(err) 52 } 53 return res 54 } 55 56 // Implements DB. 57 func (db *GoLevelDB) Has(key []byte) bool { 58 return db.Get(key) != nil 59 } 60 61 // Implements DB. 62 func (db *GoLevelDB) Set(key []byte, value []byte) { 63 key = nonNilBytes(key) 64 value = nonNilBytes(value) 65 err := db.db.Put(key, value, nil) 66 if err != nil { 67 panic(err) 68 } 69 } 70 71 // Implements DB. 72 func (db *GoLevelDB) SetSync(key []byte, value []byte) { 73 key = nonNilBytes(key) 74 value = nonNilBytes(value) 75 err := db.db.Put(key, value, &opt.WriteOptions{Sync: true}) 76 if err != nil { 77 panic(err) 78 } 79 } 80 81 // Implements DB. 82 func (db *GoLevelDB) Delete(key []byte) { 83 key = nonNilBytes(key) 84 err := db.db.Delete(key, nil) 85 if err != nil { 86 panic(err) 87 } 88 } 89 90 // Implements DB. 91 func (db *GoLevelDB) DeleteSync(key []byte) { 92 key = nonNilBytes(key) 93 err := db.db.Delete(key, &opt.WriteOptions{Sync: true}) 94 if err != nil { 95 panic(err) 96 } 97 } 98 99 func (db *GoLevelDB) DB() *leveldb.DB { 100 return db.db 101 } 102 103 // Implements DB. 104 func (db *GoLevelDB) Close() { 105 db.db.Close() 106 } 107 108 // Implements DB. 109 func (db *GoLevelDB) Print() { 110 str, _ := db.db.GetProperty("leveldb.stats") 111 fmt.Printf("%v\n", str) 112 113 itr := db.db.NewIterator(nil, nil) 114 for itr.Next() { 115 key := itr.Key() 116 value := itr.Value() 117 fmt.Printf("[%X]:\t[%X]\n", key, value) 118 } 119 } 120 121 // Implements DB. 122 func (db *GoLevelDB) Stats() map[string]string { 123 keys := []string{ 124 "leveldb.num-files-at-level{n}", 125 "leveldb.stats", 126 "leveldb.sstables", 127 "leveldb.blockpool", 128 "leveldb.cachedblock", 129 "leveldb.openedtables", 130 "leveldb.alivesnaps", 131 "leveldb.aliveiters", 132 } 133 134 stats := make(map[string]string) 135 for _, key := range keys { 136 str, err := db.db.GetProperty(key) 137 if err == nil { 138 stats[key] = str 139 } 140 } 141 return stats 142 } 143 144 //---------------------------------------- 145 // Batch 146 147 // Implements DB. 148 func (db *GoLevelDB) NewBatch() Batch { 149 batch := new(leveldb.Batch) 150 return &goLevelDBBatch{db, batch} 151 } 152 153 type goLevelDBBatch struct { 154 db *GoLevelDB 155 batch *leveldb.Batch 156 } 157 158 // Implements Batch. 159 func (mBatch *goLevelDBBatch) Set(key, value []byte) { 160 mBatch.batch.Put(key, value) 161 } 162 163 // Implements Batch. 164 func (mBatch *goLevelDBBatch) Delete(key []byte) { 165 mBatch.batch.Delete(key) 166 } 167 168 // Implements Batch. 169 func (mBatch *goLevelDBBatch) Write() { 170 err := mBatch.db.db.Write(mBatch.batch, &opt.WriteOptions{Sync: false}) 171 if err != nil { 172 panic(err) 173 } 174 } 175 176 // Implements Batch. 177 func (mBatch *goLevelDBBatch) WriteSync() { 178 err := mBatch.db.db.Write(mBatch.batch, &opt.WriteOptions{Sync: true}) 179 if err != nil { 180 panic(err) 181 } 182 } 183 184 // Implements Batch. 185 // Close is no-op for goLevelDBBatch. 186 func (mBatch *goLevelDBBatch) Close() {} 187 188 //---------------------------------------- 189 // Iterator 190 // NOTE This is almost identical to db/c_level_db.Iterator 191 // Before creating a third version, refactor. 192 193 // Implements DB. 194 func (db *GoLevelDB) Iterator(start, end []byte) Iterator { 195 itr := db.db.NewIterator(nil, nil) 196 return newGoLevelDBIterator(itr, start, end, false) 197 } 198 199 // Implements DB. 200 func (db *GoLevelDB) ReverseIterator(start, end []byte) Iterator { 201 itr := db.db.NewIterator(nil, nil) 202 return newGoLevelDBIterator(itr, start, end, true) 203 } 204 205 type goLevelDBIterator struct { 206 source iterator.Iterator 207 start []byte 208 end []byte 209 isReverse bool 210 isInvalid bool 211 } 212 213 var _ Iterator = (*goLevelDBIterator)(nil) 214 215 func newGoLevelDBIterator(source iterator.Iterator, start, end []byte, isReverse bool) *goLevelDBIterator { 216 if isReverse { 217 if end == nil { 218 source.Last() 219 } else { 220 valid := source.Seek(end) 221 if valid { 222 eoakey := source.Key() // end or after key 223 if bytes.Compare(end, eoakey) <= 0 { 224 source.Prev() 225 } 226 } else { 227 source.Last() 228 } 229 } 230 } else { 231 if start == nil { 232 source.First() 233 } else { 234 source.Seek(start) 235 } 236 } 237 return &goLevelDBIterator{ 238 source: source, 239 start: start, 240 end: end, 241 isReverse: isReverse, 242 isInvalid: false, 243 } 244 } 245 246 // Implements Iterator. 247 func (itr *goLevelDBIterator) Domain() ([]byte, []byte) { 248 return itr.start, itr.end 249 } 250 251 // Implements Iterator. 252 func (itr *goLevelDBIterator) Valid() bool { 253 254 // Once invalid, forever invalid. 255 if itr.isInvalid { 256 return false 257 } 258 259 // Panic on DB error. No way to recover. 260 itr.assertNoError() 261 262 // If source is invalid, invalid. 263 if !itr.source.Valid() { 264 itr.isInvalid = true 265 return false 266 } 267 268 // If key is end or past it, invalid. 269 var start = itr.start 270 var end = itr.end 271 var key = itr.source.Key() 272 273 if itr.isReverse { 274 if start != nil && bytes.Compare(key, start) < 0 { 275 itr.isInvalid = true 276 return false 277 } 278 } else { 279 if end != nil && bytes.Compare(end, key) <= 0 { 280 itr.isInvalid = true 281 return false 282 } 283 } 284 285 // Valid 286 return true 287 } 288 289 // Implements Iterator. 290 func (itr *goLevelDBIterator) Key() []byte { 291 // Key returns a copy of the current key. 292 // See https://github.com/syndtr/goleveldb/blob/52c212e6c196a1404ea59592d3f1c227c9f034b2/leveldb/iterator/iter.go#L88 293 itr.assertNoError() 294 itr.assertIsValid() 295 return cp(itr.source.Key()) 296 } 297 298 // Implements Iterator. 299 func (itr *goLevelDBIterator) Value() []byte { 300 // Value returns a copy of the current value. 301 // See https://github.com/syndtr/goleveldb/blob/52c212e6c196a1404ea59592d3f1c227c9f034b2/leveldb/iterator/iter.go#L88 302 itr.assertNoError() 303 itr.assertIsValid() 304 return cp(itr.source.Value()) 305 } 306 307 // Implements Iterator. 308 func (itr *goLevelDBIterator) Next() { 309 itr.assertNoError() 310 itr.assertIsValid() 311 if itr.isReverse { 312 itr.source.Prev() 313 } else { 314 itr.source.Next() 315 } 316 } 317 318 // Implements Iterator. 319 func (itr *goLevelDBIterator) Close() { 320 itr.source.Release() 321 } 322 323 func (itr *goLevelDBIterator) assertNoError() { 324 if err := itr.source.Error(); err != nil { 325 panic(err) 326 } 327 } 328 329 func (itr goLevelDBIterator) assertIsValid() { 330 if !itr.Valid() { 331 panic("goLevelDBIterator is invalid") 332 } 333 }