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  }