github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/memdb/memdb.go (about) 1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> 2 // All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 // Package memdb provides in-memory key/value database implementation. 8 package memdb 9 10 import ( 11 "math/rand" 12 "sync" 13 14 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/comparer" 15 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/errors" 16 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/iterator" 17 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/util" 18 ) 19 20 var ( 21 ErrNotFound = errors.ErrNotFound 22 ErrIterReleased = errors.New("leveldb/memdb: iterator released") 23 ) 24 25 const tMaxHeight = 12 26 27 type dbIter struct { 28 util.BasicReleaser 29 p *DB 30 slice *util.Range 31 node int 32 forward bool 33 key, value []byte 34 err error 35 } 36 37 func (i *dbIter) fill(checkStart, checkLimit bool) bool { 38 if i.node != 0 { 39 n := i.p.nodeData[i.node] 40 m := n + i.p.nodeData[i.node+nKey] 41 i.key = i.p.kvData[n:m] 42 if i.slice != nil { 43 switch { 44 case checkLimit && i.slice.Limit != nil && i.p.cmp.Compare(i.key, i.slice.Limit) >= 0: 45 fallthrough 46 case checkStart && i.slice.Start != nil && i.p.cmp.Compare(i.key, i.slice.Start) < 0: 47 i.node = 0 48 goto bail 49 } 50 } 51 i.value = i.p.kvData[m : m+i.p.nodeData[i.node+nVal]] 52 return true 53 } 54 bail: 55 i.key = nil 56 i.value = nil 57 return false 58 } 59 60 func (i *dbIter) Valid() bool { 61 return i.node != 0 62 } 63 64 func (i *dbIter) First() bool { 65 if i.Released() { 66 i.err = ErrIterReleased 67 return false 68 } 69 70 i.forward = true 71 i.p.mu.RLock() 72 defer i.p.mu.RUnlock() 73 if i.slice != nil && i.slice.Start != nil { 74 i.node, _ = i.p.findGE(i.slice.Start, false) 75 } else { 76 i.node = i.p.nodeData[nNext] 77 } 78 return i.fill(false, true) 79 } 80 81 func (i *dbIter) Last() bool { 82 if i.Released() { 83 i.err = ErrIterReleased 84 return false 85 } 86 87 i.forward = false 88 i.p.mu.RLock() 89 defer i.p.mu.RUnlock() 90 if i.slice != nil && i.slice.Limit != nil { 91 i.node = i.p.findLT(i.slice.Limit) 92 } else { 93 i.node = i.p.findLast() 94 } 95 return i.fill(true, false) 96 } 97 98 func (i *dbIter) Seek(key []byte) bool { 99 if i.Released() { 100 i.err = ErrIterReleased 101 return false 102 } 103 104 i.forward = true 105 i.p.mu.RLock() 106 defer i.p.mu.RUnlock() 107 if i.slice != nil && i.slice.Start != nil && i.p.cmp.Compare(key, i.slice.Start) < 0 { 108 key = i.slice.Start 109 } 110 i.node, _ = i.p.findGE(key, false) 111 return i.fill(false, true) 112 } 113 114 func (i *dbIter) Next() bool { 115 if i.Released() { 116 i.err = ErrIterReleased 117 return false 118 } 119 120 if i.node == 0 { 121 if !i.forward { 122 return i.First() 123 } 124 return false 125 } 126 i.forward = true 127 i.p.mu.RLock() 128 defer i.p.mu.RUnlock() 129 i.node = i.p.nodeData[i.node+nNext] 130 return i.fill(false, true) 131 } 132 133 func (i *dbIter) Prev() bool { 134 if i.Released() { 135 i.err = ErrIterReleased 136 return false 137 } 138 139 if i.node == 0 { 140 if i.forward { 141 return i.Last() 142 } 143 return false 144 } 145 i.forward = false 146 i.p.mu.RLock() 147 defer i.p.mu.RUnlock() 148 i.node = i.p.findLT(i.key) 149 return i.fill(true, false) 150 } 151 152 func (i *dbIter) Key() []byte { 153 return i.key 154 } 155 156 func (i *dbIter) Value() []byte { 157 return i.value 158 } 159 160 func (i *dbIter) Error() error { return i.err } 161 162 func (i *dbIter) Release() { 163 if !i.Released() { 164 i.p = nil 165 i.node = 0 166 i.key = nil 167 i.value = nil 168 i.BasicReleaser.Release() 169 } 170 } 171 172 const ( 173 nKV = iota 174 nKey 175 nVal 176 nHeight 177 nNext 178 ) 179 180 // DB is an in-memory key/value database. 181 type DB struct { 182 cmp comparer.BasicComparer 183 rnd *rand.Rand 184 185 mu sync.RWMutex 186 kvData []byte 187 // Node data: 188 // [0] : KV offset 189 // [1] : Key length 190 // [2] : Value length 191 // [3] : Height 192 // [3..height] : Next nodes 193 nodeData []int 194 prevNode [tMaxHeight]int 195 maxHeight int 196 n int 197 kvSize int 198 } 199 200 func (p *DB) randHeight() (h int) { 201 const branching = 4 202 h = 1 203 for h < tMaxHeight && p.rnd.Int()%branching == 0 { 204 h++ 205 } 206 return 207 } 208 209 // Must hold RW-lock if prev == true, as it use shared prevNode slice. 210 func (p *DB) findGE(key []byte, prev bool) (int, bool) { 211 node := 0 212 h := p.maxHeight - 1 213 for { 214 next := p.nodeData[node+nNext+h] 215 cmp := 1 216 if next != 0 { 217 o := p.nodeData[next] 218 cmp = p.cmp.Compare(p.kvData[o:o+p.nodeData[next+nKey]], key) 219 } 220 if cmp < 0 { 221 // Keep searching in this list 222 node = next 223 } else { 224 if prev { 225 p.prevNode[h] = node 226 } else if cmp == 0 { 227 return next, true 228 } 229 if h == 0 { 230 return next, cmp == 0 231 } 232 h-- 233 } 234 } 235 } 236 237 func (p *DB) findLT(key []byte) int { 238 node := 0 239 h := p.maxHeight - 1 240 for { 241 next := p.nodeData[node+nNext+h] 242 o := p.nodeData[next] 243 if next == 0 || p.cmp.Compare(p.kvData[o:o+p.nodeData[next+nKey]], key) >= 0 { 244 if h == 0 { 245 break 246 } 247 h-- 248 } else { 249 node = next 250 } 251 } 252 return node 253 } 254 255 func (p *DB) findLast() int { 256 node := 0 257 h := p.maxHeight - 1 258 for { 259 next := p.nodeData[node+nNext+h] 260 if next == 0 { 261 if h == 0 { 262 break 263 } 264 h-- 265 } else { 266 node = next 267 } 268 } 269 return node 270 } 271 272 // Put sets the value for the given key. It overwrites any previous value 273 // for that key; a DB is not a multi-map. 274 // 275 // It is safe to modify the contents of the arguments after Put returns. 276 func (p *DB) Put(key []byte, value []byte) error { 277 p.mu.Lock() 278 defer p.mu.Unlock() 279 280 if node, exact := p.findGE(key, true); exact { 281 kvOffset := len(p.kvData) 282 p.kvData = append(p.kvData, key...) 283 p.kvData = append(p.kvData, value...) 284 p.nodeData[node] = kvOffset 285 m := p.nodeData[node+nVal] 286 p.nodeData[node+nVal] = len(value) 287 p.kvSize += len(value) - m 288 return nil 289 } 290 291 h := p.randHeight() 292 if h > p.maxHeight { 293 for i := p.maxHeight; i < h; i++ { 294 p.prevNode[i] = 0 295 } 296 p.maxHeight = h 297 } 298 299 kvOffset := len(p.kvData) 300 p.kvData = append(p.kvData, key...) 301 p.kvData = append(p.kvData, value...) 302 // Node 303 node := len(p.nodeData) 304 p.nodeData = append(p.nodeData, kvOffset, len(key), len(value), h) 305 for i, n := range p.prevNode[:h] { 306 m := n + nNext + i 307 p.nodeData = append(p.nodeData, p.nodeData[m]) 308 p.nodeData[m] = node 309 } 310 311 p.kvSize += len(key) + len(value) 312 p.n++ 313 return nil 314 } 315 316 // Delete deletes the value for the given key. It returns ErrNotFound if 317 // the DB does not contain the key. 318 // 319 // It is safe to modify the contents of the arguments after Delete returns. 320 func (p *DB) Delete(key []byte) error { 321 p.mu.Lock() 322 defer p.mu.Unlock() 323 324 node, exact := p.findGE(key, true) 325 if !exact { 326 return ErrNotFound 327 } 328 329 h := p.nodeData[node+nHeight] 330 for i, n := range p.prevNode[:h] { 331 m := n + 4 + i 332 p.nodeData[m] = p.nodeData[p.nodeData[m]+nNext+i] 333 } 334 335 p.kvSize -= p.nodeData[node+nKey] + p.nodeData[node+nVal] 336 p.n-- 337 return nil 338 } 339 340 // Contains returns true if the given key are in the DB. 341 // 342 // It is safe to modify the contents of the arguments after Contains returns. 343 func (p *DB) Contains(key []byte) bool { 344 p.mu.RLock() 345 _, exact := p.findGE(key, false) 346 p.mu.RUnlock() 347 return exact 348 } 349 350 // Get gets the value for the given key. It returns error.ErrNotFound if the 351 // DB does not contain the key. 352 // 353 // The caller should not modify the contents of the returned slice, but 354 // it is safe to modify the contents of the argument after Get returns. 355 func (p *DB) Get(key []byte) (value []byte, err error) { 356 p.mu.RLock() 357 if node, exact := p.findGE(key, false); exact { 358 o := p.nodeData[node] + p.nodeData[node+nKey] 359 value = p.kvData[o : o+p.nodeData[node+nVal]] 360 } else { 361 err = ErrNotFound 362 } 363 p.mu.RUnlock() 364 return 365 } 366 367 // Find finds key/value pair whose key is greater than or equal to the 368 // given key. It returns ErrNotFound if the table doesn't contain 369 // such pair. 370 // 371 // The caller should not modify the contents of the returned slice, but 372 // it is safe to modify the contents of the argument after Find returns. 373 func (p *DB) Find(key []byte) (rkey, value []byte, err error) { 374 p.mu.RLock() 375 if node, _ := p.findGE(key, false); node != 0 { 376 n := p.nodeData[node] 377 m := n + p.nodeData[node+nKey] 378 rkey = p.kvData[n:m] 379 value = p.kvData[m : m+p.nodeData[node+nVal]] 380 } else { 381 err = ErrNotFound 382 } 383 p.mu.RUnlock() 384 return 385 } 386 387 // NewIterator returns an iterator of the DB. 388 // The returned iterator is not goroutine-safe, but it is safe to use 389 // multiple iterators concurrently, with each in a dedicated goroutine. 390 // It is also safe to use an iterator concurrently with modifying its 391 // underlying DB. However, the resultant key/value pairs are not guaranteed 392 // to be a consistent snapshot of the DB at a particular point in time. 393 // 394 // Slice allows slicing the iterator to only contains keys in the given 395 // range. A nil Range.Start is treated as a key before all keys in the 396 // DB. And a nil Range.Limit is treated as a key after all keys in 397 // the DB. 398 // 399 // The iterator must be released after use, by calling Release method. 400 // 401 // Also read Iterator documentation of the leveldb/iterator package. 402 func (p *DB) NewIterator(slice *util.Range) iterator.Iterator { 403 return &dbIter{p: p, slice: slice} 404 } 405 406 // Capacity returns keys/values buffer capacity. 407 func (p *DB) Capacity() int { 408 p.mu.RLock() 409 defer p.mu.RUnlock() 410 return cap(p.kvData) 411 } 412 413 // Size returns sum of keys and values length. Note that deleted 414 // key/value will not be accouted for, but it will still consume 415 // the buffer, since the buffer is append only. 416 func (p *DB) Size() int { 417 p.mu.RLock() 418 defer p.mu.RUnlock() 419 return p.kvSize 420 } 421 422 // Free returns keys/values free buffer before need to grow. 423 func (p *DB) Free() int { 424 p.mu.RLock() 425 defer p.mu.RUnlock() 426 return cap(p.kvData) - len(p.kvData) 427 } 428 429 // Len returns the number of entries in the DB. 430 func (p *DB) Len() int { 431 p.mu.RLock() 432 defer p.mu.RUnlock() 433 return p.n 434 } 435 436 // Reset resets the DB to initial empty state. Allows reuse the buffer. 437 func (p *DB) Reset() { 438 p.mu.Lock() 439 p.rnd = rand.New(rand.NewSource(0xdeadbeef)) 440 p.maxHeight = 1 441 p.n = 0 442 p.kvSize = 0 443 p.kvData = p.kvData[:0] 444 p.nodeData = p.nodeData[:nNext+tMaxHeight] 445 p.nodeData[nKV] = 0 446 p.nodeData[nKey] = 0 447 p.nodeData[nVal] = 0 448 p.nodeData[nHeight] = tMaxHeight 449 for n := 0; n < tMaxHeight; n++ { 450 p.nodeData[nNext+n] = 0 451 p.prevNode[n] = 0 452 } 453 p.mu.Unlock() 454 } 455 456 // New creates a new initalized in-memory key/value DB. The capacity 457 // is the initial key/value buffer capacity. The capacity is advisory, 458 // not enforced. 459 // 460 // The returned DB instance is goroutine-safe. 461 func New(cmp comparer.BasicComparer, capacity int) *DB { 462 p := &DB{ 463 cmp: cmp, 464 rnd: rand.New(rand.NewSource(0xdeadbeef)), 465 maxHeight: 1, 466 kvData: make([]byte, 0, capacity), 467 nodeData: make([]int, 4+tMaxHeight), 468 } 469 p.nodeData[nHeight] = tMaxHeight 470 return p 471 }