github.com/cilium/statedb@v0.3.2/part/node.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package part 5 6 import ( 7 "bytes" 8 "fmt" 9 "sort" 10 "strings" 11 "unsafe" 12 ) 13 14 type nodeKind uint8 15 16 const ( 17 nodeKindUnknown = iota 18 nodeKindLeaf 19 nodeKind4 20 nodeKind16 21 nodeKind48 22 nodeKind256 23 ) 24 25 // header is the common header shared by all node kinds. 26 type header[T any] struct { 27 flags uint16 // kind(4b) | unused(3b) | size(9b) 28 prefix []byte // the compressed prefix, [0] is the key 29 watch chan struct{} // watch channel that is closed when this node mutates 30 } 31 32 const kindMask = uint16(0b1111_000_00000000_0) 33 34 func (n *header[T]) kind() nodeKind { 35 return nodeKind(n.flags >> 12) 36 } 37 38 func (n *header[T]) setKind(k nodeKind) { 39 n.flags = (n.flags & ^kindMask) | (uint16(k&0b1111) << 12) 40 } 41 42 const sizeMask = uint16(0b0000_000_1111_1111_1) 43 44 func (n *header[T]) cap() int { 45 switch n.kind() { 46 case nodeKindLeaf: 47 return 0 48 case nodeKind4: 49 return 4 50 case nodeKind16: 51 return 16 52 case nodeKind48: 53 return 48 54 case nodeKind256: 55 return 256 56 default: 57 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 58 } 59 } 60 61 func (n *header[T]) isLeaf() bool { 62 return n.kind() == nodeKindLeaf 63 } 64 65 func (n *header[T]) getLeaf() *leaf[T] { 66 switch n.kind() { 67 case nodeKindLeaf: 68 return (*leaf[T])(unsafe.Pointer(n)) 69 case nodeKind4: 70 return n.node4().leaf 71 case nodeKind16: 72 return n.node16().leaf 73 case nodeKind48: 74 return n.node48().leaf 75 case nodeKind256: 76 return n.node256().leaf 77 default: 78 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 79 } 80 } 81 82 func (n *header[T]) setLeaf(l *leaf[T]) { 83 switch n.kind() { 84 case nodeKindLeaf: 85 panic("cannot setLeaf on a leaf[T]") 86 case nodeKind4: 87 n.node4().leaf = l 88 case nodeKind16: 89 n.node16().leaf = l 90 case nodeKind48: 91 n.node48().leaf = l 92 case nodeKind256: 93 n.node256().leaf = l 94 default: 95 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 96 } 97 } 98 99 func (n *header[T]) size() int { 100 return int(n.flags & sizeMask) 101 } 102 103 func (n *header[T]) setSize(size int) { 104 n.flags = (n.flags & ^sizeMask) | uint16(size)&sizeMask 105 } 106 107 func (n *header[T]) self() *header[T] { 108 return n 109 } 110 111 func (n *header[T]) node4() *node4[T] { 112 return (*node4[T])(unsafe.Pointer(n)) 113 } 114 115 func (n *header[T]) node16() *node16[T] { 116 return (*node16[T])(unsafe.Pointer(n)) 117 } 118 119 func (n *header[T]) node48() *node48[T] { 120 return (*node48[T])(unsafe.Pointer(n)) 121 } 122 123 func (n *header[T]) node256() *node256[T] { 124 return (*node256[T])(unsafe.Pointer(n)) 125 } 126 127 // clone returns a shallow clone of the node. 128 // We are working on the assumption here that only 129 // value-types are mutated in the returned clone. 130 func (n *header[T]) clone(watch bool) *header[T] { 131 var nCopy *header[T] 132 switch n.kind() { 133 case nodeKindLeaf: 134 l := *n.getLeaf() 135 nCopy = (&l).self() 136 case nodeKind4: 137 n4 := *n.node4() 138 nCopy = (&n4).self() 139 case nodeKind16: 140 n16 := *n.node16() 141 nCopy = (&n16).self() 142 case nodeKind48: 143 n48 := *n.node48() 144 nCopy = (&n48).self() 145 case nodeKind256: 146 nCopy256 := *n.node256() 147 nCopy = (&nCopy256).self() 148 default: 149 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 150 } 151 if watch { 152 nCopy.watch = make(chan struct{}) 153 } else { 154 nCopy.watch = nil 155 } 156 return nCopy 157 } 158 159 func (n *header[T]) promote(watch bool) *header[T] { 160 switch n.kind() { 161 case nodeKindLeaf: 162 node4 := &node4[T]{} 163 node4.prefix = n.prefix 164 node4.leaf = n.getLeaf() 165 node4.setKind(nodeKind4) 166 if watch { 167 node4.watch = make(chan struct{}) 168 } 169 return node4.self() 170 case nodeKind4: 171 node4 := n.node4() 172 node16 := &node16[T]{header: *n} 173 node16.setKind(nodeKind16) 174 node16.leaf = n.getLeaf() 175 size := node4.size() 176 copy(node16.children[:], node4.children[:size]) 177 copy(node16.keys[:], node4.keys[:size]) 178 if watch { 179 node16.watch = make(chan struct{}) 180 } 181 return node16.self() 182 case nodeKind16: 183 node16 := n.node16() 184 node48 := &node48[T]{header: *n} 185 node48.setKind(nodeKind48) 186 node48.leaf = n.getLeaf() 187 copy(node48.children[:], node16.children[:node16.size()]) 188 for i, k := range node16.keys[:node16.size()] { 189 node48.index[k] = int8(i) 190 } 191 if watch { 192 node48.watch = make(chan struct{}) 193 } 194 return node48.self() 195 case nodeKind48: 196 node48 := n.node48() 197 node256 := &node256[T]{header: *n} 198 node256.setKind(nodeKind256) 199 node256.leaf = n.getLeaf() 200 201 // Since Node256 has children indexed directly, iterate over the children 202 // to assign them to the right index. 203 for _, child := range node48.children[:node48.size()] { 204 node256.children[child.prefix[0]] = child 205 } 206 if watch { 207 node256.watch = make(chan struct{}) 208 } 209 return node256.self() 210 case nodeKind256: 211 panic("BUG: should not need to promote node256") 212 default: 213 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 214 } 215 } 216 217 func (n *header[T]) printTree(level int) { 218 fmt.Print(strings.Repeat(" ", level)) 219 220 var children []*header[T] 221 switch n.kind() { 222 case nodeKindLeaf: 223 fmt.Printf("leaf[%x]:", n.prefix) 224 case nodeKind4: 225 fmt.Printf("node4[%x]:", n.prefix) 226 children = n.node4().children[:n.size()] 227 case nodeKind16: 228 fmt.Printf("node16[%x]:", n.prefix) 229 children = n.node16().children[:n.size()] 230 case nodeKind48: 231 fmt.Printf("node48[%x]:", n.prefix) 232 children = n.node48().children[:n.size()] 233 case nodeKind256: 234 fmt.Printf("node256[%x]:", n.prefix) 235 children = n.node256().children[:] 236 default: 237 panic("unknown node kind") 238 } 239 if leaf := n.getLeaf(); leaf != nil { 240 fmt.Printf(" %x -> %v (L:%p W:%p)", leaf.key, leaf.value, leaf, leaf.watch) 241 } 242 fmt.Printf(" (N:%p, W:%p)\n", n, n.watch) 243 244 for _, child := range children { 245 if child != nil { 246 child.printTree(level + 1) 247 } 248 } 249 } 250 251 func (n *header[T]) children() []*header[T] { 252 switch n.kind() { 253 case nodeKindLeaf: 254 return nil 255 case nodeKind4: 256 return n.node4().children[0:n.size():4] 257 case nodeKind16: 258 return n.node16().children[0:n.size():16] 259 case nodeKind48: 260 return n.node48().children[0:n.size():48] 261 case nodeKind256: 262 return n.node256().children[:] 263 default: 264 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 265 } 266 } 267 268 func (n *header[T]) findIndex(key byte) (*header[T], int) { 269 switch n.kind() { 270 case nodeKindLeaf: 271 return nil, 0 272 case nodeKind4: 273 n4 := n.node4() 274 size := n4.size() 275 for i := 0; i < int(size); i++ { 276 if n4.keys[i] == key { 277 return n4.children[i], i 278 } else if n4.keys[i] > key { 279 return nil, i 280 } 281 } 282 return nil, size 283 case nodeKind16: 284 n16 := n.node16() 285 size := n16.size() 286 for i := 0; i < int(size); i++ { 287 if n16.keys[i] == key { 288 return n16.children[i], i 289 } else if n16.keys[i] > key { 290 return nil, i 291 } 292 } 293 return nil, size 294 case nodeKind48: 295 children := n.children() 296 idx := sort.Search(len(children), func(i int) bool { 297 return children[i].prefix[0] >= key 298 }) 299 if idx >= n.size() || children[idx].prefix[0] != key { 300 // No node found, return nil and the index into 301 // which it should go. 302 return nil, idx 303 } 304 return children[idx], idx 305 case nodeKind256: 306 return n.node256().children[key], int(key) 307 default: 308 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 309 } 310 } 311 312 func (n *header[T]) find(key byte) *header[T] { 313 switch n.kind() { 314 case nodeKindLeaf: 315 return nil 316 case nodeKind4: 317 n4 := n.node4() 318 size := n4.size() 319 for i := 0; i < int(size); i++ { 320 if n4.keys[i] == key { 321 return n4.children[i] 322 } else if n4.keys[i] > key { 323 return nil 324 } 325 } 326 return nil 327 case nodeKind16: 328 n16 := n.node16() 329 size := n16.size() 330 for i := 0; i < int(size); i++ { 331 if n16.keys[i] == key { 332 return n16.children[i] 333 } else if n16.keys[i] > key { 334 return nil 335 } 336 } 337 return nil 338 case nodeKind48: 339 n48 := n.node48() 340 idx := n48.index[key] 341 if idx < 0 { 342 return nil 343 } 344 return n48.children[idx] 345 case nodeKind256: 346 return n.node256().children[key] 347 default: 348 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 349 } 350 } 351 352 func (n *header[T]) insert(idx int, child *header[T]) { 353 size := n.size() 354 newSize := size + 1 355 switch n.kind() { 356 case nodeKind4: 357 n4 := n.node4() 358 // Shift to make room 359 copy(n4.children[idx+1:newSize], n4.children[idx:newSize]) 360 copy(n4.keys[idx+1:newSize], n4.keys[idx:newSize]) 361 n4.children[idx] = child 362 n4.keys[idx] = child.prefix[0] 363 case nodeKind16: 364 n16 := n.node16() 365 // Shift to make room 366 copy(n16.children[idx+1:newSize], n16.children[idx:newSize]) 367 copy(n16.keys[idx+1:newSize], n16.keys[idx:newSize]) 368 n16.children[idx] = child 369 n16.keys[idx] = child.prefix[0] 370 case nodeKind48: 371 // Shift to make room 372 n48 := n.node48() 373 for i := size - 1; i >= idx; i-- { 374 c := n48.children[i] 375 n48.index[c.prefix[0]] = int8(i + 1) 376 n48.children[i+1] = c 377 } 378 n48.children[idx] = child 379 n48.index[child.prefix[0]] = int8(idx) 380 case nodeKind256: 381 n.node256().children[child.prefix[0]] = child 382 default: 383 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 384 } 385 n.setSize(size + 1) 386 } 387 388 func (n *header[T]) remove(idx int) { 389 newSize := n.size() - 1 390 switch n.kind() { 391 case nodeKind4: 392 size := n.size() 393 n4 := n.node4() 394 copy(n4.keys[idx:size], n4.keys[idx+1:size]) 395 copy(n4.children[idx:size], n4.children[idx+1:size]) 396 n4.children[newSize] = nil 397 n4.keys[newSize] = 255 398 case nodeKind16: 399 size := n.size() 400 n16 := n.node16() 401 copy(n16.keys[idx:size], n16.keys[idx+1:size]) 402 copy(n16.children[idx:size], n16.children[idx+1:size]) 403 n16.children[newSize] = nil 404 n16.keys[newSize] = 255 405 case nodeKind48: 406 children := n.children() 407 key := children[idx].prefix[0] 408 n48 := n.node48() 409 for i := idx; i < newSize; i++ { 410 child := children[i+1] 411 children[i] = child 412 n48.index[child.prefix[0]] = int8(i) 413 } 414 n48.index[key] = -1 415 children[newSize] = nil 416 case nodeKind256: 417 n.node256().children[idx] = nil 418 default: 419 panic(fmt.Sprintf("unknown node kind: %x", n.kind())) 420 } 421 n.setSize(newSize) 422 } 423 424 type leaf[T any] struct { 425 header[T] 426 key []byte 427 value T 428 } 429 430 func newLeaf[T any](o *options, prefix, key []byte, value T) *leaf[T] { 431 leaf := &leaf[T]{key: key, value: value} 432 leaf.prefix = prefix 433 leaf.setKind(nodeKindLeaf) 434 435 if !o.rootOnlyWatch { 436 leaf.watch = make(chan struct{}) 437 } 438 439 return leaf 440 } 441 442 type node4[T any] struct { 443 header[T] 444 keys [4]byte 445 children [4]*header[T] 446 leaf *leaf[T] // non-nil if this node contains a value 447 } 448 449 type node16[T any] struct { 450 header[T] 451 keys [16]byte 452 children [16]*header[T] 453 leaf *leaf[T] // non-nil if this node contains a value 454 } 455 456 type node48[T any] struct { 457 header[T] 458 index [256]int8 459 children [48]*header[T] 460 leaf *leaf[T] // non-nil if this node contains a value 461 } 462 463 type node256[T any] struct { 464 header[T] 465 children [256]*header[T] 466 leaf *leaf[T] // non-nil if this node contains a value 467 } 468 469 func newNode4[T any]() *header[T] { 470 n := &node4[T]{header: header[T]{watch: make(chan struct{})}} 471 n.setKind(nodeKind4) 472 return n.self() 473 } 474 475 func search[T any](root *header[T], key []byte) (value T, watch <-chan struct{}, ok bool) { 476 this := root 477 for { 478 watch = this.watch 479 480 // Consume the prefix 481 if !bytes.HasPrefix(key, this.prefix) { 482 return 483 } 484 key = key[len(this.prefix):] 485 486 if len(key) == 0 { 487 if leaf := this.getLeaf(); leaf != nil { 488 value = leaf.value 489 watch = leaf.watch 490 ok = true 491 } 492 return 493 } 494 495 this = this.find(key[0]) 496 if this == nil { 497 return 498 } 499 } 500 } 501 502 func commonPrefix(a, b []byte) []byte { 503 n := min(len(a), len(b)) 504 for i := 0; i < n; i++ { 505 if a[i] != b[i] { 506 return a[:i] 507 } 508 } 509 return a[:n] 510 }