github.com/evdatsion/aphelion-dpos-bft@v0.32.1/libs/db/prefix_db.go (about) 1 package db 2 3 import ( 4 "bytes" 5 "fmt" 6 "sync" 7 ) 8 9 // IteratePrefix is a convenience function for iterating over a key domain 10 // restricted by prefix. 11 func IteratePrefix(db DB, prefix []byte) Iterator { 12 var start, end []byte 13 if len(prefix) == 0 { 14 start = nil 15 end = nil 16 } else { 17 start = cp(prefix) 18 end = cpIncr(prefix) 19 } 20 return db.Iterator(start, end) 21 } 22 23 /* 24 TODO: Make test, maybe rename. 25 // Like IteratePrefix but the iterator strips the prefix from the keys. 26 func IteratePrefixStripped(db DB, prefix []byte) Iterator { 27 start, end := ... 28 return newPrefixIterator(prefix, start, end, IteratePrefix(db, prefix)) 29 } 30 */ 31 32 //---------------------------------------- 33 // prefixDB 34 35 type prefixDB struct { 36 mtx sync.Mutex 37 prefix []byte 38 db DB 39 } 40 41 // NewPrefixDB lets you namespace multiple DBs within a single DB. 42 func NewPrefixDB(db DB, prefix []byte) *prefixDB { 43 return &prefixDB{ 44 prefix: prefix, 45 db: db, 46 } 47 } 48 49 // Implements atomicSetDeleter. 50 func (pdb *prefixDB) Mutex() *sync.Mutex { 51 return &(pdb.mtx) 52 } 53 54 // Implements DB. 55 func (pdb *prefixDB) Get(key []byte) []byte { 56 pdb.mtx.Lock() 57 defer pdb.mtx.Unlock() 58 59 pkey := pdb.prefixed(key) 60 value := pdb.db.Get(pkey) 61 return value 62 } 63 64 // Implements DB. 65 func (pdb *prefixDB) Has(key []byte) bool { 66 pdb.mtx.Lock() 67 defer pdb.mtx.Unlock() 68 69 return pdb.db.Has(pdb.prefixed(key)) 70 } 71 72 // Implements DB. 73 func (pdb *prefixDB) Set(key []byte, value []byte) { 74 pdb.mtx.Lock() 75 defer pdb.mtx.Unlock() 76 77 pkey := pdb.prefixed(key) 78 pdb.db.Set(pkey, value) 79 } 80 81 // Implements DB. 82 func (pdb *prefixDB) SetSync(key []byte, value []byte) { 83 pdb.mtx.Lock() 84 defer pdb.mtx.Unlock() 85 86 pdb.db.SetSync(pdb.prefixed(key), value) 87 } 88 89 // Implements DB. 90 func (pdb *prefixDB) Delete(key []byte) { 91 pdb.mtx.Lock() 92 defer pdb.mtx.Unlock() 93 94 pdb.db.Delete(pdb.prefixed(key)) 95 } 96 97 // Implements DB. 98 func (pdb *prefixDB) DeleteSync(key []byte) { 99 pdb.mtx.Lock() 100 defer pdb.mtx.Unlock() 101 102 pdb.db.DeleteSync(pdb.prefixed(key)) 103 } 104 105 // Implements DB. 106 func (pdb *prefixDB) Iterator(start, end []byte) Iterator { 107 pdb.mtx.Lock() 108 defer pdb.mtx.Unlock() 109 110 var pstart, pend []byte 111 pstart = append(cp(pdb.prefix), start...) 112 if end == nil { 113 pend = cpIncr(pdb.prefix) 114 } else { 115 pend = append(cp(pdb.prefix), end...) 116 } 117 return newPrefixIterator( 118 pdb.prefix, 119 start, 120 end, 121 pdb.db.Iterator( 122 pstart, 123 pend, 124 ), 125 ) 126 } 127 128 // Implements DB. 129 func (pdb *prefixDB) ReverseIterator(start, end []byte) Iterator { 130 pdb.mtx.Lock() 131 defer pdb.mtx.Unlock() 132 133 var pstart, pend []byte 134 pstart = append(cp(pdb.prefix), start...) 135 if end == nil { 136 pend = cpIncr(pdb.prefix) 137 } else { 138 pend = append(cp(pdb.prefix), end...) 139 } 140 ritr := pdb.db.ReverseIterator(pstart, pend) 141 return newPrefixIterator( 142 pdb.prefix, 143 start, 144 end, 145 ritr, 146 ) 147 } 148 149 // Implements DB. 150 // Panics if the underlying DB is not an 151 // atomicSetDeleter. 152 func (pdb *prefixDB) NewBatch() Batch { 153 pdb.mtx.Lock() 154 defer pdb.mtx.Unlock() 155 156 return newPrefixBatch(pdb.prefix, pdb.db.NewBatch()) 157 } 158 159 /* NOTE: Uncomment to use memBatch instead of prefixBatch 160 // Implements atomicSetDeleter. 161 func (pdb *prefixDB) SetNoLock(key []byte, value []byte) { 162 pdb.db.(atomicSetDeleter).SetNoLock(pdb.prefixed(key), value) 163 } 164 165 // Implements atomicSetDeleter. 166 func (pdb *prefixDB) SetNoLockSync(key []byte, value []byte) { 167 pdb.db.(atomicSetDeleter).SetNoLockSync(pdb.prefixed(key), value) 168 } 169 170 // Implements atomicSetDeleter. 171 func (pdb *prefixDB) DeleteNoLock(key []byte) { 172 pdb.db.(atomicSetDeleter).DeleteNoLock(pdb.prefixed(key)) 173 } 174 175 // Implements atomicSetDeleter. 176 func (pdb *prefixDB) DeleteNoLockSync(key []byte) { 177 pdb.db.(atomicSetDeleter).DeleteNoLockSync(pdb.prefixed(key)) 178 } 179 */ 180 181 // Implements DB. 182 func (pdb *prefixDB) Close() { 183 pdb.mtx.Lock() 184 defer pdb.mtx.Unlock() 185 186 pdb.db.Close() 187 } 188 189 // Implements DB. 190 func (pdb *prefixDB) Print() { 191 fmt.Printf("prefix: %X\n", pdb.prefix) 192 193 itr := pdb.Iterator(nil, nil) 194 defer itr.Close() 195 for ; itr.Valid(); itr.Next() { 196 key := itr.Key() 197 value := itr.Value() 198 fmt.Printf("[%X]:\t[%X]\n", key, value) 199 } 200 } 201 202 // Implements DB. 203 func (pdb *prefixDB) Stats() map[string]string { 204 stats := make(map[string]string) 205 stats["prefixdb.prefix.string"] = string(pdb.prefix) 206 stats["prefixdb.prefix.hex"] = fmt.Sprintf("%X", pdb.prefix) 207 source := pdb.db.Stats() 208 for key, value := range source { 209 stats["prefixdb.source."+key] = value 210 } 211 return stats 212 } 213 214 func (pdb *prefixDB) prefixed(key []byte) []byte { 215 return append(cp(pdb.prefix), key...) 216 } 217 218 //---------------------------------------- 219 // prefixBatch 220 221 type prefixBatch struct { 222 prefix []byte 223 source Batch 224 } 225 226 func newPrefixBatch(prefix []byte, source Batch) prefixBatch { 227 return prefixBatch{ 228 prefix: prefix, 229 source: source, 230 } 231 } 232 233 func (pb prefixBatch) Set(key, value []byte) { 234 pkey := append(cp(pb.prefix), key...) 235 pb.source.Set(pkey, value) 236 } 237 238 func (pb prefixBatch) Delete(key []byte) { 239 pkey := append(cp(pb.prefix), key...) 240 pb.source.Delete(pkey) 241 } 242 243 func (pb prefixBatch) Write() { 244 pb.source.Write() 245 } 246 247 func (pb prefixBatch) WriteSync() { 248 pb.source.WriteSync() 249 } 250 251 func (pb prefixBatch) Close() { 252 pb.source.Close() 253 } 254 255 //---------------------------------------- 256 // prefixIterator 257 258 var _ Iterator = (*prefixIterator)(nil) 259 260 // Strips prefix while iterating from Iterator. 261 type prefixIterator struct { 262 prefix []byte 263 start []byte 264 end []byte 265 source Iterator 266 valid bool 267 } 268 269 func newPrefixIterator(prefix, start, end []byte, source Iterator) *prefixIterator { 270 if !source.Valid() || !bytes.HasPrefix(source.Key(), prefix) { 271 return &prefixIterator{ 272 prefix: prefix, 273 start: start, 274 end: end, 275 source: source, 276 valid: false, 277 } 278 } else { 279 return &prefixIterator{ 280 prefix: prefix, 281 start: start, 282 end: end, 283 source: source, 284 valid: true, 285 } 286 } 287 } 288 289 func (itr *prefixIterator) Domain() (start []byte, end []byte) { 290 return itr.start, itr.end 291 } 292 293 func (itr *prefixIterator) Valid() bool { 294 return itr.valid && itr.source.Valid() 295 } 296 297 func (itr *prefixIterator) Next() { 298 if !itr.valid { 299 panic("prefixIterator invalid, cannot call Next()") 300 } 301 itr.source.Next() 302 if !itr.source.Valid() || !bytes.HasPrefix(itr.source.Key(), itr.prefix) { 303 itr.valid = false 304 return 305 } 306 } 307 308 func (itr *prefixIterator) Key() (key []byte) { 309 if !itr.valid { 310 panic("prefixIterator invalid, cannot call Key()") 311 } 312 return stripPrefix(itr.source.Key(), itr.prefix) 313 } 314 315 func (itr *prefixIterator) Value() (value []byte) { 316 if !itr.valid { 317 panic("prefixIterator invalid, cannot call Value()") 318 } 319 return itr.source.Value() 320 } 321 322 func (itr *prefixIterator) Close() { 323 itr.source.Close() 324 } 325 326 //---------------------------------------- 327 328 func stripPrefix(key []byte, prefix []byte) (stripped []byte) { 329 if len(key) < len(prefix) { 330 panic("should not happen") 331 } 332 if !bytes.Equal(key[:len(prefix)], prefix) { 333 panic("should not happne") 334 } 335 return key[len(prefix):] 336 }