github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/allegrosql/memdb.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package ekv
    15  
    16  import (
    17  	"bytes"
    18  	"context"
    19  	"reflect"
    20  	"sync"
    21  	"sync/atomic"
    22  	"unsafe"
    23  )
    24  
    25  const (
    26  	flagPresumeKNE KeyFlags = 1 << iota
    27  	flagKeyLocked
    28  	flagKeyLockedValExist
    29  	flagNeedCheckExists
    30  	flagNoNeedCommit
    31  
    32  	persistentFlags = flagKeyLocked | flagKeyLockedValExist
    33  	// bit 1 => red, bit 0 => black
    34  	nodeDefCausorBit uint8 = 0x80
    35  	nodeFlagsMask          = ^nodeDefCausorBit
    36  )
    37  
    38  // KeyFlags are spacetimedata associated with key
    39  type KeyFlags uint8
    40  
    41  // HasPresumeKeyNotExists returns whether the associated key use lazy check.
    42  func (f KeyFlags) HasPresumeKeyNotExists() bool {
    43  	return f&flagPresumeKNE != 0
    44  }
    45  
    46  // HasLocked returns whether the associated key has acquired pessimistic dagger.
    47  func (f KeyFlags) HasLocked() bool {
    48  	return f&flagKeyLocked != 0
    49  }
    50  
    51  // HasLockedValueExists returns whether the value exists when key locked.
    52  func (f KeyFlags) HasLockedValueExists() bool {
    53  	return f&flagKeyLockedValExist != 0
    54  }
    55  
    56  // HasNeedCheckExists returns whether the key need to check existence when it has been locked.
    57  func (f KeyFlags) HasNeedCheckExists() bool {
    58  	return f&flagNeedCheckExists != 0
    59  }
    60  
    61  // HasNoNeedCommit returns whether the key should be used in 2pc commit phase.
    62  func (f KeyFlags) HasNoNeedCommit() bool {
    63  	return f&flagNoNeedCommit != 0
    64  }
    65  
    66  // FlagsOp describes KeyFlags modify operation.
    67  type FlagsOp uint16
    68  
    69  const (
    70  	// SetPresumeKeyNotExists marks the existence of the associated key is checked lazily.
    71  	// Implies KeyFlags.HasNeedCheckExists() == true.
    72  	SetPresumeKeyNotExists FlagsOp = 1 << iota
    73  	// DelPresumeKeyNotExists reverts SetPresumeKeyNotExists.
    74  	DelPresumeKeyNotExists
    75  	// SetKeyLocked marks the associated key has acquired dagger.
    76  	SetKeyLocked
    77  	// DelKeyLocked reverts SetKeyLocked.
    78  	DelKeyLocked
    79  	// SetKeyLockedValueExists marks the value exists when key has been locked in Transaction.LockKeys.
    80  	SetKeyLockedValueExists
    81  	// SetKeyLockedValueNotExists marks the value doesn't exists when key has been locked in Transaction.LockKeys.
    82  	SetKeyLockedValueNotExists
    83  	// DelNeedCheckExists marks the key no need to be checked in Transaction.LockKeys.
    84  	DelNeedCheckExists
    85  	// SetNoNeedCommit marks the key shouldn't be used in 2pc commit phase.
    86  	SetNoNeedCommit
    87  )
    88  
    89  func applyFlagsOps(origin KeyFlags, ops ...FlagsOp) KeyFlags {
    90  	for _, op := range ops {
    91  		switch op {
    92  		case SetPresumeKeyNotExists:
    93  			origin |= flagPresumeKNE | flagNeedCheckExists
    94  		case DelPresumeKeyNotExists:
    95  			origin &= ^(flagPresumeKNE | flagNeedCheckExists)
    96  		case SetKeyLocked:
    97  			origin |= flagKeyLocked
    98  		case DelKeyLocked:
    99  			origin &= ^flagKeyLocked
   100  		case SetKeyLockedValueExists:
   101  			origin |= flagKeyLockedValExist
   102  		case DelNeedCheckExists:
   103  			origin &= ^flagNeedCheckExists
   104  		case SetKeyLockedValueNotExists:
   105  			origin &= ^flagKeyLockedValExist
   106  		case SetNoNeedCommit:
   107  			origin |= flagNoNeedCommit
   108  		}
   109  	}
   110  	return origin
   111  }
   112  
   113  var tombstone = []byte{}
   114  
   115  // memdb is rollbackable Red-Black Tree optimized for MilevaDB's transaction states buffer use scenario.
   116  // You can think memdb is a combination of two separate tree map, one for key => value and another for key => keyFlags.
   117  //
   118  // The value map is rollbackable, that means you can use the `Staging`, `Release` and `Cleanup` API to safely modify KVs.
   119  //
   120  // The flags map is not rollbackable. There are two types of flag, persistent and non-persistent.
   121  // When discarding a newly added KV in `Cleanup`, the non-persistent flags will be cleared.
   122  // If there are persistent flags associated with key, we will keep this key in node without value.
   123  type memdb struct {
   124  	// This RWMutex only used to ensure memdbSnapGetter.Get will not race with
   125  	// concurrent memdb.Set, memdb.SetWithFlags, memdb.Delete and memdb.UFIDelateFlags.
   126  	sync.RWMutex
   127  	root      memdbMemCamAddr
   128  	allocator nodeSlabPredictor
   129  	vlog      memdbVlog
   130  
   131  	entrySizeLimit  uint64
   132  	bufferSizeLimit uint64
   133  	count           int
   134  	size            int
   135  
   136  	vlogInvalid bool
   137  	dirty       bool
   138  	stages      []memdbCheckpoint
   139  }
   140  
   141  func newMemDB() *memdb {
   142  	EDB := new(memdb)
   143  	EDB.allocator.init()
   144  	EDB.root = nullAddr
   145  	EDB.stages = make([]memdbCheckpoint, 0, 2)
   146  	EDB.entrySizeLimit = atomic.LoadUint64(&TxnEntrySizeLimit)
   147  	EDB.bufferSizeLimit = atomic.LoadUint64(&TxnTotalSizeLimit)
   148  	return EDB
   149  }
   150  
   151  func (EDB *memdb) Staging() StagingHandle {
   152  	EDB.Lock()
   153  	defer EDB.Unlock()
   154  
   155  	EDB.stages = append(EDB.stages, EDB.vlog.checkpoint())
   156  	return StagingHandle(len(EDB.stages))
   157  }
   158  
   159  func (EDB *memdb) Release(h StagingHandle) {
   160  	if int(h) != len(EDB.stages) {
   161  		// This should never happens in production environment.
   162  		// Use panic to make debug easier.
   163  		panic("cannot release staging buffer")
   164  	}
   165  
   166  	EDB.Lock()
   167  	defer EDB.Unlock()
   168  	if int(h) == 1 {
   169  		tail := EDB.vlog.checkpoint()
   170  		if !EDB.stages[0].isSamePosition(&tail) {
   171  			EDB.dirty = true
   172  		}
   173  	}
   174  	EDB.stages = EDB.stages[:int(h)-1]
   175  }
   176  
   177  func (EDB *memdb) Cleanup(h StagingHandle) {
   178  	if int(h) > len(EDB.stages) {
   179  		return
   180  	}
   181  	if int(h) < len(EDB.stages) {
   182  		// This should never happens in production environment.
   183  		// Use panic to make debug easier.
   184  		panic("cannot cleanup staging buffer")
   185  	}
   186  
   187  	EDB.Lock()
   188  	defer EDB.Unlock()
   189  	cp := &EDB.stages[int(h)-1]
   190  	if !EDB.vlogInvalid {
   191  		EDB.vlog.revertToCheckpoint(EDB, cp)
   192  		EDB.vlog.truncate(cp)
   193  	}
   194  	EDB.stages = EDB.stages[:int(h)-1]
   195  }
   196  
   197  func (EDB *memdb) Reset() {
   198  	EDB.root = nullAddr
   199  	EDB.stages = EDB.stages[:0]
   200  	EDB.dirty = false
   201  	EDB.vlogInvalid = false
   202  	EDB.size = 0
   203  	EDB.count = 0
   204  	EDB.vlog.reset()
   205  	EDB.allocator.reset()
   206  }
   207  
   208  func (EDB *memdb) DiscardValues() {
   209  	EDB.vlogInvalid = true
   210  	EDB.vlog.reset()
   211  }
   212  
   213  func (EDB *memdb) InspectStage(handle StagingHandle, f func(Key, KeyFlags, []byte)) {
   214  	idx := int(handle) - 1
   215  	tail := EDB.vlog.checkpoint()
   216  	head := EDB.stages[idx]
   217  	EDB.vlog.inspectKVInLog(EDB, &head, &tail, f)
   218  }
   219  
   220  func (EDB *memdb) Get(_ context.Context, key Key) ([]byte, error) {
   221  	if EDB.vlogInvalid {
   222  		// panic for easier debugging.
   223  		panic("vlog is resetted")
   224  	}
   225  
   226  	x := EDB.traverse(key, false)
   227  	if x.isNull() {
   228  		return nil, ErrNotExist
   229  	}
   230  	if x.vptr.isNull() {
   231  		// A flag only key, act as value not exists
   232  		return nil, ErrNotExist
   233  	}
   234  	return EDB.vlog.getValue(x.vptr), nil
   235  }
   236  
   237  func (EDB *memdb) GetFlags(key Key) (KeyFlags, error) {
   238  	x := EDB.traverse(key, false)
   239  	if x.isNull() {
   240  		return 0, ErrNotExist
   241  	}
   242  	return x.getKeyFlags(), nil
   243  }
   244  
   245  func (EDB *memdb) UFIDelateFlags(key Key, ops ...FlagsOp) {
   246  	err := EDB.set(key, nil, ops...)
   247  	_ = err // set without value will never fail
   248  }
   249  
   250  func (EDB *memdb) Set(key Key, value []byte) error {
   251  	if len(value) == 0 {
   252  		return ErrCannotSetNilValue
   253  	}
   254  	return EDB.set(key, value)
   255  }
   256  
   257  func (EDB *memdb) SetWithFlags(key Key, value []byte, ops ...FlagsOp) error {
   258  	if len(value) == 0 {
   259  		return ErrCannotSetNilValue
   260  	}
   261  	return EDB.set(key, value, ops...)
   262  }
   263  
   264  func (EDB *memdb) Delete(key Key) error {
   265  	return EDB.set(key, tombstone)
   266  }
   267  
   268  func (EDB *memdb) Len() int {
   269  	return EDB.count
   270  }
   271  
   272  func (EDB *memdb) Size() int {
   273  	return EDB.size
   274  }
   275  
   276  func (EDB *memdb) Dirty() bool {
   277  	return EDB.dirty
   278  }
   279  
   280  func (EDB *memdb) set(key Key, value []byte, ops ...FlagsOp) error {
   281  	if EDB.vlogInvalid {
   282  		// panic for easier debugging.
   283  		panic("vlog is resetted")
   284  	}
   285  
   286  	if value != nil {
   287  		if size := uint64(len(key) + len(value)); size > EDB.entrySizeLimit {
   288  			return ErrEntryTooLarge.GenWithStackByArgs(EDB.entrySizeLimit, size)
   289  		}
   290  	}
   291  
   292  	EDB.Lock()
   293  	defer EDB.Unlock()
   294  
   295  	if len(EDB.stages) == 0 {
   296  		EDB.dirty = true
   297  	}
   298  	x := EDB.traverse(key, true)
   299  
   300  	if len(ops) != 0 {
   301  		flags := applyFlagsOps(x.getKeyFlags(), ops...)
   302  		if flags&persistentFlags != 0 {
   303  			EDB.dirty = true
   304  		}
   305  		x.setKeyFlags(flags)
   306  	}
   307  
   308  	if value == nil {
   309  		return nil
   310  	}
   311  
   312  	EDB.setValue(x, value)
   313  	if uint64(EDB.Size()) > EDB.bufferSizeLimit {
   314  		return ErrTxnTooLarge.GenWithStackByArgs(EDB.Size())
   315  	}
   316  	return nil
   317  }
   318  
   319  func (EDB *memdb) setValue(x memdbNodeAddr, value []byte) {
   320  	var activeCp *memdbCheckpoint
   321  	if len(EDB.stages) > 0 {
   322  		activeCp = &EDB.stages[len(EDB.stages)-1]
   323  	}
   324  
   325  	var oldVal []byte
   326  	if !x.vptr.isNull() {
   327  		oldVal = EDB.vlog.getValue(x.vptr)
   328  	}
   329  
   330  	if len(oldVal) > 0 && EDB.vlog.canModify(activeCp, x.vptr) {
   331  		// For easier to implement, we only consider this case.
   332  		// It is the most common usage in MilevaDB's transaction buffers.
   333  		if len(oldVal) == len(value) {
   334  			copy(oldVal, value)
   335  			return
   336  		}
   337  	}
   338  	x.vptr = EDB.vlog.appendValue(x.addr, x.vptr, value)
   339  	EDB.size = EDB.size - len(oldVal) + len(value)
   340  }
   341  
   342  // traverse search for and if not found and insert is true, will add a new node in.
   343  // Returns a pointer to the new node, or the node found.
   344  func (EDB *memdb) traverse(key Key, insert bool) memdbNodeAddr {
   345  	x := EDB.getRoot()
   346  	y := memdbNodeAddr{nil, nullAddr}
   347  	found := false
   348  
   349  	// walk x down the tree
   350  	for !x.isNull() && !found {
   351  		y = x
   352  		cmp := bytes.Compare(key, x.getKey())
   353  		if cmp < 0 {
   354  			x = x.getLeft(EDB)
   355  		} else if cmp > 0 {
   356  			x = x.getRight(EDB)
   357  		} else {
   358  			found = true
   359  		}
   360  	}
   361  
   362  	if found || !insert {
   363  		return x
   364  	}
   365  
   366  	z := EDB.allocNode(key)
   367  	z.up = y.addr
   368  
   369  	if y.isNull() {
   370  		EDB.root = z.addr
   371  	} else {
   372  		cmp := bytes.Compare(z.getKey(), y.getKey())
   373  		if cmp < 0 {
   374  			y.left = z.addr
   375  		} else {
   376  			y.right = z.addr
   377  		}
   378  	}
   379  
   380  	z.left = nullAddr
   381  	z.right = nullAddr
   382  
   383  	// colour this new node red
   384  	z.setRed()
   385  
   386  	// Having added a red node, we must now walk back up the tree balancing it,
   387  	// by a series of rotations and changing of colours
   388  	x = z
   389  
   390  	// While we are not at the top and our parent node is red
   391  	// NOTE: Since the root node is guaranteed black, then we
   392  	// are also going to stop if we are the child of the root
   393  
   394  	for x.addr != EDB.root {
   395  		xUp := x.getUp(EDB)
   396  		if xUp.isBlack() {
   397  			break
   398  		}
   399  
   400  		xUpUp := xUp.getUp(EDB)
   401  		// if our parent is on the left side of our grandparent
   402  		if x.up == xUpUp.left {
   403  			// get the right side of our grandparent (uncle?)
   404  			y = xUpUp.getRight(EDB)
   405  			if y.isRed() {
   406  				// make our parent black
   407  				xUp.setBlack()
   408  				// make our uncle black
   409  				y.setBlack()
   410  				// make our grandparent red
   411  				xUpUp.setRed()
   412  				// now consider our grandparent
   413  				x = xUp.getUp(EDB)
   414  			} else {
   415  				// if we are on the right side of our parent
   416  				if x.addr == xUp.right {
   417  					// Move up to our parent
   418  					x = x.getUp(EDB)
   419  					EDB.leftRotate(x)
   420  					xUp = x.getUp(EDB)
   421  					xUpUp = xUp.getUp(EDB)
   422  				}
   423  
   424  				xUp.setBlack()
   425  				xUpUp.setRed()
   426  				EDB.rightRotate(xUpUp)
   427  			}
   428  		} else {
   429  			// everything here is the same as above, but exchanging left for right
   430  			y = xUpUp.getLeft(EDB)
   431  			if y.isRed() {
   432  				xUp.setBlack()
   433  				y.setBlack()
   434  				xUpUp.setRed()
   435  
   436  				x = xUp.getUp(EDB)
   437  			} else {
   438  				if x.addr == xUp.left {
   439  					x = x.getUp(EDB)
   440  					EDB.rightRotate(x)
   441  					xUp = x.getUp(EDB)
   442  					xUpUp = xUp.getUp(EDB)
   443  				}
   444  
   445  				xUp.setBlack()
   446  				xUpUp.setRed()
   447  				EDB.leftRotate(xUpUp)
   448  			}
   449  		}
   450  	}
   451  
   452  	// Set the root node black
   453  	EDB.getRoot().setBlack()
   454  
   455  	return z
   456  }
   457  
   458  //
   459  // Rotate our tree thus:-
   460  //
   461  //             X        leftRotate(X)--->           Y
   462  //           /   \                                /   \
   463  //          A     Y     <---rightRotate(Y)       X     C
   464  //              /   \                          /   \
   465  //             B     C                        A     B
   466  //
   467  // NOTE: This does not change the ordering.
   468  //
   469  // We assume that neither X nor Y is NULL
   470  //
   471  
   472  func (EDB *memdb) leftRotate(x memdbNodeAddr) {
   473  	y := x.getRight(EDB)
   474  
   475  	// Turn Y's left subtree into X's right subtree (move B)
   476  	x.right = y.left
   477  
   478  	// If B is not null, set it's parent to be X
   479  	if !y.left.isNull() {
   480  		left := y.getLeft(EDB)
   481  		left.up = x.addr
   482  	}
   483  
   484  	// Set Y's parent to be what X's parent was
   485  	y.up = x.up
   486  
   487  	// if X was the root
   488  	if x.up.isNull() {
   489  		EDB.root = y.addr
   490  	} else {
   491  		xUp := x.getUp(EDB)
   492  		// Set X's parent's left or right pointer to be Y
   493  		if x.addr == xUp.left {
   494  			xUp.left = y.addr
   495  		} else {
   496  			xUp.right = y.addr
   497  		}
   498  	}
   499  
   500  	// Put X on Y's left
   501  	y.left = x.addr
   502  	// Set X's parent to be Y
   503  	x.up = y.addr
   504  }
   505  
   506  func (EDB *memdb) rightRotate(y memdbNodeAddr) {
   507  	x := y.getLeft(EDB)
   508  
   509  	// Turn X's right subtree into Y's left subtree (move B)
   510  	y.left = x.right
   511  
   512  	// If B is not null, set it's parent to be Y
   513  	if !x.right.isNull() {
   514  		right := x.getRight(EDB)
   515  		right.up = y.addr
   516  	}
   517  
   518  	// Set X's parent to be what Y's parent was
   519  	x.up = y.up
   520  
   521  	// if Y was the root
   522  	if y.up.isNull() {
   523  		EDB.root = x.addr
   524  	} else {
   525  		yUp := y.getUp(EDB)
   526  		// Set Y's parent's left or right pointer to be X
   527  		if y.addr == yUp.left {
   528  			yUp.left = x.addr
   529  		} else {
   530  			yUp.right = x.addr
   531  		}
   532  	}
   533  
   534  	// Put Y on X's right
   535  	x.right = y.addr
   536  	// Set Y's parent to be X
   537  	y.up = x.addr
   538  }
   539  
   540  func (EDB *memdb) deleteNode(z memdbNodeAddr) {
   541  	var x, y memdbNodeAddr
   542  
   543  	EDB.count--
   544  	EDB.size -= int(z.klen)
   545  
   546  	if z.left.isNull() || z.right.isNull() {
   547  		y = z
   548  	} else {
   549  		y = EDB.successor(z)
   550  	}
   551  
   552  	if !y.left.isNull() {
   553  		x = y.getLeft(EDB)
   554  	} else {
   555  		x = y.getRight(EDB)
   556  	}
   557  	x.up = y.up
   558  
   559  	if y.up.isNull() {
   560  		EDB.root = x.addr
   561  	} else {
   562  		yUp := y.getUp(EDB)
   563  		if y.addr == yUp.left {
   564  			yUp.left = x.addr
   565  		} else {
   566  			yUp.right = x.addr
   567  		}
   568  	}
   569  
   570  	needFix := y.isBlack()
   571  
   572  	// NOTE: traditional red-black tree will copy key from Y to Z and free Y.
   573  	// We cannot do the same thing here, due to Y's pointer is stored in vlog and the space in Z may not suiblock for Y.
   574  	// So we need to copy states from Z to Y, and relink all nodes formerly connected to Z.
   575  	if y != z {
   576  		EDB.replaceNode(z, y)
   577  	}
   578  
   579  	if needFix {
   580  		EDB.deleteNodeFix(x)
   581  	}
   582  
   583  	EDB.allocator.freeNode(z.addr)
   584  }
   585  
   586  func (EDB *memdb) replaceNode(old memdbNodeAddr, new memdbNodeAddr) {
   587  	if !old.up.isNull() {
   588  		oldUp := old.getUp(EDB)
   589  		if old.addr == oldUp.left {
   590  			oldUp.left = new.addr
   591  		} else {
   592  			oldUp.right = new.addr
   593  		}
   594  	} else {
   595  		EDB.root = new.addr
   596  	}
   597  	new.up = old.up
   598  
   599  	left := old.getLeft(EDB)
   600  	left.up = new.addr
   601  	new.left = old.left
   602  
   603  	right := old.getRight(EDB)
   604  	right.up = new.addr
   605  	new.right = old.right
   606  
   607  	if old.isBlack() {
   608  		new.setBlack()
   609  	} else {
   610  		new.setRed()
   611  	}
   612  }
   613  
   614  func (EDB *memdb) deleteNodeFix(x memdbNodeAddr) {
   615  	for x.addr != EDB.root && x.isBlack() {
   616  		xUp := x.getUp(EDB)
   617  		if x.addr == xUp.left {
   618  			w := xUp.getRight(EDB)
   619  			if w.isRed() {
   620  				w.setBlack()
   621  				xUp.setRed()
   622  				EDB.leftRotate(xUp)
   623  				w = x.getUp(EDB).getRight(EDB)
   624  			}
   625  
   626  			if w.getLeft(EDB).isBlack() && w.getRight(EDB).isBlack() {
   627  				w.setRed()
   628  				x = x.getUp(EDB)
   629  			} else {
   630  				if w.getRight(EDB).isBlack() {
   631  					w.getLeft(EDB).setBlack()
   632  					w.setRed()
   633  					EDB.rightRotate(w)
   634  					w = x.getUp(EDB).getRight(EDB)
   635  				}
   636  
   637  				xUp := x.getUp(EDB)
   638  				if xUp.isBlack() {
   639  					w.setBlack()
   640  				} else {
   641  					w.setRed()
   642  				}
   643  				xUp.setBlack()
   644  				w.getRight(EDB).setBlack()
   645  				EDB.leftRotate(xUp)
   646  				x = EDB.getRoot()
   647  			}
   648  		} else {
   649  			w := xUp.getLeft(EDB)
   650  			if w.isRed() {
   651  				w.setBlack()
   652  				xUp.setRed()
   653  				EDB.rightRotate(xUp)
   654  				w = x.getUp(EDB).getLeft(EDB)
   655  			}
   656  
   657  			if w.getRight(EDB).isBlack() && w.getLeft(EDB).isBlack() {
   658  				w.setRed()
   659  				x = x.getUp(EDB)
   660  			} else {
   661  				if w.getLeft(EDB).isBlack() {
   662  					w.getRight(EDB).setBlack()
   663  					w.setRed()
   664  					EDB.leftRotate(w)
   665  					w = x.getUp(EDB).getLeft(EDB)
   666  				}
   667  
   668  				xUp := x.getUp(EDB)
   669  				if xUp.isBlack() {
   670  					w.setBlack()
   671  				} else {
   672  					w.setRed()
   673  				}
   674  				xUp.setBlack()
   675  				w.getLeft(EDB).setBlack()
   676  				EDB.rightRotate(xUp)
   677  				x = EDB.getRoot()
   678  			}
   679  		}
   680  	}
   681  	x.setBlack()
   682  }
   683  
   684  func (EDB *memdb) successor(x memdbNodeAddr) (y memdbNodeAddr) {
   685  	if !x.right.isNull() {
   686  		// If right is not NULL then go right one and
   687  		// then keep going left until we find a node with
   688  		// no left pointer.
   689  
   690  		y = x.getRight(EDB)
   691  		for !y.left.isNull() {
   692  			y = y.getLeft(EDB)
   693  		}
   694  		return
   695  	}
   696  
   697  	// Go up the tree until we get to a node that is on the
   698  	// left of its parent (or the root) and then return the
   699  	// parent.
   700  
   701  	y = x.getUp(EDB)
   702  	for !y.isNull() && x.addr == y.right {
   703  		x = y
   704  		y = y.getUp(EDB)
   705  	}
   706  	return y
   707  }
   708  
   709  func (EDB *memdb) predecessor(x memdbNodeAddr) (y memdbNodeAddr) {
   710  	if !x.left.isNull() {
   711  		// If left is not NULL then go left one and
   712  		// then keep going right until we find a node with
   713  		// no right pointer.
   714  
   715  		y = x.getLeft(EDB)
   716  		for !y.right.isNull() {
   717  			y = y.getRight(EDB)
   718  		}
   719  		return
   720  	}
   721  
   722  	// Go up the tree until we get to a node that is on the
   723  	// right of its parent (or the root) and then return the
   724  	// parent.
   725  
   726  	y = x.getUp(EDB)
   727  	for !y.isNull() && x.addr == y.left {
   728  		x = y
   729  		y = y.getUp(EDB)
   730  	}
   731  	return y
   732  }
   733  
   734  func (EDB *memdb) getNode(x memdbMemCamAddr) memdbNodeAddr {
   735  	return memdbNodeAddr{EDB.allocator.getNode(x), x}
   736  }
   737  
   738  func (EDB *memdb) getRoot() memdbNodeAddr {
   739  	return EDB.getNode(EDB.root)
   740  }
   741  
   742  func (EDB *memdb) allocNode(key Key) memdbNodeAddr {
   743  	EDB.size += len(key)
   744  	EDB.count++
   745  	x, xn := EDB.allocator.allocNode(key)
   746  	return memdbNodeAddr{xn, x}
   747  }
   748  
   749  type memdbNodeAddr struct {
   750  	*memdbNode
   751  	addr memdbMemCamAddr
   752  }
   753  
   754  func (a *memdbNodeAddr) isNull() bool {
   755  	return a.addr.isNull()
   756  }
   757  
   758  func (a memdbNodeAddr) getUp(EDB *memdb) memdbNodeAddr {
   759  	return EDB.getNode(a.up)
   760  }
   761  
   762  func (a memdbNodeAddr) getLeft(EDB *memdb) memdbNodeAddr {
   763  	return EDB.getNode(a.left)
   764  }
   765  
   766  func (a memdbNodeAddr) getRight(EDB *memdb) memdbNodeAddr {
   767  	return EDB.getNode(a.right)
   768  }
   769  
   770  type memdbNode struct {
   771  	up    memdbMemCamAddr
   772  	left  memdbMemCamAddr
   773  	right memdbMemCamAddr
   774  	vptr  memdbMemCamAddr
   775  	klen  uint16
   776  	flags uint8
   777  }
   778  
   779  func (n *memdbNode) isRed() bool {
   780  	return n.flags&nodeDefCausorBit != 0
   781  }
   782  
   783  func (n *memdbNode) isBlack() bool {
   784  	return !n.isRed()
   785  }
   786  
   787  func (n *memdbNode) setRed() {
   788  	n.flags |= nodeDefCausorBit
   789  }
   790  
   791  func (n *memdbNode) setBlack() {
   792  	n.flags &= ^nodeDefCausorBit
   793  }
   794  
   795  func (n *memdbNode) getKey() Key {
   796  	var ret []byte
   797  	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&ret))
   798  	hdr.Data = uintptr(unsafe.Pointer(&n.flags)) + 1
   799  	hdr.Len = int(n.klen)
   800  	hdr.Cap = int(n.klen)
   801  	return ret
   802  }
   803  
   804  func (n *memdbNode) getKeyFlags() KeyFlags {
   805  	return KeyFlags(n.flags & nodeFlagsMask)
   806  }
   807  
   808  func (n *memdbNode) setKeyFlags(f KeyFlags) {
   809  	n.flags = (^nodeFlagsMask & n.flags) | uint8(f)
   810  }