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