redis-client 0.2.0 → 0.4.0

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/Gemfile +1 -2
  4. data/Gemfile.lock +2 -3
  5. data/README.md +66 -3
  6. data/Rakefile +43 -23
  7. data/lib/redis_client/command_builder.rb +83 -0
  8. data/lib/redis_client/config.rb +9 -48
  9. data/lib/redis_client/connection_mixin.rb +38 -0
  10. data/lib/redis_client/decorator.rb +84 -0
  11. data/lib/redis_client/pooled.rb +38 -30
  12. data/lib/redis_client/ruby_connection/buffered_io.rb +153 -0
  13. data/lib/redis_client/{resp3.rb → ruby_connection/resp3.rb} +0 -26
  14. data/lib/redis_client/{connection.rb → ruby_connection.rb} +26 -31
  15. data/lib/redis_client/version.rb +1 -1
  16. data/lib/redis_client.rb +162 -36
  17. data/redis-client.gemspec +2 -4
  18. metadata +12 -59
  19. data/.rubocop.yml +0 -190
  20. data/ext/redis_client/hiredis/export.clang +0 -2
  21. data/ext/redis_client/hiredis/export.gcc +0 -7
  22. data/ext/redis_client/hiredis/extconf.rb +0 -62
  23. data/ext/redis_client/hiredis/hiredis_connection.c +0 -708
  24. data/ext/redis_client/hiredis/vendor/.gitignore +0 -9
  25. data/ext/redis_client/hiredis/vendor/.travis.yml +0 -131
  26. data/ext/redis_client/hiredis/vendor/CHANGELOG.md +0 -364
  27. data/ext/redis_client/hiredis/vendor/CMakeLists.txt +0 -165
  28. data/ext/redis_client/hiredis/vendor/COPYING +0 -29
  29. data/ext/redis_client/hiredis/vendor/Makefile +0 -308
  30. data/ext/redis_client/hiredis/vendor/README.md +0 -664
  31. data/ext/redis_client/hiredis/vendor/adapters/ae.h +0 -130
  32. data/ext/redis_client/hiredis/vendor/adapters/glib.h +0 -156
  33. data/ext/redis_client/hiredis/vendor/adapters/ivykis.h +0 -84
  34. data/ext/redis_client/hiredis/vendor/adapters/libev.h +0 -179
  35. data/ext/redis_client/hiredis/vendor/adapters/libevent.h +0 -175
  36. data/ext/redis_client/hiredis/vendor/adapters/libuv.h +0 -117
  37. data/ext/redis_client/hiredis/vendor/adapters/macosx.h +0 -115
  38. data/ext/redis_client/hiredis/vendor/adapters/qt.h +0 -135
  39. data/ext/redis_client/hiredis/vendor/alloc.c +0 -86
  40. data/ext/redis_client/hiredis/vendor/alloc.h +0 -91
  41. data/ext/redis_client/hiredis/vendor/appveyor.yml +0 -24
  42. data/ext/redis_client/hiredis/vendor/async.c +0 -887
  43. data/ext/redis_client/hiredis/vendor/async.h +0 -147
  44. data/ext/redis_client/hiredis/vendor/async_private.h +0 -75
  45. data/ext/redis_client/hiredis/vendor/dict.c +0 -352
  46. data/ext/redis_client/hiredis/vendor/dict.h +0 -126
  47. data/ext/redis_client/hiredis/vendor/fmacros.h +0 -12
  48. data/ext/redis_client/hiredis/vendor/hiredis-config.cmake.in +0 -13
  49. data/ext/redis_client/hiredis/vendor/hiredis.c +0 -1174
  50. data/ext/redis_client/hiredis/vendor/hiredis.h +0 -336
  51. data/ext/redis_client/hiredis/vendor/hiredis.pc.in +0 -12
  52. data/ext/redis_client/hiredis/vendor/hiredis_ssl-config.cmake.in +0 -13
  53. data/ext/redis_client/hiredis/vendor/hiredis_ssl.h +0 -157
  54. data/ext/redis_client/hiredis/vendor/hiredis_ssl.pc.in +0 -12
  55. data/ext/redis_client/hiredis/vendor/net.c +0 -612
  56. data/ext/redis_client/hiredis/vendor/net.h +0 -56
  57. data/ext/redis_client/hiredis/vendor/read.c +0 -739
  58. data/ext/redis_client/hiredis/vendor/read.h +0 -129
  59. data/ext/redis_client/hiredis/vendor/sds.c +0 -1289
  60. data/ext/redis_client/hiredis/vendor/sds.h +0 -278
  61. data/ext/redis_client/hiredis/vendor/sdsalloc.h +0 -44
  62. data/ext/redis_client/hiredis/vendor/sockcompat.c +0 -248
  63. data/ext/redis_client/hiredis/vendor/sockcompat.h +0 -92
  64. data/ext/redis_client/hiredis/vendor/ssl.c +0 -544
  65. data/ext/redis_client/hiredis/vendor/test.c +0 -1401
  66. data/ext/redis_client/hiredis/vendor/test.sh +0 -78
  67. data/ext/redis_client/hiredis/vendor/win32.h +0 -56
  68. data/lib/redis_client/buffered_io.rb +0 -151
  69. data/lib/redis_client/hiredis_connection.rb +0 -80
