hirlite 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE +28 -0
  3. data/Rakefile +51 -0
  4. data/ext/hirlite_ext/extconf.rb +33 -0
  5. data/ext/hirlite_ext/hirlite_ext.c +14 -0
  6. data/ext/hirlite_ext/hirlite_ext.h +38 -0
  7. data/ext/hirlite_ext/rlite.c +351 -0
  8. data/lib/hirlite/rlite.rb +1 -0
  9. data/lib/hirlite/version.rb +3 -0
  10. data/lib/hirlite.rb +2 -0
  11. data/vendor/rlite/Makefile +6 -0
  12. data/vendor/rlite/deps/crc64.c +191 -0
  13. data/vendor/rlite/deps/crc64.h +3 -0
  14. data/vendor/rlite/deps/endianconv.h +73 -0
  15. data/vendor/rlite/deps/hyperloglog.c +1547 -0
  16. data/vendor/rlite/deps/hyperloglog.h +14 -0
  17. data/vendor/rlite/deps/lzf.h +100 -0
  18. data/vendor/rlite/deps/lzfP.h +159 -0
  19. data/vendor/rlite/deps/lzf_c.c +295 -0
  20. data/vendor/rlite/deps/lzf_d.c +150 -0
  21. data/vendor/rlite/deps/sha1.c +227 -0
  22. data/vendor/rlite/deps/sha1.h +19 -0
  23. data/vendor/rlite/deps/utilfromredis.c +397 -0
  24. data/vendor/rlite/deps/utilfromredis.h +11 -0
  25. data/vendor/rlite/src/Makefile +79 -0
  26. data/vendor/rlite/src/constants.h +15 -0
  27. data/vendor/rlite/src/dump.c +191 -0
  28. data/vendor/rlite/src/dump.h +3 -0
  29. data/vendor/rlite/src/hirlite.c +3985 -0
  30. data/vendor/rlite/src/hirlite.h +186 -0
  31. data/vendor/rlite/src/page_btree.c +1556 -0
  32. data/vendor/rlite/src/page_btree.h +133 -0
  33. data/vendor/rlite/src/page_key.c +283 -0
  34. data/vendor/rlite/src/page_key.h +25 -0
  35. data/vendor/rlite/src/page_list.c +718 -0
  36. data/vendor/rlite/src/page_list.h +70 -0
  37. data/vendor/rlite/src/page_long.c +61 -0
  38. data/vendor/rlite/src/page_long.h +14 -0
  39. data/vendor/rlite/src/page_multi_string.c +538 -0
  40. data/vendor/rlite/src/page_multi_string.h +18 -0
  41. data/vendor/rlite/src/page_skiplist.c +689 -0
  42. data/vendor/rlite/src/page_skiplist.h +70 -0
  43. data/vendor/rlite/src/page_string.c +55 -0
  44. data/vendor/rlite/src/page_string.h +12 -0
  45. data/vendor/rlite/src/pqsort.c +185 -0
  46. data/vendor/rlite/src/pqsort.h +40 -0
  47. data/vendor/rlite/src/restore.c +401 -0
  48. data/vendor/rlite/src/restore.h +3 -0
  49. data/vendor/rlite/src/rlite.c +1309 -0
  50. data/vendor/rlite/src/rlite.h +159 -0
  51. data/vendor/rlite/src/sort.c +530 -0
  52. data/vendor/rlite/src/sort.h +18 -0
  53. data/vendor/rlite/src/status.h +19 -0
  54. data/vendor/rlite/src/type_hash.c +607 -0
  55. data/vendor/rlite/src/type_hash.h +29 -0
  56. data/vendor/rlite/src/type_list.c +477 -0
  57. data/vendor/rlite/src/type_list.h +23 -0
  58. data/vendor/rlite/src/type_set.c +796 -0
  59. data/vendor/rlite/src/type_set.h +34 -0
  60. data/vendor/rlite/src/type_string.c +613 -0
  61. data/vendor/rlite/src/type_string.h +34 -0
  62. data/vendor/rlite/src/type_zset.c +1147 -0
  63. data/vendor/rlite/src/type_zset.h +50 -0
  64. data/vendor/rlite/src/util.c +334 -0
  65. data/vendor/rlite/src/util.h +71 -0
  66. metadata +151 -0
