ffi-nats-core 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/ffi-nats-core.gemspec +8 -0
  3. data/lib/ffi/nats/core/version.rb +1 -1
  4. data/vendor/cnats/CMakeLists.txt +137 -0
  5. data/vendor/cnats/adapters/libevent.h +220 -0
  6. data/vendor/cnats/adapters/libuv.h +472 -0
  7. data/vendor/cnats/examples/CMakeLists.txt +56 -0
  8. data/vendor/cnats/examples/asynctimeout.c +83 -0
  9. data/vendor/cnats/examples/examples.h +322 -0
  10. data/vendor/cnats/examples/libevent-pub.c +136 -0
  11. data/vendor/cnats/examples/libevent-sub.c +104 -0
  12. data/vendor/cnats/examples/libuv-pub.c +120 -0
  13. data/vendor/cnats/examples/libuv-sub.c +114 -0
  14. data/vendor/cnats/examples/publisher.c +62 -0
  15. data/vendor/cnats/examples/queuegroup.c +132 -0
  16. data/vendor/cnats/examples/replier.c +149 -0
  17. data/vendor/cnats/examples/requestor.c +75 -0
  18. data/vendor/cnats/examples/subscriber.c +133 -0
  19. data/vendor/cnats/src/CMakeLists.txt +31 -0
  20. data/vendor/cnats/src/asynccb.c +66 -0
  21. data/vendor/cnats/src/asynccb.h +42 -0
  22. data/vendor/cnats/src/buf.c +246 -0
  23. data/vendor/cnats/src/buf.h +116 -0
  24. data/vendor/cnats/src/comsock.c +474 -0
  25. data/vendor/cnats/src/comsock.h +81 -0
  26. data/vendor/cnats/src/conn.c +2725 -0
  27. data/vendor/cnats/src/conn.h +75 -0
  28. data/vendor/cnats/src/err.h +31 -0
  29. data/vendor/cnats/src/gc.h +27 -0
  30. data/vendor/cnats/src/hash.c +725 -0
  31. data/vendor/cnats/src/hash.h +141 -0
  32. data/vendor/cnats/src/include/n-unix.h +56 -0
  33. data/vendor/cnats/src/include/n-win.h +59 -0
  34. data/vendor/cnats/src/mem.h +20 -0
  35. data/vendor/cnats/src/msg.c +155 -0
  36. data/vendor/cnats/src/msg.h +43 -0
  37. data/vendor/cnats/src/nats.c +1734 -0
  38. data/vendor/cnats/src/nats.h +2024 -0
  39. data/vendor/cnats/src/natsp.h +518 -0
  40. data/vendor/cnats/src/natstime.c +79 -0
  41. data/vendor/cnats/src/natstime.h +27 -0
  42. data/vendor/cnats/src/nuid.c +265 -0
  43. data/vendor/cnats/src/nuid.h +21 -0
  44. data/vendor/cnats/src/opts.c +1030 -0
  45. data/vendor/cnats/src/opts.h +19 -0
  46. data/vendor/cnats/src/parser.c +869 -0
  47. data/vendor/cnats/src/parser.h +87 -0
  48. data/vendor/cnats/src/pub.c +293 -0
  49. data/vendor/cnats/src/srvpool.c +380 -0
  50. data/vendor/cnats/src/srvpool.h +71 -0
  51. data/vendor/cnats/src/stats.c +54 -0
  52. data/vendor/cnats/src/stats.h +21 -0
  53. data/vendor/cnats/src/status.c +60 -0
  54. data/vendor/cnats/src/status.h +95 -0
  55. data/vendor/cnats/src/sub.c +956 -0
  56. data/vendor/cnats/src/sub.h +34 -0
  57. data/vendor/cnats/src/timer.c +86 -0
  58. data/vendor/cnats/src/timer.h +57 -0
  59. data/vendor/cnats/src/unix/cond.c +103 -0
  60. data/vendor/cnats/src/unix/mutex.c +107 -0
  61. data/vendor/cnats/src/unix/sock.c +105 -0
  62. data/vendor/cnats/src/unix/thread.c +162 -0
  63. data/vendor/cnats/src/url.c +134 -0
  64. data/vendor/cnats/src/url.h +24 -0
  65. data/vendor/cnats/src/util.c +823 -0
  66. data/vendor/cnats/src/util.h +75 -0
  67. data/vendor/cnats/src/version.h +29 -0
  68. data/vendor/cnats/src/version.h.in +29 -0
  69. data/vendor/cnats/src/win/cond.c +86 -0
  70. data/vendor/cnats/src/win/mutex.c +54 -0
  71. data/vendor/cnats/src/win/sock.c +158 -0
  72. data/vendor/cnats/src/win/strings.c +108 -0
  73. data/vendor/cnats/src/win/thread.c +180 -0
  74. data/vendor/cnats/test/CMakeLists.txt +35 -0
  75. data/vendor/cnats/test/certs/ca.pem +38 -0
  76. data/vendor/cnats/test/certs/client-cert.pem +30 -0
  77. data/vendor/cnats/test/certs/client-key.pem +51 -0
  78. data/vendor/cnats/test/certs/server-cert.pem +31 -0
  79. data/vendor/cnats/test/certs/server-key.pem +51 -0
  80. data/vendor/cnats/test/dylib/CMakeLists.txt +10 -0
  81. data/vendor/cnats/test/dylib/nonats.c +13 -0
  82. data/vendor/cnats/test/list.txt +125 -0
  83. data/vendor/cnats/test/test.c +11655 -0
  84. data/vendor/cnats/test/tls.conf +15 -0
  85. data/vendor/cnats/test/tlsverify.conf +19 -0
  86. metadata +83 -1
