/
art.rs
2078 lines (1828 loc) · 71.5 KB
/
art.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
use core::panic;
use std::cmp::min;
use std::ops::RangeBounds;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use hashbrown::HashSet;
use crate::iter::{Iter, Range};
use crate::node::{FlatNode, Node256, Node48, NodeTrait, TwigNode, Version};
use crate::snapshot::Snapshot;
use crate::{KeyTrait, TrieError};
// Minimum and maximum number of children for Node4
const NODE4MIN: usize = 2;
const NODE4MAX: usize = 4;
// Minimum and maximum number of children for Node16
const NODE16MIN: usize = NODE4MAX + 1;
const NODE16MAX: usize = 16;
// Minimum and maximum number of children for Node48
const NODE48MIN: usize = NODE16MAX + 1;
const NODE48MAX: usize = 48;
// Minimum and maximum number of children for Node256
const NODE256MIN: usize = NODE48MAX + 1;
// Maximum number of active snapshots
pub(crate) const DEFAULT_MAX_ACTIVE_SNAPSHOTS: u64 = 10000;
/// A struct representing a node in an Adaptive Radix Trie.
///
/// The `Node` struct encapsulates a single node within the adaptive radix trie structure.
/// It holds information about the type of the node, which can be one of the various node types
/// defined by the `NodeType` enum.
///
/// # Type Parameters
///
/// - `P`: A type implementing the `Prefix` trait, defining the key prefix for the node.
/// - `V`: The type of value associated with the node.
///
/// # Fields
///
/// - `node_type`: The `NodeType` variant representing the type of the node, containing its
/// specific structure and associated data.
///
pub struct Node<P: KeyTrait + Clone, V: Clone> {
pub(crate) node_type: NodeType<P, V>, // Type of the node
}
impl<P: KeyTrait + Clone, V: Clone> Version for Node<P, V> {
fn version(&self) -> u64 {
match &self.node_type {
NodeType::Twig(twig) => twig.version(),
NodeType::Node1(n) => n.version(),
NodeType::Node4(n) => n.version(),
NodeType::Node16(n) => n.version(),
NodeType::Node48(n) => n.version(),
NodeType::Node256(n) => n.version(),
}
}
}
/// An enumeration representing different types of nodes in an Adaptive Radix Trie.
///
/// The `NodeType` enum encompasses various node types that can exist within the adaptive radix trie structure.
/// It includes different types of inner nodes, such as `Node4`, `Node16`, `Node48`, and `Node256`, as well as the
/// leaf nodes represented by `TwigNode`.
///
/// # Type Parameters
///
/// - `P`: A type implementing the `Prefix` trait, which is used to define the key prefix for each node.
/// - `V`: The type of value associated with each node.
///
/// # Variants
///
/// - `Twig(TwigNode<P, V>)`: Represents a Twig node, which is a leaf node in the adaptive radix trie.
/// - `Node4(FlatNode<P, Node<P, V>, 4>)`: Represents an inner node with 4 keys and 4 children.
/// - `Node16(FlatNode<P, Node<P, V>, 16>)`: Represents an inner node with 16 keys and 16 children.
/// - `Node48(Node48<P, Node<P, V>>)`: Represents an inner node with 256 keys and 48 children.
/// - `Node256(Node256<P, Node<P, V>>)`: Represents an inner node with 256 keys and 256 children.
///
pub(crate) enum NodeType<P: KeyTrait + Clone, V: Clone> {
// Twig node of the adaptive radix trie
Twig(TwigNode<P, V>),
// Inner node of the adaptive radix trie
Node1(FlatNode<P, Node<P, V>, 1>), // Node with 1 key and 1 children
Node4(FlatNode<P, Node<P, V>, 4>), // Node with 4 keys and 4 children
Node16(FlatNode<P, Node<P, V>, 16>), // Node with 16 keys and 16 children
Node48(Node48<P, Node<P, V>>), // Node with 256 keys and 48 children
Node256(Node256<P, Node<P, V>>), // Node with 256 keys and 256 children
}
impl<P: KeyTrait + Clone, V: Clone> Node<P, V> {
/// Creates a new Twig node with a given prefix, key, value, and version.
///
/// Constructs a new Twig node using the provided prefix, key, and value. The version
/// indicates the time of the insertion.
///
/// # Parameters
///
/// - `prefix`: The common prefix for the node.
/// - `key`: The key associated with the Twig node.
/// - `value`: The value to be associated with the key.
/// - `ts`: The version when the value was inserted.
///
/// # Returns
///
/// Returns a new `Node` instance with a Twig node containing the provided key, value, and version.
///
#[inline]
pub(crate) fn new_twig(prefix: P, key: P, value: V, version: u64, ts: u64) -> Node<P, V> {
// Create a new TwigNode instance using the provided prefix and key.
let mut twig = TwigNode::new(prefix, key);
// Insert the provided value into the TwigNode along with the version.
twig.insert_mut(value, version, ts);
// Return a new Node instance encapsulating the constructed Twig node.
Self {
node_type: NodeType::Twig(twig),
}
}
/// Creates a new inner Node4 node with the provided prefix.
///
/// Constructs a new Node4 node using the provided prefix. Node4 is an inner node
/// type that can store up to 4 child pointers and uses arrays for keys and pointers.
///
/// # Parameters
///
/// - `prefix`: The common prefix for the Node4 node.
///
/// # Returns
///
/// Returns a new `Node` instance with an empty Node4 node.
///
#[inline]
#[allow(dead_code)]
pub(crate) fn new_node4(prefix: P) -> Self {
// Create a new FlatNode instance using the provided prefix.
let flat_node = FlatNode::new(prefix);
// Create a new Node4 instance with the constructed FlatNode.
Self {
node_type: NodeType::Node4(flat_node),
}
}
/// Checks if the current node is full based on its type.
///
/// Determines if the current node is full by comparing the number of children to its
/// capacity, which varies based on the node type.
///
/// # Returns
///
/// Returns `true` if the node is full, `false` otherwise.
///
#[inline]
fn is_full(&self) -> bool {
match &self.node_type {
NodeType::Node1(n) => self.num_children() >= n.size(),
NodeType::Node4(n) => self.num_children() >= n.size(),
NodeType::Node16(n) => self.num_children() >= n.size(),
NodeType::Node48(n) => self.num_children() >= n.size(),
NodeType::Node256(n) => self.num_children() > n.size(),
NodeType::Twig(_) => panic!("Unexpected Twig node encountered in is_full()"),
}
}
/// Adds a child node with the given key to the current node.
///
/// Inserts a child node with the specified key into the current node.
/// Depending on the node type, this may lead to growth if the node becomes full.
///
/// # Parameters
///
/// - `key`: The key associated with the child node.
/// - `child`: The child node to be added.
///
/// # Returns
///
/// Returns a new `Node` instance with the added child node.
///
#[inline]
fn add_child(&self, key: u8, child: Node<P, V>) -> Self {
match &self.node_type {
NodeType::Node1(n) => {
// Add the child node to the Node1 instance.
let node = NodeType::Node1(n.add_child(key, child));
// Create a new Node instance with the updated NodeType.
let mut new_node = Self { node_type: node };
// Check if the node has become full and needs to be grown.
if new_node.is_full() {
new_node.grow();
}
new_node
}
NodeType::Node4(n) => {
// Add the child node to the Node4 instance.
let node = NodeType::Node4(n.add_child(key, child));
// Create a new Node instance with the updated NodeType.
let mut new_node = Self { node_type: node };
// Check if the node has become full and needs to be grown.
if new_node.is_full() {
new_node.grow();
}
new_node
}
NodeType::Node16(n) => {
// Add the child node to the Node16 instance.
let node = NodeType::Node16(n.add_child(key, child));
// Create a new Node instance with the updated NodeType.
let mut new_node = Self { node_type: node };
// Check if the node has become full and needs to be grown.
if new_node.is_full() {
new_node.grow();
}
new_node
}
NodeType::Node48(n) => {
// Add the child node to the Node48 instance.
let node = NodeType::Node48(n.add_child(key, child));
// Create a new Node instance with the updated NodeType.
let mut new_node = Self { node_type: node };
// Check if the node has become full and needs to be grown.
if new_node.is_full() {
new_node.grow();
}
new_node
}
NodeType::Node256(n) => {
// Add the child node to the Node256 instance.
let node = NodeType::Node256(n.add_child(key, child));
// Create a new Node instance with the updated NodeType.
let mut new_node = Self { node_type: node };
// Check if the node has become full and needs to be grown.
if new_node.is_full() {
new_node.grow();
}
new_node
}
NodeType::Twig(_) => panic!("Unexpected Twig node encountered in add_child()"),
}
}
/// Grows the current node to the next bigger size.
///
/// Grows the current node to a larger size based on its type.
/// This method is typically used to upgrade nodes when they become full.
///
/// ArtNodes of type NODE4 will grow to NODE16
/// ArtNodes of type NODE16 will grow to NODE48.
/// ArtNodes of type NODE48 will grow to NODE256.
/// ArtNodes of type NODE256 will not grow, as they are the biggest type of ArtNodes
#[inline]
fn grow(&mut self) {
match &mut self.node_type {
NodeType::Node1(n) => {
// Grow a Node4 to a Node16 by resizing.
let n4 = NodeType::Node4(n.resize());
self.node_type = n4;
}
NodeType::Node4(n) => {
// Grow a Node4 to a Node16 by resizing.
let n16 = NodeType::Node16(n.resize());
self.node_type = n16;
}
NodeType::Node16(n) => {
// Grow a Node16 to a Node48 by performing growth.
let n48 = NodeType::Node48(n.grow());
self.node_type = n48;
}
NodeType::Node48(n) => {
// Grow a Node48 to a Node256 by performing growth.
let n256 = NodeType::Node256(n.grow());
self.node_type = n256;
}
NodeType::Node256 { .. } => {
panic!("Node256 cannot be grown further");
}
NodeType::Twig(_) => panic!("Unexpected Twig node encountered in grow()"),
}
}
/// Recursively searches for a child node with the specified key.
///
/// Searches for a child node with the given key in the current node.
/// The search continues recursively in the child nodes based on the node type.
///
/// # Parameters
///
/// - `key`: The key associated with the child node.
///
/// # Returns
///
/// Returns an `Option` containing a reference to the found child node or `None` if not found.
///
#[inline]
fn find_child(&self, key: u8) -> Option<&Arc<Node<P, V>>> {
// If there are no children, return None.
if self.num_children() == 0 {
return None;
}
// Match the node type to find the child using the appropriate method.
match &self.node_type {
NodeType::Node1(n) => n.find_child(key),
NodeType::Node4(n) => n.find_child(key),
NodeType::Node16(n) => n.find_child(key),
NodeType::Node48(n) => n.find_child(key),
NodeType::Node256(n) => n.find_child(key),
NodeType::Twig(_) => None,
}
}
/// Replaces a child node with a new node for the given key.
///
/// Replaces the child node associated with the specified key with the provided new node.
///
/// # Parameters
///
/// - `key`: The key associated with the child node to be replaced.
/// - `node`: The new node to replace the existing child node.
///
/// # Returns
///
/// Returns a new `Node` instance with the child node replaced.
///
fn replace_child(&self, key: u8, node: Arc<Node<P, V>>) -> Self {
match &self.node_type {
NodeType::Node1(n) => {
// Replace the child node in the Node4 instance and update the NodeType.
let node = NodeType::Node1(n.replace_child(key, node));
Self { node_type: node }
}
NodeType::Node4(n) => {
// Replace the child node in the Node4 instance and update the NodeType.
let node = NodeType::Node4(n.replace_child(key, node));
Self { node_type: node }
}
NodeType::Node16(n) => {
// Replace the child node in the Node16 instance and update the NodeType.
let node = NodeType::Node16(n.replace_child(key, node));
Self { node_type: node }
}
NodeType::Node48(n) => {
// Replace the child node in the Node48 instance and update the NodeType.
let node = NodeType::Node48(n.replace_child(key, node));
Self { node_type: node }
}
NodeType::Node256(n) => {
// Replace the child node in the Node256 instance and update the NodeType.
let node = NodeType::Node256(n.replace_child(key, node));
Self { node_type: node }
}
NodeType::Twig(_) => panic!("Unexpected Twig node encountered in replace_child()"),
}
}
/// Removes a child node with the specified key from the current node.
///
/// Removes a child node with the provided key from the current node.
/// Depending on the node type, this may trigger shrinking if the number of children becomes low.
///
/// # Parameters
///
/// - `key`: The key associated with the child node to be removed.
///
/// # Returns
///
/// Returns a new `Node` instance with the child node removed.
///
#[inline]
fn delete_child(&self, key: u8) -> Self {
match &self.node_type {
NodeType::Node1(n) => {
// Delete the child node from the Node1 instance and update the NodeType.
let node = NodeType::Node1(n.delete_child(key));
Self { node_type: node }
}
NodeType::Node4(n) => {
// Delete the child node from the Node4 instance and update the NodeType.
let node = NodeType::Node4(n.delete_child(key));
let mut new_node = Self { node_type: node };
// Check if the number of remaining children is below the threshold.
if new_node.num_children() < NODE4MIN {
new_node.shrink();
}
new_node
}
NodeType::Node16(n) => {
// Delete the child node from the Node16 instance and update the NodeType.
let node = NodeType::Node16(n.delete_child(key));
let mut new_node = Self { node_type: node };
// Check if the number of remaining children is below the threshold.
if new_node.num_children() < NODE16MIN {
new_node.shrink();
}
new_node
}
NodeType::Node48(n) => {
// Delete the child node from the Node48 instance and update the NodeType.
let node = NodeType::Node48(n.delete_child(key));
let mut new_node = Self { node_type: node };
// Check if the number of remaining children is below the threshold.
if new_node.num_children() < NODE48MIN {
new_node.shrink();
}
new_node
}
NodeType::Node256(n) => {
// Delete the child node from the Node256 instance and update the NodeType.
let node = NodeType::Node256(n.delete_child(key));
let mut new_node = Self { node_type: node };
// Check if the number of remaining children is below the threshold.
if new_node.num_children() < NODE256MIN {
new_node.shrink();
}
new_node
}
NodeType::Twig(_) => panic!("Unexpected Twig node encountered in delete_child()"),
}
}
/// Checks if the node type is a Twig node.
///
/// Determines whether the current node is a Twig node based on its node type.
///
/// # Returns
///
/// Returns `true` if the node type is a Twig node, otherwise returns `false`.
///
#[inline]
pub(crate) fn is_twig(&self) -> bool {
matches!(&self.node_type, NodeType::Twig(_))
}
/// Checks if the node type is an inner node.
///
/// Determines whether the current node is an inner node, which includes Node4, Node16, Node48, and Node256.
/// The check is performed based on the absence of a Twig node.
///
/// # Returns
///
/// Returns `true` if the node type is an inner node, otherwise returns `false`.
///
#[inline]
pub(crate) fn is_inner(&self) -> bool {
!self.is_twig()
}
/// Gets the prefix associated with the node.
///
/// Retrieves the prefix associated with the current node based on its node type.
///
/// # Returns
///
/// Returns a reference to the prefix associated with the node.
///
#[inline]
pub(crate) fn prefix(&self) -> &P {
match &self.node_type {
NodeType::Node1(n) => &n.prefix,
NodeType::Node4(n) => &n.prefix,
NodeType::Node16(n) => &n.prefix,
NodeType::Node48(n) => &n.prefix,
NodeType::Node256(n) => &n.prefix,
NodeType::Twig(n) => &n.prefix,
}
}
/// Sets the prefix for the node.
///
/// Updates the prefix associated with the current node based on its node type.
///
/// # Parameters
///
/// - `prefix`: The new prefix to be associated with the node.
///
#[inline]
fn set_prefix(&mut self, prefix: P) {
match &mut self.node_type {
NodeType::Node1(n) => n.prefix = prefix,
NodeType::Node4(n) => n.prefix = prefix,
NodeType::Node16(n) => n.prefix = prefix,
NodeType::Node48(n) => n.prefix = prefix,
NodeType::Node256(n) => n.prefix = prefix,
NodeType::Twig(n) => n.prefix = prefix,
}
}
/// Shrinks the current node to a smaller size.
///
/// Shrinks the current node to a smaller size based on its type.
/// This method is typically used to downgrade nodes when the number of children becomes low.
///
/// ArtNodes of type NODE256 will shrink to NODE48
/// ArtNodes of type NODE48 will shrink to NODE16.
/// ArtNodes of type NODE16 will shrink to NODE4.
/// ArtNodes of type NODE4 will collapse into its first child.
///
/// If that child is not a twig, it will concatenate its current prefix with that of its childs
/// before replacing itself.
fn shrink(&mut self) {
match &mut self.node_type {
NodeType::Node1(n) => {
// Shrink Node1 to Node1 by resizing it.
self.node_type = NodeType::Node1(n.resize());
}
NodeType::Node4(n) => {
// Shrink Node4 to Node1 by resizing it.
self.node_type = NodeType::Node1(n.resize());
}
NodeType::Node16(n) => {
// Shrink Node16 to Node4 by resizing it.
self.node_type = NodeType::Node4(n.resize());
}
NodeType::Node48(n) => {
// Shrink Node48 to Node16 by obtaining the shrunken Node16 instance.
let n16 = n.shrink();
// Update the node type to Node16 after the shrinking operation.
let new_node = NodeType::Node16(n16);
self.node_type = new_node;
}
NodeType::Node256(n) => {
// Shrink Node256 to Node48 by obtaining the shrunken Node48 instance.
let n48 = n.shrink();
// Update the node type to Node48 after the shrinking operation.
self.node_type = NodeType::Node48(n48);
}
NodeType::Twig(_) => panic!("Twig node encountered in shrink()"),
}
}
#[inline]
pub fn num_children(&self) -> usize {
match &self.node_type {
NodeType::Node1(n) => n.num_children(),
NodeType::Node4(n) => n.num_children(),
NodeType::Node16(n) => n.num_children(),
NodeType::Node48(n) => n.num_children(),
NodeType::Node256(n) => n.num_children(),
NodeType::Twig(_) => 0,
}
}
/// TODO: fix having separate key and prefix traits to avoid copying
/// Retrieves a value from a Twig node by the specified version.
///
/// Retrieves a value from the current Twig node by matching the provided version.
///
/// # Parameters
///
/// - `ts`: The version for which to retrieve the value.
///
/// # Returns
///
/// Returns `Some((key, value, version))` if a matching value is found in the Twig node for the given version.
/// If no matching value is found, returns `None`.
///
#[inline]
pub fn get_value_by_version(&self, version: u64) -> Option<(P, V, u64, u64)> {
// Unwrap the NodeType::Twig to access the TwigNode instance.
let NodeType::Twig(twig) = &self.node_type else {
return None;
};
// Get the value from the TwigNode instance by the specified version.
let Some(val) = twig.get_leaf_by_version(version) else {
return None;
};
// Return the retrieved key, value, and version as a tuple.
// TODO: should return copy of value or reference?
Some((twig.key.clone(), val.value.clone(), val.version, val.ts))
}
pub fn node_type_name(&self) -> String {
match &self.node_type {
NodeType::Node1(_) => "Node1".to_string(),
NodeType::Node4(_) => "Node4".to_string(),
NodeType::Node16(_) => "Node16".to_string(),
NodeType::Node48(_) => "Node48".to_string(),
NodeType::Node256(_) => "Node256".to_string(),
NodeType::Twig(_) => "twig".to_string(),
}
}
/// Creates a clone of the current node.
///
/// Creates and returns a new instance of the current node with the same node type and contents.
///
/// # Returns
///
/// Returns a cloned instance of the current node with the same node type and contents.
///
fn clone_node(&self) -> Self {
// Create a new instance with the same node type as the current node.
Self {
node_type: self.node_type.clone(),
}
}
/// Inserts a key-value pair recursively into the node.
///
/// Recursively inserts a key-value pair into the current node and its child nodes.
///
/// # Parameters
///
/// - `cur_node`: A reference to the current node.
/// - `key`: The key to be inserted.
/// - `value`: The value associated with the key.
/// - `commit_version`: The version when the value was inserted.
/// - `depth`: The depth of the insertion process.
///
/// # Returns
///
/// Returns the updated node and the old value (if any) for the given key.
///
pub(crate) fn insert_recurse(
cur_node: &Arc<Node<P, V>>,
key: &P,
value: V,
commit_version: u64,
ts: u64,
depth: usize,
) -> Result<(Arc<Node<P, V>>, Option<V>), TrieError> {
// Obtain the current node's prefix and its length.
let cur_node_prefix = cur_node.prefix().clone();
let cur_node_prefix_len = cur_node.prefix().len();
// Determine the prefix of the key after the current depth.
let key_prefix = key.prefix_after(depth);
let key_prefix = key_prefix.as_slice();
// Find the longest common prefix between the current node's prefix and the key's prefix.
let longest_common_prefix = cur_node_prefix.longest_common_prefix(key_prefix);
// Create a new key that represents the remaining part of the current node's prefix after the common prefix.
let new_key = cur_node_prefix.prefix_after(longest_common_prefix);
// Extract the prefix of the current node up to the common prefix.
let prefix = cur_node_prefix.prefix_before(longest_common_prefix);
// Determine whether the current node's prefix and the key's prefix match up to the common prefix.
let is_prefix_match = min(cur_node_prefix_len, key_prefix.len()) == longest_common_prefix;
// If the current node is a Twig node and the prefixes match up to the end of both prefixes,
// update the existing value in the Twig node.
if let NodeType::Twig(ref twig) = &cur_node.node_type {
if is_prefix_match && cur_node_prefix.len() == key_prefix.len() {
let old_val = twig.get_leaf_by_version(commit_version).unwrap();
let new_twig = twig.insert(value, commit_version, ts);
return Ok((
Arc::new(Node {
node_type: NodeType::Twig(new_twig),
}),
Some(old_val.value.clone()),
));
}
}
// If the prefixes don't match, create a new Node4 with the old node and a new Twig as children.
if !is_prefix_match {
let mut old_node = cur_node.clone_node();
old_node.set_prefix(new_key);
let mut n4 = Node::new_node4(prefix);
let k1 = cur_node_prefix.at(longest_common_prefix);
let k2 = key_prefix[longest_common_prefix];
let new_twig = Node::new_twig(
key_prefix[longest_common_prefix..].into(),
key.as_slice().into(),
value,
commit_version,
ts,
);
n4 = n4.add_child(k1, old_node).add_child(k2, new_twig);
return Ok((Arc::new(n4), None));
}
// Continue the insertion process by finding or creating the appropriate child node for the next character.
let k = key_prefix[longest_common_prefix];
let child_for_key = cur_node.find_child(k);
if let Some(child) = child_for_key {
match Node::insert_recurse(
child,
key,
value,
commit_version,
ts,
depth + longest_common_prefix,
) {
Ok((new_child, old_value)) => {
let new_node = cur_node.replace_child(k, new_child);
return Ok((Arc::new(new_node), old_value));
}
Err(err) => {
return Err(err);
}
}
};
// If no child exists for the key's character, create a new Twig node and add it as a child.
let new_twig = Node::new_twig(
key_prefix[longest_common_prefix..].into(),
key.as_slice().into(),
value,
commit_version,
ts,
);
let new_node = cur_node.add_child(k, new_twig);
Ok((Arc::new(new_node), None))
}
/// Removes a key recursively from the node and its children.
///
/// Recursively removes a key from the current node and its child nodes.
///
/// # Parameters
///
/// - `cur_node`: A reference to the current node.
/// - `key`: The key to be removed.
/// - `depth`: The depth of the removal process.
///
/// # Returns
///
/// Returns a tuple containing the updated node (or `None`) and a flag indicating if the key was removed.
///
pub(crate) fn remove_recurse(
cur_node: &Arc<Node<P, V>>,
key: &P,
depth: usize,
) -> (Option<Arc<Node<P, V>>>, bool) {
// Obtain the prefix of the current node.
let prefix = cur_node.prefix().clone();
// Determine the prefix of the key after the current depth.
let key_prefix = key.prefix_after(depth);
let key_prefix = key_prefix.as_slice();
// Find the longest common prefix between the current node's prefix and the key's prefix.
let longest_common_prefix = prefix.longest_common_prefix(key_prefix);
// Determine whether the current node's prefix and the key's prefix match up to the common prefix.
let is_prefix_match = min(prefix.len(), key_prefix.len()) == longest_common_prefix;
// If the current node's prefix and the key's prefix match up to the end of both prefixes,
// the key has been found and should be removed.
if is_prefix_match && prefix.len() == key_prefix.len() {
return (None, true);
}
// Determine the character at the common prefix position.
let k = key_prefix[longest_common_prefix];
// Search for a child node corresponding to the key's character.
let child = cur_node.find_child(k);
if let Some(child_node) = child {
// Recursively attempt to remove the key from the child node.
let (_new_child, removed) =
Node::remove_recurse(child_node, key, depth + longest_common_prefix);
if removed {
// If the key was successfully removed from the child node, update the current node's child pointer.
let new_node = cur_node.delete_child(k);
return (Some(Arc::new(new_node)), true);
}
}
// If the key was not found at this level, return the current node as-is.
(Some(cur_node.clone()), false)
}
/// Recursively searches for a key in the node and its children.
///
/// Recursively searches for a key in the current node and its child nodes, considering versions.
///
/// # Parameters
///
/// - `cur_node`: A reference to the current node.
/// - `key`: The key to be searched for.
/// - `ts`: The version for which to retrieve the value.
///
/// # Returns
///
/// Returns a result containing the prefix, value, and version if the key is found, or Error if not.
///
pub fn get_recurse(
cur_node: &Node<P, V>,
key: &P,
version: u64,
) -> Result<(P, V, u64, u64), TrieError> {
// Initialize the traversal variables.
let mut cur_node = cur_node;
let mut depth = 0;
// Start a loop to navigate through the tree.
loop {
// Determine the prefix of the key after the current depth.
let key_prefix = key.prefix_after(depth);
let key_prefix = key_prefix.as_slice();
// Obtain the prefix of the current node.
let prefix = cur_node.prefix();
// Find the longest common prefix between the node's prefix and the key's prefix.
let lcp = prefix.longest_common_prefix(key_prefix);
// If the longest common prefix does not match the entire node's prefix, the key is not present.
if lcp != prefix.len() {
return Err(TrieError::KeyNotFound);
}
// If the current node's prefix length matches the key's prefix length, retrieve the value.
if prefix.len() == key_prefix.len() {
let Some(val) = cur_node.get_value_by_version(version) else {
return Err(TrieError::KeyNotFound);
};
return Ok((val.0, val.1, val.2, val.3));
}
// Determine the character at the next position after the prefix in the key.
let k = key.at(depth + prefix.len());
// Increment the depth by the prefix length.
depth += prefix.len();
// Find the child node corresponding to the character and update the current node for further traversal.
match cur_node.find_child(k) {
Some(child) => cur_node = child,
None => return Err(TrieError::KeyNotFound),
}
}
}
/// Returns an iterator that iterates over child nodes of the current node.
///
/// This function provides an iterator that traverses through the child nodes of the current node,
/// returning tuples of keys and references to child nodes.
///
/// # Returns
///
/// Returns a boxed iterator that yields tuples containing keys and references to child nodes.
///
#[allow(dead_code)]
pub fn iter(&self) -> Box<dyn Iterator<Item = (u8, &Arc<Self>)> + '_> {
match &self.node_type {
NodeType::Node1(n) => Box::new(n.iter()),
NodeType::Node4(n) => Box::new(n.iter()),
NodeType::Node16(n) => Box::new(n.iter()),
NodeType::Node48(n) => Box::new(n.iter()),
NodeType::Node256(n) => Box::new(n.iter()),
NodeType::Twig(_) => Box::new(std::iter::empty()),
}
}
}
/// A struct representing an Adaptive Radix Trie.
///
/// The `Tree` struct encompasses the entire adaptive radix trie data structure.
/// It manages the root node of the tree, maintains snapshots of the tree's state,
/// and keeps track of various properties related to snapshot management.
///
/// # Type Parameters
///
/// - `P`: A type implementing the `KeyTrait` trait, defining the prefix traits for nodes.
/// - `V`: The type of value associated with nodes.
///
/// # Fields
///
/// - `root`: An optional shared reference (using `Rc`) to the root node of the tree.
/// - `snapshots`: A `HashSet` storing snapshots of the tree's state, mapped by snapshot IDs.
/// - `max_snapshot_id`: An `AtomicU64` representing the maximum snapshot ID assigned.
/// - `max_active_snapshots`: The maximum number of active snapshots allowed.
///
pub struct Tree<P: KeyTrait, V: Clone> {
/// An optional shared reference to the root node of the tree.
pub(crate) root: Option<Arc<Node<P, V>>>,
/// A mapping of snapshot IDs to their corresponding snapshots.
pub(crate) snapshots: HashSet<u64>,
/// An atomic value indicating the maximum snapshot ID assigned.
pub(crate) max_snapshot_id: AtomicU64,
/// The maximum number of active snapshots allowed.
pub(crate) max_active_snapshots: u64,
/// A flag indicating whether the tree is closed.
pub(crate) closed: bool,
}
pub struct KV<P, V> {
pub key: P,
pub value: V,
pub version: u64,
pub ts: u64,
}
impl<P: KeyTrait, V: Clone> KV<P, V> {
pub fn new(key: P, value: V, version: u64, timestamp: u64) -> Self {
KV {
key,
value,
version,
ts: timestamp,
}
}
}
impl<P: KeyTrait + Clone, V: Clone> NodeType<P, V> {
fn clone(&self) -> Self {
match self {
// twig value not actually cloned
NodeType::Twig(twig) => NodeType::Twig(twig.clone()),
NodeType::Node1(n) => NodeType::Node1(n.clone()),
NodeType::Node4(n) => NodeType::Node4(n.clone()),
NodeType::Node16(n) => NodeType::Node16(n.clone()),
NodeType::Node48(n) => NodeType::Node48(n.clone()),
NodeType::Node256(n) => NodeType::Node256(n.clone()),
}
}
}
// Default implementation for the Tree struct
impl<P: KeyTrait, V: Clone> Default for Tree<P, V> {
fn default() -> Self {
Tree::new()
}
}
impl<P: KeyTrait, V: Clone> Tree<P, V> {
pub fn new() -> Self {
Tree {
root: None,
max_snapshot_id: AtomicU64::new(0),
snapshots: HashSet::new(),
max_active_snapshots: DEFAULT_MAX_ACTIVE_SNAPSHOTS,
closed: false,
}
}
pub fn set_max_active_snapshots(&mut self, max_active_snapshots: u64) {
self.max_active_snapshots = max_active_snapshots;
}
/// Inserts a new key-value pair with the specified version into the Trie.
///
/// This function inserts a new key-value pair into the Trie. If the key already exists,
/// the previous value associated with the key is returned. The version `ts` is used to
/// ensure proper ordering of values for versioning.
///
/// # Arguments
///
/// * `key`: A reference to the key to be inserted.
/// * `value`: The value to be associated with the key.
/// * `ts`: The version for the insertion, used for versioning.
///
/// # Returns
///
/// Returns `Ok(None)` if the key did not exist previously. If the key already existed,
/// `Ok(Some(old_value))` is returned, where `old_value` is the previous value associated with the key.
///
/// # Errors
///
/// Returns an error if the given version is older than the root's current version.
///
pub fn insert(
&mut self,
key: &P,
value: V,
version: u64,
ts: u64,
) -> Result<Option<V>, TrieError> {
// Check if the tree is already closed
self.is_closed()?;
let (new_root, old_node) = match &self.root {
None => {
let mut commit_version = version;
if version == 0 {
commit_version += 1;
}
(
Arc::new(Node::new_twig(