ffi-nats-core 0.3.0 → 0.3.1

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 (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
+ }