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,397 @@
1
+ /*
2
+ * Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * * Redistributions of source code must retain the above copyright notice,
9
+ * this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above copyright
11
+ * notice, this list of conditions and the following disclaimer in the
12
+ * documentation and/or other materials provided with the distribution.
13
+ * * Neither the name of Redis nor the names of its contributors may be used
14
+ * to endorse or promote products derived from this software without
15
+ * specific prior written permission.
16
+ *
17
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
+ * POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+ #include "utilfromredis.h"
30
+ #include <ctype.h>
31
+ #include <limits.h>
32
+ #include <string.h>
33
+ #include <stdint.h>
34
+
35
+ // https://github.com/antirez/redis/blob/unstable/src/util.c#L45
36
+ //
37
+ /* Glob-style pattern matching. */
38
+ int rl_stringmatchlen(const char *pattern, int patternLen,
39
+ const char *string, int stringLen, int nocase)
40
+ {
41
+ while(patternLen) {
42
+ switch(pattern[0]) {
43
+ case '*':
44
+ while (pattern[1] == '*') {
45
+ pattern++;
46
+ patternLen--;
47
+ }
48
+ if (patternLen == 1)
49
+ return 1; /* match */
50
+ while(stringLen) {
51
+ if (rl_stringmatchlen(pattern+1, patternLen-1,
52
+ string, stringLen, nocase))
53
+ return 1; /* match */
54
+ string++;
55
+ stringLen--;
56
+ }
57
+ return 0; /* no match */
58
+ break;
59
+ case '?':
60
+ if (stringLen == 0)
61
+ return 0; /* no match */
62
+ string++;
63
+ stringLen--;
64
+ break;
65
+ case '[':
66
+ {
67
+ int not, match;
68
+
69
+ pattern++;
70
+ patternLen--;
71
+ not = pattern[0] == '^';
72
+ if (not) {
73
+ pattern++;
74
+ patternLen--;
75
+ }
76
+ match = 0;
77
+ while(1) {
78
+ if (pattern[0] == '\\') {
79
+ pattern++;
80
+ patternLen--;
81
+ if (pattern[0] == string[0])
82
+ match = 1;
83
+ } else if (pattern[0] == ']') {
84
+ break;
85
+ } else if (patternLen == 0) {
86
+ pattern--;
87
+ patternLen++;
88
+ break;
89
+ } else if (pattern[1] == '-' && patternLen >= 3) {
90
+ int start = pattern[0];
91
+ int end = pattern[2];
92
+ int c = string[0];
93
+ if (start > end) {
94
+ int t = start;
95
+ start = end;
96
+ end = t;
97
+ }
98
+ if (nocase) {
99
+ start = tolower(start);
100
+ end = tolower(end);
101
+ c = tolower(c);
102
+ }
103
+ pattern += 2;
104
+ patternLen -= 2;
105
+ if (c >= start && c <= end)
106
+ match = 1;
107
+ } else {
108
+ if (!nocase) {
109
+ if (pattern[0] == string[0])
110
+ match = 1;
111
+ } else {
112
+ if (tolower((int)pattern[0]) == tolower((int)string[0]))
113
+ match = 1;
114
+ }
115
+ }
116
+ pattern++;
117
+ patternLen--;
118
+ }
119
+ if (not)
120
+ match = !match;
121
+ if (!match)
122
+ return 0; /* no match */
123
+ string++;
124
+ stringLen--;
125
+ break;
126
+ }
127
+ case '\\':
128
+ if (patternLen >= 2) {
129
+ pattern++;
130
+ patternLen--;
131
+ }
132
+ /* fall through */
133
+ default:
134
+ if (!nocase) {
135
+ if (pattern[0] != string[0])
136
+ return 0; /* no match */
137
+ } else {
138
+ if (tolower((int)pattern[0]) != tolower((int)string[0]))
139
+ return 0; /* no match */
140
+ }
141
+ string++;
142
+ stringLen--;
143
+ break;
144
+ }
145
+ pattern++;
146
+ patternLen--;
147
+ if (stringLen == 0) {
148
+ while(*pattern == '*') {
149
+ pattern++;
150
+ patternLen--;
151
+ }
152
+ break;
153
+ }
154
+ }
155
+ if (patternLen == 0 && stringLen == 0)
156
+ return 1;
157
+ return 0;
158
+ }
159
+
160
+ // Adapted from https://github.com/antirez/redis/blob/unstable/src/bitops.c#L287
161
+ /* BITOP op_name target_key src_key1 src_key2 src_key3 ... src_keyN */
162
+ void rl_internal_bitop(int op, unsigned long numkeys, unsigned char **objects, unsigned long *objectslen, unsigned char **result, long *resultlen)
163
+ {
164
+ unsigned long j;
165
+ unsigned long maxlen = 0; /* Array of length of src strings, and max len. */
166
+ unsigned long minlen = 0; /* Min len among the input keys. */
167
+ unsigned char *res = NULL; /* Resulting string. */
168
+
169
+
170
+ /* Lookup keys, and store pointers to the string objects into an array. */
171
+ for (j = 0; j < numkeys; j++) {
172
+ if (objectslen[j] > maxlen) maxlen = objectslen[j];
173
+ if (j == 0 || objectslen[j] < minlen) minlen = objectslen[j];
174
+ }
175
+
176
+ /* Compute the bit operation, if at least one string is not empty. */
177
+ if (maxlen) {
178
+ res = (unsigned char *)malloc(sizeof(unsigned char) * maxlen);
179
+ unsigned char output, byte;
180
+ unsigned long i;
181
+
182
+ /* Fast path: as far as we have data for all the input bitmaps we
183
+ * can take a fast path that performs much better than the
184
+ * vanilla algorithm. */
185
+ j = 0;
186
+ if (minlen && numkeys <= 16) {
187
+ unsigned long *lp[16];
188
+ unsigned long *lres = (unsigned long*) res;
189
+
190
+ memcpy(lp, objects, sizeof(unsigned long*) * numkeys);
191
+ memcpy(res, objects[0], minlen);
192
+
193
+ /* Different branches per different operations for speed (sorry). */
194
+ if (op == BITOP_AND) {
195
+ while(minlen >= sizeof(unsigned long)*4) {
196
+ for (i = 1; i < numkeys; i++) {
197
+ lres[0] &= lp[i][0];
198
+ lres[1] &= lp[i][1];
199
+ lres[2] &= lp[i][2];
200
+ lres[3] &= lp[i][3];
201
+ lp[i]+=4;
202
+ }
203
+ lres+=4;
204
+ j += sizeof(unsigned long)*4;
205
+ minlen -= sizeof(unsigned long)*4;
206
+ }
207
+ } else if (op == BITOP_OR) {
208
+ while(minlen >= sizeof(unsigned long)*4) {
209
+ for (i = 1; i < numkeys; i++) {
210
+ lres[0] |= lp[i][0];
211
+ lres[1] |= lp[i][1];
212
+ lres[2] |= lp[i][2];
213
+ lres[3] |= lp[i][3];
214
+ lp[i]+=4;
215
+ }
216
+ lres+=4;
217
+ j += sizeof(unsigned long)*4;
218
+ minlen -= sizeof(unsigned long)*4;
219
+ }
220
+ } else if (op == BITOP_XOR) {
221
+ while(minlen >= sizeof(unsigned long)*4) {
222
+ for (i = 1; i < numkeys; i++) {
223
+ lres[0] ^= lp[i][0];
224
+ lres[1] ^= lp[i][1];
225
+ lres[2] ^= lp[i][2];
226
+ lres[3] ^= lp[i][3];
227
+ lp[i]+=4;
228
+ }
229
+ lres+=4;
230
+ j += sizeof(unsigned long)*4;
231
+ minlen -= sizeof(unsigned long)*4;
232
+ }
233
+ } else if (op == BITOP_NOT) {
234
+ while(minlen >= sizeof(unsigned long)*4) {
235
+ lres[0] = ~lres[0];
236
+ lres[1] = ~lres[1];
237
+ lres[2] = ~lres[2];
238
+ lres[3] = ~lres[3];
239
+ lres+=4;
240
+ j += sizeof(unsigned long)*4;
241
+ minlen -= sizeof(unsigned long)*4;
242
+ }
243
+ }
244
+ }
245
+
246
+ /* j is set to the next byte to process by the previous loop. */
247
+ for (; j < maxlen; j++) {
248
+ output = (objectslen[0] <= j) ? 0 : objects[0][j];
249
+ if (op == BITOP_NOT) output = ~output;
250
+ for (i = 1; i < numkeys; i++) {
251
+ byte = (objectslen[i] <= j) ? 0 : objects[i][j];
252
+ switch(op) {
253
+ case BITOP_AND: output &= byte; break;
254
+ case BITOP_OR: output |= byte; break;
255
+ case BITOP_XOR: output ^= byte; break;
256
+ }
257
+ }
258
+ res[j] = output;
259
+ }
260
+ }
261
+
262
+ *result = res;
263
+ *resultlen = maxlen;
264
+ }
265
+
266
+ // https://github.com/antirez/redis/blob/unstable/src/bitops.c#L61
267
+ /* Count number of bits set in the binary array pointed by 's' and long
268
+ * 'count' bytes. The implementation of this function is required to
269
+ * work with a input string length up to 512 MB. */
270
+ size_t rl_redisPopcount(void *s, long count) {
271
+ size_t bits = 0;
272
+ unsigned char *p = s;
273
+ uint32_t *p4;
274
+ static const unsigned char bitsinbyte[256] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};
275
+
276
+ /* Count initial bytes not aligned to 32 bit. */
277
+ while((unsigned long)p & 3 && count) {
278
+ bits += bitsinbyte[*p++];
279
+ count--;
280
+ }
281
+
282
+ /* Count bits 16 bytes at a time */
283
+ p4 = (uint32_t*)p;
284
+ while(count>=16) {
285
+ uint32_t aux1, aux2, aux3, aux4;
286
+
287
+ aux1 = *p4++;
288
+ aux2 = *p4++;
289
+ aux3 = *p4++;
290
+ aux4 = *p4++;
291
+ count -= 16;
292
+
293
+ aux1 = aux1 - ((aux1 >> 1) & 0x55555555);
294
+ aux1 = (aux1 & 0x33333333) + ((aux1 >> 2) & 0x33333333);
295
+ aux2 = aux2 - ((aux2 >> 1) & 0x55555555);
296
+ aux2 = (aux2 & 0x33333333) + ((aux2 >> 2) & 0x33333333);
297
+ aux3 = aux3 - ((aux3 >> 1) & 0x55555555);
298
+ aux3 = (aux3 & 0x33333333) + ((aux3 >> 2) & 0x33333333);
299
+ aux4 = aux4 - ((aux4 >> 1) & 0x55555555);
300
+ aux4 = (aux4 & 0x33333333) + ((aux4 >> 2) & 0x33333333);
301
+ bits += ((((aux1 + (aux1 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +
302
+ ((((aux2 + (aux2 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +
303
+ ((((aux3 + (aux3 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24) +
304
+ ((((aux4 + (aux4 >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24);
305
+ }
306
+ /* Count the remaining bytes. */
307
+ p = (unsigned char*)p4;
308
+ while(count--) bits += bitsinbyte[*p++];
309
+ return bits;
310
+ }
311
+
312
+ // https://github.com/antirez/redis/blob/unstable/src/bitops.c#L110
313
+ /* Return the position of the first bit set to one (if 'bit' is 1) or
314
+ * zero (if 'bit' is 0) in the bitmap starting at 's' and long 'count' bytes.
315
+ *
316
+ * The function is guaranteed to return a value >= 0 if 'bit' is 0 since if
317
+ * no zero bit is found, it returns count*8 assuming the string is zero
318
+ * padded on the right. However if 'bit' is 1 it is possible that there is
319
+ * not a single set bit in the bitmap. In this special case -1 is returned. */
320
+ long rl_internal_bitpos(void *s, unsigned long count, int bit) {
321
+ unsigned long *l;
322
+ unsigned char *c;
323
+ unsigned long skipval, word = 0, one;
324
+ long pos = 0; /* Position of bit, to return to the caller. */
325
+ unsigned long j;
326
+
327
+ /* Process whole words first, seeking for first word that is not
328
+ * all ones or all zeros respectively if we are lookig for zeros
329
+ * or ones. This is much faster with large strings having contiguous
330
+ * blocks of 1 or 0 bits compared to the vanilla bit per bit processing.
331
+ *
332
+ * Note that if we start from an address that is not aligned
333
+ * to sizeof(unsigned long) we consume it byte by byte until it is
334
+ * aligned. */
335
+
336
+ /* Skip initial bits not aligned to sizeof(unsigned long) byte by byte. */
337
+ skipval = bit ? 0 : UCHAR_MAX;
338
+ c = (unsigned char*) s;
339
+ while((unsigned long)c & (sizeof(*l)-1) && count) {
340
+ if (*c != skipval) break;
341
+ c++;
342
+ count--;
343
+ pos += 8;
344
+ }
345
+
346
+ /* Skip bits with full word step. */
347
+ skipval = bit ? 0 : ULONG_MAX;
348
+ l = (unsigned long*) c;
349
+ while (count >= sizeof(*l)) {
350
+ if (*l != skipval) break;
351
+ l++;
352
+ count -= sizeof(*l);
353
+ pos += sizeof(*l)*8;
354
+ }
355
+
356
+ /* Load bytes into "word" considering the first byte as the most significant
357
+ * (we basically consider it as written in big endian, since we consider the
358
+ * string as a set of bits from left to right, with the first bit at position
359
+ * zero.
360
+ *
361
+ * Note that the loading is designed to work even when the bytes left
362
+ * (count) are less than a full word. We pad it with zero on the right. */
363
+ c = (unsigned char*)l;
364
+ for (j = 0; j < sizeof(*l); j++) {
365
+ word <<= 8;
366
+ if (count) {
367
+ word |= *c;
368
+ c++;
369
+ count--;
370
+ }
371
+ }
372
+
373
+ /* Special case:
374
+ * If bits in the string are all zero and we are looking for one,
375
+ * return -1 to signal that there is not a single "1" in the whole
376
+ * string. This can't happen when we are looking for "0" as we assume
377
+ * that the right of the string is zero padded. */
378
+ if (bit == 1 && word == 0) return -1;
379
+
380
+ /* Last word left, scan bit by bit. The first thing we need is to
381
+ * have a single "1" set in the most significant position in an
382
+ * unsigned long. We don't know the size of the long so we use a
383
+ * simple trick. */
384
+ one = ULONG_MAX; /* All bits set to 1.*/
385
+ one >>= 1; /* All bits set to 1 but the MSB. */
386
+ one = ~one; /* All bits set to 0 but the MSB. */
387
+
388
+ while(one) {
389
+ if (((one & word) != 0) == bit) return pos;
390
+ pos++;
391
+ one >>= 1;
392
+ }
393
+
394
+ /* If we reached this point, there is a bug in the algorithm, since
395
+ * the case of no match is handled as a special case before. */
396
+ return -2;
397
+ }
@@ -0,0 +1,11 @@
1
+ #include <stdlib.h>
2
+
3
+ #define BITOP_AND 0
4
+ #define BITOP_OR 1
5
+ #define BITOP_XOR 2
6
+ #define BITOP_NOT 3
7
+
8
+ int rl_stringmatchlen(const char *pattern, int patternLen, const char *string, int stringLen, int nocase);
9
+ void rl_internal_bitop(int op, unsigned long numkeys, unsigned char **objects, unsigned long *objectslen, unsigned char **result, long *resultlen);
10
+ size_t rl_redisPopcount(void *s, long count);
11
+ long rl_internal_bitpos(void *s, unsigned long count, int bit);
@@ -0,0 +1,79 @@
1
+ OPTIMIZATION?=-O2
2
+
3
+ ifeq ($(uname_S),SunOS)
4
+ # make isinf() available
5
+ CFLAGS?= -pedantic $(OPTIMIZATION) -Wall -W -D__EXTENSIONS__ -D_XPG6
6
+ DEBUG?=-g -ggdb
7
+ else
8
+ CFLAGS?= -pedantic $(OPTIMIZATION) -Wall -W $(ARCH) $(PROF)
9
+ DEBUG?=-g -ggdb
10
+ endif
11
+
12
+ DEBUG.gcc += -rdynamic
13
+ CFLAGS.gcc += -std=c99 -I./
14
+
15
+ ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
16
+ DEBUG += ${DEBUG.clang}
17
+ CFLAGS += ${CFLAGS.clang}
18
+ else
19
+ DEBUG += ${DEBUG.gcc}
20
+ CFLAGS += ${CFLAGS.gcc}
21
+ endif
22
+
23
+ LIBS=-lm
24
+
25
+ all: buildtest buildhirlitetest
26
+
27
+ gcov: CFLAGS += -fprofile-arcs -ftest-coverage
28
+ gcov: clean test
29
+
30
+ builddebug: CFLAGS += -DDEBUG=1
31
+ builddebug: clean buildtest
32
+
33
+ debug: builddebug vtest
34
+
35
+ lcov: gcov
36
+ mkdir -p lcov
37
+ lcov --directory . --capture --output-file lcov/app.info
38
+ genhtml lcov/app.info -o lcov/html
39
+
40
+ full-lcov: CFLAGS += -fprofile-arcs -ftest-coverage -DDEBUG=1
41
+ full-lcov: clean buildtest buildhirlitetest
42
+
43
+ clang-analyzer:
44
+ rm -rf analyzer
45
+ scan-build -o analyzer make
46
+
47
+ .c.o:
48
+ $(CC) $(ARCH) $(DEBUG) $(CFLAGS) -c $<
49
+
50
+ libhirlite.a: hirlite.o librlite.a
51
+ ar -cq libhirlite.a rlite.o page_skiplist.o page_string.o page_list.o page_btree.o page_key.o type_string.o type_list.o type_set.o type_zset.o type_hash.o page_long.o page_multi_string.o util.o utilfromredis.o hyperloglog.o sha1.o crc64.o restore.o dump.o lzf_c.o lzf_d.o sort.o pqsort.o hirlite.o
52
+
53
+ librlite.a: rlite.o page_skiplist.o page_string.o page_list.o page_btree.o page_key.o page_multi_string.o page_long.o type_string.o type_list.o type_set.o type_zset.o type_hash.o util.o restore.o dump.o sort.o pqsort.o ../deps/utilfromredis.o ../deps/hyperloglog.o ../deps/sha1.o ../deps/crc64.o ../deps/lzf_c.o ../deps/lzf_d.o
54
+ ar -cq librlite.a rlite.o page_skiplist.o page_string.o page_list.o page_btree.o page_key.o type_string.o type_list.o type_set.o type_zset.o type_hash.o page_long.o page_multi_string.o util.o utilfromredis.o hyperloglog.o sha1.o crc64.o lzf_c.o lzf_d.o restore.o dump.o sort.o pqsort.o
55
+
56
+ buildtest: librlite.a test/rlite-test.o test/btree-test.o test/list-test.o test/string-test.o test/multi_string-test.o test/multi-test.o test/key-test.o test/type_string-test.o test/type_list-test.o test/type_set-test.o test/type_zset-test.o test/type_hash-test.o test/skiplist-test.o test/long-test.o test/restore-test.o test/hyperloglog-test.o test/dump-test.o test/sort-test.o test/test_util.o test/test.o
57
+ $(CC) $(DEBUG) $(CFLAGS) -o rlite-test test.o rlite-test.o btree-test.o list-test.o string-test.o multi_string-test.o multi-test.o key-test.o type_string-test.o type_list-test.o type_set-test.o type_zset-test.o type_hash-test.o skiplist-test.o long-test.o restore-test.o hyperloglog-test.o dump-test.o sort-test.o test_util.o librlite.a $(LIBS)
58
+
59
+ buildhirlitetest: libhirlite.a test/echo.o test/hash.o test/list.o test/parser.o test/set.o test/string.o test/test_hirlite.o test/zset.o test/db.o test/multi.o test/sort.o
60
+ $(CC) $(DEBUG) $(CFLAGS) -o hirlite-test echo.o hash.o list.o parser.o set.o string.o test_hirlite.o zset.o db.o multi.o sort.o libhirlite.a $(LIBS)
61
+
62
+ rlitetest: buildtest
63
+ ./rlite-test
64
+
65
+ hirlitetest: buildhirlitetest
66
+ ./hirlite-test
67
+
68
+ test: rlitetest hirlitetest
69
+
70
+ vrlitetest: buildtest
71
+ valgrind --track-origins=yes --leak-check=full --show-reachable=yes ./rlite-test
72
+
73
+ vhirlitetest: buildhirlitetest
74
+ valgrind --track-origins=yes --leak-check=full --show-reachable=yes ./hirlite-test
75
+
76
+ vtest: vrlitetest vhirlitetest
77
+
78
+ clean:
79
+ rm -rf *-test *.o *.a *.dSYM *.gcda *.gcno lcov
@@ -0,0 +1,15 @@
1
+ #define _POSIX_C_SOURCE 199309L
2
+
3
+ #define RLITE_CRLF "\r\n"
4
+ #define RLITE_STR_OK "OK"
5
+ #define RLITE_STR_ERR "ERR"
6
+ #define RLITE_PONG "PONG"
7
+ #define RLITE_QUEUED "QUEUED"
8
+ #define RLITE_WRONGTYPEERR "WRONGTYPE Operation against a key holding the wrong kind of value"
9
+ #define RLITE_WRONGNUMBEROFARGUMENTS "ERR wrong number of arguments for %s"
10
+ #define RLITE_NOKEYERR "ERR No such key"
11
+ #define RLITE_SYNTAXERR "ERR syntax error"
12
+ #define RLITE_SAMEOBJECTERR "ERR source and destination objects are the same"
13
+ #define RLITE_OUTOFRANGEERR "ERR index out of range"
14
+ #define RLITE_INVALIDMINMAXERR "ERR min or max not valid string range item"
15
+ #define RLITE_NOSCRIPTERR "NOSCRIPT No matching script. Please use EVAL."
@@ -0,0 +1,191 @@
1
+ #include <arpa/inet.h>
2
+ #include "rlite.h"
3
+ #include "util.h"
4
+ #include "../deps/crc64.h"
5
+ #include "../deps/endianconv.h"
6
+
7
+ int rl_dump(struct rlite *db, const unsigned char *key, long keylen, unsigned char **data, long *datalen)
8
+ {
9
+ int retval;
10
+ uint64_t crc;
11
+ unsigned char type;
12
+ unsigned char *value = NULL, *value2 = NULL;
13
+ unsigned char *buf = NULL;
14
+ long buflen;
15
+ long valuelen, value2len;
16
+ unsigned char **values = NULL;
17
+ long i = -1, *valueslen = NULL;
18
+ uint32_t length;
19
+ double score;
20
+ char f[40];
21
+
22
+ RL_CALL(rl_key_get, RL_FOUND, db, key, keylen, &type, NULL, NULL, NULL, NULL);
23
+ if (type == RL_TYPE_STRING) {
24
+ RL_CALL(rl_get, RL_OK, db, key, keylen, &value, &valuelen);
25
+ RL_MALLOC(buf, sizeof(unsigned char) * (16 + valuelen));
26
+ buf[0] = REDIS_RDB_TYPE_STRING;
27
+ buf[1] = (REDIS_RDB_32BITLEN << 6);
28
+ length = htonl(valuelen);
29
+ memcpy(&buf[2], &length, 4);
30
+ memcpy(&buf[6], value, valuelen);
31
+ buflen = valuelen + 6;
32
+ } else if (type == RL_TYPE_LIST) {
33
+ RL_CALL(rl_lrange, RL_OK, db, key, keylen, 0, -1, &valuelen, &values, &valueslen);
34
+ buflen = 16;
35
+ for (i = 0; i < valuelen; i++) {
36
+ buflen += 5 + valueslen[i];
37
+ }
38
+ RL_MALLOC(buf, sizeof(unsigned char) * buflen);
39
+ buf[0] = REDIS_RDB_TYPE_LIST;
40
+ buf[1] = (REDIS_RDB_32BITLEN << 6);
41
+ length = htonl(valuelen);
42
+ memcpy(&buf[2], &length, 4);
43
+ buflen = 6;
44
+ for (i = 0; i < valuelen; i++) {
45
+ buf[buflen++] = (REDIS_RDB_32BITLEN << 6);
46
+ length = htonl(valueslen[i]);
47
+ memcpy(&buf[buflen], &length, 4);
48
+ buflen += 4;
49
+ memcpy(&buf[buflen], values[i], valueslen[i]);
50
+ buflen += valueslen[i];
51
+ }
52
+ } else if (type == RL_TYPE_SET) {
53
+ rl_set_iterator *iterator;
54
+ RL_CALL(rl_smembers, RL_OK, db, &iterator, key, keylen);
55
+ buflen = 16;
56
+ length = 0;
57
+ while ((retval = rl_set_iterator_next(iterator, NULL, &valuelen)) == RL_OK) {
58
+ buflen += 5 + valuelen;
59
+ length++;
60
+ }
61
+ if (retval != RL_END) {
62
+ goto cleanup;
63
+ }
64
+
65
+ RL_MALLOC(buf, sizeof(unsigned char) * buflen);
66
+ buf[0] = REDIS_RDB_TYPE_SET;
67
+ buf[1] = (REDIS_RDB_32BITLEN << 6);
68
+ length = htonl(length);
69
+ memcpy(&buf[2], &length, 4);
70
+ buflen = 6;
71
+
72
+ RL_CALL(rl_smembers, RL_OK, db, &iterator, key, keylen);
73
+ while ((retval = rl_set_iterator_next(iterator, &value, &valuelen)) == RL_OK) {
74
+ buf[buflen++] = (REDIS_RDB_32BITLEN << 6);
75
+ length = htonl(valuelen);
76
+ memcpy(&buf[buflen], &length, 4);
77
+ buflen += 4;
78
+ memcpy(&buf[buflen], value, valuelen);
79
+ buflen += valuelen;
80
+ rl_free(value);
81
+ value = NULL;
82
+ }
83
+ if (retval != RL_END) {
84
+ goto cleanup;
85
+ }
86
+ } else if (type == RL_TYPE_ZSET) {
87
+ rl_zset_iterator *iterator;
88
+ RL_CALL(rl_zrange, RL_OK, db, key, keylen, 0, -1, &iterator);
89
+ buflen = 16;
90
+ length = 0;
91
+ while ((retval = rl_zset_iterator_next(iterator, &score, NULL, &valuelen)) == RL_OK) {
92
+ buflen += 6 + valuelen + snprintf(f, 40, "%lf", score);
93
+ length++;
94
+ }
95
+ if (retval != RL_END) {
96
+ goto cleanup;
97
+ }
98
+
99
+ RL_MALLOC(buf, sizeof(unsigned char) * buflen);
100
+ buf[0] = REDIS_RDB_TYPE_ZSET;
101
+ buf[1] = (REDIS_RDB_32BITLEN << 6);
102
+ length = htonl(length);
103
+ memcpy(&buf[2], &length, 4);
104
+ buflen = 6;
105
+
106
+ RL_CALL(rl_zrange, RL_OK, db, key, keylen, 0, -1, &iterator);
107
+ while ((retval = rl_zset_iterator_next(iterator, &score, &value, &valuelen)) == RL_OK) {
108
+ buf[buflen++] = (REDIS_RDB_32BITLEN << 6);
109
+ length = htonl(valuelen);
110
+ memcpy(&buf[buflen], &length, 4);
111
+ buflen += 4;
112
+ memcpy(&buf[buflen], value, valuelen);
113
+ buflen += valuelen;
114
+ rl_free(value);
115
+ value = NULL;
116
+
117
+ valuelen = snprintf(f, 40, "%lf", score);
118
+ buf[buflen++] = valuelen;
119
+ memcpy(&buf[buflen], f, valuelen);
120
+ buflen += valuelen;
121
+ }
122
+ if (retval != RL_END) {
123
+ goto cleanup;
124
+ }
125
+ } else if (type == RL_TYPE_HASH) {
126
+ rl_hash_iterator *iterator;
127
+ RL_CALL(rl_hgetall, RL_OK, db, &iterator, key, keylen);
128
+ buflen = 16;
129
+ length = 0;
130
+ while ((retval = rl_hash_iterator_next(iterator, NULL, &value2len, NULL, &valuelen)) == RL_OK) {
131
+ buflen += 10 + valuelen + value2len;
132
+ length++;
133
+ }
134
+ if (retval != RL_END) {
135
+ goto cleanup;
136
+ }
137
+
138
+ RL_MALLOC(buf, sizeof(unsigned char) * buflen);
139
+ buf[0] = REDIS_RDB_TYPE_HASH;
140
+ buf[1] = (REDIS_RDB_32BITLEN << 6);
141
+ length = htonl(length);
142
+ memcpy(&buf[2], &length, 4);
143
+ buflen = 6;
144
+
145
+ RL_CALL(rl_hgetall, RL_OK, db, &iterator, key, keylen);
146
+ while ((retval = rl_hash_iterator_next(iterator, &value, &valuelen, &value2, &value2len)) == RL_OK) {
147
+ buf[buflen++] = (REDIS_RDB_32BITLEN << 6);
148
+ length = htonl(valuelen);
149
+ memcpy(&buf[buflen], &length, 4);
150
+ buflen += 4;
151
+ memcpy(&buf[buflen], value, valuelen);
152
+ buflen += valuelen;
153
+ rl_free(value);
154
+ value = NULL;
155
+
156
+ buf[buflen++] = (REDIS_RDB_32BITLEN << 6);
157
+ length = htonl(value2len);
158
+ memcpy(&buf[buflen], &length, 4);
159
+ buflen += 4;
160
+ memcpy(&buf[buflen], value2, value2len);
161
+ buflen += value2len;
162
+ rl_free(value2);
163
+ value2 = NULL;
164
+ }
165
+ } else {
166
+ retval = RL_UNEXPECTED;
167
+ goto cleanup;
168
+ }
169
+ buf[buflen++] = REDIS_RDB_VERSION;
170
+ buf[buflen++] = REDIS_RDB_VERSION >> 8;
171
+
172
+ crc = rl_crc64(0, buf, buflen);
173
+ memrev64ifbe(&crc);
174
+ memcpy(&buf[buflen], &crc, 8);
175
+ buflen += 8;
176
+
177
+ *data = buf;
178
+ *datalen = buflen;
179
+ retval = RL_OK;
180
+ cleanup:
181
+ if (values) {
182
+ for (i = 0; i < valuelen; i++) {
183
+ rl_free(values[i]);
184
+ }
185
+ rl_free(values);
186
+ }
187
+ rl_free(valueslen);
188
+ rl_free(value);
189
+ rl_free(value2);
190
+ return retval;
191
+ }
@@ -0,0 +1,3 @@
1
+ #include "rlite.h"
2
+
3
+ int rl_dump(struct rlite *db, const unsigned char *key, long keylen, unsigned char **data, long *datalen);