redis-client 0.2.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/Gemfile +1 -2
  4. data/Gemfile.lock +2 -3
  5. data/README.md +71 -8
  6. data/Rakefile +43 -23
  7. data/lib/redis_client/command_builder.rb +91 -0
  8. data/lib/redis_client/config.rb +19 -50
  9. data/lib/redis_client/connection_mixin.rb +40 -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 +183 -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 -61
  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 */