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