@@ -1,147 +0,0 @@
1
- /*
2
- * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
3
- * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
4
- *
5
- * All rights reserved.
6
- *
7
- * Redistribution and use in source and binary forms, with or without
8
- * modification, are permitted provided that the following conditions are met:
9
- *
10
- * * Redistributions of source code must retain the above copyright notice,
11
- * this list of conditions and the following disclaimer.
12
- * * Redistributions in binary form must reproduce the above copyright
13
- * notice, this list of conditions and the following disclaimer in the
14
- * documentation and/or other materials provided with the distribution.
15
- * * Neither the name of Redis nor the names of its contributors may be used
16
- * to endorse or promote products derived from this software without
17
- * specific prior written permission.
18
- *
19
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
- * POSSIBILITY OF SUCH DAMAGE.
30
- */
31
-
32
- #ifndef __HIREDIS_ASYNC_H
33
- #define __HIREDIS_ASYNC_H
34
- #include "hiredis.h"
35
-
36
- #ifdef __cplusplus
37
- extern "C" {
38
- #endif
39
-
40
- struct redisAsyncContext; /* need forward declaration of redisAsyncContext */
41
- struct dict; /* dictionary header is included in async.c */
42
-
43
- /* Reply callback prototype and container */
44
- typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*);
45
- typedef struct redisCallback {
46
- struct redisCallback *next; /* simple singly linked list */
47
- redisCallbackFn *fn;
48
- int pending_subs;
49
- void *privdata;
50
- } redisCallback;
51
-
52
- /* List of callbacks for either regular replies or pub/sub */
53
- typedef struct redisCallbackList {
54
- redisCallback *head, *tail;
55
- } redisCallbackList;
56
-
57
- /* Connection callback prototypes */
58
- typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);
59
- typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);
60
- typedef void(redisTimerCallback)(void *timer, void *privdata);
61
-
62
- /* Context for an async connection to Redis */
63
- typedef struct redisAsyncContext {
64
- /* Hold the regular context, so it can be realloc'ed. */
65
- redisContext c;
66
-
67
- /* Setup error flags so they can be used directly. */
68
- int err;
69
- char *errstr;
70
-
71
- /* Not used by hiredis */
72
- void *data;
73
- void (*dataCleanup)(void *privdata);
74
-
75
- /* Event library data and hooks */
76
- struct {
77
- void *data;
78
-
79
- /* Hooks that are called when the library expects to start
80
- * reading/writing. These functions should be idempotent. */
81
- void (*addRead)(void *privdata);
82
- void (*delRead)(void *privdata);
83
- void (*addWrite)(void *privdata);
84
- void (*delWrite)(void *privdata);
85
- void (*cleanup)(void *privdata);
86
- void (*scheduleTimer)(void *privdata, struct timeval tv);
87
- } ev;
88
-
89
- /* Called when either the connection is terminated due to an error or per
90
- * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */
91
- redisDisconnectCallback *onDisconnect;
92
-
93
- /* Called when the first write event was received. */
94
- redisConnectCallback *onConnect;
95
-
96
- /* Regular command callbacks */
97
- redisCallbackList replies;
98
-
99
- /* Address used for connect() */
100
- struct sockaddr *saddr;
101
- size_t addrlen;
102
-
103
- /* Subscription callbacks */
104
- struct {
105
- redisCallbackList invalid;
106
- struct dict *channels;
107
- struct dict *patterns;
108
- } sub;
109
-
110
- /* Any configured RESP3 PUSH handler */
111
- redisAsyncPushFn *push_cb;
112
- } redisAsyncContext;
113
-
114
- /* Functions that proxy to hiredis */
115
- redisAsyncContext *redisAsyncConnectWithOptions(const redisOptions *options);
116
- redisAsyncContext *redisAsyncConnect(const char *ip, int port);
117
- redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr);
118
- redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port,
119
- const char *source_addr);
120
- redisAsyncContext *redisAsyncConnectUnix(const char *path);
121
- int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
122
- int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
123
-
124
- redisAsyncPushFn *redisAsyncSetPushCallback(redisAsyncContext *ac, redisAsyncPushFn *fn);
125
- int redisAsyncSetTimeout(redisAsyncContext *ac, struct timeval tv);
126
- void redisAsyncDisconnect(redisAsyncContext *ac);
127
- void redisAsyncFree(redisAsyncContext *ac);
128
-
129
- /* Handle read/write events */
130
- void redisAsyncHandleRead(redisAsyncContext *ac);
131
- void redisAsyncHandleWrite(redisAsyncContext *ac);
132
- void redisAsyncHandleTimeout(redisAsyncContext *ac);
133
- void redisAsyncRead(redisAsyncContext *ac);
134
- void redisAsyncWrite(redisAsyncContext *ac);
135
-
136
- /* Command functions for an async context. Write the command to the
137
- * output buffer and register the provided callback. */
138
- int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap);
139
- int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);
140
- int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen);
141
- int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len);
142
-
143
- #ifdef __cplusplus
144
- }
145
- #endif
146
-
147
- #endif
@@ -1,75 +0,0 @@
1
- /*
2
- * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
3
- * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
4
- *
5
- * All rights reserved.
6
- *
7
- * Redistribution and use in source and binary forms, with or without
8
- * modification, are permitted provided that the following conditions are met:
9
- *
10
- * * Redistributions of source code must retain the above copyright notice,
11
- * this list of conditions and the following disclaimer.
12
- * * Redistributions in binary form must reproduce the above copyright
13
- * notice, this list of conditions and the following disclaimer in the
14
- * documentation and/or other materials provided with the distribution.
15
- * * Neither the name of Redis nor the names of its contributors may be used
16
- * to endorse or promote products derived from this software without
17
- * specific prior written permission.
18
- *
19
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
- * POSSIBILITY OF SUCH DAMAGE.
30
- */
31
-
32
- #ifndef __HIREDIS_ASYNC_PRIVATE_H
33
- #define __HIREDIS_ASYNC_PRIVATE_H
34
-
35
- #define _EL_ADD_READ(ctx) \
36
- do { \
37
- refreshTimeout(ctx); \
38
- if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
39
- } while (0)
40
- #define _EL_DEL_READ(ctx) do { \
41
- if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \
42
- } while(0)
43
- #define _EL_ADD_WRITE(ctx) \
44
- do { \
45
- refreshTimeout(ctx); \
46
- if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \
47
- } while (0)
48
- #define _EL_DEL_WRITE(ctx) do { \
49
- if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \
50
- } while(0)
51
- #define _EL_CLEANUP(ctx) do { \
52
- if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \
53
- ctx->ev.cleanup = NULL; \
54
- } while(0);
55
-
56
- static inline void refreshTimeout(redisAsyncContext *ctx) {
57
- #define REDIS_TIMER_ISSET(tvp) \
58
- (tvp && ((tvp)->tv_sec || (tvp)->tv_usec))
59
-
60
- #define REDIS_EL_TIMER(ac, tvp) \
61
- if ((ac)->ev.scheduleTimer && REDIS_TIMER_ISSET(tvp)) { \
62
- (ac)->ev.scheduleTimer((ac)->ev.data, *(tvp)); \
63
- }
64
-
65
- if (ctx->c.flags & REDIS_CONNECTED) {
66
- REDIS_EL_TIMER(ctx, ctx->c.command_timeout);
67
- } else {
68
- REDIS_EL_TIMER(ctx, ctx->c.connect_timeout);
69
- }
70
- }
71
-
72
- void __redisAsyncDisconnect(redisAsyncContext *ac);
73
- void redisProcessCallbacks(redisAsyncContext *ac);
74
-
75
- #endif /* __HIREDIS_ASYNC_PRIVATE_H */
@@ -1,352 +0,0 @@
1
- /* Hash table implementation.
2
- *
3
- * This file implements in memory hash tables with insert/del/replace/find/
4
- * get-random-element operations. Hash tables will auto resize if needed
5
- * tables of power of two in size are used, collisions are handled by
6
- * chaining. See the source code for more information... :)
7
- *
8
- * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
9
- * All rights reserved.
10
- *
11
- * Redistribution and use in source and binary forms, with or without
12
- * modification, are permitted provided that the following conditions are met:
13
- *
14
- * * Redistributions of source code must retain the above copyright notice,
15
- * this list of conditions and the following disclaimer.
16
- * * Redistributions in binary form must reproduce the above copyright
17
- * notice, this list of conditions and the following disclaimer in the
18
- * documentation and/or other materials provided with the distribution.
19
- * * Neither the name of Redis nor the names of its contributors may be used
20
- * to endorse or promote products derived from this software without
21
- * specific prior written permission.
22
- *
23
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
- * POSSIBILITY OF SUCH DAMAGE.
34
- */
35
-
36
- #include "fmacros.h"
37
- #include "alloc.h"
38
- #include <stdlib.h>
39
- #include <assert.h>
40
- #include <limits.h>
41
- #include "dict.h"
42
-
43
- /* -------------------------- private prototypes ---------------------------- */
44
-
45
- static int _dictExpandIfNeeded(dict *ht);
46
- static unsigned long _dictNextPower(unsigned long size);
47
- static int _dictKeyIndex(dict *ht, const void *key);
48
- static int _dictInit(dict *ht, dictType *type, void *privDataPtr);
49
-
50
- /* -------------------------- hash functions -------------------------------- */
51
-
52
- /* Generic hash function (a popular one from Bernstein).
53
- * I tested a few and this was the best. */
54
- static unsigned int dictGenHashFunction(const unsigned char *buf, int len) {
55
- unsigned int hash = 5381;
56
-
57
- while (len--)
58
- hash = ((hash << 5) + hash) + (*buf++); /* hash * 33 + c */
59
- return hash;
60
- }
61
-
62
- /* ----------------------------- API implementation ------------------------- */
63
-
64
- /* Reset an hashtable already initialized with ht_init().
65
- * NOTE: This function should only called by ht_destroy(). */
66
- static void _dictReset(dict *ht) {
67
- ht->table = NULL;
68
- ht->size = 0;
69
- ht->sizemask = 0;
70
- ht->used = 0;
71
- }
72
-
73
- /* Create a new hash table */
74
- static dict *dictCreate(dictType *type, void *privDataPtr) {
75
- dict *ht = hi_malloc(sizeof(*ht));
76
- if (ht == NULL)
77
- return NULL;
78
-
79
- _dictInit(ht,type,privDataPtr);
80
- return ht;
81
- }
82
-
83
- /* Initialize the hash table */
84
- static int _dictInit(dict *ht, dictType *type, void *privDataPtr) {
85
- _dictReset(ht);
86
- ht->type = type;
87
- ht->privdata = privDataPtr;
88
- return DICT_OK;
89
- }
90
-
91
- /* Expand or create the hashtable */
92
- static int dictExpand(dict *ht, unsigned long size) {
93
- dict n; /* the new hashtable */
94
- unsigned long realsize = _dictNextPower(size), i;
95
-
96
- /* the size is invalid if it is smaller than the number of
97
- * elements already inside the hashtable */
98
- if (ht->used > size)
99
- return DICT_ERR;
100
-
101
- _dictInit(&n, ht->type, ht->privdata);
102
- n.size = realsize;
103
- n.sizemask = realsize-1;
104
- n.table = hi_calloc(realsize,sizeof(dictEntry*));
105
- if (n.table == NULL)
106
- return DICT_ERR;
107
-
108
- /* Copy all the elements from the old to the new table:
109
- * note that if the old hash table is empty ht->size is zero,
110
- * so dictExpand just creates an hash table. */
111
- n.used = ht->used;
112
- for (i = 0; i < ht->size && ht->used > 0; i++) {
113
- dictEntry *he, *nextHe;
114
-
115
- if (ht->table[i] == NULL) continue;
116
-
117
- /* For each hash entry on this slot... */
118
- he = ht->table[i];
119
- while(he) {
120
- unsigned int h;
121
-
122
- nextHe = he->next;
123
- /* Get the new element index */
124
- h = dictHashKey(ht, he->key) & n.sizemask;
125
- he->next = n.table[h];
126
- n.table[h] = he;
127
- ht->used--;
128
- /* Pass to the next element */
129
- he = nextHe;
130
- }
131
- }
132
- assert(ht->used == 0);
133
- hi_free(ht->table);
134
-
135
- /* Remap the new hashtable in the old */
136
- *ht = n;
137
- return DICT_OK;
138
- }
139
-
140
- /* Add an element to the target hash table */
141
- static int dictAdd(dict *ht, void *key, void *val) {
142
- int index;
143
- dictEntry *entry;
144
-
145
- /* Get the index of the new element, or -1 if
146
- * the element already exists. */
147
- if ((index = _dictKeyIndex(ht, key)) == -1)
148
- return DICT_ERR;
149
-
150
- /* Allocates the memory and stores key */
151
- entry = hi_malloc(sizeof(*entry));
152
- if (entry == NULL)
153
- return DICT_ERR;
154
-
155
- entry->next = ht->table[index];
156
- ht->table[index] = entry;
157
-
158
- /* Set the hash entry fields. */
159
- dictSetHashKey(ht, entry, key);
160
- dictSetHashVal(ht, entry, val);
161
- ht->used++;
162
- return DICT_OK;
163
- }
164
-
165
- /* Add an element, discarding the old if the key already exists.
166
- * Return 1 if the key was added from scratch, 0 if there was already an
167
- * element with such key and dictReplace() just performed a value update
168
- * operation. */
169
- static int dictReplace(dict *ht, void *key, void *val) {
170
- dictEntry *entry, auxentry;
171
-
172
- /* Try to add the element. If the key
173
- * does not exists dictAdd will succeed. */
174
- if (dictAdd(ht, key, val) == DICT_OK)
175
- return 1;
176
- /* It already exists, get the entry */
177
- entry = dictFind(ht, key);
178
- if (entry == NULL)
179
- return 0;
180
-
181
- /* Free the old value and set the new one */
182
- /* Set the new value and free the old one. Note that it is important
183
- * to do that in this order, as the value may just be exactly the same
184
- * as the previous one. In this context, think to reference counting,
185
- * you want to increment (set), and then decrement (free), and not the
186
- * reverse. */
187
- auxentry = *entry;
188
- dictSetHashVal(ht, entry, val);
189
- dictFreeEntryVal(ht, &auxentry);
190
- return 0;
191
- }
192
-
193
- /* Search and remove an element */
194
- static int dictDelete(dict *ht, const void *key) {
195
- unsigned int h;
196
- dictEntry *de, *prevde;
197
-
198
- if (ht->size == 0)
199
- return DICT_ERR;
200
- h = dictHashKey(ht, key) & ht->sizemask;
201
- de = ht->table[h];
202
-
203
- prevde = NULL;
204
- while(de) {
205
- if (dictCompareHashKeys(ht,key,de->key)) {
206
- /* Unlink the element from the list */
207
- if (prevde)
208
- prevde->next = de->next;
209
- else
210
- ht->table[h] = de->next;
211
-
212
- dictFreeEntryKey(ht,de);
213
- dictFreeEntryVal(ht,de);
214
- hi_free(de);
215
- ht->used--;
216
- return DICT_OK;
217
- }
218
- prevde = de;
219
- de = de->next;
220
- }
221
- return DICT_ERR; /* not found */
222
- }
223
-
224
- /* Destroy an entire hash table */
225
- static int _dictClear(dict *ht) {
226
- unsigned long i;
227
-
228
- /* Free all the elements */
229
- for (i = 0; i < ht->size && ht->used > 0; i++) {
230
- dictEntry *he, *nextHe;
231
-
232
- if ((he = ht->table[i]) == NULL) continue;
233
- while(he) {
234
- nextHe = he->next;
235
- dictFreeEntryKey(ht, he);
236
- dictFreeEntryVal(ht, he);
237
- hi_free(he);
238
- ht->used--;
239
- he = nextHe;
240
- }
241
- }
242
- /* Free the table and the allocated cache structure */
243
- hi_free(ht->table);
244
- /* Re-initialize the table */
245
- _dictReset(ht);
246
- return DICT_OK; /* never fails */
247
- }
248
-
249
- /* Clear & Release the hash table */
250
- static void dictRelease(dict *ht) {
251
- _dictClear(ht);
252
- hi_free(ht);
253
- }
254
-
255
- static dictEntry *dictFind(dict *ht, const void *key) {
256
- dictEntry *he;
257
- unsigned int h;
258
-
259
- if (ht->size == 0) return NULL;
260
- h = dictHashKey(ht, key) & ht->sizemask;
261
- he = ht->table[h];
262
- while(he) {
263
- if (dictCompareHashKeys(ht, key, he->key))
264
- return he;
265
- he = he->next;
266
- }
267
- return NULL;
268
- }
269
-
270
- static dictIterator *dictGetIterator(dict *ht) {
271
- dictIterator *iter = hi_malloc(sizeof(*iter));
272
- if (iter == NULL)
273
- return NULL;
274
-
275
- iter->ht = ht;
276
- iter->index = -1;
277
- iter->entry = NULL;
278
- iter->nextEntry = NULL;
279
- return iter;
280
- }
281
-
282
- static dictEntry *dictNext(dictIterator *iter) {
283
- while (1) {
284
- if (iter->entry == NULL) {
285
- iter->index++;
286
- if (iter->index >=
287
- (signed)iter->ht->size) break;
288
- iter->entry = iter->ht->table[iter->index];
289
- } else {
290
- iter->entry = iter->nextEntry;
291
- }
292
- if (iter->entry) {
293
- /* We need to save the 'next' here, the iterator user
294
- * may delete the entry we are returning. */
295
- iter->nextEntry = iter->entry->next;
296
- return iter->entry;
297
- }
298
- }
299
- return NULL;
300
- }
301
-
302
- static void dictReleaseIterator(dictIterator *iter) {
303
- hi_free(iter);
304
- }
305
-
306
- /* ------------------------- private functions ------------------------------ */
307
-
308
- /* Expand the hash table if needed */
309
- static int _dictExpandIfNeeded(dict *ht) {
310
- /* If the hash table is empty expand it to the initial size,
311
- * if the table is "full" double its size. */
312
- if (ht->size == 0)
313
- return dictExpand(ht, DICT_HT_INITIAL_SIZE);
314
- if (ht->used == ht->size)
315
- return dictExpand(ht, ht->size*2);
316
- return DICT_OK;
317
- }
318
-
319
- /* Our hash table capability is a power of two */
320
- static unsigned long _dictNextPower(unsigned long size) {
321
- unsigned long i = DICT_HT_INITIAL_SIZE;
322
-
323
- if (size >= LONG_MAX) return LONG_MAX;
324
- while(1) {
325
- if (i >= size)
326
- return i;
327
- i *= 2;
328
- }
329
- }
330
-
331
- /* Returns the index of a free slot that can be populated with
332
- * an hash entry for the given 'key'.
333
- * If the key already exists, -1 is returned. */
334
- static int _dictKeyIndex(dict *ht, const void *key) {
335
- unsigned int h;
336
- dictEntry *he;
337
-
338
- /* Expand the hashtable if needed */
339
- if (_dictExpandIfNeeded(ht) == DICT_ERR)
340
- return -1;
341
- /* Compute the key hash value */
342
- h = dictHashKey(ht, key) & ht->sizemask;
343
- /* Search if this slot does not already contain the given key */
344
- he = ht->table[h];
345
- while(he) {
346
- if (dictCompareHashKeys(ht, key, he->key))
347
- return -1;
348
- he = he->next;
349
- }
350
- return h;
351
- }
352
-
@@ -1,126 +0,0 @@
1
- /* Hash table implementation.
2
- *
3
- * This file implements in memory hash tables with insert/del/replace/find/
4
- * get-random-element operations. Hash tables will auto resize if needed
5
- * tables of power of two in size are used, collisions are handled by
6
- * chaining. See the source code for more information... :)
7
- *
8
- * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
9
- * All rights reserved.
10
- *
11
- * Redistribution and use in source and binary forms, with or without
12
- * modification, are permitted provided that the following conditions are met:
13
- *
14
- * * Redistributions of source code must retain the above copyright notice,
15
- * this list of conditions and the following disclaimer.
16
- * * Redistributions in binary form must reproduce the above copyright
17
- * notice, this list of conditions and the following disclaimer in the
18
- * documentation and/or other materials provided with the distribution.
19
- * * Neither the name of Redis nor the names of its contributors may be used
20
- * to endorse or promote products derived from this software without
21
- * specific prior written permission.
22
- *
23
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
- * POSSIBILITY OF SUCH DAMAGE.
34
- */
35
-
36
- #ifndef __DICT_H
37
- #define __DICT_H
38
-
39
- #define DICT_OK 0
40
- #define DICT_ERR 1
41
-
42
- /* Unused arguments generate annoying warnings... */
43
- #define DICT_NOTUSED(V) ((void) V)
44
-
45
- typedef struct dictEntry {
46
- void *key;
47
- void *val;
48
- struct dictEntry *next;
49
- } dictEntry;
50
-
51
- typedef struct dictType {
52
- unsigned int (*hashFunction)(const void *key);
53
- void *(*keyDup)(void *privdata, const void *key);
54
- void *(*valDup)(void *privdata, const void *obj);
55
- int (*keyCompare)(void *privdata, const void *key1, const void *key2);
56
- void (*keyDestructor)(void *privdata, void *key);
57
- void (*valDestructor)(void *privdata, void *obj);
58
- } dictType;
59
-
60
- typedef struct dict {
61
- dictEntry **table;
62
- dictType *type;
63
- unsigned long size;
64
- unsigned long sizemask;
65
- unsigned long used;
66
- void *privdata;
67
- } dict;
68
-
69
- typedef struct dictIterator {
70
- dict *ht;
71
- int index;
72
- dictEntry *entry, *nextEntry;
73
- } dictIterator;
74
-
75
- /* This is the initial size of every hash table */
76
- #define DICT_HT_INITIAL_SIZE 4
77
-
78
- /* ------------------------------- Macros ------------------------------------*/
79
- #define dictFreeEntryVal(ht, entry) \
80
- if ((ht)->type->valDestructor) \
81
- (ht)->type->valDestructor((ht)->privdata, (entry)->val)
82
-
83
- #define dictSetHashVal(ht, entry, _val_) do { \
84
- if ((ht)->type->valDup) \
85
- entry->val = (ht)->type->valDup((ht)->privdata, _val_); \
86
- else \
87
- entry->val = (_val_); \
88
- } while(0)
89
-
90
- #define dictFreeEntryKey(ht, entry) \
91
- if ((ht)->type->keyDestructor) \
92
- (ht)->type->keyDestructor((ht)->privdata, (entry)->key)
93
-
94
- #define dictSetHashKey(ht, entry, _key_) do { \
95
- if ((ht)->type->keyDup) \
96
- entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
97
- else \
98
- entry->key = (_key_); \
99
- } while(0)
100
-
101
- #define dictCompareHashKeys(ht, key1, key2) \
102
- (((ht)->type->keyCompare) ? \
103
- (ht)->type->keyCompare((ht)->privdata, key1, key2) : \
104
- (key1) == (key2))
105
-
106
- #define dictHashKey(ht, key) (ht)->type->hashFunction(key)
107
-
108
- #define dictGetEntryKey(he) ((he)->key)
109
- #define dictGetEntryVal(he) ((he)->val)
110
- #define dictSlots(ht) ((ht)->size)
111
- #define dictSize(ht) ((ht)->used)
112
-
113
- /* API */
114
- static unsigned int dictGenHashFunction(const unsigned char *buf, int len);
115
- static dict *dictCreate(dictType *type, void *privDataPtr);
116
- static int dictExpand(dict *ht, unsigned long size);
117
- static int dictAdd(dict *ht, void *key, void *val);
118
- static int dictReplace(dict *ht, void *key, void *val);
119
- static int dictDelete(dict *ht, const void *key);
120
- static void dictRelease(dict *ht);
121
- static dictEntry * dictFind(dict *ht, const void *key);
122
- static dictIterator *dictGetIterator(dict *ht);
123
- static dictEntry *dictNext(dictIterator *iter);
124
- static void dictReleaseIterator(dictIterator *iter);
125
-
126
- #endif /* __DICT_H */