hirlite 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,689 @@
1
+ #include <string.h>
2
+ #include <stdlib.h>
3
+ #include "page_skiplist.h"
4
+ #include "page_multi_string.h"
5
+ #include "util.h"
6
+
7
+ static int rl_skiplist_random_level()
8
+ {
9
+ int level = 1;
10
+ while ((rand() & 0xFFFF) < (RL_SKIPLIST_PROBABILITY * 0xFFFF)) {
11
+ level++;
12
+ }
13
+ return (level < RL_SKIPLIST_MAXLEVEL) ? level : RL_SKIPLIST_MAXLEVEL;
14
+ }
15
+
16
+ int rl_skiplist_malloc(rlite *db, rl_skiplist **_skiplist)
17
+ {
18
+ int retval = RL_OK;
19
+ rl_skiplist *skiplist;
20
+ RL_MALLOC(skiplist, sizeof(rl_skiplist));
21
+ skiplist->right = 0;
22
+ skiplist->size = 0;
23
+ skiplist->level = 1;
24
+
25
+ *_skiplist = skiplist;
26
+ cleanup:
27
+ if (retval != RL_OK) {
28
+ rl_skiplist_destroy(db, skiplist);
29
+ }
30
+ return retval;
31
+ }
32
+
33
+ int rl_skiplist_create(rlite *db, rl_skiplist **_skiplist)
34
+ {
35
+ int retval;
36
+ RL_CALL(rl_skiplist_malloc, RL_OK, db, _skiplist);
37
+ (*_skiplist)->left = db->next_empty_page;
38
+ rl_skiplist_node *node;
39
+ RL_CALL(rl_skiplist_node_create, RL_OK, db, &node, RL_SKIPLIST_MAXLEVEL, 0.0, 0);
40
+
41
+ long j;
42
+ for (j = 0; j < RL_SKIPLIST_MAXLEVEL; j++) {
43
+ node->level[j].right = 0;
44
+ node->level[j].span = 0;
45
+ }
46
+
47
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_skiplist_node, db->next_empty_page, node);
48
+ cleanup:
49
+ return retval;
50
+ }
51
+
52
+ int rl_skiplist_destroy(rlite *UNUSED(db), void *skiplist)
53
+ {
54
+ rl_free(skiplist);
55
+ return RL_OK;
56
+ }
57
+
58
+ int rl_skiplist_node_create(rlite *UNUSED(db), rl_skiplist_node **_node, long level, double score, long value)
59
+ {
60
+ int retval = RL_OK;
61
+ rl_skiplist_node *node;
62
+ RL_MALLOC(node, sizeof(rl_skiplist_node) + level * sizeof(struct rl_skiplist_node_level));
63
+ node->num_levels = level;
64
+ node->score = score;
65
+ node->value = value;
66
+ node->left = 0;
67
+ long i;
68
+ for (i = 0; i < level; i++) {
69
+ node->level[i].right = 0;
70
+ node->level[i].span = 0;
71
+ }
72
+ *_node = node;
73
+ cleanup:
74
+ return retval;
75
+ }
76
+
77
+ int rl_skiplist_node_destroy(rlite *UNUSED(db), void *node)
78
+ {
79
+ rl_free(node);
80
+ return RL_OK;
81
+ }
82
+
83
+ int rl_skiplist_iterator_create(rlite *db, rl_skiplist_iterator **_iterator, rl_skiplist *skiplist, long next_node_page, int direction, int size)
84
+ {
85
+ int retval;
86
+ rl_skiplist_iterator *iterator;
87
+ RL_MALLOC(iterator, sizeof(*iterator))
88
+ iterator->db = db;
89
+ iterator->skiplist = skiplist;
90
+ if (direction == -1) {
91
+ iterator->direction = -1;
92
+ }
93
+ else {
94
+ iterator->direction = 1;
95
+ }
96
+ if (next_node_page) {
97
+ iterator->node_page = next_node_page;
98
+ }
99
+ else {
100
+ if (iterator->direction == 1) {
101
+ iterator->node_page = skiplist->left;
102
+ iterator->size = 1;
103
+ iterator->position = 0;
104
+ // first node_page is the index node, skip it
105
+ RL_CALL(rl_skiplist_iterator_next, RL_OK, iterator, NULL);
106
+ }
107
+ else {
108
+ iterator->node_page = skiplist->right;
109
+ }
110
+ }
111
+ if (size) {
112
+ iterator->size = size;
113
+ }
114
+ else {
115
+ iterator->size = skiplist->size;
116
+ }
117
+ iterator->position = 0;
118
+ *_iterator = iterator;
119
+ retval = RL_OK;
120
+ cleanup:
121
+ return retval;
122
+ }
123
+
124
+ int rl_skiplist_iterator_destroy(rlite *UNUSED(db), rl_skiplist_iterator *iterator)
125
+ {
126
+ rl_free(iterator);
127
+ return RL_OK;
128
+ }
129
+ int rl_skiplist_iterator_next(rl_skiplist_iterator *iterator, rl_skiplist_node **retnode)
130
+ {
131
+ int retval;
132
+ if (!iterator->node_page || iterator->position == iterator->size) {
133
+ retval = RL_END;
134
+ goto cleanup;
135
+ }
136
+ void *_node;
137
+ rl_skiplist_node *node;
138
+ RL_CALL(rl_read, RL_FOUND, iterator->db, &rl_data_type_skiplist_node, iterator->node_page, iterator->skiplist, &_node, 1);
139
+ node = _node;
140
+ if (iterator->direction == 1) {
141
+ iterator->node_page = node->level[0].right;
142
+ }
143
+ else {
144
+ iterator->node_page = node->left;
145
+ }
146
+ if (retnode) {
147
+ *retnode = node;
148
+ }
149
+ iterator->position++;
150
+ retval = RL_OK;
151
+ cleanup:
152
+ if (retval != RL_OK) {
153
+ rl_skiplist_iterator_destroy(iterator->db, iterator);
154
+ }
155
+ return retval;
156
+ }
157
+
158
+ static int rl_skiplist_get_update(rlite *db, rl_skiplist *skiplist, double score, int exclude, unsigned char *value, long valuelen, rl_skiplist_node *update_node[RL_SKIPLIST_MAXLEVEL], long update_node_page[RL_SKIPLIST_MAXLEVEL], long rank[RL_SKIPLIST_MAXLEVEL])
159
+ {
160
+ void *_node;
161
+ rl_skiplist_node *node, *next_node;
162
+ long i, node_page, tmp;
163
+ if (update_node_page) {
164
+ for (i = 0; i < RL_SKIPLIST_MAXLEVEL; i++) {
165
+ update_node_page[i] = 0;
166
+ }
167
+ }
168
+
169
+ int cmp, retval;
170
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, skiplist->left, skiplist, &_node, 1);
171
+ if (update_node_page) {
172
+ update_node_page[0] = skiplist->left;
173
+ }
174
+ node_page = skiplist->left;
175
+ node = _node;
176
+
177
+ for (i = skiplist->level - 1; i >= 0; i--) {
178
+ if (rank) {
179
+ rank[i] = i == (skiplist->level - 1) ? 0 : rank[i + 1];
180
+ }
181
+ while (1) {
182
+ tmp = node->level[i].right;
183
+ if (tmp == 0) {
184
+ break;
185
+ }
186
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, tmp, skiplist, &_node, 1);
187
+ next_node = _node;
188
+ if (next_node->score > score) {
189
+ break;
190
+ }
191
+ if (next_node->score == score) {
192
+ if (value == NULL) {
193
+ if (exclude) {
194
+ break;
195
+ }
196
+ }
197
+ else {
198
+ RL_CALL(rl_multi_string_cmp_str, RL_OK, db, next_node->value, value, valuelen, &cmp);
199
+ if (cmp > 0 || (cmp == 0 && exclude)) {
200
+ break;
201
+ }
202
+ }
203
+ }
204
+ if (rank) {
205
+ rank[i] += node->level[i].span;
206
+ }
207
+ node = next_node;
208
+ node_page = tmp;
209
+ }
210
+ update_node[i] = node;
211
+ if (update_node_page) {
212
+ update_node_page[i] = node_page;
213
+ }
214
+ }
215
+ retval = RL_OK;
216
+ cleanup:
217
+ return retval;
218
+ }
219
+
220
+ int rl_skiplist_add(rlite *db, rl_skiplist *skiplist, long skiplist_page, double score, unsigned char *value, long valuelen)
221
+ {
222
+ void *_node;
223
+ rl_skiplist_node *node;
224
+ long node_page, tmp;
225
+ long rank[RL_SKIPLIST_MAXLEVEL];
226
+ rl_skiplist_node *update_node[RL_SKIPLIST_MAXLEVEL];
227
+ long update_node_page[RL_SKIPLIST_MAXLEVEL];
228
+ long value_page;
229
+ int retval;
230
+ RL_CALL(rl_multi_string_set, RL_OK, db, &value_page, value, valuelen);
231
+ RL_CALL(rl_skiplist_get_update, RL_OK, db, skiplist, score, 0, value, valuelen, update_node, update_node_page, rank);
232
+
233
+ long i, level = rl_skiplist_random_level();
234
+ if (level > skiplist->level) {
235
+ for (i = skiplist->level; i < level; i++) {
236
+ rank[i] = 0;
237
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, skiplist->left, skiplist, &_node, 1);
238
+ update_node[i] = _node;
239
+ update_node[i]->level[i].span = skiplist->size;
240
+ update_node_page[i] = skiplist->left;
241
+ }
242
+ skiplist->level = level;
243
+ }
244
+ RL_CALL(rl_skiplist_node_create, RL_OK, db, &node, level, score, value_page);
245
+ node_page = db->next_empty_page;
246
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_skiplist_node, db->next_empty_page, node);
247
+ for (i = 0; i < level || i < skiplist->level; i++) {
248
+ if (i < level) {
249
+ node->level[i].right = update_node[i]->level[i].right;
250
+ update_node[i]->level[i].right = node_page;
251
+
252
+ node->level[i].span = update_node[i]->level[i].span - (rank[0] - rank[i]);
253
+ update_node[i]->level[i].span = (rank[0] - rank[i]) + 1;
254
+ }
255
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_skiplist_node, update_node_page[i], update_node[i]);
256
+ }
257
+
258
+ for (i = level; i < skiplist->level; i++) {
259
+ update_node[i]->level[i].span++;
260
+ }
261
+
262
+ node->left = (update_node_page[0] == skiplist->left) ? 0 : update_node_page[0];
263
+ if (node->level[0].right) {
264
+ tmp = node_page;
265
+ node_page = node->level[0].right;
266
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, node_page, skiplist, &_node, 1);
267
+ node = _node;
268
+ node->left = tmp;
269
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_skiplist_node, node_page, node);
270
+ }
271
+ else {
272
+ skiplist->right = node_page;
273
+ }
274
+ skiplist->size++;
275
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_skiplist, skiplist_page, skiplist);
276
+ retval = RL_OK;
277
+ cleanup:
278
+ return retval;
279
+ }
280
+
281
+ /**
282
+ *
283
+ * RL_SKIPLIST_BEFORE_SCORE is the last node before the score and value
284
+ * RL_SKIPLIST_UPTO_SCORE is the last node before the range, including exact match
285
+ * RL_SKIPLIST_INCLUDE_SCORE is the first node in the range, including exact match
286
+ * RL_SKIPLIST_EXCLUDE_SCORE is the first node in the range, excluding exact match
287
+ */
288
+ int rl_skiplist_first_node(rlite *db, rl_skiplist *skiplist, double score, int range_mode, unsigned char *value, long valuelen, rl_skiplist_node **retnode, long *_rank)
289
+ {
290
+ rl_skiplist_node *update_node[RL_SKIPLIST_MAXLEVEL];
291
+ long rank[RL_SKIPLIST_MAXLEVEL];
292
+ int exclude = range_mode == RL_SKIPLIST_BEFORE_SCORE || range_mode == RL_SKIPLIST_UPTO_SCORE ? 1 : 0;
293
+ int cmp, return_retnode = exclude;
294
+ int retval;
295
+ RL_CALL(rl_skiplist_get_update, RL_OK, db, skiplist, score, exclude, value, valuelen, update_node, NULL, rank);
296
+
297
+ if (range_mode == RL_SKIPLIST_INCLUDE_SCORE && update_node[0]->value) {
298
+ if (update_node[0]->score == score || update_node[0]->score > score) {
299
+ if (!value || !update_node[0]->value) {
300
+ cmp = 0;
301
+ }
302
+ else {
303
+ RL_CALL(rl_multi_string_cmp_str, RL_OK, db, update_node[0]->value, value, valuelen, &cmp);
304
+ }
305
+ if (cmp == 0) {
306
+ return_retnode = 1;
307
+ }
308
+ }
309
+ }
310
+
311
+ if (range_mode == RL_SKIPLIST_UPTO_SCORE && update_node[0]->level[0].right) {
312
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, update_node[0]->level[0].right, skiplist, (void **)&update_node[1], 1);
313
+ if (update_node[1]->score == score) {
314
+ if (!value) {
315
+ cmp = 0;
316
+ }
317
+ else {
318
+ RL_CALL(rl_multi_string_cmp_str, RL_OK, db, update_node[1]->value, value, valuelen, &cmp);
319
+ }
320
+ if (cmp == 0) {
321
+ return_retnode = 0;
322
+ }
323
+ }
324
+ }
325
+
326
+ if (_rank) {
327
+ *_rank = rank[0] - return_retnode;
328
+ }
329
+
330
+ if (return_retnode) {
331
+ if (retnode) {
332
+ *retnode = update_node[0];
333
+ }
334
+ retval = RL_FOUND;
335
+
336
+ goto cleanup;
337
+ }
338
+ else if (update_node[0]->level[0].right) {
339
+ if (retnode) {
340
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, update_node[0]->level[0].right, skiplist, (void **)retnode, 1);
341
+ }
342
+ retval = RL_FOUND;
343
+
344
+ goto cleanup;
345
+ }
346
+
347
+ retval = RL_NOT_FOUND;
348
+ cleanup:
349
+ return retval;
350
+
351
+ }
352
+
353
+ int rl_skiplist_delete(rlite *db, rl_skiplist *skiplist, long skiplist_page, double score, unsigned char *value, long valuelen)
354
+ {
355
+ rl_skiplist_node *update_node[RL_SKIPLIST_MAXLEVEL];
356
+ long update_node_page[RL_SKIPLIST_MAXLEVEL];
357
+ int retval;
358
+ RL_CALL(rl_skiplist_get_update, RL_OK, db, skiplist, score, 1, value, valuelen, update_node, update_node_page, NULL);
359
+
360
+ void *_node;
361
+ rl_skiplist_node *node, *next_node;
362
+ long node_page = update_node[0]->level[0].right;
363
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, node_page, skiplist, &_node, 1);
364
+ node = _node;
365
+
366
+ int cmp;
367
+ RL_CALL(rl_multi_string_cmp_str, RL_OK, db, node->value, value, valuelen, &cmp);
368
+
369
+ if (node->score != score || cmp != 0) {
370
+ retval = RL_NOT_FOUND;
371
+ goto cleanup;
372
+ }
373
+
374
+ long i;
375
+ for (i = 0; i < skiplist->level; i++) {
376
+ if (update_node[i]->level[i].right == node_page) {
377
+ update_node[i]->level[i].span += node->level[i].span - 1;
378
+ update_node[i]->level[i].right = node->level[i].right;
379
+ }
380
+ else {
381
+ update_node[i]->level[i].span--;
382
+ }
383
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_skiplist_node, update_node_page[i], update_node[i]);
384
+ }
385
+
386
+ long next_node_page = node->level[0].right;
387
+ if (next_node_page) {
388
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, next_node_page, skiplist, &_node, 1);
389
+ next_node = _node;
390
+ next_node->left = node->left;
391
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_skiplist_node, next_node_page, next_node);
392
+ }
393
+ else {
394
+ skiplist->right = node->left;
395
+ }
396
+
397
+ RL_CALL(rl_multi_string_delete, RL_OK, db, node->value);
398
+ RL_CALL(rl_delete, RL_OK, db, node_page);
399
+ node_page = skiplist->left;
400
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, skiplist->left, skiplist, &_node, 1);
401
+ node = _node;
402
+ while (skiplist->level > 0 && node->level[skiplist->level - 1].right == 0) {
403
+ skiplist->level--;
404
+ }
405
+ if (skiplist->size-- > 1) {
406
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_skiplist, skiplist_page, skiplist);
407
+ retval = RL_OK;
408
+ }
409
+ else {
410
+ RL_CALL(rl_delete, RL_OK, db, node_page);
411
+ RL_CALL(rl_delete, RL_OK, db, skiplist_page);
412
+ retval = RL_DELETED;
413
+ }
414
+ cleanup:
415
+ return retval;
416
+ }
417
+
418
+ int rl_skiplist_delete_all(rlite *db, rl_skiplist *skiplist)
419
+ {
420
+ int retval = RL_OK;
421
+ long page = skiplist->left, next_page;
422
+ void *_node;
423
+ rl_skiplist_node *node;
424
+ while (page != 0) {
425
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, page, skiplist, &_node, 1);
426
+ node = _node;
427
+ next_page = node->level[0].right;
428
+ if (node->value) {
429
+ RL_CALL(rl_multi_string_delete, RL_OK, db, node->value);
430
+ }
431
+ RL_CALL(rl_delete, RL_OK, db, page);
432
+ page = next_page;
433
+ }
434
+ retval = RL_OK;
435
+ cleanup:
436
+ return retval;
437
+ }
438
+
439
+ #ifdef DEBUG
440
+ int rl_skiplist_print(rlite *db, rl_skiplist *skiplist)
441
+ {
442
+ printf("left: %ld, right: %ld, size: %ld, level: %ld\n", skiplist->left, skiplist->right, skiplist->size, skiplist->level);
443
+ long page = skiplist->left;
444
+ int retval;
445
+ long i, j;
446
+ void *_node;
447
+ rl_skiplist_node *node;
448
+
449
+ j = 0;
450
+ while (page > 0) {
451
+ if (j++ > skiplist->size + 1) {
452
+ fprintf(stderr, "Too many nodes, expected %ld\n", skiplist->size);
453
+ return RL_UNEXPECTED;
454
+ }
455
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, page, skiplist, &_node, 1);
456
+ node = _node;
457
+ printf("page: %ld, value: %ld, score: %lf, left: %ld", page, node->value, node->score, node->left);
458
+ for (i = 0; i < node->num_levels; i++) {
459
+ if (node->level[i].right) {
460
+ printf(", level[%ld].right: %ld, level[%ld].span: %ld", i, node->level[i].right, i, node->level[i].span);
461
+ }
462
+ }
463
+ printf("\n");
464
+ page = node->level[0].right;
465
+ }
466
+ retval = RL_OK;
467
+ cleanup:
468
+ return retval;
469
+ }
470
+ #endif
471
+
472
+ int rl_skiplist_is_balanced(rlite *db, rl_skiplist *skiplist)
473
+ {
474
+ long page = skiplist->left;
475
+ int retval;
476
+ long i = 0;
477
+ void *_node;
478
+ rl_skiplist_node *node;
479
+ rl_skiplist_node **nodes;
480
+ long *nodes_page = NULL;
481
+ RL_MALLOC(nodes, sizeof(rl_skiplist_node *) * (skiplist->size + 1));
482
+ RL_MALLOC(nodes_page, sizeof(long) * (skiplist->size + 1));
483
+
484
+ while (page > 0) {
485
+ if (i > skiplist->size + 1) {
486
+ fprintf(stderr, "Too many nodes, expected %ld\n", skiplist->size);
487
+ retval = RL_UNEXPECTED;
488
+ goto cleanup;
489
+ }
490
+ nodes_page[i] = page;
491
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, page, skiplist, &_node, 1);
492
+ node = _node;
493
+ nodes[i++] = node;
494
+ page = node->level[0].right;
495
+ }
496
+ if (i != skiplist->size + 1) {
497
+ fprintf(stderr, "Number of nodes (%ld) doesn't match skiplist size (%ld)\n", i - 1, skiplist->size);
498
+ retval = RL_UNEXPECTED;
499
+ goto cleanup;
500
+ }
501
+ int cmp;
502
+
503
+ // node 0 is not really a value node, ignore it
504
+ for (i = 2; i < skiplist->size; i++) {
505
+ if (nodes[i - 1]->score > nodes[i]->score) {
506
+ fprintf(stderr, "skiplist score is not sorted at position %ld (%lf > %lf)\n", i, nodes[i - 1]->score, nodes[i]->score);
507
+ retval = RL_UNEXPECTED;
508
+ goto cleanup;
509
+ }
510
+ else if (nodes[i - 1]->score == nodes[i]->score) {
511
+ RL_CALL(rl_multi_string_cmp, RL_OK, db, nodes[i - 1]->value, nodes[i]->value, &cmp);
512
+ if (cmp > 0) {
513
+ fprintf(stderr, "skiplist score is not sorted at position %ld (same score, cmp is %d)\n", i, cmp);
514
+ retval = RL_UNEXPECTED;
515
+ goto cleanup;
516
+ }
517
+ }
518
+ }
519
+
520
+ for (i = 2; i < skiplist->size; i++) {
521
+ if (nodes[i]->left != nodes_page[i - 1]) {
522
+ fprintf(stderr, "expected skiplist node[%ld] left page to be %ld, got %ld\n", i, nodes_page[i - 1], nodes[i]->left);
523
+ retval = RL_UNEXPECTED;
524
+ goto cleanup;
525
+ }
526
+ }
527
+
528
+ long pos;
529
+ for (i = 1; i < skiplist->level; i++) {
530
+ node = nodes[0];
531
+ if (node->level[i].right == 0) {
532
+ fprintf(stderr, "There has to be at least one node in level %ld\n", i);
533
+ retval = RL_UNEXPECTED;
534
+ goto cleanup;
535
+ }
536
+ pos = 0;
537
+ while (1) {
538
+ pos += node->level[i].span;
539
+ page = node->level[i].right;
540
+ if (page == 0) {
541
+ break;
542
+ }
543
+ if (nodes_page[pos] != page) {
544
+ fprintf(stderr, "expected skiplist at level %ld node page to be %ld, got %ld\n", i, nodes_page[pos], page);
545
+ retval = RL_UNEXPECTED;
546
+ goto cleanup;
547
+ }
548
+ node = nodes[pos];
549
+ }
550
+ }
551
+
552
+ retval = RL_OK;
553
+ cleanup:
554
+ rl_free(nodes_page);
555
+ rl_free(nodes);
556
+ return retval;
557
+ }
558
+
559
+ int rl_skiplist_serialize(struct rlite *UNUSED(db), void *obj, unsigned char *data)
560
+ {
561
+ rl_skiplist *skiplist = obj;
562
+ put_4bytes(&data[0], skiplist->left);
563
+ put_4bytes(&data[4], skiplist->right);
564
+ put_4bytes(&data[8], skiplist->size);
565
+ put_4bytes(&data[12], skiplist->level);
566
+ return RL_OK;
567
+ }
568
+ int rl_skiplist_deserialize(struct rlite *db, void **obj, void *UNUSED(context), unsigned char *data)
569
+ {
570
+ rl_skiplist *skiplist;
571
+ int retval;
572
+ RL_CALL(rl_skiplist_malloc, RL_OK, db, &skiplist);
573
+ skiplist->left = get_4bytes(&data[0]);
574
+ skiplist->right = get_4bytes(&data[4]);
575
+ skiplist->size = get_4bytes(&data[8]);
576
+ skiplist->level = get_4bytes(&data[12]);
577
+ *obj = skiplist;
578
+ retval = RL_OK;
579
+ cleanup:
580
+ return retval;
581
+ }
582
+
583
+ int rl_skiplist_node_serialize(struct rlite *UNUSED(db), void *obj, unsigned char *data)
584
+ {
585
+ rl_skiplist_node *node = obj;
586
+ put_4bytes(data, node->value);
587
+ put_double(&data[4], node->score);
588
+ put_4bytes(&data[12], node->left);
589
+ put_4bytes(&data[16], node->num_levels);
590
+ long i, pos = 20;
591
+ for (i = 0; i < node->num_levels; i++) {
592
+ put_4bytes(&data[pos], node->level[i].right);
593
+ put_4bytes(&data[pos + 4], node->level[i].span);
594
+ pos += 8;
595
+ }
596
+ return RL_OK;
597
+ }
598
+
599
+ int rl_skiplist_node_deserialize(struct rlite *db, void **obj, void *UNUSED(context), unsigned char *data)
600
+ {
601
+ rl_skiplist_node *node;
602
+ long value = get_4bytes(data);
603
+ double score = get_double(&data[4]);
604
+ long left = get_4bytes(&data[12]);
605
+ long level = get_4bytes(&data[16]);;
606
+ int retval;
607
+ RL_CALL(rl_skiplist_node_create, RL_OK, db, &node, level, score, value);
608
+ node->left = left;
609
+ long i, pos = 20;
610
+ for (i = 0; i < node->num_levels; i++) {
611
+ node->level[i].right = get_4bytes(&data[pos]);
612
+ node->level[i].span = get_4bytes(&data[pos + 4]);
613
+ pos += 8;
614
+ }
615
+ *obj = node;
616
+ cleanup:
617
+ return retval;
618
+ }
619
+
620
+ int rl_skiplist_node_by_rank(rlite *db, rl_skiplist *skiplist, long rank, rl_skiplist_node **retnode, long *retnode_page)
621
+ {
622
+ void *_node;
623
+ rl_skiplist_node *node;
624
+ long node_page = 0;
625
+ long i, pos = 0;
626
+
627
+ // increment the rank in 1 to ignore the first node thats not actually a data node
628
+ rank++;
629
+
630
+ int retval;
631
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, skiplist->left, skiplist, &_node, 1);
632
+ node = _node;
633
+
634
+ for (i = skiplist->level - 1; i >= 0; i--) {
635
+ if (pos == rank) {
636
+ break;
637
+ }
638
+ while (1) {
639
+ if (node->level[i].right == 0 || pos + node->level[i].span > rank) {
640
+ break;
641
+ }
642
+ pos += node->level[i].span;
643
+ node_page = node->level[i].right;
644
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_skiplist_node, node_page, skiplist, &_node, 1);
645
+ node = _node;
646
+ }
647
+ }
648
+ if (rank != pos) {
649
+ retval = RL_NOT_FOUND;
650
+ }
651
+ else {
652
+ if (retnode) {
653
+ *retnode = node;
654
+ }
655
+ if (retnode_page) {
656
+ *retnode_page = node_page;
657
+ }
658
+ retval = RL_OK;
659
+ }
660
+ cleanup:
661
+ return retval;
662
+ }
663
+
664
+ int rl_skiplist_pages(struct rlite *db, rl_skiplist *skiplist, short *pages)
665
+ {
666
+ int retval;
667
+ rl_skiplist_iterator *iterator = NULL;
668
+ RL_CALL(rl_skiplist_iterator_create, RL_OK, db, &iterator, skiplist, 0, 1, 0);
669
+ pages[skiplist->right] = 1;
670
+ pages[skiplist->left] = 1;
671
+ do {
672
+ if (iterator->node_page) {
673
+ pages[iterator->node_page] = 1;
674
+ }
675
+ }
676
+ while ((retval = rl_skiplist_iterator_next(iterator, NULL)) == RL_OK);
677
+ iterator = NULL;
678
+
679
+ if (retval != RL_END) {
680
+ goto cleanup;
681
+ }
682
+
683
+ retval = RL_OK;
684
+ cleanup:
685
+ if (retval != RL_OK) {
686
+ rl_skiplist_iterator_destroy(db, iterator);
687
+ }
688
+ return retval;
689
+ }