@@ -0,0 +1,1556 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+ #include <stdio.h>
4
+ #include <math.h>
5
+ #include "status.h"
6
+ #include "page_btree.h"
7
+ #include "rlite.h"
8
+ #include "util.h"
9
+
10
+ rl_btree_type rl_btree_type_hash_sha1_key = {
11
+ 0,
12
+ 0,
13
+ sizeof(unsigned char) * 20,
14
+ sizeof(rl_key),
15
+ sha1_cmp,
16
+ #ifdef DEBUG
17
+ sha1_formatter,
18
+ #endif
19
+ };
20
+
21
+ rl_btree_type rl_btree_type_hash_sha1_hashkey = {
22
+ 0,
23
+ 0,
24
+ sizeof(unsigned char) * 20,
25
+ sizeof(rl_hashkey),
26
+ sha1_cmp,
27
+ #ifdef DEBUG
28
+ sha1_formatter,
29
+ #endif
30
+ };
31
+
32
+ rl_btree_type rl_btree_type_set_long = {
33
+ 0,
34
+ 0,
35
+ sizeof(long),
36
+ 0,
37
+ long_cmp,
38
+ #ifdef DEBUG
39
+ long_formatter,
40
+ #endif
41
+ };
42
+
43
+ rl_btree_type rl_btree_type_hash_long_long = {
44
+ 0,
45
+ 0,
46
+ sizeof(long),
47
+ sizeof(long),
48
+ long_cmp,
49
+ #ifdef DEBUG
50
+ long_formatter,
51
+ #endif
52
+ };
53
+
54
+ rl_btree_type rl_btree_type_hash_sha1_double = {
55
+ 0,
56
+ 0,
57
+ sizeof(unsigned char) * 20,
58
+ sizeof(double),
59
+ sha1_cmp,
60
+ #ifdef DEBUG
61
+ sha1_formatter,
62
+ #endif
63
+ };
64
+
65
+ rl_btree_type rl_btree_type_hash_sha1_long = {
66
+ 0,
67
+ 0,
68
+ sizeof(unsigned char) * 20,
69
+ sizeof(long),
70
+ sha1_cmp,
71
+ #ifdef DEBUG
72
+ sha1_formatter,
73
+ #endif
74
+ };
75
+
76
+
77
+ void rl_btree_init()
78
+ {
79
+ rl_btree_type_hash_sha1_hashkey.btree_type = &rl_data_type_btree_hash_sha1_hashkey;
80
+ rl_btree_type_hash_sha1_hashkey.btree_node_type = &rl_data_type_btree_node_hash_sha1_hashkey;
81
+ rl_btree_type_hash_sha1_key.btree_type = &rl_data_type_btree_hash_sha1_key;
82
+ rl_btree_type_hash_sha1_key.btree_node_type = &rl_data_type_btree_node_hash_sha1_key;
83
+ rl_btree_type_hash_long_long.btree_type = &rl_data_type_btree_hash_long_long;
84
+ rl_btree_type_hash_long_long.btree_node_type = &rl_data_type_btree_node_hash_long_long;
85
+ rl_btree_type_set_long.btree_type = &rl_data_type_btree_set_long;
86
+ rl_btree_type_set_long.btree_node_type = &rl_data_type_btree_node_set_long;
87
+ rl_btree_type_hash_sha1_double.btree_type = &rl_data_type_btree_hash_sha1_double;
88
+ rl_btree_type_hash_sha1_double.btree_node_type = &rl_data_type_btree_node_hash_sha1_double;
89
+ rl_btree_type_hash_sha1_long.btree_type = &rl_data_type_btree_hash_sha1_long;
90
+ rl_btree_type_hash_sha1_long.btree_node_type = &rl_data_type_btree_node_hash_sha1_long;
91
+ }
92
+
93
+ int rl_btree_serialize(struct rlite *UNUSED(db), void *obj, unsigned char *data)
94
+ {
95
+ rl_btree *tree = obj;
96
+ put_4bytes(data, tree->root);
97
+ put_4bytes(&data[4], tree->height);
98
+ put_4bytes(&data[8], tree->max_node_size);
99
+ put_4bytes(&data[12], tree->number_of_elements);
100
+ return RL_OK;
101
+ }
102
+
103
+ int rl_btree_deserialize(struct rlite *db, void **obj, void *context, unsigned char *data)
104
+ {
105
+ rl_btree *btree;
106
+ int retval = RL_OK;
107
+ RL_MALLOC(btree, sizeof(*btree));
108
+ btree->type = context;
109
+ btree->db = db;
110
+ btree->root = get_4bytes(data);
111
+ btree->height = get_4bytes(&data[4]);
112
+ btree->max_node_size = get_4bytes(&data[8]);
113
+ btree->number_of_elements = get_4bytes(&data[12]);
114
+ *obj = btree;
115
+ cleanup:
116
+ return retval;
117
+ }
118
+
119
+ #ifdef DEBUG
120
+ int rl_print_btree_node(rlite *UNUSED(db), rl_btree *btree, rl_btree_node *node, long level);
121
+ #endif
122
+
123
+
124
+ int rl_btree_node_create(rlite *UNUSED(db), rl_btree *btree, rl_btree_node **_node)
125
+ {
126
+ int retval = RL_OK;
127
+ rl_btree_node *node;
128
+ RL_MALLOC(node, sizeof(rl_btree_node));
129
+ RL_MALLOC(node->scores, sizeof(void *) * btree->max_node_size);
130
+ node->children = NULL;
131
+ if (btree->type->value_size) {
132
+ RL_MALLOC(node->values, sizeof(void *) * btree->max_node_size);
133
+ }
134
+ else {
135
+ node->values = NULL;
136
+ }
137
+ node->size = 0;
138
+ *_node = node;
139
+ cleanup:
140
+ if (retval != RL_OK && node) {
141
+ if (node->scores) {
142
+ rl_free(node->scores);
143
+ }
144
+ rl_free(node);
145
+ }
146
+ return retval;
147
+ }
148
+
149
+ int rl_btree_node_destroy(rlite *UNUSED(db), void *_node)
150
+ {
151
+ rl_btree_node *node = _node;
152
+ long i;
153
+ if (node->scores) {
154
+ for (i = 0; i < node->size; i++) {
155
+ rl_free(node->scores[i]);
156
+ }
157
+ rl_free(node->scores);
158
+ }
159
+ if (node->values) {
160
+ for (i = 0; i < node->size; i++) {
161
+ rl_free(node->values[i]);
162
+ }
163
+ rl_free(node->values);
164
+ }
165
+ if (node->children) {
166
+ rl_free(node->children);
167
+ }
168
+ rl_free(node);
169
+ return RL_OK;
170
+ }
171
+
172
+ int rl_btree_create_size(rlite *db, rl_btree **_btree, rl_btree_type *type, long max_node_size)
173
+ {
174
+ int retval = RL_OK;
175
+ rl_btree *btree;
176
+ rl_btree_node *root = NULL;
177
+ RL_MALLOC(btree, sizeof(*btree));
178
+ btree->number_of_elements = 0;
179
+ btree->max_node_size = max_node_size;
180
+ btree->type = type;
181
+ btree->db = db;
182
+ btree->root = db->next_empty_page;
183
+ btree->height = 1;
184
+ retval = rl_btree_node_create(db, btree, &root);
185
+ if (retval != RL_OK) {
186
+ rl_btree_destroy(db, btree);
187
+ goto cleanup;
188
+ }
189
+ root->size = 0;
190
+ retval = rl_write(db, type->btree_node_type, db->next_empty_page, root);
191
+ if (retval != RL_OK) {
192
+ rl_btree_destroy(db, btree);
193
+ goto cleanup;
194
+ }
195
+ *_btree = btree;
196
+ cleanup:
197
+ return retval;
198
+ }
199
+
200
+ int rl_btree_create(rlite *db, rl_btree **_btree, rl_btree_type *type)
201
+ {
202
+ long size = (db->page_size - 12) / (type->score_size + type->value_size + 4);
203
+ // TODO: make btree work with even number of elements
204
+ if (size % 2 != 0) {
205
+ size--;
206
+ }
207
+ return rl_btree_create_size(db, _btree, type, size);
208
+ }
209
+
210
+ int rl_btree_destroy(rlite *UNUSED(db), void *btree)
211
+ {
212
+ rl_free(btree);
213
+ return RL_OK;
214
+ }
215
+
216
+ int rl_btree_find_score(rlite *db, rl_btree *btree, void *score, void **value, rl_btree_node *** nodes, long **positions)
217
+ {
218
+ if ((!nodes && positions) || (nodes && !positions)) {
219
+ return RL_INVALID_PARAMETERS;
220
+ }
221
+ void *_node;
222
+ int retval;
223
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, btree->root, btree, &_node, 1);
224
+ rl_btree_node *node = _node;
225
+ long i, pos, min, max;
226
+ int cmp = 0;
227
+ for (i = 0; i < btree->height; i++) {
228
+ if (nodes) {
229
+ (*nodes)[i] = node;
230
+ }
231
+ pos = 0;
232
+ min = 0;
233
+ max = node->size - 1;
234
+ while (min <= max) {
235
+ pos = (max - min) / 2 + min;
236
+ cmp = btree->type->cmp(score, node->scores[pos]);
237
+ if (cmp == 0) {
238
+ if (value && node->values) {
239
+ *value = node->values[pos];
240
+ }
241
+ if (nodes) {
242
+ if (positions) {
243
+ (*positions)[i] = pos;
244
+ }
245
+ for (i++; i < btree->height; i++) {
246
+ (*nodes)[i] = NULL;
247
+ }
248
+ }
249
+ retval = RL_FOUND;
250
+ goto cleanup;
251
+ }
252
+ else if (cmp > 0) {
253
+ if (max == pos) {
254
+ pos++;
255
+ break;
256
+ }
257
+ if (min == pos) {
258
+ min++;
259
+ continue;
260
+ }
261
+ min = pos;
262
+ }
263
+ else {
264
+ if (max == pos) {
265
+ break;
266
+ }
267
+ max = pos;
268
+ }
269
+ }
270
+ if (positions) {
271
+ if (pos == max && btree->type->cmp(score, node->scores[pos]) == 1) {
272
+ pos++;
273
+ }
274
+ (*positions)[i] = pos;
275
+ }
276
+ if (node->children) {
277
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[pos], btree, &_node, 1);
278
+ node = _node;
279
+ }
280
+ }
281
+ retval = RL_NOT_FOUND;
282
+ cleanup:
283
+ return retval;
284
+ }
285
+
286
+ int rl_btree_random_element(rlite *db, rl_btree *btree, void **score, void **value)
287
+ {
288
+ int retval;
289
+ long i, h = btree->height;
290
+ long *acc = NULL, random, pos;
291
+ void *_node;
292
+ rl_btree_node *node;
293
+
294
+ RL_MALLOC(acc, sizeof(long) * h);
295
+ acc[0] = 1;
296
+ for (i = 1; i < h; i++) {
297
+ acc[i] = acc[i - 1] + ceil(acc[i - 1] * 0.75 * btree->max_node_size);
298
+ }
299
+
300
+ random = 1 + (long)(((float)rand() / RAND_MAX) * acc[h - 1]);
301
+
302
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, btree->root, btree, &_node, 1);
303
+ node = _node;
304
+ for (i = 0; i < h; i++) {
305
+ if (random > acc[i]) {
306
+ pos = (long)(((float)rand() / RAND_MAX) * (1 + node->size));
307
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[pos], btree, &_node, 1);
308
+ node = _node;
309
+ }
310
+ else {
311
+ pos = (long)(((float)rand() / RAND_MAX) * node->size);
312
+ if (score) {
313
+ *score = node->scores[pos];
314
+ }
315
+ if (value && node->values) {
316
+ *value = node->values[pos];
317
+ }
318
+ break;
319
+ }
320
+ }
321
+ retval = RL_OK;
322
+ cleanup:
323
+ rl_free(acc);
324
+ return retval;
325
+ }
326
+
327
+ int rl_btree_add_element(rlite *db, rl_btree *btree, long btree_page, void *score, void *value)
328
+ {
329
+ int retval;
330
+ long *positions = NULL;
331
+ rl_btree_node *right;
332
+ rl_btree_node **nodes;
333
+ RL_MALLOC(nodes, sizeof(rl_btree_node *) * btree->height);
334
+ RL_MALLOC(positions, sizeof(long) * btree->height);
335
+ void *tmp;
336
+ long i, pos;
337
+ long node_page = 0;
338
+ long child = -1;
339
+ RL_CALL(rl_btree_find_score, RL_NOT_FOUND, db, btree, score, NULL, &nodes, &positions);
340
+ retval = RL_OK;
341
+ rl_btree_node *node = NULL;
342
+ for (i = btree->height - 1; i >= 0; i--) {
343
+ if (i == 0) {
344
+ node_page = btree->root;
345
+ }
346
+ else {
347
+ node_page = nodes[i - 1]->children[positions[i - 1]];
348
+ }
349
+ node = nodes[i];
350
+
351
+ if (node->size < btree->max_node_size) {
352
+ memmove(&node->scores[positions[i] + 1], &node->scores[positions[i]], sizeof(void *) * (node->size - positions[i]));
353
+ if (node->values) {
354
+ memmove(&node->values[positions[i] + 1], &node->values[positions[i]], sizeof(void *) * (node->size - positions[i]));
355
+ }
356
+ if (node->children) {
357
+ memmove(&node->children[positions[i] + 2], &node->children[positions[i] + 1], sizeof(long) * (node->size - positions[i]));
358
+ }
359
+ node->scores[positions[i]] = score;
360
+ if (node->values) {
361
+ node->values[positions[i]] = value;
362
+ }
363
+ if (child != -1) {
364
+ if (!node->children) {
365
+ fprintf(stderr, "Adding child, but children is not initialized\n");
366
+ }
367
+ node->children[positions[i] + 1] = child;
368
+ }
369
+ node->size++;
370
+ score = NULL;
371
+ value = NULL;
372
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, node_page, node);
373
+ break;
374
+ }
375
+ else {
376
+ pos = positions[i];
377
+
378
+ RL_CALL(rl_btree_node_create, RL_OK, db, btree, &right);
379
+ if (child != -1) {
380
+ right->children = rl_malloc(sizeof(long) * (btree->max_node_size + 1));
381
+ if (!right->children) {
382
+ rl_btree_node_destroy(db, right);
383
+ retval = RL_OUT_OF_MEMORY;
384
+ goto cleanup;
385
+ }
386
+ }
387
+
388
+ if (pos < btree->max_node_size / 2) {
389
+ if (child != -1) {
390
+ memmove(right->children, &node->children[btree->max_node_size / 2], sizeof(void *) * (btree->max_node_size / 2 + 1));
391
+ memmove(&node->children[pos + 2], &node->children[pos + 1], sizeof(void *) * (btree->max_node_size / 2 - 1 - pos));
392
+ node->children[pos + 1] = child;
393
+
394
+ }
395
+ tmp = node->scores[btree->max_node_size / 2 - 1];
396
+ memmove(&node->scores[pos + 1], &node->scores[pos], sizeof(void *) * (btree->max_node_size / 2 - 1 - pos));
397
+ node->scores[pos] = score;
398
+ score = tmp;
399
+ memmove(right->scores, &node->scores[btree->max_node_size / 2], sizeof(void *) * btree->max_node_size / 2);
400
+ if (node->values) {
401
+ tmp = node->values[btree->max_node_size / 2 - 1];
402
+ memmove(&node->values[pos + 1], &node->values[pos], sizeof(void *) * (btree->max_node_size / 2 - 1 - pos));
403
+ node->values[pos] = value;
404
+ memmove(right->values, &node->values[btree->max_node_size / 2], sizeof(void *) * btree->max_node_size / 2);
405
+ value = tmp;
406
+ }
407
+ }
408
+
409
+ if (pos == btree->max_node_size / 2) {
410
+ if (child != -1) {
411
+ memmove(&right->children[1], &node->children[btree->max_node_size / 2 + 1], sizeof(void *) * (btree->max_node_size / 2));
412
+ right->children[0] = child;
413
+ }
414
+ memmove(right->scores, &node->scores[btree->max_node_size / 2], sizeof(void *) * btree->max_node_size / 2);
415
+ if (node->values) {
416
+ memmove(right->values, &node->values[btree->max_node_size / 2], sizeof(void *) * btree->max_node_size / 2);
417
+ }
418
+ }
419
+
420
+ if (pos > btree->max_node_size / 2) {
421
+ if (child != -1) {
422
+ memmove(right->children, &node->children[btree->max_node_size / 2 + 1], sizeof(void *) * (pos - btree->max_node_size / 2));
423
+ right->children[pos - btree->max_node_size / 2] = child;
424
+ memmove(&right->children[pos - btree->max_node_size / 2 + 1], &node->children[pos + 1], sizeof(void *) * (btree->max_node_size - pos));
425
+ }
426
+ tmp = node->scores[btree->max_node_size / 2];
427
+ memmove(right->scores, &node->scores[btree->max_node_size / 2 + 1], sizeof(void *) * (pos - btree->max_node_size / 2 - 1));
428
+ right->scores[pos - btree->max_node_size / 2 - 1] = score;
429
+ memmove(&right->scores[pos - btree->max_node_size / 2], &node->scores[pos], sizeof(void *) * (btree->max_node_size - pos));
430
+ score = tmp;
431
+ if (node->values) {
432
+ tmp = node->values[btree->max_node_size / 2];
433
+ memmove(right->values, &node->values[btree->max_node_size / 2 + 1], sizeof(void *) * (pos - btree->max_node_size / 2 - 1));
434
+ right->values[pos - btree->max_node_size / 2 - 1] = value;
435
+ memmove(&right->values[pos - btree->max_node_size / 2], &node->values[pos], sizeof(void *) * (btree->max_node_size - pos));
436
+ value = tmp;
437
+ }
438
+ }
439
+
440
+ node->size = right->size = btree->max_node_size / 2;
441
+ child = db->next_empty_page;
442
+ retval = rl_write(db, btree->type->btree_node_type, node_page, node);
443
+ if (retval != RL_OK) {
444
+ rl_btree_node_destroy(db, right);
445
+ goto cleanup;
446
+ }
447
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, child, right);
448
+ }
449
+ }
450
+ if (score) {
451
+ rl_btree_node *old_root = node;
452
+ RL_CALL(rl_btree_node_create, RL_OK, db, btree, &node);
453
+ node->size = 1;
454
+ node->scores[0] = score;
455
+ if (node->values) {
456
+ node->values[0] = value;
457
+ }
458
+ // too late to dereference them after this point, handed over
459
+ value = NULL;
460
+ score = NULL;
461
+ if (old_root) {
462
+ node->children = rl_malloc(sizeof(long) * (btree->max_node_size + 1));
463
+ if (!node->children) {
464
+ retval = RL_OUT_OF_MEMORY;
465
+ rl_btree_node_destroy(db, node);
466
+ goto cleanup;
467
+ }
468
+ if (node_page == 0) {
469
+ node_page = db->next_empty_page;
470
+ }
471
+ node->children[0] = node_page;
472
+ retval = rl_write(db, btree->type->btree_node_type, node->children[0], old_root);
473
+ if (retval != RL_OK) {
474
+ rl_btree_node_destroy(db, node);
475
+ goto cleanup;
476
+ }
477
+ node->children[1] = child;
478
+ }
479
+ else if (btree->root) {
480
+ RL_CALL(rl_delete, RL_OK, db, btree->root);
481
+ }
482
+ btree->root = db->next_empty_page;
483
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, btree->root, node);
484
+ btree->height++;
485
+ }
486
+ btree->number_of_elements++;
487
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_type, btree_page, btree);
488
+ retval = RL_OK;
489
+ cleanup:
490
+ if (retval != RL_OK) {
491
+ free(value);
492
+ free(score);
493
+ }
494
+ rl_free(nodes);
495
+ rl_free(positions);
496
+
497
+ return retval;
498
+ }
499
+
500
+ int rl_btree_update_element(rlite *db, rl_btree *btree, void *score, void *value)
501
+ {
502
+ int retval;
503
+ long *positions = NULL;
504
+ rl_btree_node **nodes;
505
+ RL_MALLOC(nodes, sizeof(rl_btree_node *) * btree->height);
506
+ RL_MALLOC(positions, sizeof(long) * btree->height);
507
+ long i;
508
+ long node_page;
509
+ RL_CALL(rl_btree_find_score, RL_FOUND, db, btree, score, NULL, &nodes, &positions);
510
+
511
+ rl_btree_node *node;
512
+ for (i = btree->height - 1; i >= 0; i--) {
513
+ node = nodes[i];
514
+ if (!node) {
515
+ continue;
516
+ }
517
+
518
+ if (i == 0) {
519
+ node_page = btree->root;
520
+ }
521
+ else {
522
+ node_page = nodes[i - 1]->children[positions[i - 1]];
523
+ }
524
+ if (node->values[positions[i]] != value) {
525
+ rl_free(node->values[positions[i]]);
526
+ node->values[positions[i]] = value;
527
+ }
528
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, node_page, node);
529
+ break;
530
+ }
531
+ cleanup:
532
+ rl_free(nodes);
533
+ rl_free(positions);
534
+ return retval;
535
+ }
536
+
537
+ int rl_btree_remove_element(struct rlite *db, rl_btree *btree, long btree_page, void *score)
538
+ {
539
+ void *tmp;
540
+ int retval;
541
+ long *positions = NULL;
542
+ rl_btree_node **nodes;
543
+ RL_MALLOC(nodes, sizeof(rl_btree_node *) * btree->height);
544
+ RL_MALLOC(positions, sizeof(long) * btree->height);
545
+ long i, j;
546
+ long node_page = 0, child_node_page, sibling_node_page, parent_node_page;
547
+ RL_CALL(rl_btree_find_score, RL_FOUND, db, btree, score, NULL, &nodes, &positions);
548
+ retval = RL_OK;
549
+
550
+ rl_btree_node *node, *parent_node, *sibling_node, *child_node;
551
+ for (i = btree->height - 1; i >= 0; i--) {
552
+ node = nodes[i];
553
+ if (!node) {
554
+ continue;
555
+ }
556
+
557
+ if (i == 0) {
558
+ node_page = btree->root;
559
+ }
560
+ else {
561
+ node_page = nodes[i - 1]->children[positions[i - 1]];
562
+ }
563
+
564
+ rl_free(node->scores[positions[i]]);
565
+ if (node->values) {
566
+ rl_free(node->values[positions[i]]);
567
+ }
568
+ if (node->children) {
569
+ j = i;
570
+ child_node = node;
571
+ child_node_page = node_page;
572
+ for (; i < btree->height - 1; i++) {
573
+ child_node_page = child_node->children[positions[i]];
574
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, child_node->children[positions[i]], btree, &tmp, 1);
575
+ child_node = tmp;
576
+ nodes[i + 1] = child_node;
577
+ positions[i + 1] = child_node->size;
578
+ }
579
+
580
+ if (child_node->children) {
581
+ fprintf(stderr, "last child_node mustn't have children\n");
582
+ retval = RL_UNEXPECTED;
583
+ goto cleanup;
584
+ }
585
+
586
+ // only the leaf node loses an element, to replace the deleted one
587
+ child_node->size--;
588
+ node->scores[positions[j]] = child_node->scores[child_node->size];
589
+ if (node->values) {
590
+ node->values[positions[j]] = child_node->values[child_node->size];
591
+ }
592
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, node_page, node);
593
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, child_node_page, child_node);
594
+ break;
595
+ }
596
+ else {
597
+ memmove(&node->scores[positions[i]], &node->scores[positions[i] + 1], sizeof(void *) * (node->size - positions[i] - 1));
598
+ if (node->values) {
599
+ memmove(&node->values[positions[i]], &node->values[positions[i] + 1], sizeof(void *) * (node->size - positions[i] - 1));
600
+ }
601
+
602
+ if (--node->size > 0) {
603
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, node_page, node);
604
+ }
605
+ else {
606
+ if (i == 0 && node->children) {
607
+ // we have an empty root, promote the only child if any
608
+ btree->height--;
609
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[0], btree, &tmp, 1);
610
+ parent_node = tmp;
611
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, node->children[0], parent_node);
612
+ RL_CALL(rl_delete, RL_OK, db, node_page);
613
+ }
614
+ }
615
+ break;
616
+ }
617
+ }
618
+
619
+ for (; i >= 0; i--) {
620
+ if (i == 0) {
621
+ node_page = btree->root;
622
+ }
623
+ else {
624
+ node_page = nodes[i - 1]->children[positions[i - 1]];
625
+ }
626
+ node = nodes[i];
627
+ if (i == 0) {
628
+ if (node->size == 0) {
629
+ btree->height--;
630
+ if (node->children) {
631
+ btree->root = node->children[0];
632
+ }
633
+ else {
634
+ RL_CALL(rl_delete, RL_OK, db, btree->root);
635
+ btree->root = 0;
636
+ }
637
+ }
638
+ break;
639
+ }
640
+ if (node->size >= btree->max_node_size / 2 || i == 0) {
641
+ break;
642
+ }
643
+ else {
644
+ if (i == 1) {
645
+ parent_node_page = btree->root;
646
+ }
647
+ else {
648
+ parent_node_page = nodes[i - 2]->children[positions[i - 2]];
649
+ }
650
+ parent_node = nodes[i - 1];
651
+ if (parent_node->size == 0) {
652
+ fprintf(stderr, "Empty parent\n");
653
+ retval = RL_UNEXPECTED;
654
+ goto cleanup;
655
+ }
656
+ if (positions[i - 1] > 0) {
657
+ sibling_node_page = parent_node->children[positions[i - 1] - 1];
658
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, parent_node->children[positions[i - 1] - 1], btree, &tmp, 1);
659
+ sibling_node = tmp;
660
+ if (sibling_node->size > btree->max_node_size / 2) {
661
+ memmove(&node->scores[1], &node->scores[0], sizeof(void *) * (node->size));
662
+ if (node->values) {
663
+ memmove(&node->values[1], &node->values[0], sizeof(void *) * (node->size));
664
+ }
665
+ if (node->children) {
666
+ memmove(&node->children[1], &node->children[0], sizeof(long) * (node->size + 1));
667
+ node->children[0] = sibling_node->children[sibling_node->size];
668
+ }
669
+ node->scores[0] = parent_node->scores[positions[i - 1] - 1];
670
+ if (node->values) {
671
+ node->values[0] = parent_node->values[positions[i - 1] - 1];
672
+ }
673
+
674
+ parent_node->scores[positions[i - 1] - 1] = sibling_node->scores[sibling_node->size - 1];
675
+ if (parent_node->values) {
676
+ parent_node->values[positions[i - 1] - 1] = sibling_node->values[sibling_node->size - 1];
677
+ }
678
+
679
+ sibling_node->size--;
680
+ node->size++;
681
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, node_page, node);
682
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, sibling_node_page, sibling_node);
683
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, parent_node_page, parent_node);
684
+ break;
685
+ }
686
+ }
687
+ if (positions[i - 1] < parent_node->size) {
688
+ sibling_node_page = parent_node->children[positions[i - 1] + 1];
689
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, parent_node->children[positions[i - 1] + 1], btree, &tmp, 1);
690
+ sibling_node = tmp;
691
+ if (sibling_node->size > btree->max_node_size / 2) {
692
+ node->scores[node->size] = parent_node->scores[positions[i - 1]];
693
+ if (node->values) {
694
+ node->values[node->size] = parent_node->values[positions[i - 1]];
695
+ }
696
+
697
+ parent_node->scores[positions[i - 1]] = sibling_node->scores[0];
698
+ if (parent_node->values) {
699
+ parent_node->values[positions[i - 1]] = sibling_node->values[0];
700
+ }
701
+
702
+ memmove(&sibling_node->scores[0], &sibling_node->scores[1], sizeof(void *) * (sibling_node->size - 1));
703
+ if (node->values) {
704
+ memmove(&sibling_node->values[0], &sibling_node->values[1], sizeof(void *) * (sibling_node->size - 1));
705
+ }
706
+ if (node->children) {
707
+ node->children[node->size + 1] = sibling_node->children[0];
708
+ memmove(&sibling_node->children[0], &sibling_node->children[1], sizeof(long) * (sibling_node->size));
709
+ }
710
+
711
+ sibling_node->size--;
712
+ node->size++;
713
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, sibling_node_page, sibling_node);
714
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, node_page, node);
715
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, parent_node_page, parent_node);
716
+ break;
717
+ }
718
+ }
719
+
720
+ // not taking from either slibing, need to merge with either
721
+ // if either of them exists, they have the minimum number of elements
722
+ if (positions[i - 1] > 0) {
723
+ sibling_node_page = parent_node->children[positions[i - 1] - 1];
724
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, parent_node->children[positions[i - 1] - 1], btree, &tmp, 1);
725
+ sibling_node = tmp;
726
+ sibling_node->scores[sibling_node->size] = parent_node->scores[positions[i - 1] - 1];
727
+ if (parent_node->values) {
728
+ sibling_node->values[sibling_node->size] = parent_node->values[positions[i - 1] - 1];
729
+ }
730
+ memmove(&sibling_node->scores[sibling_node->size + 1], &node->scores[0], sizeof(void *) * (node->size));
731
+ if (sibling_node->values) {
732
+ memmove(&sibling_node->values[sibling_node->size + 1], &node->values[0], sizeof(void *) * (node->size));
733
+ }
734
+ if (sibling_node->children) {
735
+ memmove(&sibling_node->children[sibling_node->size + 1], &node->children[0], sizeof(void *) * (node->size + 1));
736
+ }
737
+
738
+ if (positions[i - 1] < parent_node->size) {
739
+ memmove(&parent_node->scores[positions[i - 1] - 1], &parent_node->scores[positions[i - 1]], sizeof(void *) * (parent_node->size - positions[i - 1]));
740
+ if (parent_node->values) {
741
+ memmove(&parent_node->values[positions[i - 1] - 1], &parent_node->values[positions[i - 1]], sizeof(void *) * (parent_node->size - positions[i - 1]));
742
+ }
743
+ memmove(&parent_node->children[positions[i - 1]], &parent_node->children[positions[i - 1] + 1], sizeof(void *) * (parent_node->size - positions[i - 1]));
744
+ }
745
+ parent_node->size--;
746
+ sibling_node->size += 1 + node->size;
747
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, sibling_node_page, sibling_node);
748
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, parent_node_page, parent_node);
749
+ rl_free(node->scores);
750
+ node->scores = NULL;
751
+ rl_free(node->values);
752
+ node->values = NULL;
753
+ RL_CALL(rl_delete, RL_OK, db, node_page);
754
+ continue;
755
+ }
756
+ if (positions[i - 1] < parent_node->size) {
757
+ sibling_node_page = parent_node->children[positions[i - 1] + 1];
758
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, parent_node->children[positions[i - 1] + 1], btree, &tmp, 1);
759
+ sibling_node = tmp;
760
+ node->scores[node->size] = parent_node->scores[positions[i - 1]];
761
+ if (parent_node->values) {
762
+ node->values[node->size] = parent_node->values[positions[i - 1]];
763
+ }
764
+ memmove(&node->scores[node->size + 1], &sibling_node->scores[0], sizeof(void *) * (sibling_node->size));
765
+ if (node->values) {
766
+ memmove(&node->values[node->size + 1], &sibling_node->values[0], sizeof(void *) * (sibling_node->size));
767
+ }
768
+ if (node->children) {
769
+ memmove(&node->children[node->size + 1], &sibling_node->children[0], sizeof(void *) * (sibling_node->size + 1));
770
+ }
771
+
772
+
773
+ memmove(&parent_node->scores[positions[i - 1]], &parent_node->scores[positions[i - 1] + 1], sizeof(void *) * (parent_node->size - positions[i - 1] - 1));
774
+ if (parent_node->values) {
775
+ memmove(&parent_node->values[positions[i - 1]], &parent_node->values[positions[i - 1] + 1], sizeof(void *) * (parent_node->size - positions[i - 1] - 1));
776
+ }
777
+ memmove(&parent_node->children[positions[i - 1] + 1], &parent_node->children[positions[i - 1] + 2], sizeof(void *) * (parent_node->size - positions[i - 1] - 1));
778
+
779
+ parent_node->size--;
780
+ node->size += 1 + sibling_node->size;
781
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, node_page, node);
782
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_node_type, parent_node_page, parent_node);
783
+ // rl_freeing manually scores before calling destroy to avoid deleting scores that were handed over to `node`
784
+ rl_free(sibling_node->scores);
785
+ sibling_node->scores = NULL;
786
+ rl_free(sibling_node->values);
787
+ sibling_node->values = NULL;
788
+ RL_CALL(rl_delete, RL_OK, db, sibling_node_page);
789
+ continue;
790
+ }
791
+
792
+ // this shouldn't happen
793
+ fprintf(stderr, "No sibling to borrow or merge\n");
794
+ retval = RL_INVALID_STATE;
795
+ goto cleanup;
796
+ }
797
+ }
798
+
799
+ if (btree->number_of_elements-- == 1) {
800
+ RL_CALL(rl_delete, RL_OK, db, btree_page);
801
+ retval = RL_DELETED;
802
+ }
803
+ else {
804
+ RL_CALL(rl_write, RL_OK, db, btree->type->btree_type, btree_page, btree);
805
+ retval = RL_OK;
806
+ }
807
+ cleanup:
808
+ rl_free(nodes);
809
+ rl_free(positions);
810
+
811
+ return retval;
812
+ }
813
+
814
+ int rl_btree_node_pages(rlite *db, rl_btree *btree, rl_btree_node *node, short *pages)
815
+ {
816
+ void *tmp;
817
+ int i, retval = RL_OK;
818
+ rl_btree_node *child;
819
+ for (i = 0; i < node->size + 1; i++) {
820
+ if (node->children) {
821
+ pages[node->children[i]] = 1;
822
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[i], btree, &tmp, 1);
823
+ child = tmp;
824
+ retval = rl_btree_node_pages(db, btree, child, pages);
825
+ if (retval != RL_OK) {
826
+ break;
827
+ }
828
+ }
829
+ }
830
+ cleanup:
831
+ return retval;
832
+ }
833
+
834
+ int rl_btree_pages(rlite *db, rl_btree *btree, short *pages)
835
+ {
836
+ void *tmp;
837
+ rl_btree_node *node;
838
+ pages[btree->root] = 1;
839
+ int retval;
840
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, btree->root, btree, &tmp, 1);
841
+ node = tmp;
842
+ RL_CALL(rl_btree_node_pages, RL_OK, db, btree, node, pages);
843
+ cleanup:
844
+ return retval;
845
+ }
846
+
847
+ int rl_btree_node_delete(struct rlite *db, rl_btree *btree, rl_btree_node *node)
848
+ {
849
+ void *tmp;
850
+ int i, retval = RL_OK;
851
+ long page;
852
+ rl_btree_node *child;
853
+ for (i = 0; i < node->size + 1; i++) {
854
+ if (node->children) {
855
+ page = node->children[i];
856
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, page , btree, &tmp, 1);
857
+ child = tmp;
858
+ RL_CALL(rl_btree_node_delete, RL_OK, db, btree, child);
859
+ RL_CALL(rl_delete, RL_OK, db, page);
860
+ }
861
+ }
862
+ retval = RL_OK;
863
+ cleanup:
864
+ return retval;
865
+ }
866
+
867
+ int rl_btree_delete(struct rlite *db, rl_btree *btree)
868
+ {
869
+ void *tmp;
870
+ rl_btree_node *node;
871
+ int retval = rl_read(db, btree->type->btree_node_type, btree->root, btree, &tmp, 1);
872
+ if (retval != RL_FOUND) {
873
+ goto cleanup;
874
+ }
875
+ node = tmp;
876
+ RL_CALL(rl_btree_node_delete, RL_OK, db, btree, node);
877
+ RL_CALL(rl_delete, RL_OK, db, btree->root);
878
+ cleanup:
879
+ return retval;
880
+ }
881
+
882
+ int rl_btree_node_is_balanced(rlite *db, rl_btree *btree, rl_btree_node *node, int is_root)
883
+ {
884
+ if (!is_root && node->size < btree->max_node_size / 2) {
885
+ fprintf(stderr, "Non root node is below maximum\n");
886
+ return RL_INVALID_STATE;
887
+ }
888
+
889
+ void *tmp;
890
+ int i, retval = RL_OK;
891
+ rl_btree_node *child;
892
+ for (i = 0; i < node->size + 1; i++) {
893
+ if (node->children) {
894
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[i], btree, &tmp, 1);
895
+ child = tmp;
896
+ retval = rl_btree_node_is_balanced(db, btree, child, 0);
897
+ if (retval != RL_OK) {
898
+ fprintf(stderr, "Child is not balanced %p\n", (void *)child);
899
+ break;
900
+ }
901
+ }
902
+ }
903
+ cleanup:
904
+ return retval;
905
+ }
906
+
907
+ int rl_btree_is_balanced(rlite *db, rl_btree *btree)
908
+ {
909
+ void **scores = NULL, *tmp;
910
+ rl_btree_node *node;
911
+ int retval = rl_read(db, btree->type->btree_node_type, btree->root, btree, &tmp, 1);
912
+ if (retval != RL_FOUND) {
913
+ fprintf(stderr, "Unable to read btree in page %ld (%d)\n", btree->root, retval);
914
+ goto cleanup;
915
+ }
916
+ node = tmp;
917
+ RL_CALL(rl_btree_node_is_balanced, RL_OK, db, btree, node, 1);
918
+
919
+ long size = (long)pow(btree->max_node_size + 1, btree->height + 1);
920
+ RL_MALLOC(scores, sizeof(void *) * size);
921
+ size = 0;
922
+ rl_flatten_btree(db, btree, &scores, &size);
923
+ long i, j;
924
+ for (i = 0; i < size; i++) {
925
+ for (j = i + 1; j < size; j++) {
926
+ if (btree->type->cmp(scores[i], scores[j]) >= 0) {
927
+ #ifdef DEBUG
928
+ rl_print_btree(db, btree);
929
+ #endif
930
+ fprintf(stderr, "btree is not sorted");
931
+ char *str;
932
+ RL_MALLOC(str, sizeof(char) * 100);
933
+ #ifdef DEBUG
934
+ fprintf(stderr, " (");
935
+ int strlen;
936
+ btree->type->formatter(scores[i], &str, &strlen);
937
+ str[strlen] = 0;
938
+ fprintf(stderr, "%s >= ", str);
939
+ btree->type->formatter(scores[j], &str, &strlen);
940
+ str[strlen] = 0;
941
+ fprintf(stderr, "%s)\n", str);
942
+ #else
943
+ fprintf(stderr, "\n");
944
+ #endif
945
+ retval = RL_INVALID_STATE;
946
+ goto cleanup;
947
+ }
948
+ }
949
+ }
950
+ cleanup:
951
+ rl_free(scores);
952
+ return retval;
953
+ }
954
+
955
+ #ifdef DEBUG
956
+ int rl_print_btree_node(rlite *db, rl_btree *btree, rl_btree_node *node, long level)
957
+ {
958
+ int retval = RL_OK;
959
+ long i, j;
960
+ void *tmp;
961
+ rl_btree_node *child;
962
+ if (node->children) {
963
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[0], btree, &tmp, 1);
964
+ child = tmp;
965
+ RL_CALL(rl_print_btree_node, RL_OK, db, btree, child, level + 1);
966
+ }
967
+ char *score;
968
+ int size;
969
+ for (i = 0; i < node->size; i++) {
970
+ for (j = 0; j < level; j++) {
971
+ putchar('=');
972
+ }
973
+ btree->type->formatter(node->scores[i], &score, &size);
974
+ fwrite(score, sizeof(char), size, stdout);
975
+ rl_free(score);
976
+ printf("\n");
977
+ if (node->values) {
978
+ for (j = 0; j < level; j++) {
979
+ putchar('*');
980
+ }
981
+ printf("%p\n", node->values[i]);
982
+ }
983
+ if (node->children) {
984
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[i + 1], btree, &tmp, 1);
985
+ child = tmp;
986
+ RL_CALL(rl_print_btree_node, RL_OK, db, btree, child, level + 1);
987
+ }
988
+ }
989
+ cleanup:
990
+ return retval;
991
+ }
992
+
993
+ int rl_print_btree(rlite *db, rl_btree *btree)
994
+ {
995
+ rl_btree_node *node;
996
+ void *tmp;
997
+ int retval;
998
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, btree->root, btree, &tmp, 1);
999
+ node = tmp;
1000
+ printf("-------\n");
1001
+ RL_CALL(rl_print_btree_node, RL_OK, db, btree, node, 1);
1002
+ printf("-------\n");
1003
+ cleanup:
1004
+ return retval;
1005
+ }
1006
+ #endif
1007
+
1008
+ int rl_flatten_btree_node(rlite *db, rl_btree *btree, rl_btree_node *node, void *** scores, long *size)
1009
+ {
1010
+ int retval = RL_OK;
1011
+ long i;
1012
+ void *tmp;
1013
+ rl_btree_node *child;
1014
+ if (node->children) {
1015
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[0], btree, &tmp, 1);
1016
+ child = tmp;
1017
+ RL_CALL(rl_flatten_btree_node, RL_OK, db, btree, child, scores, size);
1018
+ }
1019
+ for (i = 0; i < node->size; i++) {
1020
+ (*scores)[*size] = node->scores[i];
1021
+ (*size)++;
1022
+ if (node->children) {
1023
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, node->children[i + 1], btree, &tmp, 1);
1024
+ child = tmp;
1025
+ RL_CALL(rl_flatten_btree_node, RL_OK, db, btree, child, scores, size);
1026
+ }
1027
+ }
1028
+ retval = RL_OK;
1029
+ cleanup:
1030
+ return retval;
1031
+ }
1032
+
1033
+ int rl_flatten_btree(rlite *db, rl_btree *btree, void *** scores, long *size)
1034
+ {
1035
+ void *node;
1036
+ int retval = rl_read(db, btree->type->btree_node_type, btree->root, btree, &node, 1);
1037
+ if (retval != RL_FOUND) {
1038
+ return retval;
1039
+ }
1040
+ return rl_flatten_btree_node(db, btree, node, scores, size);
1041
+ }
1042
+
1043
+ int rl_btree_node_serialize_hash_sha1_key(rlite *UNUSED(db), void *obj, unsigned char *data)
1044
+ {
1045
+ rl_btree_node *node = (rl_btree_node *)obj;
1046
+ put_4bytes(data, node->size);
1047
+ long i, pos = 4;
1048
+ rl_key *key;
1049
+ for (i = 0; i < node->size; i++) {
1050
+ memcpy(&data[pos], node->scores[i], sizeof(unsigned char) * 20);
1051
+ key = node->values[i];
1052
+ data[pos + 20] = key->type;
1053
+ put_4bytes(&data[pos + 21], key->string_page);
1054
+ put_4bytes(&data[pos + 25], key->value_page);
1055
+ put_8bytes(&data[pos + 29], key->expires);
1056
+ put_4bytes(&data[pos + 37], key->version);
1057
+ put_4bytes(&data[pos + 41], node->children ? node->children[i] : 0);
1058
+ pos += 45;
1059
+ }
1060
+ put_4bytes(&data[pos], node->children ? node->children[node->size] : 0);
1061
+ return RL_OK;
1062
+ }
1063
+
1064
+ int rl_btree_node_deserialize_hash_sha1_key(rlite *db, void **obj, void *context, unsigned char *data)
1065
+ {
1066
+ rl_btree_node *node = NULL;
1067
+ rl_btree *btree = (rl_btree *) context;
1068
+ int retval;
1069
+ RL_CALL(rl_btree_node_create, RL_OK, db, btree, &node);
1070
+ node->size = (long)get_4bytes(data);
1071
+ long i, pos = 4, child;
1072
+ rl_key *key;
1073
+ for (i = 0; i < node->size; i++) {
1074
+ node->scores[i] = rl_malloc(sizeof(unsigned char) * 20);
1075
+ if (!node->scores[i]) {
1076
+ node->size = i;
1077
+ retval = RL_OUT_OF_MEMORY;
1078
+ goto cleanup;
1079
+ }
1080
+ memcpy(node->scores[i], &data[pos], sizeof(unsigned char) * 20);
1081
+ key = node->values[i] = rl_malloc(sizeof(rl_key));
1082
+ if (!node->values[i]) {
1083
+ rl_free(node->scores[i]);
1084
+ node->size = i;
1085
+ retval = RL_OUT_OF_MEMORY;
1086
+ goto cleanup;
1087
+ }
1088
+ key->type = data[pos + 20];
1089
+ key->string_page = get_4bytes(&data[pos + 21]);
1090
+ key->value_page = get_4bytes(&data[pos + 25]);
1091
+ key->expires = get_8bytes(&data[pos + 29]);
1092
+ key->version = get_4bytes(&data[pos + 37]);
1093
+ child = get_4bytes(&data[pos + 41]);
1094
+ if (child != 0) {
1095
+ if (!node->children) {
1096
+ node->children = rl_malloc(sizeof(long) * (btree->max_node_size + 1));
1097
+ if (!node->children) {
1098
+ rl_free(node->scores[i]);
1099
+ rl_free(node->values[i]);
1100
+ node->size = i;
1101
+ retval = RL_OUT_OF_MEMORY;
1102
+ goto cleanup;
1103
+ }
1104
+ }
1105
+ node->children[i] = child;
1106
+ }
1107
+ pos += 45;
1108
+ }
1109
+ child = get_4bytes(&data[pos]);
1110
+ if (child != 0) {
1111
+ node->children[node->size] = child;
1112
+ }
1113
+ *obj = node;
1114
+ cleanup:
1115
+ if (retval != RL_OK && node) {
1116
+ rl_btree_node_destroy(db, node);
1117
+ }
1118
+ return retval;
1119
+ }
1120
+
1121
+ int rl_btree_node_serialize_hash_sha1_hashkey(rlite *UNUSED(db), void *obj, unsigned char *data)
1122
+ {
1123
+ rl_btree_node *node = (rl_btree_node *)obj;
1124
+ put_4bytes(data, node->size);
1125
+ long i, pos = 4;
1126
+ rl_hashkey *hashkey;
1127
+ for (i = 0; i < node->size; i++) {
1128
+ memcpy(&data[pos], node->scores[i], sizeof(unsigned char) * 20);
1129
+ hashkey = node->values[i];
1130
+ put_4bytes(&data[pos + 20], hashkey->string_page);
1131
+ put_4bytes(&data[pos + 24], hashkey->value_page);
1132
+ put_4bytes(&data[pos + 28], node->children ? node->children[i] : 0);
1133
+ pos += 32;
1134
+ }
1135
+ put_4bytes(&data[pos], node->children ? node->children[node->size] : 0);
1136
+ return RL_OK;
1137
+ }
1138
+
1139
+ int rl_btree_node_deserialize_hash_sha1_hashkey(rlite *db, void **obj, void *context, unsigned char *data)
1140
+ {
1141
+ rl_btree_node *node = NULL;
1142
+ rl_btree *btree = (rl_btree *) context;
1143
+ int retval;
1144
+ RL_CALL(rl_btree_node_create, RL_OK, db, btree, &node);
1145
+ node->size = (long)get_4bytes(data);
1146
+ long i, pos = 4, child;
1147
+ rl_hashkey *hashkey;
1148
+ for (i = 0; i < node->size; i++) {
1149
+ node->scores[i] = rl_malloc(sizeof(unsigned char) * 20);
1150
+ if (!node->scores[i]) {
1151
+ node->size = i;
1152
+ retval = RL_OUT_OF_MEMORY;
1153
+ goto cleanup;
1154
+ }
1155
+ memcpy(node->scores[i], &data[pos], sizeof(unsigned char) * 20);
1156
+ hashkey = node->values[i] = rl_malloc(sizeof(rl_hashkey));
1157
+ if (!node->values[i]) {
1158
+ rl_free(node->scores[i]);
1159
+ node->size = i;
1160
+ retval = RL_OUT_OF_MEMORY;
1161
+ goto cleanup;
1162
+ }
1163
+ hashkey->string_page = get_4bytes(&data[pos + 20]);
1164
+ hashkey->value_page = get_4bytes(&data[pos + 24]);
1165
+ child = get_4bytes(&data[pos + 28]);
1166
+ if (child != 0) {
1167
+ if (!node->children) {
1168
+ node->children = rl_malloc(sizeof(long) * (btree->max_node_size + 1));
1169
+ if (!node->children) {
1170
+ rl_free(node->scores[i]);
1171
+ rl_free(node->values[i]);
1172
+ node->size = i;
1173
+ retval = RL_OUT_OF_MEMORY;
1174
+ goto cleanup;
1175
+ }
1176
+ }
1177
+ node->children[i] = child;
1178
+ }
1179
+ pos += 32;
1180
+ }
1181
+ child = get_4bytes(&data[pos]);
1182
+ if (child != 0) {
1183
+ node->children[node->size] = child;
1184
+ }
1185
+ *obj = node;
1186
+ cleanup:
1187
+ if (retval != RL_OK && node) {
1188
+ rl_btree_node_destroy(db, node);
1189
+ }
1190
+ return retval;
1191
+ }
1192
+
1193
+
1194
+ int rl_btree_node_serialize_set_long(struct rlite *UNUSED(db), void *obj, unsigned char *data)
1195
+ {
1196
+ rl_btree_node *node = obj;
1197
+ put_4bytes(data, node->size);
1198
+ long i, pos = 4;
1199
+ for (i = 0; i < node->size; i++) {
1200
+ put_4bytes(&data[pos], *(long *)(node->scores[i]));
1201
+ put_4bytes(&data[pos + 4], node->children ? node->children[i] : 0);
1202
+ pos += 8;
1203
+ }
1204
+ put_4bytes(&data[pos], node->children ? node->children[node->size] : 0);
1205
+ return RL_OK;
1206
+ }
1207
+
1208
+ int rl_btree_node_deserialize_set_long(struct rlite *db, void **obj, void *context, unsigned char *data)
1209
+ {
1210
+ rl_btree *btree = context;
1211
+ rl_btree_node *node = NULL;
1212
+ long i, pos = 4, child;
1213
+ int retval;
1214
+ RL_CALL(rl_btree_node_create, RL_OK, db, btree, &node);
1215
+ node->size = (long)get_4bytes(data);
1216
+ for (i = 0; i < node->size; i++) {
1217
+ node->scores[i] = rl_malloc(sizeof(long));
1218
+ if (!node->scores[i]) {
1219
+ node->size = i;
1220
+ retval = RL_OUT_OF_MEMORY;
1221
+ goto cleanup;
1222
+ }
1223
+ *(long *)node->scores[i] = get_4bytes(&data[pos]);
1224
+ child = get_4bytes(&data[pos + 4]);
1225
+ if (child != 0) {
1226
+ if (!node->children) {
1227
+ node->children = rl_malloc(sizeof(long) * (btree->max_node_size + 1));
1228
+ if (!node->children) {
1229
+ rl_free(node->scores[i]);
1230
+ node->size = i;
1231
+ retval = RL_OUT_OF_MEMORY;
1232
+ goto cleanup;
1233
+ }
1234
+ }
1235
+ node->children[i] = child;
1236
+ }
1237
+ pos += 8;
1238
+ }
1239
+ child = get_4bytes(&data[pos]);
1240
+ if (child != 0) {
1241
+ node->children[node->size] = child;
1242
+ }
1243
+ *obj = node;
1244
+ cleanup:
1245
+ if (retval != RL_OK && node) {
1246
+ rl_btree_node_destroy(db, node);
1247
+ }
1248
+ return retval;
1249
+ }
1250
+
1251
+ int rl_btree_node_serialize_hash_long_long(struct rlite *UNUSED(db), void *obj, unsigned char *data)
1252
+ {
1253
+ rl_btree_node *node = obj;
1254
+ long i, pos = 4;
1255
+ put_4bytes(data, node->size);
1256
+ for (i = 0; i < node->size; i++) {
1257
+ put_4bytes(&data[pos], *(long *)(node->scores[i]));
1258
+ put_4bytes(&data[pos + 4], node->children ? node->children[i] : 0);
1259
+ put_4bytes(&data[pos + 8], *(long *)node->values[i]);
1260
+ pos += 12;
1261
+ }
1262
+ put_4bytes(&data[pos], node->children ? node->children[node->size] : 0);
1263
+ return RL_OK;
1264
+ }
1265
+
1266
+ int rl_btree_node_deserialize_hash_long_long(struct rlite *db, void **obj, void *context, unsigned char *data)
1267
+ {
1268
+ rl_btree *btree = context;
1269
+ rl_btree_node *node = NULL;
1270
+ long i, pos = 4, child;
1271
+ int retval;
1272
+ RL_CALL(rl_btree_node_create, RL_OK, db, btree, &node);
1273
+ node->size = (long)get_4bytes(data);
1274
+ for (i = 0; i < node->size; i++) {
1275
+ node->scores[i] = rl_malloc(sizeof(long));
1276
+ if (!node->scores[i]) {
1277
+ node->size = i;
1278
+ retval = RL_OUT_OF_MEMORY;
1279
+ goto cleanup;
1280
+ }
1281
+ *(long *)node->scores[i] = get_4bytes(&data[pos]);
1282
+ child = get_4bytes(&data[pos + 4]);
1283
+ if (child != 0) {
1284
+ if (!node->children) {
1285
+ node->children = rl_malloc(sizeof(long) * (btree->max_node_size + 1));
1286
+ if (!node->children) {
1287
+ rl_free(node->scores[i]);
1288
+ node->size = i;
1289
+ retval = RL_OUT_OF_MEMORY;
1290
+ goto cleanup;
1291
+ }
1292
+ }
1293
+ node->children[i] = child;
1294
+ }
1295
+ node->values[i] = rl_malloc(sizeof(long));
1296
+ if (!node->values[i]) {
1297
+ rl_free(node->scores[i]);
1298
+ node->size = i;
1299
+ retval = RL_OUT_OF_MEMORY;
1300
+ goto cleanup;
1301
+ }
1302
+ *(long *)node->values[i] = get_4bytes(&data[pos + 8]);
1303
+ pos += 12;
1304
+ }
1305
+ child = get_4bytes(&data[pos]);
1306
+ if (child != 0) {
1307
+ node->children[node->size] = child;
1308
+ }
1309
+ *obj = node;
1310
+ cleanup:
1311
+ if (retval != RL_OK && node) {
1312
+ rl_btree_node_destroy(db, node);
1313
+ }
1314
+ return retval;
1315
+ }
1316
+
1317
+ int rl_btree_node_serialize_hash_sha1_long(struct rlite *UNUSED(db), void *obj, unsigned char *data)
1318
+ {
1319
+ rl_btree_node *node = obj;
1320
+ long i, pos = 4;
1321
+ put_4bytes(data, node->size);
1322
+ for (i = 0; i < node->size; i++) {
1323
+ memcpy(&data[pos], node->scores[i], sizeof(unsigned char) * 20);
1324
+ put_double(&data[pos + 20], *(long *)(node->values[i]));
1325
+ put_4bytes(&data[pos + 24], node->children ? node->children[i] : 0);
1326
+ pos += 28;
1327
+ }
1328
+ put_4bytes(&data[pos], node->children ? node->children[node->size] : 0);
1329
+ return RL_OK;
1330
+ }
1331
+ int rl_btree_node_deserialize_hash_sha1_long(struct rlite *db, void **obj, void *context, unsigned char *data)
1332
+ {
1333
+ rl_btree *btree = context;
1334
+ rl_btree_node *node = NULL;
1335
+ long i, pos = 4, child;
1336
+ int retval;
1337
+ RL_CALL(rl_btree_node_create, RL_OK, db, btree, &node);
1338
+ node->size = (long)get_4bytes(data);
1339
+ for (i = 0; i < node->size; i++) {
1340
+ node->scores[i] = rl_malloc(sizeof(unsigned char) * 20);
1341
+ if (!node->scores[i]) {
1342
+ node->size = i;
1343
+ retval = RL_OUT_OF_MEMORY;
1344
+ goto cleanup;
1345
+ }
1346
+ memcpy(node->scores[i], &data[pos], sizeof(unsigned char) * 20);
1347
+ node->values[i] = rl_malloc(sizeof(double));
1348
+ if (!node->values[i]) {
1349
+ rl_free(node->scores[i]);
1350
+ node->size = i;
1351
+ retval = RL_OUT_OF_MEMORY;
1352
+ goto cleanup;
1353
+ }
1354
+ *(long *)node->values[i] = get_double(&data[pos + 20]);
1355
+ child = get_4bytes(&data[pos + 24]);
1356
+ if (child != 0) {
1357
+ if (!node->children) {
1358
+ node->children = rl_malloc(sizeof(long) * (btree->max_node_size + 1));
1359
+ if (!node->children) {
1360
+ rl_free(node->scores[i]);
1361
+ node->size = i;
1362
+ retval = RL_OUT_OF_MEMORY;
1363
+ goto cleanup;
1364
+ }
1365
+ }
1366
+ node->children[i] = child;
1367
+ }
1368
+ pos += 28;
1369
+ }
1370
+ child = get_4bytes(&data[pos]);
1371
+ if (child != 0) {
1372
+ node->children[node->size] = child;
1373
+ }
1374
+ *obj = node;
1375
+ cleanup:
1376
+ if (retval != RL_OK && node) {
1377
+ rl_btree_node_destroy(db, node);
1378
+ }
1379
+ return retval;
1380
+ }
1381
+
1382
+ int rl_btree_node_serialize_hash_sha1_double(struct rlite *UNUSED(db), void *obj, unsigned char *data)
1383
+ {
1384
+ rl_btree_node *node = obj;
1385
+ long i, pos = 4;
1386
+ put_4bytes(data, node->size);
1387
+ for (i = 0; i < node->size; i++) {
1388
+ memcpy(&data[pos], node->scores[i], sizeof(unsigned char) * 20);
1389
+ put_double(&data[pos + 20], *(double *)(node->values[i]));
1390
+ put_4bytes(&data[pos + 28], node->children ? node->children[i] : 0);
1391
+ pos += 32;
1392
+ }
1393
+ put_4bytes(&data[pos], node->children ? node->children[node->size] : 0);
1394
+ return RL_OK;
1395
+ }
1396
+
1397
+ int rl_btree_node_deserialize_hash_sha1_double(struct rlite *db, void **obj, void *context, unsigned char *data)
1398
+ {
1399
+ rl_btree *btree = context;
1400
+ rl_btree_node *node = NULL;
1401
+ long i, pos = 4, child;
1402
+ int retval;
1403
+ RL_CALL(rl_btree_node_create, RL_OK, db, btree, &node);
1404
+ node->size = (long)get_4bytes(data);
1405
+ for (i = 0; i < node->size; i++) {
1406
+ node->scores[i] = rl_malloc(sizeof(unsigned char) * 20);
1407
+ if (!node->scores[i]) {
1408
+ node->size = i;
1409
+ retval = RL_OUT_OF_MEMORY;
1410
+ goto cleanup;
1411
+ }
1412
+ memcpy(node->scores[i], &data[pos], sizeof(unsigned char) * 20);
1413
+ node->values[i] = rl_malloc(sizeof(double));
1414
+ if (!node->values[i]) {
1415
+ rl_free(node->scores[i]);
1416
+ node->size = i;
1417
+ retval = RL_OUT_OF_MEMORY;
1418
+ goto cleanup;
1419
+ }
1420
+ *(double *)node->values[i] = get_double(&data[pos + 20]);
1421
+ child = get_4bytes(&data[pos + 28]);
1422
+ if (child != 0) {
1423
+ if (!node->children) {
1424
+ node->children = rl_malloc(sizeof(long) * (btree->max_node_size + 1));
1425
+ if (!node->children) {
1426
+ rl_free(node->scores[i]);
1427
+ node->size = i;
1428
+ retval = RL_OUT_OF_MEMORY;
1429
+ goto cleanup;
1430
+ }
1431
+ }
1432
+ node->children[i] = child;
1433
+ }
1434
+ pos += 32;
1435
+ }
1436
+ child = get_4bytes(&data[pos]);
1437
+ if (child != 0) {
1438
+ node->children[node->size] = child;
1439
+ }
1440
+ *obj = node;
1441
+ cleanup:
1442
+ if (retval != RL_OK && node) {
1443
+ rl_btree_node_destroy(db, node);
1444
+ }
1445
+ return retval;
1446
+ }
1447
+
1448
+ int rl_btree_iterator_create(rlite *db, rl_btree *btree, rl_btree_iterator **_iterator)
1449
+ {
1450
+ int retval;
1451
+ long i;
1452
+ void *tmp;
1453
+ rl_btree_iterator *iterator = NULL;
1454
+ if (btree->number_of_elements == 0) {
1455
+ retval = RL_NOT_FOUND;
1456
+ goto cleanup;
1457
+ }
1458
+ RL_MALLOC(iterator, sizeof(rl_btree_iterator) + sizeof(struct rl_btree_iterator_nodes) * btree->height);
1459
+ iterator->db = db;
1460
+ iterator->btree = btree;
1461
+ iterator->position = btree->height;
1462
+ iterator->size = btree->number_of_elements;
1463
+
1464
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, btree->root, btree, &tmp, 0);
1465
+ iterator->nodes[0].node = tmp;
1466
+ iterator->nodes[0].position = 0;
1467
+
1468
+ for (i = 1; i < btree->height; i++) {
1469
+ RL_CALL(rl_read, RL_FOUND, db, btree->type->btree_node_type, iterator->nodes[i - 1].node->children[0], btree, &tmp, 0);
1470
+ iterator->nodes[i].node = tmp;
1471
+ iterator->nodes[i].position = 0;
1472
+ }
1473
+
1474
+ *_iterator = iterator;
1475
+ retval = RL_OK;
1476
+ cleanup:
1477
+ if (retval != RL_OK) {
1478
+ rl_btree_iterator_destroy(iterator);
1479
+ }
1480
+ return retval;
1481
+ }
1482
+
1483
+ int rl_btree_iterator_next(rl_btree_iterator *iterator, void **score, void **value)
1484
+ {
1485
+ int retval;
1486
+ rl_btree_node *node = NULL;
1487
+ if (iterator == NULL || iterator->position == 0) {
1488
+ retval = RL_END;
1489
+ goto cleanup;
1490
+ }
1491
+ long position;
1492
+ void *tmp;
1493
+ rl_btree *btree = iterator->btree;
1494
+ node = iterator->nodes[iterator->position - 1].node;
1495
+ position = iterator->nodes[iterator->position - 1].position;
1496
+ if (score) {
1497
+ RL_MALLOC(*score, iterator->btree->type->score_size);
1498
+ memcpy(*score, node->scores[position], iterator->btree->type->score_size);
1499
+ }
1500
+ if (value) {
1501
+ RL_MALLOC(*value, iterator->btree->type->value_size);
1502
+ memcpy(*value, node->values[position], iterator->btree->type->value_size);
1503
+ }
1504
+
1505
+ if (node->children) {
1506
+ iterator->nodes[iterator->position - 1].position++;
1507
+ while (iterator->position < iterator->btree->height) {
1508
+ position = node->children[iterator->nodes[iterator->position - 1].position];
1509
+ RL_CALL(rl_read, RL_FOUND, iterator->db, btree->type->btree_node_type, position, btree, &tmp, 0);
1510
+ iterator->nodes[iterator->position].position = 0;
1511
+ node = iterator->nodes[iterator->position++].node = tmp;
1512
+ }
1513
+ }
1514
+ else {
1515
+ if (node->size == iterator->nodes[iterator->position - 1].position + 1) {
1516
+ while (--iterator->position > 0) {
1517
+ RL_CALL(rl_btree_node_nocache_destroy, RL_OK, iterator->db, node);
1518
+ node = iterator->nodes[iterator->position - 1].node;
1519
+ if (iterator->nodes[iterator->position - 1].position < node->size) {
1520
+ break;
1521
+ }
1522
+ }
1523
+ if (iterator->position == 0) {
1524
+ RL_CALL(rl_btree_node_nocache_destroy, RL_OK, iterator->db, node);
1525
+ }
1526
+ }
1527
+ else {
1528
+ iterator->nodes[iterator->position - 1].position++;
1529
+ }
1530
+ }
1531
+
1532
+ retval = RL_OK;
1533
+ cleanup:
1534
+ if (retval != RL_OK) {
1535
+ if (iterator) {
1536
+ while (--iterator->position >= 0) {
1537
+ rl_btree_node_nocache_destroy(iterator->db, iterator->nodes[iterator->position].node);
1538
+ }
1539
+ rl_btree_iterator_destroy(iterator);
1540
+ }
1541
+ }
1542
+ return retval;
1543
+ }
1544
+
1545
+ int rl_btree_iterator_destroy(rl_btree_iterator *iterator)
1546
+ {
1547
+ int retval = RL_OK;
1548
+ if (iterator) {
1549
+ while (--iterator->position >= 0) {
1550
+ RL_CALL(rl_btree_node_nocache_destroy, RL_OK, iterator->db, iterator->nodes[iterator->position].node);
1551
+ }
1552
+ }
1553
+ cleanup:
1554
+ rl_free(iterator);
1555
+ return retval;
1556
+ }