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,718 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+ #include <stdio.h>
4
+ #include <math.h>
5
+ #include "rlite.h"
6
+ #include "status.h"
7
+ #include "page_list.h"
8
+ #include "page_string.h"
9
+ #include "util.h"
10
+
11
+ #ifdef DEBUG
12
+ int rl_print_list_node(rl_list *list, rl_list_node *node);
13
+ #endif
14
+ int rl_list_node_create(rlite *db, rl_list *list, rl_list_node **node);
15
+
16
+ rl_list_type rl_list_type_long = {
17
+ 0,
18
+ 0,
19
+ sizeof(long),
20
+ long_cmp,
21
+ #ifdef DEBUG
22
+ long_formatter,
23
+ #endif
24
+ };
25
+
26
+ int rl_list_serialize(rlite *UNUSED(db), void *obj, unsigned char *data)
27
+ {
28
+ rl_list *list = obj;
29
+ put_4bytes(data, list->left);
30
+ put_4bytes(&data[4], list->right);
31
+ put_4bytes(&data[8], list->max_node_size);
32
+ put_4bytes(&data[12], list->size);
33
+ return RL_OK;
34
+ }
35
+
36
+ int rl_list_deserialize(rlite *UNUSED(db), void **obj, void *context, unsigned char *data)
37
+ {
38
+ rl_list *list;
39
+ int retval = RL_OK;
40
+ RL_MALLOC(list, sizeof(*list));
41
+ list->type = context;
42
+ list->left = get_4bytes(data);
43
+ list->right = get_4bytes(&data[4]);
44
+ list->max_node_size = get_4bytes(&data[8]);
45
+ list->size = get_4bytes(&data[12]);
46
+ *obj = list;
47
+ cleanup:
48
+ return retval;
49
+ }
50
+
51
+ int rl_list_node_serialize_long(rlite *UNUSED(db), void *obj, unsigned char *data)
52
+ {
53
+ rl_list_node *node = obj;
54
+
55
+ put_4bytes(data, node->size);
56
+ put_4bytes(&data[4], node->left);
57
+ put_4bytes(&data[8], node->right);
58
+ long i, pos = 12;
59
+ for (i = 0; i < node->size; i++) {
60
+ put_4bytes(&data[pos], *(long *)(node->elements[i]));
61
+ pos += 4;
62
+ }
63
+ return RL_OK;
64
+ }
65
+
66
+ int rl_list_node_deserialize_long(rlite *db, void **obj, void *context, unsigned char *data)
67
+ {
68
+ rl_list *list = context;
69
+ rl_list_node *node = NULL;
70
+ long i = 0, pos = 12;
71
+ int retval;
72
+ RL_CALL(rl_list_node_create, RL_OK, db, list, &node);
73
+ node->size = (long)get_4bytes(data);
74
+ node->left = (long)get_4bytes(&data[4]);
75
+ node->right = (long)get_4bytes(&data[8]);
76
+ for (i = 0; i < node->size; i++) {
77
+ RL_MALLOC(node->elements[i], sizeof(long))
78
+ *(long *)node->elements[i] = get_4bytes(&data[pos]);
79
+ pos += 4;
80
+ }
81
+ *obj = node;
82
+ retval = RL_OK;
83
+ cleanup:
84
+ if (retval != RL_OK && node) {
85
+ node->size = i;
86
+ rl_list_node_destroy(db, node);
87
+ }
88
+ return retval;
89
+ }
90
+
91
+ void rl_list_init()
92
+ {
93
+ rl_list_type_long.list_type = &rl_data_type_list_long;
94
+ rl_list_type_long.list_node_type = &rl_data_type_list_node_long;
95
+ }
96
+
97
+ int rl_list_node_create(rlite *UNUSED(db), rl_list *list, rl_list_node **_node)
98
+ {
99
+ int retval;
100
+ rl_list_node *node;
101
+ RL_MALLOC(node, sizeof(rl_list_node));
102
+ RL_MALLOC(node->elements, sizeof(void *) * list->max_node_size);
103
+ node->size = 0;
104
+ node->left = 0;
105
+ node->right = 0;
106
+ *_node = node;
107
+ retval = RL_OK;
108
+ cleanup:
109
+ if (retval != RL_OK) {
110
+ if (node) {
111
+ rl_free(node->elements);
112
+ }
113
+ rl_free(node);
114
+ }
115
+ return retval;
116
+ }
117
+
118
+ int rl_list_node_destroy(rlite *UNUSED(db), void *_node)
119
+ {
120
+ rl_list_node *node = _node;
121
+ long i;
122
+ if (node->elements) {
123
+ for (i = 0; i < node->size; i++) {
124
+ rl_free(node->elements[i]);
125
+ }
126
+ rl_free(node->elements);
127
+ }
128
+ rl_free(node);
129
+ return 0;
130
+ }
131
+
132
+ int rl_list_create(rlite *db, rl_list **_list, rl_list_type *type)
133
+ {
134
+ int retval;
135
+ rl_list *list;
136
+ RL_MALLOC(list, sizeof(rl_list))
137
+ list->max_node_size = (db->page_size - 12) / type->element_size;
138
+ list->type = type;
139
+ rl_list_node *node;
140
+ RL_CALL(rl_list_node_create, RL_OK, db, list, &node);
141
+ node->left = 0;
142
+ node->right = 0;
143
+ list->size = 0;
144
+ list->left = db->next_empty_page;
145
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, db->next_empty_page, node);
146
+ list->right = list->left;
147
+ *_list = list;
148
+ retval = RL_OK;
149
+ cleanup:
150
+ if (retval != RL_OK) {
151
+ rl_list_destroy(db, list);
152
+ }
153
+ return retval;
154
+ }
155
+
156
+ int rl_list_destroy(rlite *UNUSED(db), void *list)
157
+ {
158
+ rl_free(list);
159
+ return RL_OK;
160
+ }
161
+
162
+ int rl_list_find_element(rlite *db, rl_list *list, void *element, void **found_element, long *position, rl_list_node **found_node, long *found_node_page)
163
+ {
164
+ if (!list->type->cmp) {
165
+ fprintf(stderr, "Trying to find an element without cmp\n");
166
+ return RL_UNEXPECTED;
167
+ }
168
+ void *_node;
169
+ rl_list_node *node;
170
+ long pos = 0, i, number = list->left;
171
+ int retval = RL_OK;
172
+ while (number != 0) {
173
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &_node, 1);
174
+ node = _node;
175
+ for (i = 0; i < node->size; i++) {
176
+ if (list->type->cmp(node->elements[i], element) == 0) {
177
+ if (found_node_page) {
178
+ *found_node_page = number;
179
+ }
180
+ if (found_node) {
181
+ *found_node = node;
182
+ }
183
+ if (found_element) {
184
+ *found_element = node->elements[i];
185
+ }
186
+ if (position) {
187
+ *position = pos + i;
188
+ }
189
+ retval = RL_FOUND;
190
+ goto cleanup;
191
+ }
192
+ }
193
+ pos += node->size;
194
+ number = node->right;
195
+ }
196
+ retval = RL_NOT_FOUND;
197
+ cleanup:
198
+ return retval;
199
+ }
200
+
201
+ static int rl_find_element_by_position(rlite *db, rl_list *list, long *position, long *_pos, rl_list_node **_node, long *_number, int add)
202
+ {
203
+ rl_list_node *node;
204
+ void *tmp_node;
205
+ long pos = 0, number;
206
+ if (*position >= list->size + add || *position <= - list->size - 1 - add) {
207
+ return RL_INVALID_PARAMETERS;
208
+ }
209
+ int retval = RL_OK;
210
+ if (*position >= 0) {
211
+ number = list->left;
212
+ while (1) {
213
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &tmp_node, 1);
214
+ node = tmp_node;
215
+ if (pos + node->size > *position) {
216
+ break;
217
+ }
218
+ if (node->right != 0) {
219
+ number = node->right;
220
+ pos += node->size;
221
+ }
222
+ else {
223
+ break;
224
+ }
225
+ }
226
+ }
227
+ else {
228
+ *position = list->size + *position + add;
229
+ pos = list->size;
230
+ number = list->right;
231
+ while (1) {
232
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &tmp_node, 1);
233
+ node = tmp_node;
234
+ pos -= node->size;
235
+ if (pos <= *position) {
236
+ break;
237
+ }
238
+ if (node->left != 0) {
239
+ number = node->left;
240
+ }
241
+ else {
242
+ break;
243
+ }
244
+ }
245
+ }
246
+ *_pos = pos;
247
+ *_node = node;
248
+ if (_number) {
249
+ *_number = number;
250
+ }
251
+ cleanup:
252
+ return retval;
253
+ }
254
+
255
+ int rl_list_get_element(struct rlite *db, rl_list *list, void **element, long position)
256
+ {
257
+ long pos;
258
+ rl_list_node *node;
259
+ int retval;
260
+ RL_CALL(rl_find_element_by_position, RL_FOUND, db, list, &position, &pos, &node, NULL, 0);
261
+ *element = node->elements[position - pos];
262
+ cleanup:
263
+ return retval;
264
+ }
265
+
266
+ int rl_list_add_element(rlite *db, rl_list *list, long list_page, void *element, long position)
267
+ {
268
+ rl_list_node *node, *sibling_node, *new_node, *old_node;
269
+ long pos;
270
+ long number, sibling_number;
271
+ void *_node;
272
+ int retval;
273
+ RL_CALL(rl_find_element_by_position, RL_FOUND, db, list, &position, &pos, &node, &number, 1);
274
+
275
+ if (node->size != list->max_node_size) {
276
+ if (position - pos + 1 < list->max_node_size) {
277
+ memmove(&node->elements[position - pos + 1], &node->elements[position - pos], sizeof(void *) * (node->size - (position - pos)));
278
+ }
279
+ node->elements[position - pos] = element;
280
+ element = NULL;
281
+ node->size++;
282
+
283
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, number, node);
284
+ }
285
+ else {
286
+ if (node->left) {
287
+ sibling_number = node->left;
288
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, sibling_number, list, &_node, 1);
289
+ sibling_node = _node;
290
+ if (sibling_node->size != list->max_node_size) {
291
+ if (position == pos) {
292
+ sibling_node->elements[sibling_node->size] = element;
293
+ }
294
+ else {
295
+ sibling_node->elements[sibling_node->size] = node->elements[0];
296
+ memmove(&node->elements[0], &node->elements[1], sizeof(void *) * (position - pos - 1));
297
+ node->elements[position - pos - 1] = element;
298
+ }
299
+ element = NULL;
300
+ sibling_node->size++;
301
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, number, node);
302
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, sibling_number, sibling_node);
303
+ goto succeeded;
304
+ }
305
+ }
306
+ if (node->right) {
307
+ sibling_number = node->right;
308
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, sibling_number, list, &_node, 1);
309
+ sibling_node = _node;
310
+ if (sibling_node->size != list->max_node_size) {
311
+ memmove(&sibling_node->elements[1], &sibling_node->elements[0], sizeof(void *) * sibling_node->size);
312
+ if (position - pos == node->size) {
313
+ sibling_node->elements[0] = element;
314
+ }
315
+ else {
316
+ sibling_node->elements[0] = node->elements[node->size - 1];
317
+ memmove(&node->elements[position - pos + 1], &node->elements[position - pos], sizeof(void *) * (node->size - position + pos - 1));
318
+ node->elements[position - pos] = element;
319
+ }
320
+ element = NULL;
321
+ sibling_node->size++;
322
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, number, node);
323
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, sibling_number, sibling_node);
324
+ goto succeeded;
325
+ }
326
+ }
327
+ RL_CALL(rl_list_node_create, RL_OK, db, list, &new_node);
328
+ if (position - pos == node->size) {
329
+ new_node->elements[0] = element;
330
+ }
331
+ else {
332
+ new_node->elements[0] = node->elements[node->size - 1];
333
+ memmove(&node->elements[position - pos + 1], &node->elements[position - pos], sizeof(void *) * (node->size - position + pos - 1));
334
+ node->elements[position - pos] = element;
335
+ }
336
+ element = NULL;
337
+ new_node->size = 1;
338
+ new_node->left = number;
339
+ new_node->right = node->right;
340
+ node->right = db->next_empty_page;
341
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, db->next_empty_page, new_node);
342
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, number, node);
343
+ if (new_node->right != 0) {
344
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, new_node->right, list, &_node, 1);
345
+ old_node = _node;
346
+ old_node->left = node->right;
347
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, new_node->right, old_node);
348
+ }
349
+ else {
350
+ list->right = node->right;
351
+ }
352
+ }
353
+
354
+ succeeded:
355
+ list->size++;
356
+ RL_CALL(rl_write, RL_OK, db, list->type->list_type, list_page, list);
357
+ cleanup:
358
+ if (retval != RL_OK) {
359
+ rl_free(element);
360
+ }
361
+ return retval;
362
+ }
363
+
364
+ int rl_list_remove_element(rlite *db, rl_list *list, long list_page, long position)
365
+ {
366
+ rl_list_node *node, *sibling_node;
367
+ long pos, number;
368
+ void *_node;
369
+ int retval;
370
+ RL_CALL(rl_find_element_by_position, RL_FOUND, db, list, &position, &pos, &node, &number, 0);
371
+
372
+ if (node->size - (position - pos + 1) > 0) {
373
+ rl_free(node->elements[position - pos]);
374
+ memmove(&node->elements[position - pos], &node->elements[position - pos + 1], sizeof(void *) * (node->size - (position - pos + 1)));
375
+ }
376
+ else {
377
+ rl_free(node->elements[node->size - 1]);
378
+ }
379
+ if (--node->size == 0) {
380
+ if (list->left == number) {
381
+ list->left = node->right;
382
+ }
383
+ if (list->right == number) {
384
+ list->right = node->left;
385
+ }
386
+ if (node->left) {
387
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, node->left, list, &_node, 1);
388
+ sibling_node = _node;
389
+ sibling_node->right = node->right;
390
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, node->left, sibling_node);
391
+ }
392
+ if (node->right) {
393
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, node->right, list, &_node, 1);
394
+ sibling_node = _node;
395
+ sibling_node->left = node->left;
396
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, node->right, sibling_node);
397
+ }
398
+ RL_CALL(rl_delete, RL_OK, db, number);
399
+ }
400
+ else {
401
+ if (node->left) {
402
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, node->left, list, &_node, 1);
403
+ sibling_node = _node;
404
+ if (sibling_node->size + node->size <= list->max_node_size) {
405
+ memmove(&sibling_node->elements[sibling_node->size], node->elements, sizeof(void *) * node->size);
406
+ sibling_node->right = node->right;
407
+ sibling_node->size += node->size;
408
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, node->left, sibling_node);
409
+ if (node->right) {
410
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, node->right, list, &_node, 1);
411
+ sibling_node = _node;
412
+ sibling_node->left = node->left;
413
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, node->right, sibling_node);
414
+ }
415
+ else {
416
+ list->right = node->left;
417
+ }
418
+ // don't rl_free each element
419
+ rl_free(node->elements);
420
+ node->elements = NULL;
421
+
422
+ rl_delete(db, number);
423
+ if (retval != RL_OK) {
424
+ goto cleanup;
425
+ }
426
+ goto succeeded;
427
+ }
428
+ }
429
+ if (node->right) {
430
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, node->right, list, &_node, 1);
431
+ sibling_node = _node;
432
+ if (sibling_node->size + node->size <= list->max_node_size) {
433
+ memmove(&sibling_node->elements[node->size], sibling_node->elements, sizeof(void *) * sibling_node->size);
434
+ memmove(sibling_node->elements, node->elements, sizeof(void *) * node->size);
435
+ sibling_node->left = node->left;
436
+ sibling_node->size += node->size;
437
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, node->right, sibling_node);
438
+ if (node->left) {
439
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, node->left, list, &_node, 1);
440
+ sibling_node = _node;
441
+ sibling_node->right = node->right;
442
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, node->left, sibling_node);
443
+ }
444
+ else {
445
+ list->left = node->right;
446
+ }
447
+ // don't rl_free each element
448
+ rl_free(node->elements);
449
+ node->elements = NULL;
450
+
451
+ rl_delete(db, number);
452
+ if (retval != RL_OK) {
453
+ goto cleanup;
454
+ }
455
+ goto succeeded;
456
+ }
457
+ }
458
+ RL_CALL(rl_write, RL_OK, db, list->type->list_node_type, number, node);
459
+ }
460
+ succeeded:
461
+ retval = RL_OK;
462
+ list->size--;
463
+ if (list->size == 0) {
464
+ RL_CALL(rl_delete, RL_OK, db, list_page);
465
+ retval = RL_DELETED;
466
+ }
467
+ else {
468
+ RL_CALL(rl_write, RL_OK, db, list->type->list_type, list_page, list);
469
+ }
470
+ cleanup:
471
+ return retval;
472
+ }
473
+
474
+ int rl_list_is_balanced(rlite *db, rl_list *list)
475
+ {
476
+ rl_list_iterator *iterator;
477
+ long i = 0, number = list->left, size = 0;
478
+ long prev_size;
479
+ long max_node = (list->size / list->max_node_size + 1) * 2;
480
+ int retval = RL_OK;
481
+ long *left = NULL;
482
+ long *right;
483
+ RL_MALLOC(right, sizeof(long) * max_node);
484
+ RL_MALLOC(left, sizeof(long) * max_node);
485
+ rl_list_node *node;
486
+ void *_node;
487
+ while (number != 0) {
488
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &_node, 1);
489
+ node = _node;
490
+ size += node->size;
491
+ left[i] = node->left;
492
+ right[i] = node->right;
493
+ if (i != 0) {
494
+ if (node->size + prev_size < list->max_node_size) {
495
+ fprintf(stderr, "Two continous node could be merged\n");
496
+ retval = RL_INVALID_STATE;
497
+ goto cleanup;
498
+ }
499
+ }
500
+ if (node->size == 0) {
501
+ fprintf(stderr, "Empty node in list\n");
502
+ retval = RL_INVALID_STATE;
503
+ goto cleanup;
504
+ }
505
+ prev_size = node->size;
506
+ number = node->right;
507
+ if (i >= 2 && right[i - 2] != left[i]) {
508
+ fprintf(stderr, "Left and right pointers mismatch at position %ld\n", i);
509
+ retval = RL_INVALID_STATE;
510
+ goto cleanup;
511
+ }
512
+ i++;
513
+ }
514
+
515
+ if (size != list->size) {
516
+ fprintf(stderr, "Expected size %ld, got %ld\n", size, list->size);
517
+ retval = RL_UNEXPECTED;
518
+ goto cleanup;
519
+ }
520
+
521
+ i = 0;
522
+ retval = rl_list_iterator_create(db, &iterator, list, 1);
523
+ while ((retval = rl_list_iterator_next(iterator, NULL)) == RL_OK) {
524
+ i++;
525
+ }
526
+ if (retval != RL_END) {
527
+ goto cleanup;
528
+ }
529
+ if (i != size) {
530
+ fprintf(stderr, "Expected to iterate %ld times but only did %ld\n", size, i);
531
+ retval = RL_UNEXPECTED;
532
+ goto cleanup;
533
+ }
534
+
535
+ i = 0;
536
+ retval = rl_list_iterator_create(db, &iterator, list, -1);
537
+ while ((retval = rl_list_iterator_next(iterator, NULL)) == RL_OK) {
538
+ i++;
539
+ }
540
+ if (retval != RL_END) {
541
+ goto cleanup;
542
+ }
543
+ if (i != size) {
544
+ fprintf(stderr, "Expected to iterate %ld times but only did %ld\n", size, i);
545
+ retval = RL_UNEXPECTED;
546
+ goto cleanup;
547
+ }
548
+
549
+ retval = RL_OK;
550
+ cleanup:
551
+ rl_free(right);
552
+ rl_free(left);
553
+ return retval;
554
+ }
555
+
556
+ #ifdef DEBUG
557
+ int rl_print_list(rlite *db, rl_list *list)
558
+ {
559
+ if (!list->type->formatter) {
560
+ fprintf(stderr, "Trying to print an element without formatter\n");
561
+ return RL_UNEXPECTED;
562
+ }
563
+ printf("-------\n");
564
+ rl_list_node *node;
565
+ void *_node;
566
+ char *element;
567
+ int size;
568
+ long i, number = list->left;
569
+ int retval = RL_OK;
570
+ while (number != 0) {
571
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &_node, 1);
572
+ node = _node;
573
+ for (i = 0; i < node->size; i++) {
574
+ RL_CALL(list->type->formatter, RL_OK, node->elements[i], &element, &size);
575
+ fwrite(element, sizeof(char), size, stdout);
576
+ rl_free(element);
577
+ printf("\n");
578
+ }
579
+ number = node->right;
580
+ }
581
+ printf("-------\n");
582
+ cleanup:
583
+ return retval;
584
+ }
585
+ #endif
586
+
587
+ int rl_flatten_list(rlite *db, rl_list *list, void **scores)
588
+ {
589
+ long i, number = list->left, pos = 0;
590
+ rl_list_node *node;
591
+ void *_node;
592
+ int retval = RL_OK;
593
+ while (number != 0) {
594
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &_node, 1);
595
+ node = _node;
596
+ for (i = 0; i < node->size; i++) {
597
+ scores[pos++] = node->elements[i];
598
+ }
599
+ number = node->right;
600
+ }
601
+ retval = RL_OK;
602
+ cleanup:
603
+ return retval;
604
+ }
605
+
606
+ int rl_list_iterator_create(rlite *db, rl_list_iterator **_iterator, rl_list *list, int direction)
607
+ {
608
+ void *_node;
609
+ int retval;
610
+ rl_list_iterator *iterator = NULL;
611
+ RL_MALLOC(iterator, sizeof(*iterator));
612
+ iterator->db = db;
613
+ iterator->list = list;
614
+ if (direction < 0) {
615
+ iterator->direction = -1;
616
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, list->right, list, &_node, 0);
617
+ iterator->node = _node;
618
+ iterator->node_position = iterator->node->size - 1;
619
+ }
620
+ else {
621
+ iterator->direction = 1;
622
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, list->left, list, &_node, 0);
623
+ iterator->node = _node;
624
+ iterator->node_position = 0;
625
+ }
626
+ *_iterator = iterator;
627
+ retval = RL_OK;
628
+ cleanup:
629
+ if (retval != RL_OK) {
630
+ rl_list_iterator_destroy(db, iterator);
631
+ }
632
+ return retval;
633
+ }
634
+
635
+ int rl_list_iterator_destroy(rlite *UNUSED(db), rl_list_iterator *iterator)
636
+ {
637
+ if (iterator->node) {
638
+ rl_list_node_nocache_destroy(iterator->db, iterator->node);
639
+ }
640
+ rl_free(iterator);
641
+ return RL_OK;
642
+ }
643
+
644
+ int rl_list_iterator_next(rl_list_iterator *iterator, void **element)
645
+ {
646
+ int retval;
647
+ if (iterator->node == NULL) {
648
+ retval = RL_END;
649
+ goto cleanup;
650
+ }
651
+ if (element) {
652
+ RL_MALLOC(*element, iterator->list->type->element_size);
653
+ memcpy(*element, iterator->node->elements[iterator->node_position], iterator->list->type->element_size);
654
+ }
655
+ iterator->node_position += iterator->direction;
656
+ if (iterator->node_position < 0 || iterator->node_position == iterator->node->size) {
657
+ long next_node_page = iterator->direction == 1 ? iterator->node->right : iterator->node->left;
658
+ RL_CALL(rl_list_node_nocache_destroy, RL_OK, iterator->db, iterator->node);
659
+ iterator->node = NULL;
660
+ if (next_node_page) {
661
+ void *_node;
662
+ RL_CALL(rl_read, RL_FOUND, iterator->db, iterator->list->type->list_node_type, next_node_page, iterator->list, &_node, 0);
663
+ iterator->node = _node;
664
+ iterator->node_position = iterator->direction == 1 ? 0 : (iterator->node->size - 1);
665
+ }
666
+ }
667
+ if (iterator->node && iterator->node_position < -1) {
668
+ retval = RL_UNEXPECTED;
669
+ goto cleanup;
670
+ }
671
+ retval = RL_OK;
672
+ cleanup:
673
+ if (retval != RL_OK) {
674
+ if (iterator->node) {
675
+ rl_list_node_nocache_destroy(iterator->db, iterator->node);
676
+ }
677
+ rl_list_iterator_destroy(iterator->db, iterator);
678
+ }
679
+ return retval;
680
+ }
681
+
682
+ int rl_list_pages(struct rlite *db, rl_list *list, short *pages)
683
+ {
684
+ rl_list_node *node;
685
+ void *_node;
686
+ long number = list->left;
687
+ int retval = RL_OK;
688
+ pages[number] = 1;
689
+ while (number != 0) {
690
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &_node, 1);
691
+ node = _node;
692
+ number = node->right;
693
+ if (number) {
694
+ pages[number] = 1;
695
+ }
696
+ }
697
+ retval = RL_OK;
698
+ cleanup:
699
+ return retval;
700
+ }
701
+
702
+ int rl_list_delete(struct rlite *db, rl_list *list)
703
+ {
704
+ rl_list_node *node;
705
+ void *_node;
706
+ long number = list->left, new_number;
707
+ int retval = RL_OK;
708
+ while (number != 0) {
709
+ RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &_node, 1);
710
+ node = _node;
711
+ new_number = node->right;
712
+ RL_CALL(rl_delete, RL_OK, db, number);
713
+ number = new_number;
714
+ }
715
+ retval = RL_OK;
716
+ cleanup:
717
+ return retval;
718
+ }