1+ #include " ART.h"
2+ #include " ArtNode.h"
3+
4+ /*
5+ * QuART related insertNodeX methods
6+ */
7+
8+ namespace ART {
9+ // fp insert method for Node4
10+ void Node4::tailInsertNode4 (ART * tree, ArtNode** nodeRef, uint8_t keyByte,
11+ ArtNode* child,
12+ std::array<ArtNode*, maxPrefixLength>& temp_fp_path,
13+ size_t & temp_fp_path_length, size_t depth_prev) {
14+ // Insert leaf into inner node
15+ if (this ->count < 4 ) {
16+ // Insert element
17+ unsigned pos;
18+ for (pos = 0 ; (pos < this ->count ) && (this ->key [pos] < keyByte); pos++)
19+ ;
20+ memmove (this ->key + pos + 1 , this ->key + pos, this ->count - pos);
21+ memmove (this ->child + pos + 1 , this ->child + pos,
22+ (this ->count - pos) * sizeof (uintptr_t ));
23+ this ->key [pos] = keyByte;
24+ this ->child [pos] = child;
25+
26+ // If what's being inserted is a leaf
27+ if (isLeaf (child)) {
28+ // If the new value is greater than or equal to the current fp_leaf,
29+ // update the fp_leaf, fp and fp_path
30+ if (getLeafValue (child) >= getLeafValue (tree->fp_leaf )) {
31+ tree->fp_leaf = child;
32+ tree->fp = temp_fp_path[temp_fp_path_length - 1 ];
33+ tree->fp_path = temp_fp_path;
34+ tree->fp_path_length =
35+ temp_fp_path_length; // update fp_path size
36+ tree->fp_depth = depth_prev;
37+ tree->fp_ref = nodeRef;
38+ }
39+ }
40+
41+ this ->count ++;
42+ } else {
43+ // Grow to Node16
44+ Node16* newNode = new Node16 ();
45+ *nodeRef = newNode;
46+ newNode->count = 4 ;
47+ copyPrefix (this , newNode);
48+ for (unsigned i = 0 ; i < 4 ; i++)
49+ newNode->key [i] = flipSign (this ->key [i]);
50+ memcpy (newNode->child , this ->child , this ->count * sizeof (uintptr_t ));
51+
52+ // The sizes of temp_fp_path and fp_path before operations
53+ int temp_fp_path_length_old = temp_fp_path_length;
54+ int fp_path_length_old = tree->fp_path_length ;
55+ // If the changing node is on the fp_path
56+ if (temp_fp_path_length_old <= fp_path_length_old &&
57+ tree->fp_path [temp_fp_path_length_old - 1 ] == this ) {
58+ // Change the node to the newNode which has a greater capacity
59+ temp_fp_path[temp_fp_path_length_old - 1 ] = newNode;
60+ // If the new value doesn't create a new fp_leaf, restore the
61+ // remaining part of the fp_path
62+ if (getLeafValue (child) < getLeafValue (tree->fp_leaf )) {
63+ // create a deep copy of remainder of fp_path here
64+ std::array<ArtNode*, maxPrefixLength> fp_path_remainder;
65+ std::copy (tree->fp_path .begin () + temp_fp_path_length_old,
66+ tree->fp_path .end (), fp_path_remainder.begin ());
67+ tree->fp_path = temp_fp_path; // update fp_path
68+ tree->fp_path_length =
69+ temp_fp_path_length_old; // update fp_path size
70+ // Add the remaining part of the fp_path
71+ for (int i = 0 ;
72+ i < fp_path_length_old - temp_fp_path_length_old; i++) {
73+ tree->fp_path [i + temp_fp_path_length_old] =
74+ fp_path_remainder[i];
75+ tree->fp_path_length ++;
76+ }
77+ tree->fp = tree->fp_path [tree->fp_path_length - 1 ];
78+ }
79+ }
80+
81+ delete this ;
82+ return newNode->tailInsertNode16 (tree, nodeRef, keyByte, child,
83+ temp_fp_path, temp_fp_path_length,
84+ depth_prev);
85+ }
86+ }
87+
88+ // fp insert method for Node16
89+ void Node16::tailInsertNode16 (
90+ ART * tree, ArtNode** nodeRef, uint8_t keyByte, ArtNode* child,
91+ std::array<ArtNode*, maxPrefixLength>& temp_fp_path,
92+ size_t & temp_fp_path_length, size_t depth_prev) {
93+ // Insert leaf into inner node
94+ if (this ->count < 16 ) {
95+ // Insert element
96+ uint8_t keyByteFlipped = flipSign (keyByte);
97+ __m128i cmp = _mm_cmplt_epi8 (
98+ _mm_set1_epi8 (keyByteFlipped),
99+ _mm_loadu_si128 (reinterpret_cast <__m128i*>(this ->key )));
100+ uint16_t bitfield =
101+ _mm_movemask_epi8 (cmp) & (0xFFFF >> (16 - this ->count ));
102+ unsigned pos = bitfield ? ctz (bitfield) : this ->count ;
103+ memmove (this ->key + pos + 1 , this ->key + pos, this ->count - pos);
104+ memmove (this ->child + pos + 1 , this ->child + pos,
105+ (this ->count - pos) * sizeof (uintptr_t ));
106+
107+ this ->key [pos] = keyByteFlipped;
108+ this ->child [pos] = child;
109+
110+ // If what's being inserted is a leaf
111+ if (isLeaf (child)) {
112+ // If the new value is greater than or equal to the current fp_leaf,
113+ // update the fp_leaf, fp and fp_path
114+ if (getLeafValue (child) >= getLeafValue (tree->fp_leaf )) {
115+ tree->fp_leaf = child;
116+ tree->fp = temp_fp_path[temp_fp_path_length - 1 ];
117+ tree->fp_path = temp_fp_path;
118+ tree->fp_path_length = temp_fp_path_length;
119+ tree->fp_depth = depth_prev;
120+ tree->fp_ref = nodeRef;
121+ }
122+ }
123+
124+ this ->count ++;
125+ } else {
126+ // Grow to Node48
127+ Node48* newNode = new Node48 ();
128+ *nodeRef = newNode;
129+ memcpy (newNode->child , this ->child , this ->count * sizeof (uintptr_t ));
130+ for (unsigned i = 0 ; i < this ->count ; i++)
131+ newNode->childIndex [flipSign (this ->key [i])] = i;
132+ copyPrefix (this , newNode);
133+ newNode->count = this ->count ;
134+
135+ // The sizes of temp_fp_path and fp_path before operations
136+ int temp_fp_path_length_old = temp_fp_path_length;
137+ int fp_path_length_old = tree->fp_path_length ;
138+ // If the changing node is on the fp_path
139+ if (temp_fp_path_length_old <= fp_path_length_old &&
140+ tree->fp_path [temp_fp_path_length_old - 1 ] == this ) {
141+ // Change the node to the newNode which has a greater capacity
142+ temp_fp_path[temp_fp_path_length_old - 1 ] = newNode;
143+ // If the new value doesn't create a new fp_leaf, restore the
144+ // remaining part of the fp_path
145+ if (getLeafValue (child) < getLeafValue (tree->fp_leaf )) {
146+ // create a deep copy of remainder of fp_path here
147+ std::array<ArtNode*, maxPrefixLength> fp_path_remainder;
148+ std::copy (tree->fp_path .begin () + temp_fp_path_length_old,
149+ tree->fp_path .end (), fp_path_remainder.begin ());
150+ tree->fp_path = temp_fp_path; // update fp_path
151+ tree->fp_path_length =
152+ temp_fp_path_length_old; // update fp_path size
153+ // Add the remaining part of the fp_path
154+ for (int i = 0 ;
155+ i < fp_path_length_old - temp_fp_path_length_old; i++) {
156+ tree->fp_path [i + temp_fp_path_length_old] =
157+ fp_path_remainder[i];
158+ tree->fp_path_length ++;
159+ }
160+ tree->fp = tree->fp_path [tree->fp_path_length -
161+ 1 ]; // update the fp pointer
162+ }
163+ }
164+
165+ delete this ;
166+ return newNode->tailInsertNode48 (tree, nodeRef, keyByte, child,
167+ temp_fp_path, temp_fp_path_length,
168+ depth_prev);
169+ }
170+ }
171+
172+ // fp insert method for Node48
173+ void Node48::tailInsertNode48 (
174+ ART * tree, ArtNode** nodeRef, uint8_t keyByte, ArtNode* child,
175+ std::array<ArtNode*, maxPrefixLength>& temp_fp_path,
176+ size_t & temp_fp_path_length, size_t depth_prev) {
177+ // Insert leaf into inner node
178+ if (this ->count < 48 ) {
179+ // Insert element
180+ unsigned pos = this ->count ;
181+ if (this ->child [pos])
182+ for (pos = 0 ; this ->child [pos] != NULL ; pos++)
183+ ;
184+ this ->child [pos] = child;
185+ this ->childIndex [keyByte] = pos;
186+ this ->count ++;
187+
188+ // If what's being inserted is a leaf
189+ if (isLeaf (child)) {
190+ // If the new value is greater than or equal to the current fp_leaf,
191+ // update the fp_leaf, fp and fp_path
192+ if (getLeafValue (child) >= getLeafValue (tree->fp_leaf )) {
193+ tree->fp_leaf = child;
194+ tree->fp = temp_fp_path[temp_fp_path_length - 1 ];
195+ tree->fp_path = temp_fp_path;
196+ tree->fp_path_length = temp_fp_path_length;
197+ tree->fp_depth = depth_prev;
198+ tree->fp_ref = nodeRef;
199+ }
200+ }
201+
202+ } else {
203+ // Grow to Node256
204+ Node256* newNode = new Node256 ();
205+ for (unsigned i = 0 ; i < 256 ; i++)
206+ if (this ->childIndex [i] != 48 )
207+ newNode->child [i] = this ->child [this ->childIndex [i]];
208+ newNode->count = this ->count ;
209+ copyPrefix (this , newNode);
210+ *nodeRef = newNode;
211+
212+ // The sizes of temp_fp_path and fp_path before operations
213+ int temp_fp_path_length_old = temp_fp_path_length;
214+ int fp_path_length_old = tree->fp_path_length ;
215+ // If the changing node is on the fp_path
216+ if (temp_fp_path_length_old <= fp_path_length_old &&
217+ tree->fp_path [temp_fp_path_length_old - 1 ] == this ) {
218+ // Change the node to the newNode which has a greater capacity
219+ temp_fp_path[temp_fp_path_length_old - 1 ] = newNode;
220+ // If the new value doesn't create a new fp_leaf, restore the
221+ // remaining part of the fp_path
222+ if (getLeafValue (child) < getLeafValue (tree->fp_leaf )) {
223+ // create a deep copy of remainder of fp_path here
224+ std::array<ArtNode*, maxPrefixLength> fp_path_remainder;
225+ std::copy (tree->fp_path .begin () + temp_fp_path_length_old,
226+ tree->fp_path .end (), fp_path_remainder.begin ());
227+ tree->fp_path = temp_fp_path; // update fp_path
228+ tree->fp_path_length =
229+ temp_fp_path_length_old; // update fp_path size
230+ // Add the remaining part of the fp_path
231+ for (int i = 0 ;
232+ i < fp_path_length_old - temp_fp_path_length_old; i++) {
233+ tree->fp_path [i + temp_fp_path_length_old] =
234+ fp_path_remainder[i];
235+ tree->fp_path_length ++;
236+ }
237+ tree->fp = tree->fp_path [tree->fp_path_length -
238+ 1 ]; // update the fp pointer
239+ }
240+ }
241+
242+ delete this ;
243+ return newNode->tailInsertNode256 (tree, nodeRef, keyByte, child,
244+ temp_fp_path, temp_fp_path_length,
245+ depth_prev);
246+ }
247+ }
248+
249+ // fp insert method for Node256
250+ void Node256::tailInsertNode256 (
251+ ART * tree, ArtNode** nodeRef, uint8_t keyByte, ArtNode* child,
252+ std::array<ArtNode*, maxPrefixLength>& temp_fp_path,
253+ size_t & temp_fp_path_length, size_t depth_prev) {
254+ // Insert leaf into inner node
255+ this ->count ++;
256+ this ->child [keyByte] = child;
257+
258+ // If what's being inserted is a leaf
259+ if (isLeaf (child)) {
260+ // If the new value is greater than or equal to the current fp_leaf,
261+ // update the fp_leaf, fp and fp_path
262+ if (getLeafValue (child) >= getLeafValue (tree->fp_leaf )) {
263+ tree->fp_leaf = child;
264+ tree->fp = temp_fp_path[temp_fp_path_length - 1 ];
265+ tree->fp_path = temp_fp_path;
266+ tree->fp_path_length = temp_fp_path_length;
267+ tree->fp_depth = depth_prev;
268+ tree->fp_ref = nodeRef;
269+ }
270+ }
271+ }
272+ } // namespace ART
0 commit comments