github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/roaringset/binary_search_tree.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package roaringset 13 14 import ( 15 "bytes" 16 17 "github.com/weaviate/weaviate/adapters/repos/db/lsmkv/rbtree" 18 "github.com/weaviate/weaviate/entities/lsmkv" 19 ) 20 21 type BinarySearchTree struct { 22 root *BinarySearchNode 23 } 24 25 type Insert struct { 26 Additions []uint64 27 Deletions []uint64 28 } 29 30 func (t *BinarySearchTree) Insert(key []byte, values Insert) { 31 if t.root == nil { 32 t.root = &BinarySearchNode{ 33 Key: key, 34 Value: BitmapLayer{ 35 Additions: NewBitmap(values.Additions...), 36 Deletions: NewBitmap(values.Deletions...), 37 }, 38 colourIsRed: false, // root node is always black 39 } 40 return 41 } 42 43 if newRoot := t.root.insert(key, values); newRoot != nil { 44 t.root = newRoot 45 } 46 t.root.colourIsRed = false // Can be flipped in the process of balancing, but root is always black 47 } 48 49 // Get creates copies of underlying bitmaps to prevent future (concurrent) 50 // read and writes after layer being returned 51 func (t *BinarySearchTree) Get(key []byte) (BitmapLayer, error) { 52 if t.root == nil { 53 return BitmapLayer{}, lsmkv.NotFound 54 } 55 56 return t.root.get(key) 57 } 58 59 // FlattenInOrder creates list of ordered copies of bst nodes 60 // Only Key and Value fields are populated 61 func (t *BinarySearchTree) FlattenInOrder() []*BinarySearchNode { 62 if t.root == nil { 63 return nil 64 } 65 66 return t.root.flattenInOrder() 67 } 68 69 type BinarySearchNode struct { 70 Key []byte 71 Value BitmapLayer 72 left *BinarySearchNode 73 right *BinarySearchNode 74 parent *BinarySearchNode 75 colourIsRed bool 76 } 77 78 func (n *BinarySearchNode) Parent() rbtree.Node { 79 if n == nil { 80 return nil 81 } 82 return n.parent 83 } 84 85 func (n *BinarySearchNode) SetParent(parent rbtree.Node) { 86 if n == nil { 87 addNewSearchNodeRoaringSetReceiver(&n) 88 } 89 90 if parent == nil { 91 n.parent = nil 92 return 93 } 94 95 n.parent = parent.(*BinarySearchNode) 96 } 97 98 func (n *BinarySearchNode) Left() rbtree.Node { 99 if n == nil { 100 return nil 101 } 102 return n.left 103 } 104 105 func (n *BinarySearchNode) SetLeft(left rbtree.Node) { 106 if n == nil { 107 addNewSearchNodeRoaringSetReceiver(&n) 108 } 109 110 if left == nil { 111 n.left = nil 112 return 113 } 114 115 n.left = left.(*BinarySearchNode) 116 } 117 118 func (n *BinarySearchNode) Right() rbtree.Node { 119 if n == nil { 120 return nil 121 } 122 return n.right 123 } 124 125 func (n *BinarySearchNode) SetRight(right rbtree.Node) { 126 if n == nil { 127 addNewSearchNodeRoaringSetReceiver(&n) 128 } 129 130 if right == nil { 131 n.right = nil 132 return 133 } 134 135 n.right = right.(*BinarySearchNode) 136 } 137 138 func (n *BinarySearchNode) IsRed() bool { 139 if n == nil { 140 return false 141 } 142 return n.colourIsRed 143 } 144 145 func (n *BinarySearchNode) SetRed(isRed bool) { 146 n.colourIsRed = isRed 147 } 148 149 func (n *BinarySearchNode) IsNil() bool { 150 return n == nil 151 } 152 153 func addNewSearchNodeRoaringSetReceiver(nodePtr **BinarySearchNode) { 154 *nodePtr = &BinarySearchNode{} 155 } 156 157 func (n *BinarySearchNode) insert(key []byte, values Insert) *BinarySearchNode { 158 if bytes.Equal(key, n.Key) { 159 // Merging the new additions and deletions into the existing ones is a 160 // four-step process: 161 // 162 // 1. make sure anything that's added is not part of the deleted list, in 163 // case it was previously deleted 164 // 2. actually add the new entries to additions 165 // 3. make sure anything that's deleted is not part of the additions list, 166 // in case it was recently added 167 // 4. actually add the new entries to deletions (this step is vital in case 168 // a delete points to an entry of a previous segment that's not added in 169 // this memtable) 170 for _, x := range values.Additions { 171 n.Value.Deletions.Remove(x) 172 n.Value.Additions.Set(x) 173 } 174 175 for _, x := range values.Deletions { 176 n.Value.Additions.Remove(x) 177 n.Value.Deletions.Set(x) 178 } 179 180 return nil 181 } 182 183 if bytes.Compare(key, n.Key) < 0 { 184 if n.left != nil { 185 return n.left.insert(key, values) 186 } else { 187 n.left = &BinarySearchNode{ 188 Key: key, 189 Value: BitmapLayer{ 190 Additions: NewBitmap(values.Additions...), 191 Deletions: NewBitmap(values.Deletions...), 192 }, 193 parent: n, 194 colourIsRed: true, 195 } 196 return BinarySearchNodeFromRB(rbtree.Rebalance(n.left)) 197 } 198 } else { 199 if n.right != nil { 200 return n.right.insert(key, values) 201 } else { 202 n.right = &BinarySearchNode{ 203 Key: key, 204 Value: BitmapLayer{ 205 Additions: NewBitmap(values.Additions...), 206 Deletions: NewBitmap(values.Deletions...), 207 }, 208 parent: n, 209 colourIsRed: true, 210 } 211 return BinarySearchNodeFromRB(rbtree.Rebalance(n.right)) 212 } 213 } 214 } 215 216 func (n *BinarySearchNode) get(key []byte) (BitmapLayer, error) { 217 if bytes.Equal(n.Key, key) { 218 return n.Value.Clone(), nil 219 } 220 221 if bytes.Compare(key, n.Key) < 0 { 222 if n.left == nil { 223 return BitmapLayer{}, lsmkv.NotFound 224 } 225 226 return n.left.get(key) 227 } else { 228 if n.right == nil { 229 return BitmapLayer{}, lsmkv.NotFound 230 } 231 232 return n.right.get(key) 233 } 234 } 235 236 func BinarySearchNodeFromRB(rbNode rbtree.Node) (bsNode *BinarySearchNode) { 237 if rbNode == nil { 238 bsNode = nil 239 return 240 } 241 bsNode = rbNode.(*BinarySearchNode) 242 return 243 } 244 245 func (n *BinarySearchNode) flattenInOrder() []*BinarySearchNode { 246 var left []*BinarySearchNode 247 var right []*BinarySearchNode 248 249 if n.left != nil { 250 left = n.left.flattenInOrder() 251 } 252 253 if n.right != nil { 254 right = n.right.flattenInOrder() 255 } 256 257 key := make([]byte, len(n.Key)) 258 copy(key, n.Key) 259 260 right = append([]*BinarySearchNode{{ 261 Key: key, 262 Value: BitmapLayer{ 263 Additions: Condense(n.Value.Additions), 264 Deletions: Condense(n.Value.Deletions), 265 }, 266 }}, right...) 267 return append(left, right...) 268 }