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,133 @@
1
+ #ifndef _RL_PAGE_BTREE_H
2
+ #define _RL_PAGE_BTREE_H
3
+
4
+ #define rl_btree_nocache_destroy(db, btree) rl_btree_destroy(db, btree)
5
+ #define rl_btree_node_nocache_destroy(db, node) rl_btree_node_destroy(db, node)
6
+
7
+ struct rl_data_type;
8
+ struct rl_btree;
9
+ struct rl_btree_node;
10
+ struct rlite;
11
+
12
+ typedef struct {
13
+ struct rl_data_type *btree_type;
14
+ struct rl_data_type *btree_node_type;
15
+ int score_size;
16
+ int value_size;
17
+ int (*cmp)(void *v1, void *v2);
18
+ #ifdef DEBUG
19
+ int (*formatter)(void *v, char **str, int *size);
20
+ #endif
21
+ } rl_btree_type;
22
+
23
+ int sha1_cmp(void *v1, void *v2);
24
+ #ifdef DEBUG
25
+ int sha1_formatter(void *v, char **str, int *size);
26
+ #endif
27
+
28
+ typedef struct rl_hashkey {
29
+ long string_page;
30
+ long value_page;
31
+ } rl_hashkey;
32
+
33
+ typedef struct rl_key {
34
+ unsigned char type;
35
+ long string_page;
36
+ long value_page;
37
+ unsigned long long expires;
38
+ long version;
39
+ } rl_key;
40
+
41
+ extern rl_btree_type rl_btree_type_set_long;
42
+ extern rl_btree_type rl_btree_type_hash_long_long;
43
+ extern rl_btree_type rl_btree_type_hash_sha1_key;
44
+ extern rl_btree_type rl_btree_type_hash_sha1_long;
45
+ extern rl_btree_type rl_btree_type_hash_sha1_hashkey;
46
+ extern rl_btree_type rl_btree_type_hash_sha1_double;
47
+
48
+ typedef struct rl_btree_node {
49
+ void **scores;
50
+ // children is null when the node is a leaf
51
+ // when created, allocs size+1.
52
+ long *children;
53
+ void **values;
54
+ // size is the number of children used; allocs the maximum on creation
55
+ long size;
56
+ } rl_btree_node;
57
+
58
+ typedef struct rl_btree {
59
+ struct rlite *db;
60
+ long max_node_size; // maximum number of scores in a node
61
+ long height;
62
+ rl_btree_type *type;
63
+ long root;
64
+ long number_of_elements;
65
+ } rl_btree;
66
+
67
+ typedef struct {
68
+ struct rlite *db;
69
+ rl_btree *btree;
70
+ long size;
71
+ long position;
72
+ struct rl_btree_iterator_nodes {
73
+ long position;
74
+ rl_btree_node *node;
75
+ } nodes[];
76
+ } rl_btree_iterator;
77
+
78
+ void rl_btree_init();
79
+ int rl_btree_create_size(struct rlite *db, rl_btree **btree, rl_btree_type *type, long max_node_size);
80
+ int rl_btree_create(struct rlite *db, rl_btree **btree, rl_btree_type *type);
81
+ int rl_btree_destroy(struct rlite *db, void *btree);
82
+ int rl_btree_node_destroy(struct rlite *db, void *node);
83
+ int rl_btree_add_element(struct rlite *db, rl_btree *btree, long btree_page, void *score, void *value);
84
+ int rl_btree_update_element(struct rlite *db, rl_btree *btree, void *score, void *value);
85
+ int rl_btree_remove_element(struct rlite *db, rl_btree *btree, long btree_page, void *score);
86
+ int rl_btree_find_score(struct rlite *db, rl_btree *btree, void *score, void **value, rl_btree_node *** nodes, long **positions);
87
+ /**
88
+ * rl_btree_random_element
89
+ *
90
+ * notice that all the elements in the tree do not have the same probability,
91
+ * and the order in which they were inserted is relevant. For example,
92
+ * inserting ascendenly will probably results in a lower probability
93
+ * to the elements with a higher score. The odds are approximately evenly
94
+ * distributed in the tree nodes, and even within the node, but not all nodes
95
+ * have the same number of elements.
96
+ *
97
+ * A true random element with even probabilities can be done, but it would
98
+ * be really expensive to generate (O(n) instead of O(log n)).
99
+ */
100
+ int rl_btree_random_element(struct rlite *db, rl_btree *btree, void **score, void **value);
101
+ int rl_print_btree(struct rlite *db, rl_btree *btree);
102
+ int rl_btree_is_balanced(struct rlite *db, rl_btree *btree);
103
+ int rl_flatten_btree(struct rlite *db, rl_btree *btree, void *** scores, long *size);
104
+
105
+ int rl_btree_iterator_create(struct rlite *db, rl_btree *btree, rl_btree_iterator **iterator);
106
+ int rl_btree_iterator_next(rl_btree_iterator *iterator, void **score, void **value);
107
+ int rl_btree_iterator_destroy(rl_btree_iterator *iterator);
108
+
109
+ int rl_btree_serialize(struct rlite *db, void *obj, unsigned char *data);
110
+ int rl_btree_deserialize(struct rlite *db, void **obj, void *context, unsigned char *data);
111
+
112
+ int rl_btree_node_serialize_hash_sha1_key(struct rlite *db, void *obj, unsigned char *data);
113
+ int rl_btree_node_deserialize_hash_sha1_key(struct rlite *db, void **obj, void *context, unsigned char *data);
114
+
115
+ int rl_btree_node_serialize_hash_sha1_long(struct rlite *db, void *obj, unsigned char *data);
116
+ int rl_btree_node_deserialize_hash_sha1_long(struct rlite *db, void **obj, void *context, unsigned char *data);
117
+
118
+ int rl_btree_node_serialize_hash_sha1_hashkey(struct rlite *db, void *obj, unsigned char *data);
119
+ int rl_btree_node_deserialize_hash_sha1_hashkey(struct rlite *db, void **obj, void *context, unsigned char *data);
120
+
121
+ int rl_btree_node_serialize_set_long(struct rlite *db, void *obj, unsigned char *data);
122
+ int rl_btree_node_deserialize_set_long(struct rlite *db, void **obj, void *context, unsigned char *data);
123
+
124
+ int rl_btree_node_serialize_hash_long_long(struct rlite *db, void *obj, unsigned char *data);
125
+ int rl_btree_node_deserialize_hash_long_long(struct rlite *db, void **obj, void *context, unsigned char *data);
126
+
127
+ int rl_btree_node_serialize_hash_sha1_double(struct rlite *db, void *obj, unsigned char *data);
128
+ int rl_btree_node_deserialize_hash_sha1_double(struct rlite *db, void **obj, void *context, unsigned char *data);
129
+
130
+ int rl_btree_pages(struct rlite *db, rl_btree *btree, short *pages);
131
+ int rl_btree_delete(struct rlite *db, rl_btree *btree);
132
+
133
+ #endif
@@ -0,0 +1,283 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+ #include "rlite.h"
4
+ #include "util.h"
5
+ #include "page_btree.h"
6
+ #include "page_key.h"
7
+ #include "page_multi_string.h"
8
+ #include "type_string.h"
9
+ #include "type_zset.h"
10
+ #include "type_hash.h"
11
+
12
+ #define TYPES_LENGTH 5
13
+ rl_type types[TYPES_LENGTH] = {
14
+ {
15
+ RL_TYPE_STRING,
16
+ "string",
17
+ rl_string_delete
18
+ },
19
+ {
20
+ RL_TYPE_LIST,
21
+ "list",
22
+ rl_llist_delete
23
+ },
24
+ {
25
+ RL_TYPE_SET,
26
+ "set",
27
+ rl_set_delete
28
+ },
29
+ {
30
+ RL_TYPE_ZSET,
31
+ "zset",
32
+ rl_zset_delete
33
+ },
34
+ {
35
+ RL_TYPE_HASH,
36
+ "hash",
37
+ rl_hash_delete
38
+ },
39
+ };
40
+
41
+ static int get_type(char identifier, rl_type **type)
42
+ {
43
+ long i;
44
+ for (i = 0; i < TYPES_LENGTH; i++) {
45
+ if (types[i].identifier == identifier) {
46
+ *type = &types[i];
47
+ return RL_OK;
48
+ }
49
+ }
50
+ return RL_UNEXPECTED;
51
+ }
52
+
53
+ int rl_key_set(rlite *db, const unsigned char *key, long keylen, unsigned char type, long value_page, unsigned long long expires, long version)
54
+ {
55
+ int retval;
56
+
57
+ rl_key *key_obj = NULL;
58
+ unsigned char *digest = NULL;
59
+ RL_CALL2(rl_key_delete, RL_OK, RL_NOT_FOUND, db, key, keylen);
60
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
61
+ RL_CALL(sha1, RL_OK, key, keylen, digest);
62
+ rl_btree *btree;
63
+ RL_CALL(rl_get_key_btree, RL_OK, db, &btree, 1);
64
+ RL_MALLOC(key_obj, sizeof(*key_obj))
65
+ RL_CALL(rl_multi_string_set, RL_OK, db, &key_obj->string_page, key, keylen);
66
+ key_obj->type = type;
67
+ key_obj->value_page = value_page;
68
+ key_obj->expires = expires;
69
+ // reserving version=0 for non existent keys
70
+ if (version == 0) {
71
+ version = 1;
72
+ }
73
+ key_obj->version = version;
74
+
75
+ RL_CALL(rl_btree_add_element, RL_OK, db, btree, db->databases[db->selected_database], digest, key_obj);
76
+ retval = RL_OK;
77
+ cleanup:
78
+ if (retval != RL_OK) {
79
+ rl_free(digest);
80
+ rl_free(key_obj);
81
+ }
82
+ return retval;
83
+ }
84
+
85
+ static int rl_key_get_hash_ignore_expire(struct rlite *db, unsigned char digest[20], unsigned char *type, long *string_page, long *value_page, unsigned long long *expires, long *version, int ignore_expire)
86
+ {
87
+ int retval;
88
+ rl_btree *btree;
89
+ rl_key *key_obj;
90
+ RL_CALL(rl_get_key_btree, RL_OK, db, &btree, 0);
91
+ void *tmp = NULL;
92
+ retval = rl_btree_find_score(db, btree, digest, &tmp, NULL, NULL);
93
+ if (retval == RL_FOUND) {
94
+ key_obj = tmp;
95
+ if (ignore_expire == 0 && key_obj->expires != 0 && key_obj->expires <= rl_mstime()) {
96
+ retval = RL_DELETED;
97
+ goto cleanup;
98
+ }
99
+ else {
100
+ if (type) {
101
+ *type = key_obj->type;
102
+ }
103
+ if (string_page) {
104
+ *string_page = key_obj->string_page;
105
+ }
106
+ if (value_page) {
107
+ *value_page = key_obj->value_page;
108
+ }
109
+ if (expires) {
110
+ *expires = key_obj->expires;
111
+ }
112
+ if (version) {
113
+ *version = key_obj->version;
114
+ }
115
+ }
116
+ }
117
+ cleanup:
118
+ return retval;
119
+ }
120
+
121
+ static int rl_key_get_ignore_expire(struct rlite *db, const unsigned char *key, long keylen, unsigned char *type, long *string_page, long *value_page, unsigned long long *expires, long *version, int ignore_expire)
122
+ {
123
+ unsigned char digest[20];
124
+ int retval;
125
+ RL_CALL(sha1, RL_OK, key, keylen, digest);
126
+ RL_CALL2(rl_key_get_hash_ignore_expire, RL_FOUND, RL_DELETED, db, digest, type, string_page, value_page, expires, version, ignore_expire);
127
+ if (retval == RL_DELETED) {
128
+ rl_key_delete_with_value(db, key, keylen);
129
+ if (version) {
130
+ *version = 0;
131
+ }
132
+ retval = RL_NOT_FOUND;
133
+ }
134
+ cleanup:
135
+ return retval;
136
+ }
137
+
138
+ static int rl_key_sha_check_version(struct rlite *db, struct watched_key* key) {
139
+ int retval;
140
+ long version;
141
+ int selected_database = db->selected_database;
142
+ // if the key has expired, the version is still valid, according to
143
+ // https://code.google.com/p/redis/issues/detail?id=270
144
+ // it seems to be relevant to redis being stateful and single process
145
+ // I don't think it is possible to replicate exactly the behavior, but
146
+ // this is pretty close.
147
+ RL_CALL2(rl_key_get_hash_ignore_expire, RL_FOUND, RL_NOT_FOUND, db, key->digest, NULL, NULL, NULL, NULL, &version, 1);
148
+ if (retval == RL_NOT_FOUND) {
149
+ version = 0;
150
+ }
151
+ if (version != key->version) {
152
+ retval = RL_OUTDATED;
153
+ } else {
154
+ retval = RL_OK;
155
+ }
156
+ cleanup:
157
+ db->selected_database = selected_database;
158
+ return retval;
159
+ }
160
+
161
+ int rl_check_watched_keys(struct rlite *db, int watched_count, struct watched_key** keys)
162
+ {
163
+ int i, retval = RL_OK;
164
+
165
+ for (i = 0; i < watched_count; i++) {
166
+ RL_CALL(rl_key_sha_check_version, RL_OK, db, keys[i]);
167
+ }
168
+ cleanup:
169
+ return retval;
170
+ }
171
+
172
+ int rl_watch(struct rlite *db, struct watched_key** _watched_key, const unsigned char *key, long keylen) {
173
+ int retval;
174
+ struct watched_key* wkey = NULL;
175
+ RL_MALLOC(wkey, sizeof(struct watched_key));
176
+ wkey->database = db->selected_database;
177
+
178
+ RL_CALL(sha1, RL_OK, key, keylen, wkey->digest);
179
+ RL_CALL2(rl_key_get_hash_ignore_expire, RL_FOUND, RL_NOT_FOUND, db, wkey->digest, NULL, NULL, NULL, NULL, &wkey->version, 1);
180
+ if (retval == RL_NOT_FOUND) {
181
+ wkey->version = 0;
182
+ }
183
+
184
+ *_watched_key = wkey;
185
+ retval = RL_OK;
186
+ cleanup:
187
+ if (retval != RL_OK) {
188
+ rl_free(wkey);
189
+ }
190
+ return retval;
191
+ }
192
+
193
+ int rl_key_get(struct rlite *db, const unsigned char *key, long keylen, unsigned char *type, long *string_page, long *value_page, unsigned long long *expires, long *version)
194
+ {
195
+ return rl_key_get_ignore_expire(db, key, keylen, type, string_page, value_page, expires, version, 0);
196
+ }
197
+
198
+ int rl_key_get_or_create(struct rlite *db, const unsigned char *key, long keylen, unsigned char type, long *page, long *version)
199
+ {
200
+ unsigned char existing_type;
201
+ int retval = rl_key_get(db, key, keylen, &existing_type, NULL, page, NULL, version);
202
+ long _version;
203
+ if (retval == RL_FOUND) {
204
+ if (existing_type != type) {
205
+ return RL_WRONG_TYPE;
206
+ }
207
+ }
208
+ else if (retval == RL_NOT_FOUND) {
209
+ _version = rand();
210
+ if (version) {
211
+ *version = _version;
212
+ }
213
+ rl_alloc_page_number(db, page);
214
+ RL_CALL(rl_key_set, RL_OK, db, key, keylen, type, *page, 0, _version);
215
+ retval = RL_NOT_FOUND;
216
+ }
217
+ cleanup:
218
+ return retval;
219
+ }
220
+
221
+ int rl_key_delete(struct rlite *db, const unsigned char *key, long keylen)
222
+ {
223
+ int retval;
224
+ void *tmp;
225
+ unsigned char *digest;
226
+ rl_btree *btree = NULL;
227
+ rl_key *key_obj = NULL;
228
+ RL_MALLOC(digest, sizeof(unsigned char) * 20);
229
+ RL_CALL(sha1, RL_OK, key, keylen, digest);
230
+ RL_CALL(rl_get_key_btree, RL_OK, db, &btree, 0);
231
+ retval = rl_btree_find_score(db, btree, digest, &tmp, NULL, NULL);
232
+ if (retval == RL_FOUND) {
233
+ key_obj = tmp;
234
+ RL_CALL(rl_multi_string_delete, RL_OK, db, key_obj->string_page);
235
+ retval = rl_btree_remove_element(db, btree, db->databases[db->selected_database], digest);
236
+ if (retval == RL_DELETED) {
237
+ db->databases[db->selected_database] = 0;
238
+ retval = RL_OK;
239
+ }
240
+ else if (retval != RL_OK) {
241
+ goto cleanup;
242
+ }
243
+ }
244
+ cleanup:
245
+ rl_free(digest);
246
+ return retval;
247
+ }
248
+
249
+ int rl_key_expires(struct rlite *db, const unsigned char *key, long keylen, unsigned long long expires)
250
+ {
251
+ int retval;
252
+ unsigned char type;
253
+ long string_page, value_page, version;
254
+ RL_CALL(rl_key_get, RL_FOUND, db, key, keylen, &type, &string_page, &value_page, NULL, &version);
255
+ RL_CALL(rl_key_set, RL_OK, db, key, keylen, type, value_page, expires, version + 1);
256
+ cleanup:
257
+ return retval;
258
+ }
259
+
260
+ int rl_key_delete_value(struct rlite *db, unsigned char identifier, long value_page)
261
+ {
262
+ int retval;
263
+ rl_type *type;
264
+ RL_CALL(get_type, RL_OK, identifier, &type);
265
+ RL_CALL(type->delete, RL_OK, db, value_page);
266
+ retval = RL_OK;
267
+ cleanup:
268
+ return retval;
269
+ }
270
+
271
+ int rl_key_delete_with_value(struct rlite *db, const unsigned char *key, long keylen)
272
+ {
273
+ int retval;
274
+ unsigned char identifier;
275
+ long value_page;
276
+ unsigned long long expires;
277
+ RL_CALL(rl_key_get_ignore_expire, RL_FOUND, db, key, keylen, &identifier, NULL, &value_page, &expires, NULL, 1);
278
+ RL_CALL(rl_key_delete_value, RL_OK, db, identifier, value_page);
279
+ RL_CALL(rl_key_delete, RL_OK, db, key, keylen);
280
+ retval = expires != 0 && expires <= rl_mstime() ? RL_NOT_FOUND : RL_OK;
281
+ cleanup:
282
+ return retval;
283
+ }
@@ -0,0 +1,25 @@
1
+ #ifndef _RL_OBJ_KEY_H
2
+ #define _RL_OBJ_KEY_H
3
+
4
+ struct rlite;
5
+ struct watched_key;
6
+
7
+ typedef struct {
8
+ char identifier;
9
+ const char *name;
10
+ int (*delete)(struct rlite *db, long value_page);
11
+ } rl_type;
12
+
13
+ extern rl_type types[];
14
+
15
+ int rl_key_get_or_create(struct rlite *db, const unsigned char *key, long keylen, unsigned char type, long *page, long *version);
16
+ int rl_key_get(struct rlite *db, const unsigned char *key, long keylen, unsigned char *type, long *string_page, long *value_page, unsigned long long *expires, long *version);
17
+ int rl_check_watched_keys(struct rlite *db, int watched_count, struct watched_key** keys);
18
+ int rl_key_set(struct rlite *db, const unsigned char *key, long keylen, unsigned char type, long page, unsigned long long expires, long version);
19
+ int rl_key_delete(struct rlite *db, const unsigned char *key, long keylen);
20
+ int rl_key_expires(struct rlite *db, const unsigned char *key, long keylen, unsigned long long expires);
21
+ int rl_key_delete_value(struct rlite *db, unsigned char identifier, long value_page);
22
+ int rl_key_delete_with_value(struct rlite *db, const unsigned char *key, long keylen);
23
+ int rl_watch(struct rlite *db, struct watched_key** _watched_key, const unsigned char *key, long keylen);
24
+
25
+ #endif