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  }