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,19 @@
1
+ #ifndef _RL_STATUS_H
2
+ #define _RL_STATUS_H
3
+
4
+ #define RL_OK 0
5
+ #define RL_INVALID_STATE 1
6
+ #define RL_FOUND 2
7
+ #define RL_NOT_FOUND 3
8
+ #define RL_OUT_OF_MEMORY 4
9
+ #define RL_INVALID_PARAMETERS 5
10
+ #define RL_UNEXPECTED 6
11
+ #define RL_NOT_IMPLEMENTED 7
12
+ #define RL_WRONG_TYPE 8
13
+ #define RL_END 9
14
+ #define RL_DELETED 10
15
+ #define RL_NAN 11
16
+ #define RL_OVERFLOW 12
17
+ #define RL_OUTDATED 13
18
+
19
+ #endif
@@ -0,0 +1,607 @@
1
+ #include <float.h>
2
+ #include <ctype.h>
3
+ #include <errno.h>
4
+ #include <math.h>
5
+ #include <stdlib.h>
6
+ #include "rlite.h"
7
+ #include "page_multi_string.h"
8
+ #include "type_hash.h"
9
+ #include "page_btree.h"
10
+ #include "util.h"
11
+
12
+ static int rl_hash_create(rlite *db, long btree_page, rl_btree **btree)
13
+ {
14
+ rl_btree *hash = NULL;
15
+
16
+ int retval;
17
+ RL_CALL(rl_btree_create, RL_OK, db, &hash, &rl_btree_type_hash_sha1_hashkey);
18
+ RL_CALL(rl_write, RL_OK, db, &rl_data_type_btree_hash_sha1_hashkey, btree_page, hash);
19
+
20
+ if (btree) {
21
+ *btree = hash;
22
+ }
23
+ cleanup:
24
+ return retval;
25
+ }
26
+
27
+ static int rl_hash_read(rlite *db, long hash_page_number, rl_btree **btree)
28
+ {
29
+ void *tmp;
30
+ int retval;
31
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_btree_hash_sha1_hashkey, hash_page_number, &rl_btree_type_hash_sha1_hashkey, &tmp, 1);
32
+ *btree = tmp;
33
+ retval = RL_OK;
34
+ cleanup:
35
+ return retval;
36
+ }
37
+
38
+ static int rl_hash_get_objects(rlite *db, const unsigned char *key, long keylen, long *_hash_page_number, rl_btree **btree, int update_version, int create)
39
+ {
40
+ long hash_page_number = 0, version = 0;
41
+ int retval;
42
+ unsigned long long expires = 0;
43
+ if (create) {
44
+ retval = rl_key_get_or_create(db, key, keylen, RL_TYPE_HASH, &hash_page_number, &version);
45
+ if (retval != RL_FOUND && retval != RL_NOT_FOUND) {
46
+ goto cleanup;
47
+ }
48
+ else if (retval == RL_NOT_FOUND) {
49
+ retval = rl_hash_create(db, hash_page_number, btree);
50
+ goto cleanup;
51
+ }
52
+ else {
53
+ RL_CALL(rl_hash_read, RL_OK, db, hash_page_number, btree);
54
+ }
55
+ }
56
+ else {
57
+ unsigned char type;
58
+ retval = rl_key_get(db, key, keylen, &type, NULL, &hash_page_number, &expires, &version);
59
+ if (retval != RL_FOUND) {
60
+ goto cleanup;
61
+ }
62
+ if (type != RL_TYPE_HASH) {
63
+ retval = RL_WRONG_TYPE;
64
+ goto cleanup;
65
+ }
66
+ RL_CALL(rl_hash_read, RL_OK, db, hash_page_number, btree);
67
+ }
68
+ if (update_version) {
69
+ RL_CALL(rl_key_set, RL_OK, db, key, keylen, RL_TYPE_HASH, hash_page_number, expires, version + 1);
70
+ }
71
+ cleanup:
72
+ if (_hash_page_number) {
73
+ *_hash_page_number = hash_page_number;
74
+ }
75
+ return retval;
76
+ }
77
+
78
+ int rl_hset(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen, unsigned char *data, long datalen, long *added, int update)
79
+ {
80
+ int retval;
81
+ long hash_page_number;
82
+ rl_btree *hash;
83
+ unsigned char *digest = NULL;
84
+ rl_hashkey *hashkey = NULL;
85
+ long add = 1;
86
+ void *tmp;
87
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, &hash_page_number, &hash, 1, 1);
88
+
89
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
90
+ RL_CALL(sha1, RL_OK, field, fieldlen, digest);
91
+
92
+ retval = rl_btree_find_score(db, hash, digest, &tmp, NULL, NULL);
93
+ if (retval == RL_FOUND) {
94
+ add = 0;
95
+ if (!update) {
96
+ goto cleanup;
97
+ }
98
+ hashkey = tmp;
99
+ rl_multi_string_delete(db, hashkey->string_page);
100
+ rl_multi_string_delete(db, hashkey->value_page);
101
+ }
102
+
103
+ RL_MALLOC(hashkey, sizeof(*hashkey));
104
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->string_page, field, fieldlen);
105
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->value_page, data, datalen);
106
+ if (update) {
107
+ retval = rl_btree_update_element(db, hash, digest, hashkey);
108
+ if (retval == RL_OK) {
109
+ add = 0;
110
+ rl_free(digest);
111
+ digest = NULL;
112
+ }
113
+ else if (retval != RL_NOT_FOUND) {
114
+ goto cleanup;
115
+ }
116
+ }
117
+ if (add) {
118
+ retval = rl_btree_add_element(db, hash, hash_page_number, digest, hashkey);
119
+ if (retval == RL_FOUND) {
120
+ add = 0;
121
+ }
122
+ if (retval != RL_OK) {
123
+ goto cleanup;
124
+ }
125
+ }
126
+ retval = RL_OK;
127
+ cleanup:
128
+ if (added) {
129
+ *added = add;
130
+ }
131
+ if (retval != RL_OK) {
132
+ rl_free(digest);
133
+ rl_free(hashkey);
134
+ }
135
+ return retval;
136
+ }
137
+
138
+ int rl_hget(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen, unsigned char **data, long *datalen)
139
+ {
140
+ int retval;
141
+ long hash_page_number;
142
+ rl_btree *hash;
143
+ void *tmp;
144
+ unsigned char *digest = NULL;
145
+ rl_hashkey *hashkey;
146
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, &hash_page_number, &hash, 0, 0);
147
+
148
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
149
+ RL_CALL(sha1, RL_OK, field, fieldlen, digest);
150
+
151
+ retval = rl_btree_find_score(db, hash, digest, &tmp, NULL, NULL);
152
+ if (retval == RL_FOUND) {
153
+ if (data || datalen) {
154
+ hashkey = tmp;
155
+ rl_multi_string_get(db, hashkey->value_page, data, datalen);
156
+ }
157
+ }
158
+ cleanup:
159
+ rl_free(digest);
160
+ return retval;
161
+ }
162
+
163
+ int rl_hmget(struct rlite *db, const unsigned char *key, long keylen, int fieldc, unsigned char **fields, long *fieldslen, unsigned char ***_data, long **_datalen)
164
+ {
165
+ int retval;
166
+ long hash_page_number;
167
+ rl_btree *hash;
168
+ void *tmp;
169
+ unsigned char *digest = NULL;
170
+ rl_hashkey *hashkey;
171
+
172
+ unsigned char **data = malloc(sizeof(unsigned char *) * fieldc);
173
+ long *datalen = malloc(sizeof(long) * fieldc);
174
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, &hash_page_number, &hash, 0, 0);
175
+
176
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
177
+ int i;
178
+ for (i = 0; i < fieldc; i++) {
179
+ RL_CALL(sha1, RL_OK, fields[i], fieldslen[i], digest);
180
+
181
+ retval = rl_btree_find_score(db, hash, digest, &tmp, NULL, NULL);
182
+ if (retval == RL_FOUND) {
183
+ hashkey = tmp;
184
+ rl_multi_string_get(db, hashkey->value_page, &data[i], &datalen[i]);
185
+ }
186
+ else if (retval == RL_NOT_FOUND) {
187
+ data[i] = NULL;
188
+ datalen[i] = -1;
189
+ }
190
+ else {
191
+ goto cleanup;
192
+ }
193
+ }
194
+ *_data = data;
195
+ *_datalen = datalen;
196
+ retval = RL_OK;
197
+ cleanup:
198
+ if (retval != RL_OK) {
199
+ rl_free(data);
200
+ rl_free(datalen);
201
+ }
202
+ rl_free(digest);
203
+ return retval;
204
+ }
205
+
206
+ int rl_hmset(struct rlite *db, const unsigned char *key, long keylen, int fieldc, unsigned char **fields, long *fieldslen, unsigned char **datas, long *dataslen)
207
+ {
208
+ int i, retval;
209
+ long hash_page_number;
210
+ rl_btree *hash;
211
+ unsigned char *digest = NULL;
212
+ rl_hashkey *hashkey = NULL;
213
+ void *tmp;
214
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, &hash_page_number, &hash, 1, 1);
215
+
216
+ for (i = 0; i < fieldc; i++) {
217
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
218
+ RL_CALL(sha1, RL_OK, fields[i], fieldslen[i], digest);
219
+
220
+ retval = rl_btree_find_score(db, hash, digest, &tmp, NULL, NULL);
221
+ if (retval == RL_FOUND) {
222
+ hashkey = tmp;
223
+ rl_multi_string_delete(db, hashkey->value_page);
224
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->value_page, datas[i], dataslen[i]);
225
+ retval = rl_btree_update_element(db, hash, digest, hashkey);
226
+ if (retval == RL_OK) {
227
+ rl_free(digest);
228
+ digest = NULL;
229
+ }
230
+ else {
231
+ goto cleanup;
232
+ }
233
+ }
234
+ else if (retval == RL_NOT_FOUND) {
235
+ RL_MALLOC(hashkey, sizeof(*hashkey));
236
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->string_page, fields[i], fieldslen[i]);
237
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->value_page, datas[i], dataslen[i]);
238
+
239
+ retval = rl_btree_add_element(db, hash, hash_page_number, digest, hashkey);
240
+ if (retval != RL_FOUND && retval != RL_OK) {
241
+ goto cleanup;
242
+ }
243
+ }
244
+ }
245
+ retval = RL_OK;
246
+ cleanup:
247
+ if (retval != RL_OK) {
248
+ rl_free(digest);
249
+ rl_free(hashkey);
250
+ }
251
+ return retval;
252
+ }
253
+
254
+ int rl_hexists(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen)
255
+ {
256
+ int retval;
257
+ long hash_page_number;
258
+ rl_btree *hash;
259
+ unsigned char *digest = NULL;
260
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, &hash_page_number, &hash, 0, 0);
261
+
262
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
263
+ RL_CALL(sha1, RL_OK, field, fieldlen, digest);
264
+
265
+ retval = rl_btree_find_score(db, hash, digest, NULL, NULL, NULL);
266
+ cleanup:
267
+ rl_free(digest);
268
+ return retval;
269
+ }
270
+
271
+ int rl_hdel(struct rlite *db, const unsigned char *key, long keylen, long fieldsc, unsigned char **fields, long *fieldslen, long *delcount)
272
+ {
273
+ int retval;
274
+ long hash_page_number;
275
+ rl_btree *hash;
276
+ rl_hashkey *hashkey;
277
+ void *tmp;
278
+ long i;
279
+ long deleted = 0;
280
+ int keydeleted = 0;
281
+ unsigned char *digest = NULL;
282
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, &hash_page_number, &hash, 1, 0);
283
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
284
+
285
+ for (i = 0; i < fieldsc; i++) {
286
+ RL_CALL(sha1, RL_OK, fields[i], fieldslen[i], digest);
287
+ retval = rl_btree_find_score(db, hash, digest, &tmp, NULL, NULL);
288
+ if (retval == RL_FOUND) {
289
+ deleted++;
290
+ hashkey = tmp;
291
+ rl_multi_string_delete(db, hashkey->string_page);
292
+ rl_multi_string_delete(db, hashkey->value_page);
293
+ retval = rl_btree_remove_element(db, hash, hash_page_number, digest);
294
+ if (retval != RL_OK && retval != RL_DELETED) {
295
+ goto cleanup;
296
+ }
297
+ if (retval == RL_DELETED) {
298
+ keydeleted = 1;
299
+ break;
300
+ }
301
+ }
302
+ }
303
+ if (delcount) {
304
+ *delcount = deleted;
305
+ }
306
+ if (keydeleted) {
307
+ RL_CALL(rl_key_delete, RL_OK, db, key, keylen);
308
+ }
309
+ retval = RL_OK;
310
+ cleanup:
311
+ rl_free(digest);
312
+ return retval;
313
+ }
314
+
315
+ int rl_hgetall(struct rlite *db, rl_hash_iterator **iterator, const unsigned char *key, long keylen)
316
+ {
317
+ int retval;
318
+ rl_btree *hash;
319
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, NULL, &hash, 0, 0);
320
+ RL_CALL(rl_btree_iterator_create, RL_OK, db, hash, iterator);
321
+ cleanup:
322
+ return retval;
323
+ }
324
+
325
+ int rl_hlen(struct rlite *db, const unsigned char *key, long keylen, long *len)
326
+ {
327
+ int retval;
328
+ rl_btree *hash;
329
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, NULL, &hash, 0, 0);
330
+ *len = hash->number_of_elements;
331
+ retval = RL_OK;
332
+ cleanup:
333
+ return retval;
334
+ }
335
+
336
+ int rl_hincrby(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen, long increment, long *newvalue)
337
+ {
338
+ int retval;
339
+ rl_btree *hash;
340
+ void *tmp;
341
+ unsigned char *digest = NULL, *data = NULL;
342
+ char *end;
343
+ long datalen, hash_page_number;
344
+ long long value;
345
+ rl_hashkey *hashkey;
346
+
347
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, &hash_page_number, &hash, 1, 1);
348
+
349
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
350
+ RL_CALL(sha1, RL_OK, field, fieldlen, digest);
351
+
352
+ retval = rl_btree_find_score(db, hash, digest, &tmp, NULL, NULL);
353
+ if (retval == RL_FOUND) {
354
+ hashkey = tmp;
355
+ rl_multi_string_get(db, hashkey->value_page, &data, &datalen);
356
+ tmp = realloc(data, sizeof(unsigned char) * (datalen + 1));
357
+ if (!tmp) {
358
+ retval = RL_OUT_OF_MEMORY;
359
+ goto cleanup;
360
+ }
361
+ data = tmp;
362
+ data[datalen] = '\0';
363
+ value = strtoll((char *)data, &end, 10);
364
+ if (isspace(((char *)data)[0]) || end[0] != '\0' || errno == ERANGE) {
365
+ rl_free(digest);
366
+ retval = RL_NAN;
367
+ goto cleanup;
368
+ }
369
+ rl_free(data);
370
+ data = NULL;
371
+
372
+ if ((increment < 0 && value < 0 && increment < (LLONG_MIN - value)) ||
373
+ (increment > 0 && value > 0 && increment > (LLONG_MAX - value))) {
374
+ rl_free(digest);
375
+ retval = RL_OVERFLOW;
376
+ goto cleanup;
377
+ }
378
+
379
+ value += increment;
380
+ rl_multi_string_delete(db, hashkey->value_page);
381
+
382
+ RL_MALLOC(data, sizeof(unsigned char) * MAX_LLONG_DIGITS);
383
+ datalen = snprintf((char *)data, MAX_LLONG_DIGITS, "%lld", value);
384
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->value_page, data, datalen);
385
+
386
+ retval = rl_btree_update_element(db, hash, digest, hashkey);
387
+ if (retval == RL_OK) {
388
+ rl_free(digest);
389
+ digest = NULL;
390
+ if (newvalue) {
391
+ *newvalue = value;
392
+ }
393
+ }
394
+ else if (retval != RL_NOT_FOUND) {
395
+ goto cleanup;
396
+ }
397
+ }
398
+ else if (retval == RL_NOT_FOUND) {
399
+ RL_MALLOC(data, sizeof(unsigned char) * MAX_LLONG_DIGITS);
400
+ datalen = snprintf((char *)data, MAX_LLONG_DIGITS, "%ld", increment);
401
+
402
+ RL_MALLOC(hashkey, sizeof(*hashkey));
403
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->string_page, field, fieldlen);
404
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->value_page, data, datalen);
405
+ RL_CALL(rl_btree_add_element, RL_OK, db, hash, hash_page_number, digest, hashkey);
406
+ if (newvalue) {
407
+ *newvalue = increment;
408
+ }
409
+ }
410
+ else {
411
+ goto cleanup;
412
+ }
413
+
414
+ retval = RL_OK;
415
+ cleanup:
416
+ rl_free(data);
417
+ return retval;
418
+ }
419
+
420
+ int rl_hincrbyfloat(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen, double increment, double *newvalue)
421
+ {
422
+ int retval;
423
+ rl_btree *hash;
424
+ void *tmp;
425
+ unsigned char *digest = NULL, *data = NULL;
426
+ char *end;
427
+ long dataalloc, datalen, hash_page_number;
428
+ double value;
429
+ rl_hashkey *hashkey;
430
+
431
+ RL_CALL(rl_hash_get_objects, RL_OK, db, key, keylen, &hash_page_number, &hash, 1, 1);
432
+
433
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
434
+ RL_CALL(sha1, RL_OK, field, fieldlen, digest);
435
+
436
+ retval = rl_btree_find_score(db, hash, digest, &tmp, NULL, NULL);
437
+ if (retval == RL_FOUND) {
438
+ hashkey = tmp;
439
+ rl_multi_string_get(db, hashkey->value_page, &data, &datalen);
440
+ dataalloc = (datalen / 8 + 1) * 8;
441
+ tmp = realloc(data, sizeof(unsigned char) * dataalloc);
442
+ if (!tmp) {
443
+ retval = RL_OUT_OF_MEMORY;
444
+ goto cleanup;
445
+ }
446
+ data = tmp;
447
+ // valgrind reads 8 bytes at a time
448
+ memset(&data[datalen], 0, dataalloc - datalen);
449
+ value = strtod((char *)data, &end);
450
+ if (isspace(((char *)data)[0]) || end[0] != '\0' ||
451
+ (errno == ERANGE && (value == HUGE_VAL || value == -HUGE_VAL || value == 0)) ||
452
+ errno == EINVAL || isnan(value)) {
453
+ rl_free(digest);
454
+ retval = RL_NAN;
455
+ goto cleanup;
456
+ }
457
+ rl_free(data);
458
+ data = NULL;
459
+ value += increment;
460
+ rl_multi_string_delete(db, hashkey->value_page);
461
+
462
+ RL_MALLOC(data, sizeof(unsigned char) * MAX_DOUBLE_DIGITS);
463
+ datalen = snprintf((char *)data, MAX_DOUBLE_DIGITS, "%lf", value);
464
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->value_page, data, datalen);
465
+
466
+ retval = rl_btree_update_element(db, hash, digest, hashkey);
467
+ if (retval == RL_OK) {
468
+ rl_free(digest);
469
+ digest = NULL;
470
+ if (newvalue) {
471
+ *newvalue = value;
472
+ }
473
+ }
474
+ else if (retval != RL_NOT_FOUND) {
475
+ goto cleanup;
476
+ }
477
+ }
478
+ else if (retval == RL_NOT_FOUND) {
479
+ RL_MALLOC(data, sizeof(unsigned char) * MAX_DOUBLE_DIGITS);
480
+ datalen = snprintf((char *)data, MAX_DOUBLE_DIGITS, "%lf", increment);
481
+
482
+ RL_MALLOC(hashkey, sizeof(*hashkey));
483
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->string_page, field, fieldlen);
484
+ RL_CALL(rl_multi_string_set, RL_OK, db, &hashkey->value_page, data, datalen);
485
+ RL_CALL(rl_btree_add_element, RL_OK, db, hash, hash_page_number, digest, hashkey);
486
+ if (newvalue) {
487
+ *newvalue = increment;
488
+ }
489
+ }
490
+ else {
491
+ goto cleanup;
492
+ }
493
+
494
+ retval = RL_OK;
495
+ cleanup:
496
+ rl_free(data);
497
+ return retval;
498
+ }
499
+
500
+ int rl_hash_iterator_next(rl_hash_iterator *iterator, unsigned char **field, long *fieldlen, unsigned char **member, long *memberlen)
501
+ {
502
+ void *tmp;
503
+ rl_hashkey *hashkey = NULL;
504
+ int retval;
505
+ if (member && !memberlen) {
506
+ fprintf(stderr, "If member is provided, memberlen is required\n");
507
+ return RL_UNEXPECTED;
508
+ }
509
+
510
+ if (field && !fieldlen) {
511
+ fprintf(stderr, "If field is provided, fieldlen is required\n");
512
+ return RL_UNEXPECTED;
513
+ }
514
+
515
+ RL_CALL(rl_btree_iterator_next, RL_OK, iterator, NULL, &tmp);
516
+ hashkey = tmp;
517
+
518
+ if (fieldlen) {
519
+ retval = rl_multi_string_get(iterator->db, hashkey->string_page, field, fieldlen);
520
+ if (retval != RL_OK) {
521
+ rl_btree_iterator_destroy(iterator);
522
+ goto cleanup;
523
+ }
524
+ }
525
+
526
+ if (memberlen) {
527
+ retval = rl_multi_string_get(iterator->db, hashkey->value_page, member, memberlen);
528
+ if (retval != RL_OK) {
529
+ rl_btree_iterator_destroy(iterator);
530
+ goto cleanup;
531
+ }
532
+ }
533
+ cleanup:
534
+ rl_free(hashkey);
535
+ return retval;
536
+ }
537
+
538
+ int rl_hash_iterator_destroy(rl_hash_iterator *iterator)
539
+ {
540
+ return rl_btree_iterator_destroy(iterator);
541
+ }
542
+
543
+ int rl_hash_pages(struct rlite *db, long page, short *pages)
544
+ {
545
+ rl_btree *btree;
546
+ rl_btree_iterator *iterator = NULL;
547
+ int retval;
548
+ void *tmp;
549
+ rl_hashkey *hashkey;
550
+
551
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_btree_hash_sha1_hashkey, page, &rl_btree_type_hash_sha1_hashkey, &tmp, 1);
552
+ btree = tmp;
553
+
554
+ RL_CALL(rl_btree_pages, RL_OK, db, btree, pages);
555
+
556
+ RL_CALL(rl_btree_iterator_create, RL_OK, db, btree, &iterator);
557
+ while ((retval = rl_btree_iterator_next(iterator, NULL, &tmp)) == RL_OK) {
558
+ hashkey = tmp;
559
+ pages[hashkey->value_page] = 1;
560
+ RL_CALL(rl_multi_string_pages, RL_OK, db, hashkey->value_page, pages);
561
+ pages[hashkey->string_page] = 1;
562
+ RL_CALL(rl_multi_string_pages, RL_OK, db, hashkey->string_page, pages);
563
+ rl_free(hashkey);
564
+ }
565
+ iterator = NULL;
566
+
567
+ if (retval != RL_END) {
568
+ goto cleanup;
569
+ }
570
+ retval = RL_OK;
571
+ cleanup:
572
+ if (retval != RL_OK) {
573
+ if (iterator) {
574
+ rl_btree_iterator_destroy(iterator);
575
+ }
576
+ }
577
+ return retval;
578
+ }
579
+
580
+ int rl_hash_delete(rlite *db, long value_page)
581
+ {
582
+ rl_btree *hash;
583
+ rl_btree_iterator *iterator;
584
+ rl_hashkey *hashkey = NULL;
585
+ int retval;
586
+ void *tmp;
587
+ RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_btree_hash_sha1_hashkey, value_page, &rl_btree_type_hash_sha1_hashkey, &tmp, 1);
588
+ hash = tmp;
589
+ RL_CALL(rl_btree_iterator_create, RL_OK, db, hash, &iterator);
590
+ while ((retval = rl_btree_iterator_next(iterator, NULL, &tmp)) == RL_OK) {
591
+ hashkey = tmp;
592
+ rl_multi_string_delete(db, hashkey->string_page);
593
+ rl_multi_string_delete(db, hashkey->value_page);
594
+ rl_free(hashkey);
595
+ }
596
+ iterator = NULL;
597
+
598
+ if (retval != RL_END) {
599
+ goto cleanup;
600
+ }
601
+
602
+ RL_CALL(rl_btree_delete, RL_OK, db, hash);
603
+ RL_CALL(rl_delete, RL_OK, db, value_page);
604
+ retval = RL_OK;
605
+ cleanup:
606
+ return retval;
607
+ }
@@ -0,0 +1,29 @@
1
+ #ifndef _RL_TYPE_HASH_H
2
+ #define _RL_TYPE_HASH_H
3
+
4
+ #include "page_btree.h"
5
+
6
+ #define RL_TYPE_HASH 'H'
7
+
8
+ struct rlite;
9
+
10
+ typedef rl_btree_iterator rl_hash_iterator;
11
+
12
+ int rl_hash_iterator_next(rl_hash_iterator *iterator, unsigned char **field, long *fieldlen, unsigned char **member, long *memberlen);
13
+ int rl_hash_iterator_destroy(rl_hash_iterator *iterator);
14
+
15
+ int rl_hset(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen, unsigned char *data, long datalen, long *added, int update);
16
+ int rl_hget(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen, unsigned char **data, long *datalen);
17
+ int rl_hexists(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen);
18
+ int rl_hdel(struct rlite *db, const unsigned char *key, long keylen, long fieldsc, unsigned char **fields, long *fieldslen, long *delcount);
19
+ int rl_hgetall(struct rlite *db, rl_hash_iterator **iterator, const unsigned char *key, long keylen);
20
+ int rl_hlen(struct rlite *db, const unsigned char *key, long keylen, long *len);
21
+ int rl_hmget(struct rlite *db, const unsigned char *key, long keylen, int fieldc, unsigned char **fields, long *fieldslen, unsigned char ***_data, long **_datalen);
22
+ int rl_hmset(struct rlite *db, const unsigned char *key, long keylen, int fieldc, unsigned char **fields, long *fieldslen, unsigned char **datas, long *dataslen);
23
+ int rl_hincrby(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen, long increment, long *newvalue);
24
+ int rl_hincrbyfloat(struct rlite *db, const unsigned char *key, long keylen, unsigned char *field, long fieldlen, double increment, double *newvalue);
25
+
26
+ int rl_hash_pages(struct rlite *db, long page, short *pages);
27
+ int rl_hash_delete(struct rlite *db, long value_page);
28
+
29
+ #endif