github.com/lbryio/lbcd@v0.22.119/database/internal/treap/immutable.go (about)

     1  // Copyright (c) 2015-2016 The btcsuite developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package treap
     6  
     7  import (
     8  	"bytes"
     9  	"math/rand"
    10  )
    11  
    12  // cloneTreapNode returns a shallow copy of the passed node.
    13  func cloneTreapNode(node *treapNode) *treapNode {
    14  	return &treapNode{
    15  		key:      node.key,
    16  		value:    node.value,
    17  		priority: node.priority,
    18  		left:     node.left,
    19  		right:    node.right,
    20  	}
    21  }
    22  
    23  // Immutable represents a treap data structure which is used to hold ordered
    24  // key/value pairs using a combination of binary search tree and heap semantics.
    25  // It is a self-organizing and randomized data structure that doesn't require
    26  // complex operations to maintain balance.  Search, insert, and delete
    27  // operations are all O(log n).  In addition, it provides O(1) snapshots for
    28  // multi-version concurrency control (MVCC).
    29  //
    30  // All operations which result in modifying the treap return a new version of
    31  // the treap with only the modified nodes updated.  All unmodified nodes are
    32  // shared with the previous version.  This is extremely useful in concurrent
    33  // applications since the caller only has to atomically replace the treap
    34  // pointer with the newly returned version after performing any mutations.  All
    35  // readers can simply use their existing pointer as a snapshot since the treap
    36  // it points to is immutable.  This effectively provides O(1) snapshot
    37  // capability with efficient memory usage characteristics since the old nodes
    38  // only remain allocated until there are no longer any references to them.
    39  type Immutable struct {
    40  	root  *treapNode
    41  	count int
    42  
    43  	// totalSize is the best estimate of the total size of of all data in
    44  	// the treap including the keys, values, and node sizes.
    45  	totalSize uint64
    46  }
    47  
    48  // newImmutable returns a new immutable treap given the passed parameters.
    49  func newImmutable(root *treapNode, count int, totalSize uint64) *Immutable {
    50  	return &Immutable{root: root, count: count, totalSize: totalSize}
    51  }
    52  
    53  // Len returns the number of items stored in the treap.
    54  func (t *Immutable) Len() int {
    55  	return t.count
    56  }
    57  
    58  // Size returns a best estimate of the total number of bytes the treap is
    59  // consuming including all of the fields used to represent the nodes as well as
    60  // the size of the keys and values.  Shared values are not detected, so the
    61  // returned size assumes each value is pointing to different memory.
    62  func (t *Immutable) Size() uint64 {
    63  	return t.totalSize
    64  }
    65  
    66  // get returns the treap node that contains the passed key.  It will return nil
    67  // when the key does not exist.
    68  func (t *Immutable) get(key []byte) *treapNode {
    69  	for node := t.root; node != nil; {
    70  		// Traverse left or right depending on the result of the
    71  		// comparison.
    72  		compareResult := bytes.Compare(key, node.key)
    73  		if compareResult < 0 {
    74  			node = node.left
    75  			continue
    76  		}
    77  		if compareResult > 0 {
    78  			node = node.right
    79  			continue
    80  		}
    81  
    82  		// The key exists.
    83  		return node
    84  	}
    85  
    86  	// A nil node was reached which means the key does not exist.
    87  	return nil
    88  }
    89  
    90  // Has returns whether or not the passed key exists.
    91  func (t *Immutable) Has(key []byte) bool {
    92  	if node := t.get(key); node != nil {
    93  		return true
    94  	}
    95  	return false
    96  }
    97  
    98  // Get returns the value for the passed key.  The function will return nil when
    99  // the key does not exist.
   100  func (t *Immutable) Get(key []byte) []byte {
   101  	if node := t.get(key); node != nil {
   102  		return node.value
   103  	}
   104  	return nil
   105  }
   106  
   107  // Put inserts the passed key/value pair.
   108  func (t *Immutable) Put(key, value []byte) *Immutable {
   109  	// Use an empty byte slice for the value when none was provided.  This
   110  	// ultimately allows key existence to be determined from the value since
   111  	// an empty byte slice is distinguishable from nil.
   112  	if value == nil {
   113  		value = emptySlice
   114  	}
   115  
   116  	// The node is the root of the tree if there isn't already one.
   117  	if t.root == nil {
   118  		root := newTreapNode(key, value, rand.Int())
   119  		return newImmutable(root, 1, nodeSize(root))
   120  	}
   121  
   122  	// Find the binary tree insertion point and construct a replaced list of
   123  	// parents while doing so.  This is done because this is an immutable
   124  	// data structure so regardless of where in the treap the new key/value
   125  	// pair ends up, all ancestors up to and including the root need to be
   126  	// replaced.
   127  	//
   128  	// When the key matches an entry already in the treap, replace the node
   129  	// with a new one that has the new value set and return.
   130  	var parents parentStack
   131  	var compareResult int
   132  	for node := t.root; node != nil; {
   133  		// Clone the node and link its parent to it if needed.
   134  		nodeCopy := cloneTreapNode(node)
   135  		if oldParent := parents.At(0); oldParent != nil {
   136  			if oldParent.left == node {
   137  				oldParent.left = nodeCopy
   138  			} else {
   139  				oldParent.right = nodeCopy
   140  			}
   141  		}
   142  		parents.Push(nodeCopy)
   143  
   144  		// Traverse left or right depending on the result of comparing
   145  		// the keys.
   146  		compareResult = bytes.Compare(key, node.key)
   147  		if compareResult < 0 {
   148  			node = node.left
   149  			continue
   150  		}
   151  		if compareResult > 0 {
   152  			node = node.right
   153  			continue
   154  		}
   155  
   156  		// The key already exists, so update its value.
   157  		nodeCopy.value = value
   158  
   159  		// Return new immutable treap with the replaced node and
   160  		// ancestors up to and including the root of the tree.
   161  		newRoot := parents.At(parents.Len() - 1)
   162  		newTotalSize := t.totalSize - uint64(len(node.value)) +
   163  			uint64(len(value))
   164  		return newImmutable(newRoot, t.count, newTotalSize)
   165  	}
   166  
   167  	// Link the new node into the binary tree in the correct position.
   168  	node := newTreapNode(key, value, rand.Int())
   169  	parent := parents.At(0)
   170  	if compareResult < 0 {
   171  		parent.left = node
   172  	} else {
   173  		parent.right = node
   174  	}
   175  
   176  	// Perform any rotations needed to maintain the min-heap and replace
   177  	// the ancestors up to and including the tree root.
   178  	newRoot := parents.At(parents.Len() - 1)
   179  	for parents.Len() > 0 {
   180  		// There is nothing left to do when the node's priority is
   181  		// greater than or equal to its parent's priority.
   182  		parent = parents.Pop()
   183  		if node.priority >= parent.priority {
   184  			break
   185  		}
   186  
   187  		// Perform a right rotation if the node is on the left side or
   188  		// a left rotation if the node is on the right side.
   189  		if parent.left == node {
   190  			node.right, parent.left = parent, node.right
   191  		} else {
   192  			node.left, parent.right = parent, node.left
   193  		}
   194  
   195  		// Either set the new root of the tree when there is no
   196  		// grandparent or relink the grandparent to the node based on
   197  		// which side the old parent the node is replacing was on.
   198  		grandparent := parents.At(0)
   199  		if grandparent == nil {
   200  			newRoot = node
   201  		} else if grandparent.left == parent {
   202  			grandparent.left = node
   203  		} else {
   204  			grandparent.right = node
   205  		}
   206  	}
   207  
   208  	return newImmutable(newRoot, t.count+1, t.totalSize+nodeSize(node))
   209  }
   210  
   211  // Delete removes the passed key from the treap and returns the resulting treap
   212  // if it exists.  The original immutable treap is returned if the key does not
   213  // exist.
   214  func (t *Immutable) Delete(key []byte) *Immutable {
   215  	// Find the node for the key while constructing a list of parents while
   216  	// doing so.
   217  	var parents parentStack
   218  	var delNode *treapNode
   219  	for node := t.root; node != nil; {
   220  		parents.Push(node)
   221  
   222  		// Traverse left or right depending on the result of the
   223  		// comparison.
   224  		compareResult := bytes.Compare(key, node.key)
   225  		if compareResult < 0 {
   226  			node = node.left
   227  			continue
   228  		}
   229  		if compareResult > 0 {
   230  			node = node.right
   231  			continue
   232  		}
   233  
   234  		// The key exists.
   235  		delNode = node
   236  		break
   237  	}
   238  
   239  	// There is nothing to do if the key does not exist.
   240  	if delNode == nil {
   241  		return t
   242  	}
   243  
   244  	// When the only node in the tree is the root node and it is the one
   245  	// being deleted, there is nothing else to do besides removing it.
   246  	parent := parents.At(1)
   247  	if parent == nil && delNode.left == nil && delNode.right == nil {
   248  		return newImmutable(nil, 0, 0)
   249  	}
   250  
   251  	// Construct a replaced list of parents and the node to delete itself.
   252  	// This is done because this is an immutable data structure and
   253  	// therefore all ancestors of the node that will be deleted, up to and
   254  	// including the root, need to be replaced.
   255  	var newParents parentStack
   256  	for i := parents.Len(); i > 0; i-- {
   257  		node := parents.At(i - 1)
   258  		nodeCopy := cloneTreapNode(node)
   259  		if oldParent := newParents.At(0); oldParent != nil {
   260  			if oldParent.left == node {
   261  				oldParent.left = nodeCopy
   262  			} else {
   263  				oldParent.right = nodeCopy
   264  			}
   265  		}
   266  		newParents.Push(nodeCopy)
   267  	}
   268  	delNode = newParents.Pop()
   269  	parent = newParents.At(0)
   270  
   271  	// Perform rotations to move the node to delete to a leaf position while
   272  	// maintaining the min-heap while replacing the modified children.
   273  	var child *treapNode
   274  	newRoot := newParents.At(newParents.Len() - 1)
   275  	for delNode.left != nil || delNode.right != nil {
   276  		// Choose the child with the higher priority.
   277  		var isLeft bool
   278  		if delNode.left == nil {
   279  			child = delNode.right
   280  		} else if delNode.right == nil {
   281  			child = delNode.left
   282  			isLeft = true
   283  		} else if delNode.left.priority >= delNode.right.priority {
   284  			child = delNode.left
   285  			isLeft = true
   286  		} else {
   287  			child = delNode.right
   288  		}
   289  
   290  		// Rotate left or right depending on which side the child node
   291  		// is on.  This has the effect of moving the node to delete
   292  		// towards the bottom of the tree while maintaining the
   293  		// min-heap.
   294  		child = cloneTreapNode(child)
   295  		if isLeft {
   296  			child.right, delNode.left = delNode, child.right
   297  		} else {
   298  			child.left, delNode.right = delNode, child.left
   299  		}
   300  
   301  		// Either set the new root of the tree when there is no
   302  		// grandparent or relink the grandparent to the node based on
   303  		// which side the old parent the node is replacing was on.
   304  		//
   305  		// Since the node to be deleted was just moved down a level, the
   306  		// new grandparent is now the current parent and the new parent
   307  		// is the current child.
   308  		if parent == nil {
   309  			newRoot = child
   310  		} else if parent.left == delNode {
   311  			parent.left = child
   312  		} else {
   313  			parent.right = child
   314  		}
   315  
   316  		// The parent for the node to delete is now what was previously
   317  		// its child.
   318  		parent = child
   319  	}
   320  
   321  	// Delete the node, which is now a leaf node, by disconnecting it from
   322  	// its parent.
   323  	if parent.right == delNode {
   324  		parent.right = nil
   325  	} else {
   326  		parent.left = nil
   327  	}
   328  
   329  	return newImmutable(newRoot, t.count-1, t.totalSize-nodeSize(delNode))
   330  }
   331  
   332  // ForEach invokes the passed function with every key/value pair in the treap
   333  // in ascending order.
   334  func (t *Immutable) ForEach(fn func(k, v []byte) bool) {
   335  	// Add the root node and all children to the left of it to the list of
   336  	// nodes to traverse and loop until they, and all of their child nodes,
   337  	// have been traversed.
   338  	var parents parentStack
   339  	for node := t.root; node != nil; node = node.left {
   340  		parents.Push(node)
   341  	}
   342  	for parents.Len() > 0 {
   343  		node := parents.Pop()
   344  		if !fn(node.key, node.value) {
   345  			return
   346  		}
   347  
   348  		// Extend the nodes to traverse by all children to the left of
   349  		// the current node's right child.
   350  		for node := node.right; node != nil; node = node.left {
   351  			parents.Push(node)
   352  		}
   353  	}
   354  }
   355  
   356  // NewImmutable returns a new empty immutable treap ready for use.  See the
   357  // documentation for the Immutable structure for more details.
   358  func NewImmutable() *Immutable {
   359  	return &Immutable{}
   360  }