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,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
+ }