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