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,70 @@
1
+ #ifndef _RL_PAGE_LIST_H
2
+ #define _RL_PAGE_LIST_H
3
+
4
+ struct rlite;
5
+ struct rl_list;
6
+ struct rl_list_node;
7
+
8
+ #define rl_list_nocache_destroy(db, list) rl_list_destroy(db, list)
9
+ #define rl_list_node_nocache_destroy(db, node) rl_list_node_destroy(db, node)
10
+
11
+ typedef struct {
12
+ struct rl_data_type *list_type;
13
+ struct rl_data_type *list_node_type;
14
+ int element_size;
15
+ int (*cmp)(void *v1, void *v2);
16
+ #ifdef DEBUG
17
+ int (*formatter)(void *v, char **str, int *size);
18
+ #endif
19
+ } rl_list_type;
20
+
21
+ extern rl_list_type rl_list_type_long;
22
+
23
+ typedef struct rl_list_node {
24
+ long size;
25
+ long left;
26
+ long right;
27
+ void **elements;
28
+ } rl_list_node;
29
+
30
+ typedef struct rl_list {
31
+ long max_node_size; // maximum number of elements in a node
32
+ long size;
33
+ rl_list_type *type;
34
+ long left;
35
+ long right;
36
+ } rl_list;
37
+
38
+ typedef struct rl_list_iterator {
39
+ struct rlite *db;
40
+ rl_list *list;
41
+ rl_list_node *node;
42
+ int direction; // 1 for right, -1 for left
43
+ long node_position;
44
+ } rl_list_iterator;
45
+
46
+ void rl_list_init();
47
+ int rl_list_create(struct rlite *db, rl_list **_list, rl_list_type *type);
48
+ int rl_list_destroy(struct rlite *db, void *list);
49
+ int rl_list_node_destroy(struct rlite *db, void *node);
50
+ int rl_list_get_element(struct rlite *db, rl_list *list, void **element, long position);
51
+ int rl_list_add_element(struct rlite *db, rl_list *list, long list_page, void *element, long position);
52
+ int rl_list_remove_element(struct rlite *db, rl_list *list, long list_page, long position);
53
+ int rl_list_find_element(struct rlite *db, rl_list *list, void *element, void **found_element, long *position, rl_list_node **found_node, long *found_node_page);
54
+ int rl_list_iterator_create(struct rlite *db, rl_list_iterator **iterator, rl_list *list, int direction);
55
+ int rl_list_iterator_destroy(struct rlite *db, rl_list_iterator *iterator);
56
+ int rl_list_iterator_next(rl_list_iterator *iterator, void **element);
57
+ int rl_print_list(struct rlite *db, rl_list *list);
58
+ int rl_list_is_balanced(struct rlite *db, rl_list *list);
59
+ int rl_flatten_list(struct rlite *db, rl_list *list, void **elements);
60
+
61
+ int rl_list_serialize(struct rlite *db, void *obj, unsigned char *data);
62
+ int rl_list_deserialize(struct rlite *db, void **obj, void *context, unsigned char *data);
63
+
64
+ int rl_list_node_serialize_long(struct rlite *db, void *obj, unsigned char *data);
65
+ int rl_list_node_deserialize_long(struct rlite *db, void **obj, void *context, unsigned char *data);
66
+
67
+ int rl_list_pages(struct rlite *db, rl_list *list, short *pages);
68
+ int rl_list_delete(struct rlite *db, rl_list *list);
69
+
70
+ #endif
@@ -0,0 +1,61 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+ #include "rlite.h"
4
+ #include "page_long.h"
5
+ #include "util.h"
6
+
7
+ int rl_long_serialize(rlite *UNUSED(db), void *obj, unsigned char *data)
8
+ {
9
+ put_4bytes(data, *(long *)obj);
10
+ return RL_OK;
11
+ }
12
+
13
+ int rl_long_deserialize(rlite *UNUSED(db), void **obj, void *UNUSED(context), unsigned char *data)
14
+ {
15
+ int retval;
16
+ long *value;
17
+ RL_MALLOC(value, sizeof(long));
18
+ *value = get_4bytes(data);
19
+ *obj = value;
20
+ retval = RL_OK;
21
+ cleanup:
22
+ return retval;
23
+ }
24
+
25
+ int rl_long_destroy(rlite *UNUSED(db), void *obj)
26
+ {
27
+ free(obj);
28
+ return RL_OK;
29
+ }
30
+
31
+ int rl_long_set(rlite *db, long value, long number)
32
+ {
33
+ int retval;
34
+ long *val;
35
+ RL_MALLOC(val, sizeof(*val));
36
+ *val = value;
37
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_long, number, val);
38
+
39
+ retval = RL_OK;
40
+ cleanup:
41
+ return retval;
42
+ }
43
+
44
+ int rl_long_create(struct rlite *db, long value, long *number)
45
+ {
46
+ if (number) {
47
+ *number = db->next_empty_page;
48
+ }
49
+ return rl_long_set(db, value, db->next_empty_page);
50
+ }
51
+
52
+ int rl_long_get(rlite *db, long *value, long number)
53
+ {
54
+ void *data;
55
+ int retval;
56
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_long, number, NULL, &data, 1);
57
+ *value = *(long *)data;
58
+ retval = RL_OK;
59
+ cleanup:
60
+ return retval;
61
+ }
@@ -0,0 +1,14 @@
1
+ #ifndef _RL_PAGE_LONG_H
2
+ #define _RL_PAGE_LONG_H
3
+
4
+ struct rlite;
5
+
6
+ int rl_long_serialize(struct rlite *db, void *obj, unsigned char *data);
7
+ int rl_long_deserialize(struct rlite *db, void **obj, void *context, unsigned char *data);
8
+ int rl_long_destroy(struct rlite *db, void *obj);
9
+ int rl_long_create(struct rlite *db, long value, long *number);
10
+ int rl_long_get(struct rlite *db, long *value, long number);
11
+ int rl_long_set(struct rlite *db, long value, long number);
12
+
13
+ #endif
14
+
@@ -0,0 +1,538 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+ #include "../deps/sha1.h"
4
+ #include "rlite.h"
5
+ #include "page_list.h"
6
+ #include "page_string.h"
7
+ #include "page_multi_string.h"
8
+ #include "util.h"
9
+
10
+ int rl_normalize_string_range(long totalsize, long *start, long *stop)
11
+ {
12
+ if (*start < 0) {
13
+ *start += totalsize;
14
+ if (*start < 0) {
15
+ *start = 0;
16
+ }
17
+ }
18
+ if (*stop < 0) {
19
+ *stop += totalsize;
20
+ if (*stop < 0) {
21
+ *stop = 0;
22
+ }
23
+ }
24
+ if (*start >= totalsize) {
25
+ *start = totalsize;
26
+ }
27
+ if (*stop >= totalsize) {
28
+ *stop = totalsize - 1;
29
+ }
30
+ return RL_OK;
31
+ }
32
+
33
+ int rl_multi_string_cmp(struct rlite *db, long p1, long p2, int *cmp)
34
+ {
35
+ rl_list *list1 = NULL, *list2 = NULL;
36
+ rl_list_node *node1 = NULL, *node2 = NULL;
37
+ void *_list, *_node;
38
+ unsigned char *str1, *str2;
39
+
40
+ int retval;
41
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, p1, &rl_list_type_long, &_list, 0);
42
+ list1 = _list;
43
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, p2, &rl_list_type_long, &_list, 0);
44
+ list2 = _list;
45
+
46
+ long node_number1 = list1->left, node_number2 = list2->left, i;
47
+ int first = 1;
48
+ while (1) {
49
+ if (node_number1 == 0 || node_number2 == 0) {
50
+ if (node_number1 == 0 && node_number2 == 0) {
51
+ *cmp = 0;
52
+ }
53
+ else if (node_number1 == 0) {
54
+ *cmp = -1;
55
+ }
56
+ else {
57
+ *cmp = 1;
58
+ }
59
+ retval = RL_OK;
60
+ goto cleanup;
61
+ }
62
+ RL_CALL(rl_read, RL_FOUND, db, list1->type->list_node_type, node_number1, list1, &_node, 0);
63
+ node1 = _node;
64
+ RL_CALL(rl_read, RL_FOUND, db, list2->type->list_node_type, node_number2, list2, &_node, 0);
65
+ node2 = _node;
66
+ if (first) {
67
+ if (*(long *)node1->elements[0] == 0) {
68
+ *cmp = -1;
69
+ retval = RL_OK;
70
+ goto cleanup;
71
+ }
72
+ if (*(long *)node2->elements[0] == 0) {
73
+ *cmp = 1;
74
+ retval = RL_OK;
75
+ goto cleanup;
76
+ }
77
+ }
78
+ for (i = first ? 1 : 0; i < node1->size; i++) {
79
+ first = 0;
80
+ RL_CALL(rl_string_get, RL_OK, db, &str1, *(long *)node1->elements[i]);
81
+ RL_CALL(rl_string_get, RL_OK, db, &str2, *(long *)node2->elements[i]);
82
+ *cmp = memcmp(str1, str2, db->page_size);
83
+ if (*cmp != 0) {
84
+ if (*cmp < 0) {
85
+ *cmp = -1;
86
+ }
87
+ else {
88
+ *cmp = 1;
89
+ }
90
+ goto cleanup;
91
+ }
92
+ }
93
+ node_number1 = node1->right;
94
+ node_number2 = node2->right;
95
+ rl_list_node_nocache_destroy(db, node1);
96
+ rl_list_node_nocache_destroy(db, node2);
97
+ node1 = node2 = NULL;
98
+ }
99
+ cleanup:
100
+ rl_list_nocache_destroy(db, list1);
101
+ rl_list_nocache_destroy(db, list2);
102
+ if (node1) {
103
+ rl_list_node_nocache_destroy(db, node1);
104
+ }
105
+ if (node2) {
106
+ rl_list_node_nocache_destroy(db, node2);
107
+ }
108
+ return retval;
109
+ }
110
+
111
+ int rl_multi_string_cmp_str(struct rlite *db, long p1, unsigned char *str, long len, int *cmp)
112
+ {
113
+ rl_list *list1 = NULL;
114
+ rl_list_node *node1 = NULL;
115
+ void *_list, *_node;
116
+ unsigned char *str1;
117
+
118
+ int retval;
119
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, p1, &rl_list_type_long, &_list, 0);
120
+ list1 = _list;
121
+
122
+ long node_number1 = list1->left, i, pos = 0;
123
+ int first = 1;
124
+ long cmplen;
125
+ long stored_length = 0;
126
+ *cmp = 0;
127
+ do {
128
+ if (node_number1 == 0) {
129
+ *cmp = len == 0 ? 0 : -1;
130
+ break;
131
+ }
132
+ RL_CALL(rl_read, RL_FOUND, db, list1->type->list_node_type, node_number1, list1, &_node, 0);
133
+ node1 = _node;
134
+ if (first) {
135
+ stored_length = *(long *)node1->elements[0];
136
+ if (stored_length == 0) {
137
+ *cmp = len == 0 ? 0 : -1;
138
+ }
139
+ }
140
+ for (i = first ? 1 : 0; i < node1->size; i++) {
141
+ RL_CALL(rl_string_get, RL_OK, db, &str1, *(long *)node1->elements[i]);
142
+ cmplen = db->page_size < len - pos ? db->page_size : len - pos;
143
+ if (cmplen == 0) {
144
+ // finished with str, the page_multi_string starts with str
145
+ *cmp = 1;
146
+ break;
147
+ }
148
+ *cmp = memcmp(str1, &str[pos], cmplen);
149
+ if (*cmp != 0) {
150
+ if (*cmp < 0) {
151
+ *cmp = -1;
152
+ }
153
+ else {
154
+ *cmp = 1;
155
+ }
156
+ goto cleanup;
157
+ }
158
+ pos += cmplen;
159
+ }
160
+ if (*cmp == 0 && len == pos && stored_length != len) {
161
+ *cmp = stored_length > len ? 1 : -1;
162
+ }
163
+ first = 0;
164
+ node_number1 = node1->right;
165
+ rl_list_node_nocache_destroy(db, node1);
166
+ node1 = NULL;
167
+ }
168
+ while (len > pos);
169
+ retval = RL_OK;
170
+ cleanup:
171
+ rl_list_nocache_destroy(db, list1);
172
+ if (node1) {
173
+ rl_list_node_nocache_destroy(db, node1);
174
+ }
175
+ return retval;
176
+ }
177
+
178
+ static int append(struct rlite *db, rl_list *list, long list_page_number, const unsigned char *data, long size)
179
+ {
180
+ int retval = RL_OK;
181
+ long *page;
182
+ long pos = 0, to_copy;
183
+ unsigned char *string = NULL;
184
+ while (pos < size) {
185
+ RL_MALLOC(page, sizeof(*page));
186
+ retval = rl_string_create(db, &string, page);
187
+ if (retval != RL_OK) {
188
+ goto cleanup;
189
+ }
190
+ to_copy = db->page_size;
191
+ if (pos + to_copy > size) {
192
+ to_copy = size - pos;
193
+ }
194
+ memcpy(string, &data[pos], sizeof(unsigned char) * to_copy);
195
+ string = NULL;
196
+ RL_CALL(rl_list_add_element, RL_OK, db, list, list_page_number, page, -1);
197
+ page = NULL;
198
+ pos += to_copy;
199
+ }
200
+ cleanup:
201
+ rl_free(string);
202
+ rl_free(page);
203
+ return retval;
204
+ }
205
+
206
+ int rl_multi_string_append(struct rlite *db, long number, const unsigned char *data, long datasize, long *newlength)
207
+ {
208
+ rl_list *list = NULL;
209
+ unsigned char *tmp_data;
210
+ void *tmp;
211
+ int retval;
212
+ long size, cpsize;
213
+ long string_page_number;
214
+
215
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &tmp, 0);
216
+ list = tmp;
217
+
218
+ RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, 0);
219
+ size = *(long *)tmp;
220
+ RL_MALLOC(tmp, sizeof(long));
221
+ *(long *)tmp = size + datasize;
222
+ RL_CALL(rl_list_add_element, RL_OK, db, list, number, tmp, 0);
223
+ RL_CALL(rl_list_remove_element, RL_OK, db, list, number, 1);
224
+ if (newlength) {
225
+ *newlength = size + datasize;
226
+ }
227
+
228
+ size = size % db->page_size;
229
+
230
+ if (size > 0) {
231
+ RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, -1);
232
+ string_page_number = *(long *)tmp;
233
+ RL_CALL(rl_string_get, RL_OK, db, &tmp_data, string_page_number);
234
+ cpsize = db->page_size - size;
235
+ if (cpsize > datasize) {
236
+ cpsize = datasize;
237
+ }
238
+ memcpy(&tmp_data[size], data, cpsize * sizeof(unsigned char));
239
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_string, string_page_number, tmp_data);
240
+ data = &data[cpsize];
241
+ datasize -= cpsize;
242
+ }
243
+
244
+ if (datasize > 0) {
245
+ RL_CALL(append, RL_OK, db, list, number, data, datasize);
246
+ }
247
+
248
+ retval = RL_OK;
249
+ cleanup:
250
+ return retval;
251
+ }
252
+
253
+ int rl_multi_string_getrange(struct rlite *db, long number, unsigned char **_data, long *size, long start, long stop)
254
+ {
255
+ long totalsize;
256
+ rl_list *list = NULL;
257
+ rl_list_node *node = NULL;
258
+ void *_list, *tmp;
259
+ unsigned char *data = NULL;
260
+ int retval;
261
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &_list, 0);
262
+ list = _list;
263
+ unsigned char *tmp_data;
264
+ long i, pos = 0, pagesize, pagestart;
265
+
266
+ RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, 0);
267
+ totalsize = *(long *)tmp;
268
+ if (totalsize == 0) {
269
+ *size = 0;
270
+ if (_data) {
271
+ *_data = NULL;
272
+ }
273
+ retval = RL_OK;
274
+ goto cleanup;
275
+ }
276
+ rl_normalize_string_range(totalsize, &start, &stop);
277
+ if (stop < start) {
278
+ *size = 0;
279
+ if (_data) {
280
+ *_data = NULL;
281
+ }
282
+ retval = RL_OK;
283
+ goto cleanup;
284
+ }
285
+ *size = stop - start + 1;
286
+ if (!_data) {
287
+ retval = RL_OK;
288
+ goto cleanup;
289
+ }
290
+
291
+ RL_MALLOC(data, sizeof(unsigned char) * (*size + 1));
292
+
293
+ i = start / db->page_size;
294
+ pagestart = start % db->page_size;
295
+ // pos = i * db->page_size + pagestart;
296
+ // the first element in the list is the length of the array, skip to the second
297
+ for (i++; i < list->size; i++) {
298
+ RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, i);
299
+ RL_CALL(rl_string_get, RL_OK, db, &tmp_data, *(long *)tmp);
300
+ pagesize = db->page_size - pagestart;
301
+ if (pos + pagesize > *size) {
302
+ pagesize = *size - pos;
303
+ }
304
+ memcpy(&data[pos], &tmp_data[pagestart], sizeof(unsigned char) * pagesize);
305
+ pos += pagesize;
306
+ pagestart = 0;
307
+ }
308
+ data[*size] = 0;
309
+ *_data = data;
310
+ retval = RL_OK;
311
+ cleanup:
312
+ if (retval != RL_OK) {
313
+ rl_free(data);
314
+ }
315
+ if (list) {
316
+ rl_list_nocache_destroy(db, list);
317
+ }
318
+ if (node) {
319
+ rl_list_node_nocache_destroy(db, node);
320
+ }
321
+ return retval;
322
+ }
323
+
324
+ int rl_multi_string_get(struct rlite *db, long number, unsigned char **_data, long *size)
325
+ {
326
+ return rl_multi_string_getrange(db, number, _data, size, 0, -1);
327
+ }
328
+
329
+ int rl_multi_string_set(struct rlite *db, long *number, const unsigned char *data, long size)
330
+ {
331
+ int retval;
332
+ long *page = NULL;
333
+ rl_list *list = NULL;
334
+ RL_CALL(rl_list_create, RL_OK, db, &list, &rl_list_type_long);
335
+ *number = db->next_empty_page;
336
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_list_long, *number, list);
337
+ RL_MALLOC(page, sizeof(*page));
338
+ *page = size;
339
+ RL_CALL(rl_list_add_element, RL_OK, db, list, *number, page, -1);
340
+ page = NULL;
341
+ RL_CALL(append, RL_OK, db, list, *number, data, size);
342
+ cleanup:
343
+ return retval;
344
+ }
345
+ int rl_multi_string_setrange(struct rlite *db, long number, const unsigned char *data, long size, long offset, long *newlength)
346
+ {
347
+ long oldsize, newsize;
348
+ rl_list *list = NULL;
349
+ void *_list, *tmp;
350
+ int retval;
351
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &_list, 1);
352
+ list = _list;
353
+ unsigned char *tmp_data;
354
+ long i, pagesize, pagestart, page;
355
+ if (offset < 0) {
356
+ retval = RL_INVALID_PARAMETERS;
357
+ goto cleanup;
358
+ }
359
+
360
+ RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, 0);
361
+ oldsize = *(long *)tmp;
362
+ if (oldsize > offset) {
363
+ i = offset / db->page_size;
364
+ pagestart = offset % db->page_size;
365
+
366
+ newsize = offset + size;
367
+ if (newsize > (list->size - 1) * db->page_size) {
368
+ newsize = (list->size - 1) * db->page_size;
369
+ }
370
+ if (newsize > oldsize) {
371
+ RL_CALL(rl_list_remove_element, RL_OK, db, list, number, 0);
372
+ RL_MALLOC(tmp, sizeof(long));
373
+ *(long *)tmp = newsize;
374
+ RL_CALL(rl_list_add_element, RL_OK, db, list, number, tmp, 0);
375
+ }
376
+
377
+ for (i++; size > 0 && i < list->size; i++) {
378
+ RL_CALL(rl_list_get_element, RL_FOUND, db, list, &tmp, i);
379
+ page = *(long *)tmp;
380
+ RL_CALL(rl_string_get, RL_OK, db, &tmp_data, page);
381
+ pagesize = db->page_size - pagestart;
382
+ if (pagesize > size) {
383
+ pagesize = size;
384
+ }
385
+ memcpy(&tmp_data[pagestart], data, sizeof(char) * pagesize);
386
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_string, page, tmp_data);
387
+
388
+ // if there's more bytes that did not enter in this page it will be caught with an append
389
+ if (oldsize < pagesize + pagestart) {
390
+ oldsize = pagesize + pagestart;
391
+ }
392
+ data += pagesize;
393
+ offset += pagesize;
394
+ size -= pagesize;
395
+ pagestart = 0;
396
+ }
397
+ if (newlength) {
398
+ *newlength = oldsize;
399
+ }
400
+ }
401
+
402
+ if (oldsize < offset) {
403
+ RL_MALLOC(tmp_data, sizeof(char) * (size + offset - oldsize));
404
+ memset(tmp_data, 0, offset - oldsize);
405
+ memcpy(&tmp_data[offset - oldsize], data, sizeof(char) * size);
406
+ RL_CALL(rl_multi_string_append, RL_OK, db, number, tmp_data, size + offset - oldsize, newlength);
407
+ rl_free(tmp_data);
408
+ }
409
+ else if (oldsize == offset && size > 0) {
410
+ RL_CALL(rl_multi_string_append, RL_OK, db, number, data, size, newlength);
411
+ }
412
+ retval = RL_OK;
413
+ cleanup:
414
+ return retval;
415
+ }
416
+
417
+
418
+ int rl_multi_string_sha1(struct rlite *db, unsigned char digest[20], long number)
419
+ {
420
+ unsigned char *data;
421
+ long datalen;
422
+ SHA1_CTX sha;
423
+ SHA1Init(&sha);
424
+
425
+ void *tmp;
426
+ rl_list *list;
427
+ rl_list_iterator *iterator = NULL;
428
+ int retval;
429
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &tmp, 0);
430
+ list = tmp;
431
+
432
+ RL_CALL(rl_list_iterator_create, RL_OK, db, &iterator, list, 1);
433
+
434
+ long size = 0;
435
+ while ((retval = rl_list_iterator_next(iterator, &tmp)) == RL_OK) {
436
+ if (size == 0) {
437
+ size = *(long *)tmp;
438
+ rl_free(tmp);
439
+ continue;
440
+ }
441
+ RL_CALL(rl_string_get, RL_OK, db, &data, *(long *)tmp);
442
+ datalen = size > db->page_size ? db->page_size : size;
443
+ SHA1Update(&sha, data, datalen);
444
+ size -= datalen;
445
+ rl_free(tmp);
446
+ }
447
+ iterator = NULL;
448
+
449
+ if (retval != RL_END) {
450
+ goto cleanup;
451
+ }
452
+
453
+ RL_CALL(rl_list_nocache_destroy, RL_OK, db, list);
454
+
455
+ SHA1Final(digest, &sha);
456
+ retval = RL_OK;
457
+ cleanup:
458
+ if (iterator) {
459
+ rl_list_iterator_destroy(db, iterator);
460
+ }
461
+ return retval;
462
+ }
463
+
464
+ int rl_multi_string_pages(struct rlite *db, long page, short *pages)
465
+ {
466
+ void *tmp;
467
+ rl_list *list;
468
+ rl_list_iterator *iterator = NULL;
469
+ int retval;
470
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, page, &rl_list_type_long, &tmp, 0);
471
+ list = tmp;
472
+
473
+ RL_CALL(rl_list_pages, RL_OK, db, list, pages);
474
+ RL_CALL(rl_list_iterator_create, RL_OK, db, &iterator, list, 1);
475
+
476
+ int first = 1;
477
+ while ((retval = rl_list_iterator_next(iterator, &tmp)) == RL_OK) {
478
+ if (first) {
479
+ first = 0;
480
+ }
481
+ else {
482
+ pages[*(long *)tmp] = 1;
483
+ }
484
+ rl_free(tmp);
485
+ }
486
+ iterator = NULL;
487
+
488
+ if (retval != RL_END) {
489
+ goto cleanup;
490
+ }
491
+
492
+ RL_CALL(rl_list_nocache_destroy, RL_OK, db, list);
493
+
494
+ retval = RL_OK;
495
+ cleanup:
496
+ if (iterator) {
497
+ rl_list_iterator_destroy(db, iterator);
498
+ }
499
+ return retval;
500
+ }
501
+
502
+ int rl_multi_string_delete(struct rlite *db, long page)
503
+ {
504
+ void *tmp;
505
+ rl_list *list;
506
+ rl_list_iterator *iterator = NULL;
507
+ int retval;
508
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, page, &rl_list_type_long, &tmp, 1);
509
+ list = tmp;
510
+
511
+ RL_CALL(rl_list_iterator_create, RL_OK, db, &iterator, list, 1);
512
+
513
+ int first = 1;
514
+ while ((retval = rl_list_iterator_next(iterator, &tmp)) == RL_OK) {
515
+ if (first) {
516
+ first = 0;
517
+ }
518
+ else {
519
+ RL_CALL(rl_delete, RL_OK, db, *(long *)tmp);
520
+ }
521
+ rl_free(tmp);
522
+ }
523
+ iterator = NULL;
524
+
525
+ if (retval != RL_END) {
526
+ goto cleanup;
527
+ }
528
+
529
+ RL_CALL(rl_list_delete, RL_OK, db, list);
530
+ RL_CALL(rl_delete, RL_OK, db, page);
531
+
532
+ retval = RL_OK;
533
+ cleanup:
534
+ if (iterator) {
535
+ rl_list_iterator_destroy(db, iterator);
536
+ }
537
+ return retval;
538
+ }
@@ -0,0 +1,18 @@
1
+ #ifndef _RL_OBJ_STRING_H
2
+ #define _RL_OBJ_STRING_H
3
+
4
+ struct rlite;
5
+
6
+ int rl_normalize_string_range(long totalsize, long *start, long *stop);
7
+ int rl_multi_string_cmp(struct rlite *db, long p1, long p2, int *cmp);
8
+ int rl_multi_string_cmp_str(struct rlite *db, long p1, unsigned char *str, long len, int *cmp);
9
+ int rl_multi_string_getrange(struct rlite *db, long number, unsigned char **_data, long *size, long start, long stop);
10
+ int rl_multi_string_get(struct rlite *db, long number, unsigned char **data, long *size);
11
+ int rl_multi_string_setrange(struct rlite *db, long number, const unsigned char *data, long size, long offset, long *newlength);
12
+ int rl_multi_string_set(struct rlite *db, long *number, const unsigned char *data, long size);
13
+ int rl_multi_string_append(struct rlite *db, long number, const unsigned char *data, long datasize, long *newlength);
14
+ int rl_multi_string_sha1(struct rlite *db, unsigned char data[20], long number);
15
+ int rl_multi_string_pages(struct rlite *db, long page, short *pages);
16
+ int rl_multi_string_delete(struct rlite *db, long page);
17
+
18
+ #endif