@@ -0,0 +1,75 @@
1
+ // Copyright 2015 Apcera Inc. All rights reserved.
2
+
3
+ #ifndef CONN_H_
4
+ #define CONN_H_
5
+
6
+ #include "natsp.h"
7
+
8
+ #ifdef DEV_MODE
9
+ // For type safety
10
+
11
+ void natsConn_Lock(natsConnection *nc);
12
+ void natsConn_Unlock(natsConnection *nc);
13
+
14
+ #else
15
+ // We know what we are doing :-)
16
+
17
+ #define natsConn_Lock(c) (natsMutex_Lock((c)->mu))
18
+ #define natsConn_Unlock(c) (natsMutex_Unlock((c)->mu))
19
+
20
+ #endif // DEV_MODE
21
+
22
+ natsStatus
23
+ natsConn_create(natsConnection **newConn, natsOptions *options);
24
+
25
+ void
26
+ natsConn_retain(natsConnection *nc);
27
+
28
+ void
29
+ natsConn_release(natsConnection *nc);
30
+
31
+ natsStatus
32
+ natsConn_bufferWrite(natsConnection *nc, const char *buffer, int len);
33
+
34
+ natsStatus
35
+ natsConn_bufferFlush(natsConnection *nc);
36
+
37
+ bool
38
+ natsConn_isClosed(natsConnection *nc);
39
+
40
+ bool
41
+ natsConn_isReconnecting(natsConnection *nc);
42
+
43
+ void
44
+ natsConn_kickFlusher(natsConnection *nc);
45
+
46
+ natsStatus
47
+ natsConn_processMsg(natsConnection *nc, char *buf, int bufLen);
48
+
49
+ void
50
+ natsConn_processOK(natsConnection *nc);
51
+
52
+ void
53
+ natsConn_processErr(natsConnection *nc, char *buf, int bufLen);
54
+
55
+ void
56
+ natsConn_processPing(natsConnection *nc);
57
+
58
+ void
59
+ natsConn_processPong(natsConnection *nc);
60
+
61
+ natsStatus
62
+ natsConn_subscribe(natsSubscription **newSub,
63
+ natsConnection *nc, const char *subj, const char *queue,
64
+ int64_t timeout, natsMsgHandler cb, void *cbClosure);
65
+
66
+ natsStatus
67
+ natsConn_unsubscribe(natsConnection *nc, natsSubscription *sub, int max);
68
+
69
+ void
70
+ natsConn_removeSubscription(natsConnection *nc, natsSubscription *sub, bool needsLock);
71
+
72
+ void
73
+ natsConn_processAsyncINFO(natsConnection *nc, char *buf, int len);
74
+
75
+ #endif /* CONN_H_ */
@@ -0,0 +1,31 @@
1
+ // Copyright 2015 Apcera Inc. All rights reserved.
2
+
3
+
4
+ #ifndef ERR_H_
5
+ #define ERR_H_
6
+
7
+ #include "status.h"
8
+ #include "nats.h"
9
+ #include "natsp.h"
10
+
11
+ #define NATS_SSL_ERR_REASON_STRING ERR_reason_error_string(ERR_get_error())
12
+
13
+ #define nats_setDefaultError(e) nats_setError((e), "%s", natsStatus_GetText(e))
14
+
15
+ #define nats_setError(e, f, ...) nats_setErrorReal(__FILE__, __NATS_FUNCTION__, __LINE__, (e), (f), __VA_ARGS__)
16
+
17
+ natsStatus
18
+ nats_setErrorReal(const char *fileName, const char *funcName, int line, natsStatus errSts, const void *errTxtFmt, ...);
19
+
20
+ #define NATS_UPDATE_ERR_STACK(s) (s == NATS_OK ? s : nats_updateErrStack(s, __NATS_FUNCTION__))
21
+
22
+ natsStatus
23
+ nats_updateErrStack(natsStatus err, const char *func);
24
+
25
+ void
26
+ nats_clearLastError(void);
27
+
28
+ void
29
+ nats_doNotUpdateErrStack(bool skipStackUpdate);
30
+
31
+ #endif /* ERR_H_ */
@@ -0,0 +1,27 @@
1
+ // Copyright 2015 Apcera Inc. All rights reserved.
2
+
3
+
4
+ #ifndef GC_H_
5
+ #define GC_H_
6
+
7
+ // This callback implements the specific code to free the given object.
8
+ // This is invoked by the garbage collector.
9
+ typedef void (*nats_FreeObjectCb)(void *object);
10
+
11
+ // This structure should be included as the first field of any object
12
+ // that needs to be garbage collected.
13
+ typedef struct __natsGCItem
14
+ {
15
+ struct __natsGCItem *next;
16
+ nats_FreeObjectCb freeCb;
17
+
18
+ } natsGCItem;
19
+
20
+ // Gives the object to the garbage collector.
21
+ // Returns 'true' if the GC takes ownership, 'false' otherwise (in this case,
22
+ // the caller is responsible for freeing the object).
23
+ bool
24
+ natsGC_collect(natsGCItem *item);
25
+
26
+
27
+ #endif /* GC_H_ */
@@ -0,0 +1,725 @@
1
+ // Copyright 2015 Apcera Inc. All rights reserved.
2
+
3
+ #include "natsp.h"
4
+
5
+ #include <string.h>
6
+
7
+ #include "status.h"
8
+ #include "mem.h"
9
+ #include "hash.h"
10
+
11
+ #define _freeEntry(e) { NATS_FREE(e); (e) = NULL; }
12
+
13
+ #define _OFF32 (2166136261)
14
+ #define _YP32 (709607)
15
+
16
+ #define _BSZ (8)
17
+ #define _WSZ (4)
18
+
19
+ static int _DWSZ = _WSZ << 1; // 8
20
+ static int _DDWSZ = _WSZ << 2; // 16
21
+
22
+ static int _MAX_BKT_SIZE = (1 << 30) - 1;
23
+
24
+ natsStatus
25
+ natsHash_Create(natsHash **newHash, int initialSize)
26
+ {
27
+ natsHash *hash = NULL;
28
+
29
+ if (initialSize <= 0)
30
+ return nats_setDefaultError(NATS_INVALID_ARG);
31
+
32
+ if ((initialSize & (initialSize - 1)) != 0)
33
+ {
34
+ // Size of buckets must be power of 2
35
+ initialSize--;
36
+ initialSize |= initialSize >> 1;
37
+ initialSize |= initialSize >> 2;
38
+ initialSize |= initialSize >> 4;
39
+ initialSize |= initialSize >> 8;
40
+ initialSize |= initialSize >> 16;
41
+ initialSize++;
42
+ }
43
+
44
+ hash = (natsHash*) NATS_CALLOC(1, sizeof(natsHash));
45
+ if (hash == NULL)
46
+ return nats_setDefaultError(NATS_NO_MEMORY);
47
+
48
+ hash->mask = (initialSize - 1);
49
+ hash->numBkts = initialSize;
50
+ hash->canResize = true;
51
+ hash->bkts = (natsHashEntry**) NATS_CALLOC(initialSize, sizeof(natsHashEntry*));
52
+ if (hash->bkts == NULL)
53
+ {
54
+ NATS_FREE(hash);
55
+ return nats_setDefaultError(NATS_NO_MEMORY);
56
+ }
57
+
58
+ *newHash = hash;
59
+
60
+ return NATS_OK;
61
+ }
62
+
63
+ static natsStatus
64
+ _resize(natsHash *hash, int newSize)
65
+ {
66
+ natsHashEntry **bkts = NULL;
67
+ int newMask = newSize - 1;
68
+ natsHashEntry *ne;
69
+ natsHashEntry *e;
70
+ int k;
71
+ int newIndex;
72
+
73
+ bkts = (natsHashEntry**) NATS_CALLOC(newSize, sizeof(natsHashEntry*));
74
+ if (bkts == NULL)
75
+ return nats_setDefaultError(NATS_NO_MEMORY);
76
+
77
+ for (k = 0; k < hash->numBkts; k++)
78
+ {
79
+ e = hash->bkts[k];
80
+ while (e != NULL)
81
+ {
82
+ ne = e;
83
+ e = e->next;
84
+
85
+ newIndex = ne->key & newMask;
86
+ ne->next = bkts[newIndex];
87
+ bkts[newIndex] = ne;
88
+ }
89
+ }
90
+
91
+ NATS_FREE(hash->bkts);
92
+ hash->bkts = bkts;
93
+ hash->mask = newMask;
94
+ hash->numBkts = newSize;
95
+
96
+ return NATS_OK;
97
+ }
98
+
99
+ static natsStatus
100
+ _grow(natsHash *hash)
101
+ {
102
+ // Can't grow beyond max signed int for now
103
+ if (hash->numBkts >= _MAX_BKT_SIZE)
104
+ return nats_setDefaultError(NATS_NO_MEMORY);
105
+
106
+ return _resize(hash, 2 * (hash->numBkts));
107
+ }
108
+
109
+ static void
110
+ _shrink(natsHash *hash)
111
+ {
112
+ if (hash->numBkts <= _BSZ)
113
+ return;
114
+
115
+ // Ignore memory issue when resizing, since if we fail to allocate
116
+ // the original hash is still intact.
117
+ (void) _resize(hash, hash->numBkts / 2);
118
+ }
119
+
120
+ static natsHashEntry*
121
+ _createEntry(int64_t key, void *data)
122
+ {
123
+ natsHashEntry *e = (natsHashEntry*) NATS_MALLOC(sizeof(natsHashEntry));
124
+
125
+ if (e == NULL)
126
+ return NULL;
127
+
128
+ e->key = key;
129
+ e->data = data;
130
+ e->next = NULL;
131
+
132
+ return e;
133
+ }
134
+
135
+ natsStatus
136
+ natsHash_Set(natsHash *hash, int64_t key, void *data, void **oldData)
137
+ {
138
+ natsStatus s = NATS_OK;
139
+ int index = (int) (key & hash->mask);
140
+ natsHashEntry *newEntry = NULL;
141
+ natsHashEntry *e;
142
+
143
+ if (oldData != NULL)
144
+ *oldData = NULL;
145
+
146
+ e = (natsHashEntry*) hash->bkts[index];
147
+ while (e != NULL)
148
+ {
149
+ if (e->key == key)
150
+ {
151
+ // Success, replace data field
152
+ if (oldData != NULL)
153
+ *oldData = e->data;
154
+ e->data = data;
155
+ return NATS_OK;
156
+ }
157
+
158
+ e = e->next;
159
+ }
160
+
161
+ // We have a new entry here
162
+ newEntry = _createEntry(key, data);
163
+ if (newEntry == NULL)
164
+ return nats_setDefaultError(NATS_NO_MEMORY);
165
+
166
+ newEntry->next = hash->bkts[index];
167
+ hash->bkts[index] = newEntry;
168
+ hash->used++;
169
+
170
+ // Check for resizing
171
+ if (hash->canResize && (hash->used > hash->numBkts))
172
+ s = _grow(hash);
173
+
174
+ return NATS_UPDATE_ERR_STACK(s);
175
+ }
176
+
177
+ void*
178
+ natsHash_Get(natsHash *hash, int64_t key)
179
+ {
180
+ natsHashEntry *e;
181
+
182
+ e = hash->bkts[key & hash->mask];
183
+ while (e != NULL)
184
+ {
185
+ if (e->key == key)
186
+ return e->data;
187
+
188
+ e = e->next;
189
+ }
190
+
191
+ return NULL;
192
+ }
193
+
194
+ void*
195
+ natsHash_Remove(natsHash *hash, int64_t key)
196
+ {
197
+ natsHashEntry *entryRemoved = NULL;
198
+ void *dataRemoved = NULL;
199
+ natsHashEntry **e;
200
+
201
+ e = (natsHashEntry**) &(hash->bkts[key & hash->mask]);
202
+ while (*e != NULL)
203
+ {
204
+ if ((*e)->key == key)
205
+ {
206
+ // Success
207
+ entryRemoved = *e;
208
+ dataRemoved = entryRemoved->data;
209
+
210
+ *e = entryRemoved->next;
211
+ _freeEntry(entryRemoved);
212
+
213
+ hash->used--;
214
+
215
+ // Check for resizing
216
+ if (hash->canResize
217
+ && (hash->numBkts > _BSZ)
218
+ && (hash->used < hash->numBkts / 4))
219
+ {
220
+ _shrink(hash);
221
+ }
222
+
223
+ break;
224
+ }
225
+
226
+ e = (natsHashEntry**) &((*e)->next);
227
+ }
228
+
229
+ return dataRemoved;
230
+ }
231
+
232
+ void
233
+ natsHash_Destroy(natsHash *hash)
234
+ {
235
+ natsHashEntry *e, *ne;
236
+ int i;
237
+
238
+ if (hash == NULL)
239
+ return;
240
+
241
+ for (i = 0; i < hash->numBkts; i++)
242
+ {
243
+ e = hash->bkts[i];
244
+ while (e != NULL)
245
+ {
246
+ ne = e->next;
247
+
248
+ _freeEntry(e);
249
+
250
+ e = ne;
251
+ }
252
+ }
253
+
254
+ NATS_FREE(hash->bkts);
255
+ NATS_FREE(hash);
256
+ }
257
+
258
+ void
259
+ natsHashIter_Init(natsHashIter *iter, natsHash *hash)
260
+ {
261
+ memset(iter, 0, sizeof(natsHashIter));
262
+
263
+ hash->canResize = false;
264
+ iter->hash = hash;
265
+ iter->current = hash->bkts[0];
266
+ iter->next = iter->current;
267
+ }
268
+
269
+ bool
270
+ natsHashIter_Next(natsHashIter *iter, int64_t *key, void **value)
271
+ {
272
+ if ((iter->started) && (iter->next == NULL))
273
+ return false;
274
+
275
+ if (!(iter->started) && (iter->current == NULL))
276
+ {
277
+ while ((iter->next == NULL)
278
+ && (iter->currBkt < (iter->hash->numBkts - 1)))
279
+ {
280
+ iter->next = iter->hash->bkts[++(iter->currBkt)];
281
+ }
282
+
283
+ if (iter->next == NULL)
284
+ {
285
+ iter->started = true;
286
+ return false;
287
+ }
288
+ }
289
+
290
+ iter->started = true;
291
+
292
+ iter->current = iter->next;
293
+ if (iter->current != NULL)
294
+ {
295
+ if (key != NULL)
296
+ *key = iter->current->key;
297
+ if (value != NULL)
298
+ *value = iter->current->data;
299
+
300
+ iter->next = iter->current->next;
301
+ }
302
+
303
+ while ((iter->next == NULL)
304
+ && (iter->currBkt < (iter->hash->numBkts - 1)))
305
+ {
306
+ iter->next = iter->hash->bkts[++(iter->currBkt)];
307
+ }
308
+
309
+ return true;
310
+ }
311
+
312
+ natsStatus
313
+ natsHashIter_RemoveCurrent(natsHashIter *iter)
314
+ {
315
+ int64_t key;
316
+
317
+ if (iter->current == NULL)
318
+ return nats_setDefaultError(NATS_NOT_FOUND);
319
+
320
+ key = iter->current->key;
321
+ iter->current = iter->next;
322
+
323
+ (void) natsHash_Remove(iter->hash, key);
324
+
325
+ return NATS_OK;
326
+ }
327
+
328
+ void
329
+ natsHashIter_Done(natsHashIter *iter)
330
+ {
331
+ iter->hash->canResize = true;
332
+ }
333
+
334
+
335
+ // Jesteress derivative of FNV1A from [http://www.sanmayce.com/Fastest_Hash/]
336
+ uint32_t
337
+ natsStrHash_Hash(const char *data, int dataLen)
338
+ {
339
+ int i = 0;
340
+ int dlen = dataLen;
341
+ uint32_t h32 = (uint32_t)_OFF32;
342
+ uint64_t k1, k2;
343
+
344
+ for (; dlen >= _DDWSZ; dlen -= _DDWSZ)
345
+ {
346
+ k1 = *(uint64_t*) &(data[i]);
347
+ k2 = *(uint64_t*) &(data[i + 4]);
348
+ h32 = (uint32_t) ((((uint64_t) h32) ^ ((k1<<5 | k1>>27) ^ k2)) * _YP32);
349
+ i += _DDWSZ;
350
+ }
351
+
352
+ // Cases: 0,1,2,3,4,5,6,7
353
+ if ((dlen & _DWSZ) > 0)
354
+ {
355
+ k1 = *(uint64_t*) &(data[i]);
356
+ h32 = (uint32_t) ((((uint64_t) h32) ^ k1) * _YP32);
357
+ i += _DWSZ;
358
+ }
359
+ if ((dlen & _WSZ) > 0)
360
+ {
361
+ k1 = *(uint32_t*) &(data[i]);
362
+ h32 = (uint32_t) ((((uint64_t) h32) ^ k1) * _YP32);
363
+ i += _WSZ;
364
+ }
365
+ if ((dlen & 1) > 0)
366
+ {
367
+ h32 = (h32 ^ (uint32_t)(data[i])) * _YP32;
368
+ }
369
+
370
+ return h32 ^ (h32 >> 16);
371
+ }
372
+
373
+ natsStatus
374
+ natsStrHash_Create(natsStrHash **newHash, int initialSize)
375
+ {
376
+ natsStrHash *hash = NULL;
377
+
378
+ if (initialSize <= 0)
379
+ return nats_setDefaultError(NATS_INVALID_ARG);
380
+
381
+ if ((initialSize & (initialSize - 1)) != 0)
382
+ {
383
+ // Size of buckets must be power of 2
384
+ initialSize--;
385
+ initialSize |= initialSize >> 1;
386
+ initialSize |= initialSize >> 2;
387
+ initialSize |= initialSize >> 4;
388
+ initialSize |= initialSize >> 8;
389
+ initialSize |= initialSize >> 16;
390
+ initialSize++;
391
+ }
392
+
393
+ hash = (natsStrHash*) NATS_CALLOC(1, sizeof(natsStrHash));
394
+ if (hash == NULL)
395
+ return nats_setDefaultError(NATS_NO_MEMORY);
396
+
397
+ hash->mask = (initialSize - 1);
398
+ hash->numBkts = initialSize;
399
+ hash->canResize = true;
400
+ hash->bkts = (natsStrHashEntry**) NATS_CALLOC(initialSize, sizeof(natsStrHashEntry*));
401
+ if (hash->bkts == NULL)
402
+ {
403
+ NATS_FREE(hash);
404
+ return nats_setDefaultError(NATS_NO_MEMORY);
405
+ }
406
+
407
+ *newHash = hash;
408
+
409
+ return NATS_OK;
410
+ }
411
+
412
+ static natsStatus
413
+ _resizeStr(natsStrHash *hash, int newSize)
414
+ {
415
+ natsStrHashEntry **bkts = NULL;
416
+ int newMask = newSize - 1;
417
+ natsStrHashEntry *ne;
418
+ natsStrHashEntry *e;
419
+ int k;
420
+ int newIndex;
421
+
422
+ bkts = (natsStrHashEntry**) NATS_CALLOC(newSize, sizeof(natsStrHashEntry*));
423
+ if (bkts == NULL)
424
+ return nats_setDefaultError(NATS_NO_MEMORY);
425
+
426
+ for (k = 0; k < hash->numBkts; k++)
427
+ {
428
+ e = hash->bkts[k];
429
+ while (e != NULL)
430
+ {
431
+ ne = e;
432
+ e = e->next;
433
+
434
+ newIndex = ne->hk & newMask;
435
+ ne->next = bkts[newIndex];
436
+ bkts[newIndex] = ne;
437
+ }
438
+ }
439
+
440
+ NATS_FREE(hash->bkts);
441
+ hash->bkts = bkts;
442
+ hash->mask = newMask;
443
+ hash->numBkts = newSize;
444
+
445
+ return NATS_OK;
446
+ }
447
+
448
+ static natsStatus
449
+ _growStr(natsStrHash *hash)
450
+ {
451
+ // Can't grow beyond max signed int for now
452
+ if (hash->numBkts >= _MAX_BKT_SIZE)
453
+ return nats_setDefaultError(NATS_NO_MEMORY);
454
+
455
+ return _resizeStr(hash, 2 * (hash->numBkts));
456
+ }
457
+
458
+ static void
459
+ _shrinkStr(natsStrHash *hash)
460
+ {
461
+ if (hash->numBkts <= _BSZ)
462
+ return;
463
+
464
+ // Ignore memory issue when resizing, since if we fail to allocate
465
+ // the original hash is still intact.
466
+ (void) _resizeStr(hash, hash->numBkts / 2);
467
+ }
468
+
469
+
470
+ static natsStrHashEntry*
471
+ _createStrEntry(uint32_t hk, char *key, bool copyKey, void *data)
472
+ {
473
+ natsStrHashEntry *e = (natsStrHashEntry*) NATS_MALLOC(sizeof(natsStrHashEntry));
474
+
475
+ if (e == NULL)
476
+ return NULL;
477
+
478
+ e->hk = hk;
479
+ e->key = (copyKey ? NATS_STRDUP(key) : key);
480
+ e->freeKey = copyKey;
481
+ e->data = data;
482
+ e->next = NULL;
483
+
484
+ if (e->key == NULL)
485
+ {
486
+ NATS_FREE(e);
487
+ return NULL;
488
+ }
489
+
490
+ return e;
491
+ }
492
+
493
+ natsStatus
494
+ natsStrHash_Set(natsStrHash *hash, char *key, bool copyKey,
495
+ void *data, void **oldData)
496
+ {
497
+ natsStatus s = NATS_OK;
498
+ uint32_t hk = 0;
499
+ int index = 0;
500
+ natsStrHashEntry *newEntry = NULL;
501
+ natsStrHashEntry *e;
502
+ char *oldKey;
503
+
504
+ if (oldData != NULL)
505
+ *oldData = NULL;
506
+
507
+ hk = natsStrHash_Hash(key, (int) strlen(key));
508
+ index = hk & hash->mask;
509
+
510
+ e = (natsStrHashEntry*) hash->bkts[index];
511
+ while (e != NULL)
512
+ {
513
+ if ((e->hk == hk)
514
+ && (strcmp(e->key, key) == 0))
515
+ {
516
+ // Success, replace data field
517
+ if (oldData != NULL)
518
+ *oldData = e->data;
519
+ e->data = data;
520
+
521
+ if (copyKey)
522
+ {
523
+ oldKey = e->key;
524
+ e->key = NATS_STRDUP(key);
525
+
526
+ if (e->freeKey)
527
+ NATS_FREE(oldKey);
528
+
529
+ e->freeKey = true;
530
+ }
531
+ return NATS_OK;
532
+ }
533
+
534
+ e = e->next;
535
+ }
536
+
537
+ // We have a new entry here
538
+ newEntry = _createStrEntry(hk, key, copyKey, data);
539
+ if (newEntry == NULL)
540
+ return nats_setDefaultError(NATS_NO_MEMORY);
541
+
542
+ newEntry->next = hash->bkts[index];
543
+ hash->bkts[index] = newEntry;
544
+ hash->used++;
545
+
546
+ // Check for resizing
547
+ if (hash->canResize && (hash->used > hash->numBkts))
548
+ s = _growStr(hash);
549
+
550
+ return NATS_UPDATE_ERR_STACK(s);
551
+ }
552
+
553
+ void*
554
+ natsStrHash_Get(natsStrHash *hash, char *key)
555
+ {
556
+ natsStrHashEntry *e;
557
+ uint32_t hk = natsStrHash_Hash(key, (int) strlen(key));
558
+
559
+ e = hash->bkts[hk & hash->mask];
560
+ while (e != NULL)
561
+ {
562
+ if ((e->hk == hk)
563
+ && (strcmp(e->key, key) == 0))
564
+ {
565
+ return e->data;
566
+ }
567
+
568
+ e = e->next;
569
+ }
570
+
571
+ return NULL;
572
+ }
573
+
574
+ static void
575
+ _freeStrEntry(natsStrHashEntry *e)
576
+ {
577
+ if (e->freeKey)
578
+ NATS_FREE(e->key);
579
+
580
+ NATS_FREE(e);
581
+ }
582
+
583
+ void*
584
+ natsStrHash_Remove(natsStrHash *hash, char *key)
585
+ {
586
+ natsStrHashEntry *entryRemoved = NULL;
587
+ void *dataRemoved = NULL;
588
+ natsStrHashEntry **e;
589
+ uint32_t hk;
590
+
591
+ hk = natsStrHash_Hash(key, (int) strlen(key));
592
+
593
+ e = (natsStrHashEntry**) &(hash->bkts[hk & hash->mask]);
594
+ while (*e != NULL)
595
+ {
596
+ if (((*e)->hk == hk)
597
+ && (strcmp((*e)->key, key) == 0))
598
+ {
599
+ // Success
600
+ entryRemoved = *e;
601
+ dataRemoved = entryRemoved->data;
602
+
603
+ *e = entryRemoved->next;
604
+ _freeStrEntry(entryRemoved);
605
+
606
+ hash->used--;
607
+
608
+ // Check for resizing
609
+ if (hash->canResize
610
+ && (hash->numBkts > _BSZ)
611
+ && (hash->used < hash->numBkts / 4))
612
+ {
613
+ _shrinkStr(hash);
614
+ }
615
+
616
+ break;
617
+ }
618
+
619
+ e = (natsStrHashEntry**) &((*e)->next);
620
+ }
621
+
622
+ return dataRemoved;
623
+ }
624
+
625
+ void
626
+ natsStrHash_Destroy(natsStrHash *hash)
627
+ {
628
+ natsStrHashEntry *e, *ne;
629
+ int i;
630
+
631
+ if (hash == NULL)
632
+ return;
633
+
634
+ for (i = 0; i < hash->numBkts; i++)
635
+ {
636
+ e = hash->bkts[i];
637
+ while (e != NULL)
638
+ {
639
+ ne = e->next;
640
+
641
+ _freeStrEntry(e);
642
+
643
+ e = ne;
644
+ }
645
+ }
646
+
647
+ NATS_FREE(hash->bkts);
648
+ NATS_FREE(hash);
649
+ }
650
+
651
+ void
652
+ natsStrHashIter_Init(natsStrHashIter *iter, natsStrHash *hash)
653
+ {
654
+ memset(iter, 0, sizeof(natsStrHashIter));
655
+
656
+ hash->canResize = false;
657
+ iter->hash = hash;
658
+ iter->current = hash->bkts[0];
659
+ iter->next = iter->current;
660
+ }
661
+
662
+ bool
663
+ natsStrHashIter_Next(natsStrHashIter *iter, char **key, void **value)
664
+ {
665
+ if ((iter->started) && (iter->next == NULL))
666
+ return false;
667
+
668
+ if (!(iter->started) && (iter->current == NULL))
669
+ {
670
+ while ((iter->next == NULL)
671
+ && (iter->currBkt < (iter->hash->numBkts - 1)))
672
+ {
673
+ iter->next = iter->hash->bkts[++(iter->currBkt)];
674
+ }
675
+
676
+ if (iter->next == NULL)
677
+ {
678
+ iter->started = true;
679
+ return false;
680
+ }
681
+ }
682
+
683
+ iter->started = true;
684
+
685
+ iter->current = iter->next;
686
+ if (iter->current != NULL)
687
+ {
688
+ if (key != NULL)
689
+ *key = iter->current->key;
690
+ if (value != NULL)
691
+ *value = iter->current->data;
692
+
693
+ iter->next = iter->current->next;
694
+ }
695
+
696
+ while ((iter->next == NULL)
697
+ && (iter->currBkt < (iter->hash->numBkts - 1)))
698
+ {
699
+ iter->next = iter->hash->bkts[++(iter->currBkt)];
700
+ }
701
+
702
+ return true;
703
+ }
704
+
705
+ natsStatus
706
+ natsStrHashIter_RemoveCurrent(natsStrHashIter *iter)
707
+ {
708
+ char *key;
709
+
710
+ if (iter->current == NULL)
711
+ return nats_setDefaultError(NATS_NOT_FOUND);
712
+
713
+ key = iter->current->key;
714
+ iter->current = iter->next;
715
+
716
+ (void) natsStrHash_Remove(iter->hash, key);
717
+
718
+ return NATS_OK;
719
+ }
720
+
721
+ void
722
+ natsStrHashIter_Done(natsStrHashIter *iter)
723
+ {
724
+ natsHashIter_Done((natsHashIter*) iter);
725
+ }