View difference between Paste ID: 5psbTPdf and xXfZJf3f
SHOW: | | - or go back to the newest paste.
1
diff --git a/include/common/uthash.h b/include/common/uthash.h
2
new file mode 100644
3
index 0000000..b6cec34
4
--- /dev/null
5
+++ b/include/common/uthash.h
6
@@ -0,0 +1,912 @@
7
+/*
8
+Copyright (c) 2003-2011, Troy D. Hanson     http://uthash.sourceforge.net
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
15
+      notice, this list of conditions and the following disclaimer.
16
+
17
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+*/
29
+
30
+#ifndef UTHASH_H
31
+#define UTHASH_H 
32
+
33
+#include <string.h>   /* memcmp,strlen */
34
+#include <stddef.h>   /* ptrdiff_t */
35
+#include <stdlib.h>   /* exit() */
36
+
37
+/* These macros use decltype or the earlier __typeof GNU extension.
38
+   As decltype is only available in newer compilers (VS2010 or gcc 4.3+
39
+   when compiling c++ source) this code uses whatever method is needed
40
+   or, for VS2008 where neither is available, uses casting workarounds. */
41
+#ifdef _MSC_VER         /* MS compiler */
42
+#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
43
+#define DECLTYPE(x) (decltype(x))
44
+#else                   /* VS2008 or older (or VS2010 in C mode) */
45
+#define NO_DECLTYPE
46
+#define DECLTYPE(x)
47
+#endif
48
+#else                   /* GNU, Sun and other compilers */
49
+#define DECLTYPE(x) (__typeof(x))
50
+#endif
51
+
52
+#ifdef NO_DECLTYPE
53
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
54
+do {                                                                             \
55
+  char **_da_dst = (char**)(&(dst));                                             \
56
+  *_da_dst = (char*)(src);                                                       \
57
+} while(0)
58
+#else 
59
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
60
+do {                                                                             \
61
+  (dst) = DECLTYPE(dst)(src);                                                    \
62
+} while(0)
63
+#endif
64
+
65
+/* a number of the hash function use uint32_t which isn't defined on win32 */
66
+#ifdef _MSC_VER
67
+typedef unsigned int uint32_t;
68
+typedef unsigned char uint8_t;
69
+#else
70
+#include <inttypes.h>   /* uint32_t */
71
+#endif
72
+
73
+#define UTHASH_VERSION 1.9.4
74
+
75
+/* #define uthash_fatal(msg) exit(-1) */        /* fatal error (out of memory,etc) */
76
+
77
+/* ha-proxy incursion */
78
+#define uthash_fatal do { \
79
+    Alert(msg); \
80
+    exit(1); \
81
+} while(0)
82
+
83
+#define uthash_malloc(sz) malloc(sz)      /* malloc fcn                      */
84
+#define uthash_free(ptr,sz) free(ptr)     /* free fcn                        */
85
+
86
+#define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */
87
+#define uthash_expand_fyi(tbl)            /* can be defined to log expands   */
88
+
89
+/* initial number of buckets */
90
+#define HASH_INITIAL_NUM_BUCKETS 32      /* initial number of buckets        */
91
+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5  /* lg2 of initial number of buckets */
92
+#define HASH_BKT_CAPACITY_THRESH 10      /* expand when bucket count reaches */
93
+
94
+/* calculate the element whose hash handle address is hhe */
95
+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
96
+
97
+#define HASH_FIND(hh,head,keyptr,keylen,out)                                     \
98
+do {                                                                             \
99
+  unsigned _hf_bkt,_hf_hashv;                                                    \
100
+  out=NULL;                                                                      \
101
+  if (head) {                                                                    \
102
+     HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt);   \
103
+     if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) {                           \
104
+       HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ],  \
105
+                        keyptr,keylen,out);                                      \
106
+     }                                                                           \
107
+  }                                                                              \
108
+} while (0)
109
+
110
+#ifdef HASH_BLOOM
111
+#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
112
+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
113
+#define HASH_BLOOM_MAKE(tbl)                                                     \
114
+do {                                                                             \
115
+  (tbl)->bloom_nbits = HASH_BLOOM;                                               \
116
+  (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN);                 \
117
+  if (!((tbl)->bloom_bv))  { uthash_fatal( "out of memory"); }                   \
118
+  memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN);                                \
119
+  (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                       \
120
+} while (0);
121
+
122
+#define HASH_BLOOM_FREE(tbl)                                                     \
123
+do {                                                                             \
124
+  uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \
125
+} while (0);
126
+
127
+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
128
+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
129
+
130
+#define HASH_BLOOM_ADD(tbl,hashv)                                                \
131
+  HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
132
+
133
+#define HASH_BLOOM_TEST(tbl,hashv)                                               \
134
+  HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
135
+
136
+#else
137
+#define HASH_BLOOM_MAKE(tbl) 
138
+#define HASH_BLOOM_FREE(tbl) 
139
+#define HASH_BLOOM_ADD(tbl,hashv) 
140
+#define HASH_BLOOM_TEST(tbl,hashv) (1)
141
+#endif
142
+
143
+#define HASH_MAKE_TABLE(hh,head)                                                 \
144
+do {                                                                             \
145
+  (head)->hh.tbl = (UT_hash_table*)uthash_malloc(                                \
146
+                  sizeof(UT_hash_table));                                        \
147
+  if (!((head)->hh.tbl))  { uthash_fatal( "out of memory"); }                    \
148
+  memset((head)->hh.tbl, 0, sizeof(UT_hash_table));                              \
149
+  (head)->hh.tbl->tail = &((head)->hh);                                          \
150
+  (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS;                        \
151
+  (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2;              \
152
+  (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head);                    \
153
+  (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc(                      \
154
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
155
+  if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); }             \
156
+  memset((head)->hh.tbl->buckets, 0,                                             \
157
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
158
+  HASH_BLOOM_MAKE((head)->hh.tbl);                                               \
159
+  (head)->hh.tbl->signature = HASH_SIGNATURE;                                    \
160
+} while(0)
161
+
162
+#define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
163
+        HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
164
+ 
165
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \
166
+do {                                                                             \
167
+ unsigned _ha_bkt;                                                               \
168
+ (add)->hh.next = NULL;                                                          \
169
+ (add)->hh.key = (char*)keyptr;                                                  \
170
+ (add)->hh.keylen = keylen_in;                                                   \
171
+ if (!(head)) {                                                                  \
172
+    head = (add);                                                                \
173
+    (head)->hh.prev = NULL;                                                      \
174
+    HASH_MAKE_TABLE(hh,head);                                                    \
175
+ } else {                                                                        \
176
+    (head)->hh.tbl->tail->next = (add);                                          \
177
+    (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail);         \
178
+    (head)->hh.tbl->tail = &((add)->hh);                                         \
179
+ }                                                                               \
180
+ (head)->hh.tbl->num_items++;                                                    \
181
+ (add)->hh.tbl = (head)->hh.tbl;                                                 \
182
+ HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets,                         \
183
+         (add)->hh.hashv, _ha_bkt);                                              \
184
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh);                   \
185
+ HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv);                                 \
186
+ HASH_EMIT_KEY(hh,head,keyptr,keylen_in);                                        \
187
+ HASH_FSCK(hh,head);                                                             \
188
+} while(0)
189
+
190
+#define HASH_TO_BKT( hashv, num_bkts, bkt )                                      \
191
+do {                                                                             \
192
+  bkt = ((hashv) & ((num_bkts) - 1));                                            \
193
+} while(0)
194
+
195
+/* delete "delptr" from the hash table.
196
+ * "the usual" patch-up process for the app-order doubly-linked-list.
197
+ * The use of _hd_hh_del below deserves special explanation.
198
+ * These used to be expressed using (delptr) but that led to a bug
199
+ * if someone used the same symbol for the head and deletee, like
200
+ *  HASH_DELETE(hh,users,users);
201
+ * We want that to work, but by changing the head (users) below
202
+ * we were forfeiting our ability to further refer to the deletee (users)
203
+ * in the patch-up process. Solution: use scratch space to
204
+ * copy the deletee pointer, then the latter references are via that
205
+ * scratch pointer rather than through the repointed (users) symbol.
206
+ */
207
+#define HASH_DELETE(hh,head,delptr)                                              \
208
+do {                                                                             \
209
+    unsigned _hd_bkt;                                                            \
210
+    struct UT_hash_handle *_hd_hh_del;                                           \
211
+    if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) )  {         \
212
+        uthash_free((head)->hh.tbl->buckets,                                     \
213
+                    (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
214
+        HASH_BLOOM_FREE((head)->hh.tbl);                                         \
215
+        uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                      \
216
+        head = NULL;                                                             \
217
+    } else {                                                                     \
218
+        _hd_hh_del = &((delptr)->hh);                                            \
219
+        if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \
220
+            (head)->hh.tbl->tail =                                               \
221
+                (UT_hash_handle*)((char*)((delptr)->hh.prev) +                   \
222
+                (head)->hh.tbl->hho);                                            \
223
+        }                                                                        \
224
+        if ((delptr)->hh.prev) {                                                 \
225
+            ((UT_hash_handle*)((char*)((delptr)->hh.prev) +                      \
226
+                    (head)->hh.tbl->hho))->next = (delptr)->hh.next;             \
227
+        } else {                                                                 \
228
+            DECLTYPE_ASSIGN(head,(delptr)->hh.next);                             \
229
+        }                                                                        \
230
+        if (_hd_hh_del->next) {                                                  \
231
+            ((UT_hash_handle*)((char*)_hd_hh_del->next +                         \
232
+                    (head)->hh.tbl->hho))->prev =                                \
233
+                    _hd_hh_del->prev;                                            \
234
+        }                                                                        \
235
+        HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);   \
236
+        HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del);        \
237
+        (head)->hh.tbl->num_items--;                                             \
238
+    }                                                                            \
239
+    HASH_FSCK(hh,head);                                                          \
240
+} while (0)
241
+
242
+
243
+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
244
+#define HASH_FIND_STR(head,findstr,out)                                          \
245
+    HASH_FIND(hh,head,findstr,strlen(findstr),out)
246
+#define HASH_ADD_STR(head,strfield,add)                                          \
247
+    HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
248
+#define HASH_FIND_INT(head,findint,out)                                          \
249
+    HASH_FIND(hh,head,findint,sizeof(int),out)
250
+#define HASH_ADD_INT(head,intfield,add)                                          \
251
+    HASH_ADD(hh,head,intfield,sizeof(int),add)
252
+#define HASH_FIND_PTR(head,findptr,out)                                          \
253
+    HASH_FIND(hh,head,findptr,sizeof(void *),out)
254
+#define HASH_ADD_PTR(head,ptrfield,add)                                          \
255
+    HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
256
+#define HASH_DEL(head,delptr)                                                    \
257
+    HASH_DELETE(hh,head,delptr)
258
+
259
+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
260
+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
261
+ */
262
+#ifdef HASH_DEBUG
263
+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
264
+#define HASH_FSCK(hh,head)                                                       \
265
+do {                                                                             \
266
+    unsigned _bkt_i;                                                             \
267
+    unsigned _count, _bkt_count;                                                 \
268
+    char *_prev;                                                                 \
269
+    struct UT_hash_handle *_thh;                                                 \
270
+    if (head) {                                                                  \
271
+        _count = 0;                                                              \
272
+        for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) {       \
273
+            _bkt_count = 0;                                                      \
274
+            _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head;                      \
275
+            _prev = NULL;                                                        \
276
+            while (_thh) {                                                       \
277
+               if (_prev != (char*)(_thh->hh_prev)) {                            \
278
+                   HASH_OOPS("invalid hh_prev %p, actual %p\n",                  \
279
+                    _thh->hh_prev, _prev );                                      \
280
+               }                                                                 \
281
+               _bkt_count++;                                                     \
282
+               _prev = (char*)(_thh);                                            \
283
+               _thh = _thh->hh_next;                                             \
284
+            }                                                                    \
285
+            _count += _bkt_count;                                                \
286
+            if ((head)->hh.tbl->buckets[_bkt_i].count !=  _bkt_count) {          \
287
+               HASH_OOPS("invalid bucket count %d, actual %d\n",                 \
288
+                (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count);              \
289
+            }                                                                    \
290
+        }                                                                        \
291
+        if (_count != (head)->hh.tbl->num_items) {                               \
292
+            HASH_OOPS("invalid hh item count %d, actual %d\n",                   \
293
+                (head)->hh.tbl->num_items, _count );                             \
294
+        }                                                                        \
295
+        /* traverse hh in app order; check next/prev integrity, count */         \
296
+        _count = 0;                                                              \
297
+        _prev = NULL;                                                            \
298
+        _thh =  &(head)->hh;                                                     \
299
+        while (_thh) {                                                           \
300
+           _count++;                                                             \
301
+           if (_prev !=(char*)(_thh->prev)) {                                    \
302
+              HASH_OOPS("invalid prev %p, actual %p\n",                          \
303
+                    _thh->prev, _prev );                                         \
304
+           }                                                                     \
305
+           _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh);                    \
306
+           _thh = ( _thh->next ?  (UT_hash_handle*)((char*)(_thh->next) +        \
307
+                                  (head)->hh.tbl->hho) : NULL );                 \
308
+        }                                                                        \
309
+        if (_count != (head)->hh.tbl->num_items) {                               \
310
+            HASH_OOPS("invalid app item count %d, actual %d\n",                  \
311
+                (head)->hh.tbl->num_items, _count );                             \
312
+        }                                                                        \
313
+    }                                                                            \
314
+} while (0)
315
+#else
316
+#define HASH_FSCK(hh,head) 
317
+#endif
318
+
319
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to 
320
+ * the descriptor to which this macro is defined for tuning the hash function.
321
+ * The app can #include <unistd.h> to get the prototype for write(2). */
322
+#ifdef HASH_EMIT_KEYS
323
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                                   \
324
+do {                                                                             \
325
+    unsigned _klen = fieldlen;                                                   \
326
+    write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                \
327
+    write(HASH_EMIT_KEYS, keyptr, fieldlen);                                     \
328
+} while (0)
329
+#else 
330
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                    
331
+#endif
332
+
333
+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
334
+#ifdef HASH_FUNCTION 
335
+#define HASH_FCN HASH_FUNCTION
336
+#else
337
+#define HASH_FCN HASH_JEN
338
+#endif
339
+
340
+/* The Bernstein hash function, used in Perl prior to v5.6 */
341
+#define HASH_BER(key,keylen,num_bkts,hashv,bkt)                                  \
342
+do {                                                                             \
343
+  unsigned _hb_keylen=keylen;                                                    \
344
+  char *_hb_key=(char*)(key);                                                    \
345
+  (hashv) = 0;                                                                   \
346
+  while (_hb_keylen--)  { (hashv) = ((hashv) * 33) + *_hb_key++; }               \
347
+  bkt = (hashv) & (num_bkts-1);                                                  \
348
+} while (0)
349
+
350
+
351
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at 
352
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
353
+#define HASH_SAX(key,keylen,num_bkts,hashv,bkt)                                  \
354
+do {                                                                             \
355
+  unsigned _sx_i;                                                                \
356
+  char *_hs_key=(char*)(key);                                                    \
357
+  hashv = 0;                                                                     \
358
+  for(_sx_i=0; _sx_i < keylen; _sx_i++)                                          \
359
+      hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i];                     \
360
+  bkt = hashv & (num_bkts-1);                                                    \
361
+} while (0)
362
+
363
+#define HASH_FNV(key,keylen,num_bkts,hashv,bkt)                                  \
364
+do {                                                                             \
365
+  unsigned _fn_i;                                                                \
366
+  char *_hf_key=(char*)(key);                                                    \
367
+  hashv = 2166136261UL;                                                          \
368
+  for(_fn_i=0; _fn_i < keylen; _fn_i++)                                          \
369
+      hashv = (hashv * 16777619) ^ _hf_key[_fn_i];                               \
370
+  bkt = hashv & (num_bkts-1);                                                    \
371
+} while(0);
372
+ 
373
+#define HASH_OAT(key,keylen,num_bkts,hashv,bkt)                                  \
374
+do {                                                                             \
375
+  unsigned _ho_i;                                                                \
376
+  char *_ho_key=(char*)(key);                                                    \
377
+  hashv = 0;                                                                     \
378
+  for(_ho_i=0; _ho_i < keylen; _ho_i++) {                                        \
379
+      hashv += _ho_key[_ho_i];                                                   \
380
+      hashv += (hashv << 10);                                                    \
381
+      hashv ^= (hashv >> 6);                                                     \
382
+  }                                                                              \
383
+  hashv += (hashv << 3);                                                         \
384
+  hashv ^= (hashv >> 11);                                                        \
385
+  hashv += (hashv << 15);                                                        \
386
+  bkt = hashv & (num_bkts-1);                                                    \
387
+} while(0)
388
+
389
+#define HASH_JEN_MIX(a,b,c)                                                      \
390
+do {                                                                             \
391
+  a -= b; a -= c; a ^= ( c >> 13 );                                              \
392
+  b -= c; b -= a; b ^= ( a << 8 );                                               \
393
+  c -= a; c -= b; c ^= ( b >> 13 );                                              \
394
+  a -= b; a -= c; a ^= ( c >> 12 );                                              \
395
+  b -= c; b -= a; b ^= ( a << 16 );                                              \
396
+  c -= a; c -= b; c ^= ( b >> 5 );                                               \
397
+  a -= b; a -= c; a ^= ( c >> 3 );                                               \
398
+  b -= c; b -= a; b ^= ( a << 10 );                                              \
399
+  c -= a; c -= b; c ^= ( b >> 15 );                                              \
400
+} while (0)
401
+
402
+#define HASH_JEN(key,keylen,num_bkts,hashv,bkt)                                  \
403
+do {                                                                             \
404
+  unsigned _hj_i,_hj_j,_hj_k;                                                    \
405
+  char *_hj_key=(char*)(key);                                                    \
406
+  hashv = 0xfeedbeef;                                                            \
407
+  _hj_i = _hj_j = 0x9e3779b9;                                                    \
408
+  _hj_k = keylen;                                                                \
409
+  while (_hj_k >= 12) {                                                          \
410
+    _hj_i +=    (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 )                      \
411
+        + ( (unsigned)_hj_key[2] << 16 )                                         \
412
+        + ( (unsigned)_hj_key[3] << 24 ) );                                      \
413
+    _hj_j +=    (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 )                      \
414
+        + ( (unsigned)_hj_key[6] << 16 )                                         \
415
+        + ( (unsigned)_hj_key[7] << 24 ) );                                      \
416
+    hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 )                         \
417
+        + ( (unsigned)_hj_key[10] << 16 )                                        \
418
+        + ( (unsigned)_hj_key[11] << 24 ) );                                     \
419
+                                                                                 \
420
+     HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                          \
421
+                                                                                 \
422
+     _hj_key += 12;                                                              \
423
+     _hj_k -= 12;                                                                \
424
+  }                                                                              \
425
+  hashv += keylen;                                                               \
426
+  switch ( _hj_k ) {                                                             \
427
+     case 11: hashv += ( (unsigned)_hj_key[10] << 24 );                          \
428
+     case 10: hashv += ( (unsigned)_hj_key[9] << 16 );                           \
429
+     case 9:  hashv += ( (unsigned)_hj_key[8] << 8 );                            \
430
+     case 8:  _hj_j += ( (unsigned)_hj_key[7] << 24 );                           \
431
+     case 7:  _hj_j += ( (unsigned)_hj_key[6] << 16 );                           \
432
+     case 6:  _hj_j += ( (unsigned)_hj_key[5] << 8 );                            \
433
+     case 5:  _hj_j += _hj_key[4];                                               \
434
+     case 4:  _hj_i += ( (unsigned)_hj_key[3] << 24 );                           \
435
+     case 3:  _hj_i += ( (unsigned)_hj_key[2] << 16 );                           \
436
+     case 2:  _hj_i += ( (unsigned)_hj_key[1] << 8 );                            \
437
+     case 1:  _hj_i += _hj_key[0];                                               \
438
+  }                                                                              \
439
+  HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                             \
440
+  bkt = hashv & (num_bkts-1);                                                    \
441
+} while(0)
442
+
443
+/* The Paul Hsieh hash function */
444
+#undef get16bits
445
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__)             \
446
+  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
447
+#define get16bits(d) (*((const uint16_t *) (d)))
448
+#endif
449
+
450
+#if !defined (get16bits)
451
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)             \
452
+                       +(uint32_t)(((const uint8_t *)(d))[0]) )
453
+#endif
454
+#define HASH_SFH(key,keylen,num_bkts,hashv,bkt)                                  \
455
+do {                                                                             \
456
+  char *_sfh_key=(char*)(key);                                                   \
457
+  uint32_t _sfh_tmp, _sfh_len = keylen;                                          \
458
+                                                                                 \
459
+  int _sfh_rem = _sfh_len & 3;                                                   \
460
+  _sfh_len >>= 2;                                                                \
461
+  hashv = 0xcafebabe;                                                            \
462
+                                                                                 \
463
+  /* Main loop */                                                                \
464
+  for (;_sfh_len > 0; _sfh_len--) {                                              \
465
+    hashv    += get16bits (_sfh_key);                                            \
466
+    _sfh_tmp       = (get16bits (_sfh_key+2) << 11) ^ hashv;                     \
467
+    hashv     = (hashv << 16) ^ _sfh_tmp;                                        \
468
+    _sfh_key += 2*sizeof (uint16_t);                                             \
469
+    hashv    += hashv >> 11;                                                     \
470
+  }                                                                              \
471
+                                                                                 \
472
+  /* Handle end cases */                                                         \
473
+  switch (_sfh_rem) {                                                            \
474
+    case 3: hashv += get16bits (_sfh_key);                                       \
475
+            hashv ^= hashv << 16;                                                \
476
+            hashv ^= _sfh_key[sizeof (uint16_t)] << 18;                          \
477
+            hashv += hashv >> 11;                                                \
478
+            break;                                                               \
479
+    case 2: hashv += get16bits (_sfh_key);                                       \
480
+            hashv ^= hashv << 11;                                                \
481
+            hashv += hashv >> 17;                                                \
482
+            break;                                                               \
483
+    case 1: hashv += *_sfh_key;                                                  \
484
+            hashv ^= hashv << 10;                                                \
485
+            hashv += hashv >> 1;                                                 \
486
+  }                                                                              \
487
+                                                                                 \
488
+    /* Force "avalanching" of final 127 bits */                                  \
489
+    hashv ^= hashv << 3;                                                         \
490
+    hashv += hashv >> 5;                                                         \
491
+    hashv ^= hashv << 4;                                                         \
492
+    hashv += hashv >> 17;                                                        \
493
+    hashv ^= hashv << 25;                                                        \
494
+    hashv += hashv >> 6;                                                         \
495
+    bkt = hashv & (num_bkts-1);                                                  \
496
+} while(0);
497
+
498
+#ifdef HASH_USING_NO_STRICT_ALIASING
499
+/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
500
+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
501
+ * MurmurHash uses the faster approach only on CPU's where we know it's safe. 
502
+ *
503
+ * Note the preprocessor built-in defines can be emitted using:
504
+ *
505
+ *   gcc -m64 -dM -E - < /dev/null                  (on gcc)
506
+ *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)
507
+ */
508
+#if (defined(__i386__) || defined(__x86_64__)) 
509
+#define MUR_GETBLOCK(p,i) p[i]
510
+#else /* non intel */
511
+#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
512
+#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
513
+#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
514
+#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
515
+#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
516
+#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
517
+#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
518
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
519
+#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >>  8))
520
+#else /* assume little endian non-intel */
521
+#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
522
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
523
+#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) <<  8))
524
+#endif
525
+#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) :           \
526
+                            (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
527
+                             (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) :  \
528
+                                                      MUR_ONE_THREE(p))))
529
+#endif
530
+#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
531
+#define MUR_FMIX(_h) \
532
+do {                 \
533
+  _h ^= _h >> 16;    \
534
+  _h *= 0x85ebca6b;  \
535
+  _h ^= _h >> 13;    \
536
+  _h *= 0xc2b2ae35l; \
537
+  _h ^= _h >> 16;    \
538
+} while(0)
539
+
540
+#define HASH_MUR(key,keylen,num_bkts,hashv,bkt)                        \
541
+do {                                                                   \
542
+  const uint8_t *_mur_data = (const uint8_t*)(key);                    \
543
+  const int _mur_nblocks = (keylen) / 4;                               \
544
+  uint32_t _mur_h1 = 0xf88D5353;                                       \
545
+  uint32_t _mur_c1 = 0xcc9e2d51;                                       \
546
+  uint32_t _mur_c2 = 0x1b873593;                                       \
547
+  const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
548
+  int _mur_i;                                                          \
549
+  for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) {                      \
550
+    uint32_t _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);               \
551
+    _mur_k1 *= _mur_c1;                                                \
552
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
553
+    _mur_k1 *= _mur_c2;                                                \
554
+                                                                       \
555
+    _mur_h1 ^= _mur_k1;                                                \
556
+    _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \
557
+    _mur_h1 = _mur_h1*5+0xe6546b64;                                    \
558
+  }                                                                    \
559
+  const uint8_t *_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
560
+  uint32_t _mur_k1=0;                                                  \
561
+  switch((keylen) & 3) {                                               \
562
+    case 3: _mur_k1 ^= _mur_tail[2] << 16;                             \
563
+    case 2: _mur_k1 ^= _mur_tail[1] << 8;                              \
564
+    case 1: _mur_k1 ^= _mur_tail[0];                                   \
565
+    _mur_k1 *= _mur_c1;                                                \
566
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
567
+    _mur_k1 *= _mur_c2;                                                \
568
+    _mur_h1 ^= _mur_k1;                                                \
569
+  }                                                                    \
570
+  _mur_h1 ^= (keylen);                                                 \
571
+  MUR_FMIX(_mur_h1);                                                   \
572
+  hashv = _mur_h1;                                                     \
573
+  bkt = hashv & (num_bkts-1);                                          \
574
+} while(0)
575
+#endif  /* HASH_USING_NO_STRICT_ALIASING */
576
+
577
+/* key comparison function; return 0 if keys equal */
578
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) 
579
+
580
+/* iterate over items in a known bucket to find desired item */
581
+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out)                       \
582
+do {                                                                             \
583
+ if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head));          \
584
+ else out=NULL;                                                                  \
585
+ while (out) {                                                                   \
586
+    if (out->hh.keylen == keylen_in) {                                           \
587
+        if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break;             \
588
+    }                                                                            \
589
+    if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
590
+    else out = NULL;                                                             \
591
+ }                                                                               \
592
+} while(0)
593
+
594
+/* add an item to a bucket  */
595
+#define HASH_ADD_TO_BKT(head,addhh)                                              \
596
+do {                                                                             \
597
+ head.count++;                                                                   \
598
+ (addhh)->hh_next = head.hh_head;                                                \
599
+ (addhh)->hh_prev = NULL;                                                        \
600
+ if (head.hh_head) { (head).hh_head->hh_prev = (addhh); }                        \
601
+ (head).hh_head=addhh;                                                           \
602
+ if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH)             \
603
+     && (addhh)->tbl->noexpand != 1) {                                           \
604
+       HASH_EXPAND_BUCKETS((addhh)->tbl);                                        \
605
+ }                                                                               \
606
+} while(0)
607
+
608
+/* remove an item from a given bucket */
609
+#define HASH_DEL_IN_BKT(hh,head,hh_del)                                          \
610
+    (head).count--;                                                              \
611
+    if ((head).hh_head == hh_del) {                                              \
612
+      (head).hh_head = hh_del->hh_next;                                          \
613
+    }                                                                            \
614
+    if (hh_del->hh_prev) {                                                       \
615
+        hh_del->hh_prev->hh_next = hh_del->hh_next;                              \
616
+    }                                                                            \
617
+    if (hh_del->hh_next) {                                                       \
618
+        hh_del->hh_next->hh_prev = hh_del->hh_prev;                              \
619
+    }                                                                
620
+
621
+/* Bucket expansion has the effect of doubling the number of buckets
622
+ * and redistributing the items into the new buckets. Ideally the
623
+ * items will distribute more or less evenly into the new buckets
624
+ * (the extent to which this is true is a measure of the quality of
625
+ * the hash function as it applies to the key domain). 
626
+ * 
627
+ * With the items distributed into more buckets, the chain length
628
+ * (item count) in each bucket is reduced. Thus by expanding buckets
629
+ * the hash keeps a bound on the chain length. This bounded chain 
630
+ * length is the essence of how a hash provides constant time lookup.
631
+ * 
632
+ * The calculation of tbl->ideal_chain_maxlen below deserves some
633
+ * explanation. First, keep in mind that we're calculating the ideal
634
+ * maximum chain length based on the *new* (doubled) bucket count.
635
+ * In fractions this is just n/b (n=number of items,b=new num buckets).
636
+ * Since the ideal chain length is an integer, we want to calculate 
637
+ * ceil(n/b). We don't depend on floating point arithmetic in this
638
+ * hash, so to calculate ceil(n/b) with integers we could write
639
+ * 
640
+ *      ceil(n/b) = (n/b) + ((n%b)?1:0)
641
+ * 
642
+ * and in fact a previous version of this hash did just that.
643
+ * But now we have improved things a bit by recognizing that b is
644
+ * always a power of two. We keep its base 2 log handy (call it lb),
645
+ * so now we can write this with a bit shift and logical AND:
646
+ * 
647
+ *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
648
+ * 
649
+ */
650
+#define HASH_EXPAND_BUCKETS(tbl)                                                 \
651
+do {                                                                             \
652
+    unsigned _he_bkt;                                                            \
653
+    unsigned _he_bkt_i;                                                          \
654
+    struct UT_hash_handle *_he_thh, *_he_hh_nxt;                                 \
655
+    UT_hash_bucket *_he_new_buckets, *_he_newbkt;                                \
656
+    _he_new_buckets = (UT_hash_bucket*)uthash_malloc(                            \
657
+             2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));              \
658
+    if (!_he_new_buckets) { uthash_fatal( "out of memory"); }                    \
659
+    memset(_he_new_buckets, 0,                                                   \
660
+            2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));               \
661
+    tbl->ideal_chain_maxlen =                                                    \
662
+       (tbl->num_items >> (tbl->log2_num_buckets+1)) +                           \
663
+       ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0);                    \
664
+    tbl->nonideal_items = 0;                                                     \
665
+    for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++)                \
666
+    {                                                                            \
667
+        _he_thh = tbl->buckets[ _he_bkt_i ].hh_head;                             \
668
+        while (_he_thh) {                                                        \
669
+           _he_hh_nxt = _he_thh->hh_next;                                        \
670
+           HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt);            \
671
+           _he_newbkt = &(_he_new_buckets[ _he_bkt ]);                           \
672
+           if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) {                \
673
+             tbl->nonideal_items++;                                              \
674
+             _he_newbkt->expand_mult = _he_newbkt->count /                       \
675
+                                        tbl->ideal_chain_maxlen;                 \
676
+           }                                                                     \
677
+           _he_thh->hh_prev = NULL;                                              \
678
+           _he_thh->hh_next = _he_newbkt->hh_head;                               \
679
+           if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev =               \
680
+                _he_thh;                                                         \
681
+           _he_newbkt->hh_head = _he_thh;                                        \
682
+           _he_thh = _he_hh_nxt;                                                 \
683
+        }                                                                        \
684
+    }                                                                            \
685
+    uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
686
+    tbl->num_buckets *= 2;                                                       \
687
+    tbl->log2_num_buckets++;                                                     \
688
+    tbl->buckets = _he_new_buckets;                                              \
689
+    tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ?         \
690
+        (tbl->ineff_expands+1) : 0;                                              \
691
+    if (tbl->ineff_expands > 1) {                                                \
692
+        tbl->noexpand=1;                                                         \
693
+        uthash_noexpand_fyi(tbl);                                                \
694
+    }                                                                            \
695
+    uthash_expand_fyi(tbl);                                                      \
696
+} while(0)
697
+
698
+
699
+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
700
+/* Note that HASH_SORT assumes the hash handle name to be hh. 
701
+ * HASH_SRT was added to allow the hash handle name to be passed in. */
702
+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
703
+#define HASH_SRT(hh,head,cmpfcn)                                                 \
704
+do {                                                                             \
705
+  unsigned _hs_i;                                                                \
706
+  unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize;               \
707
+  struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail;            \
708
+  if (head) {                                                                    \
709
+      _hs_insize = 1;                                                            \
710
+      _hs_looping = 1;                                                           \
711
+      _hs_list = &((head)->hh);                                                  \
712
+      while (_hs_looping) {                                                      \
713
+          _hs_p = _hs_list;                                                      \
714
+          _hs_list = NULL;                                                       \
715
+          _hs_tail = NULL;                                                       \
716
+          _hs_nmerges = 0;                                                       \
717
+          while (_hs_p) {                                                        \
718
+              _hs_nmerges++;                                                     \
719
+              _hs_q = _hs_p;                                                     \
720
+              _hs_psize = 0;                                                     \
721
+              for ( _hs_i = 0; _hs_i  < _hs_insize; _hs_i++ ) {                  \
722
+                  _hs_psize++;                                                   \
723
+                  _hs_q = (UT_hash_handle*)((_hs_q->next) ?                      \
724
+                          ((void*)((char*)(_hs_q->next) +                        \
725
+                          (head)->hh.tbl->hho)) : NULL);                         \
726
+                  if (! (_hs_q) ) break;                                         \
727
+              }                                                                  \
728
+              _hs_qsize = _hs_insize;                                            \
729
+              while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) {           \
730
+                  if (_hs_psize == 0) {                                          \
731
+                      _hs_e = _hs_q;                                             \
732
+                      _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
733
+                              ((void*)((char*)(_hs_q->next) +                    \
734
+                              (head)->hh.tbl->hho)) : NULL);                     \
735
+                      _hs_qsize--;                                               \
736
+                  } else if ( (_hs_qsize == 0) || !(_hs_q) ) {                   \
737
+                      _hs_e = _hs_p;                                             \
738
+                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
739
+                              ((void*)((char*)(_hs_p->next) +                    \
740
+                              (head)->hh.tbl->hho)) : NULL);                     \
741
+                      _hs_psize--;                                               \
742
+                  } else if ((                                                   \
743
+                      cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
744
+                             DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
745
+                             ) <= 0) {                                           \
746
+                      _hs_e = _hs_p;                                             \
747
+                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
748
+                              ((void*)((char*)(_hs_p->next) +                    \
749
+                              (head)->hh.tbl->hho)) : NULL);                     \
750
+                      _hs_psize--;                                               \
751
+                  } else {                                                       \
752
+                      _hs_e = _hs_q;                                             \
753
+                      _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
754
+                              ((void*)((char*)(_hs_q->next) +                    \
755
+                              (head)->hh.tbl->hho)) : NULL);                     \
756
+                      _hs_qsize--;                                               \
757
+                  }                                                              \
758
+                  if ( _hs_tail ) {                                              \
759
+                      _hs_tail->next = ((_hs_e) ?                                \
760
+                            ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL);          \
761
+                  } else {                                                       \
762
+                      _hs_list = _hs_e;                                          \
763
+                  }                                                              \
764
+                  _hs_e->prev = ((_hs_tail) ?                                    \
765
+                     ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL);              \
766
+                  _hs_tail = _hs_e;                                              \
767
+              }                                                                  \
768
+              _hs_p = _hs_q;                                                     \
769
+          }                                                                      \
770
+          _hs_tail->next = NULL;                                                 \
771
+          if ( _hs_nmerges <= 1 ) {                                              \
772
+              _hs_looping=0;                                                     \
773
+              (head)->hh.tbl->tail = _hs_tail;                                   \
774
+              DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list));      \
775
+          }                                                                      \
776
+          _hs_insize *= 2;                                                       \
777
+      }                                                                          \
778
+      HASH_FSCK(hh,head);                                                        \
779
+ }                                                                               \
780
+} while (0)
781
+
782
+/* This function selects items from one hash into another hash. 
783
+ * The end result is that the selected items have dual presence 
784
+ * in both hashes. There is no copy of the items made; rather 
785
+ * they are added into the new hash through a secondary hash 
786
+ * hash handle that must be present in the structure. */
787
+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \
788
+do {                                                                             \
789
+  unsigned _src_bkt, _dst_bkt;                                                   \
790
+  void *_last_elt=NULL, *_elt;                                                   \
791
+  UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL;                         \
792
+  ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst));                 \
793
+  if (src) {                                                                     \
794
+    for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) {     \
795
+      for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head;                \
796
+          _src_hh;                                                               \
797
+          _src_hh = _src_hh->hh_next) {                                          \
798
+          _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh);                       \
799
+          if (cond(_elt)) {                                                      \
800
+            _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho);               \
801
+            _dst_hh->key = _src_hh->key;                                         \
802
+            _dst_hh->keylen = _src_hh->keylen;                                   \
803
+            _dst_hh->hashv = _src_hh->hashv;                                     \
804
+            _dst_hh->prev = _last_elt;                                           \
805
+            _dst_hh->next = NULL;                                                \
806
+            if (_last_elt_hh) { _last_elt_hh->next = _elt; }                     \
807
+            if (!dst) {                                                          \
808
+              DECLTYPE_ASSIGN(dst,_elt);                                         \
809
+              HASH_MAKE_TABLE(hh_dst,dst);                                       \
810
+            } else {                                                             \
811
+              _dst_hh->tbl = (dst)->hh_dst.tbl;                                  \
812
+            }                                                                    \
813
+            HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt);    \
814
+            HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh);            \
815
+            (dst)->hh_dst.tbl->num_items++;                                      \
816
+            _last_elt = _elt;                                                    \
817
+            _last_elt_hh = _dst_hh;                                              \
818
+          }                                                                      \
819
+      }                                                                          \
820
+    }                                                                            \
821
+  }                                                                              \
822
+  HASH_FSCK(hh_dst,dst);                                                         \
823
+} while (0)
824
+
825
+#define HASH_CLEAR(hh,head)                                                      \
826
+do {                                                                             \
827
+  if (head) {                                                                    \
828
+    uthash_free((head)->hh.tbl->buckets,                                         \
829
+                (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket));      \
830
+    HASH_BLOOM_FREE((head)->hh.tbl);                                             \
831
+    uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \
832
+    (head)=NULL;                                                                 \
833
+  }                                                                              \
834
+} while(0)
835
+
836
+#ifdef NO_DECLTYPE
837
+#define HASH_ITER(hh,head,el,tmp)                                                \
838
+for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL);       \
839
+  el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) 
840
+#else
841
+#define HASH_ITER(hh,head,el,tmp)                                                \
842
+for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL);                 \
843
+  el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
844
+#endif
845
+
846
+/* obtain a count of items in the hash */
847
+#define HASH_COUNT(head) HASH_CNT(hh,head) 
848
+#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
849
+
850
+typedef struct UT_hash_bucket {
851
+   struct UT_hash_handle *hh_head;
852
+   unsigned count;
853
+
854
+   /* expand_mult is normally set to 0. In this situation, the max chain length
855
+    * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
856
+    * the bucket's chain exceeds this length, bucket expansion is triggered). 
857
+    * However, setting expand_mult to a non-zero value delays bucket expansion
858
+    * (that would be triggered by additions to this particular bucket)
859
+    * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
860
+    * (The multiplier is simply expand_mult+1). The whole idea of this
861
+    * multiplier is to reduce bucket expansions, since they are expensive, in
862
+    * situations where we know that a particular bucket tends to be overused.
863
+    * It is better to let its chain length grow to a longer yet-still-bounded
864
+    * value, than to do an O(n) bucket expansion too often. 
865
+    */
866
+   unsigned expand_mult;
867
+
868
+} UT_hash_bucket;
869
+
870
+/* random signature used only to find hash tables in external analysis */
871
+#define HASH_SIGNATURE 0xa0111fe1
872
+#define HASH_BLOOM_SIGNATURE 0xb12220f2
873
+
874
+typedef struct UT_hash_table {
875
+   UT_hash_bucket *buckets;
876
+   unsigned num_buckets, log2_num_buckets;
877
+   unsigned num_items;
878
+   struct UT_hash_handle *tail; /* tail hh in app order, for fast append    */
879
+   ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
880
+
881
+   /* in an ideal situation (all buckets used equally), no bucket would have
882
+    * more than ceil(#items/#buckets) items. that's the ideal chain length. */
883
+   unsigned ideal_chain_maxlen;
884
+
885
+   /* nonideal_items is the number of items in the hash whose chain position
886
+    * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
887
+    * hash distribution; reaching them in a chain traversal takes >ideal steps */
888
+   unsigned nonideal_items;
889
+
890
+   /* ineffective expands occur when a bucket doubling was performed, but 
891
+    * afterward, more than half the items in the hash had nonideal chain
892
+    * positions. If this happens on two consecutive expansions we inhibit any
893
+    * further expansion, as it's not helping; this happens when the hash
894
+    * function isn't a good fit for the key domain. When expansion is inhibited
895
+    * the hash will still work, albeit no longer in constant time. */
896
+   unsigned ineff_expands, noexpand;
897
+
898
+   uint32_t signature; /* used only to find hash tables in external analysis */
899
+#ifdef HASH_BLOOM
900
+   uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
901
+   uint8_t *bloom_bv;
902
+   char bloom_nbits;
903
+#endif
904
+
905
+} UT_hash_table;
906
+
907
+typedef struct UT_hash_handle {
908
+   struct UT_hash_table *tbl;
909
+   void *prev;                       /* prev element in app order      */
910
+   void *next;                       /* next element in app order      */
911
+   struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */
912
+   struct UT_hash_handle *hh_next;   /* next hh in bucket order        */
913
+   void *key;                        /* ptr to enclosing struct's key  */
914
+   unsigned keylen;                  /* enclosing struct's key len     */
915
+   unsigned hashv;                   /* result of hash-fcn(key)        */
916
+} UT_hash_handle;
917
+
918
+#endif /* UTHASH_H */
919
diff --git a/include/common/time.h b/include/common/time.h
920
index c9e3641..1d3fe0e 100644
921
--- a/include/common/time.h
922
+++ b/include/common/time.h
923
@@ -475,6 +475,17 @@ REGPRM3 static inline struct timeval *__tv_ms_add(struct timeval *tv, const stru
924
 	return tv;
925
 }
926
 
927
+/*
928
+ * adds <sec> sec to <from>, set the result to <tv> and returns a pointer <tv>
929
+ */
930
+#define tv_sec_add _tv_sec_add
931
+REGPRM3 struct timeval *_tv_sec_add(struct timeval *tv, const struct timeval *from, int sec);
932
+REGPRM3 static inline struct timeval *__tv_sec_add(struct timeval *tv, const struct timeval *from, int sec)
933
+{
934
+	tv->tv_sec = from->tv_sec + sec;
935
+	return tv;
936
+}
937
+
938
 
939
 /*
940
  * compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
941
diff --git a/include/common/uthash.h b/include/common/uthash.h
942
index b6cec34..ae9ab6d 100644
943
--- a/include/common/uthash.h
944
+++ b/include/common/uthash.h
945
@@ -1,5 +1,5 @@
946
 /*
947
-Copyright (c) 2003-2011, Troy D. Hanson     http://uthash.sourceforge.net
948
+Copyright (c) 2003-2013, Troy D. Hanson     http://troydhanson.github.com/uthash/
949
 All rights reserved.
950
 
951
 Redistribution and use in source and binary forms, with or without
952
@@ -28,6 +28,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
953
 #include <stddef.h>   /* ptrdiff_t */
954
 #include <stdlib.h>   /* exit() */
955
 
956
+/* ha-proxy start */
957
+#define uthash_fatal(msg) do { \
958
+    Alert(msg); \
959
+    exit(1); \
960
+} while(0)
961
+
962
+#define uthash_malloc(sz) calloc(1, sz)
963
+/* ha-proxy end */
964
+
965
 /* These macros use decltype or the earlier __typeof GNU extension.
966
    As decltype is only available in newer compilers (VS2010 or gcc 4.3+
967
    when compiling c++ source) this code uses whatever method is needed
968
@@ -64,21 +73,24 @@ typedef unsigned char uint8_t;
969
 #include <inttypes.h>   /* uint32_t */
970
 #endif
971
 
972
-#define UTHASH_VERSION 1.9.4
973
-
974
-/* #define uthash_fatal(msg) exit(-1) */        /* fatal error (out of memory,etc) */
975
-
976
-/* ha-proxy incursion */
977
-#define uthash_fatal do { \
978
-    Alert(msg); \
979
-    exit(1); \
980
-} while(0)
981
+#define UTHASH_VERSION 1.9.8
982
 
983
+#ifndef uthash_fatal
984
+#define uthash_fatal(msg) exit(-1)        /* fatal error (out of memory,etc) */
985
+#endif
986
+#ifndef uthash_malloc
987
 #define uthash_malloc(sz) malloc(sz)      /* malloc fcn                      */
988
+#endif
989
+#ifndef uthash_free
990
 #define uthash_free(ptr,sz) free(ptr)     /* free fcn                        */
991
+#endif
992
 
993
+#ifndef uthash_noexpand_fyi
994
 #define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */
995
+#endif
996
+#ifndef uthash_expand_fyi
997
 #define uthash_expand_fyi(tbl)            /* can be defined to log expands   */
998
+#endif
999
 
1000
 /* initial number of buckets */
1001
 #define HASH_INITIAL_NUM_BUCKETS 32      /* initial number of buckets        */
1002
@@ -111,12 +123,12 @@ do {
1003
   if (!((tbl)->bloom_bv))  { uthash_fatal( "out of memory"); }                   \
1004
   memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN);                                \
1005
   (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                       \
1006
-} while (0);
1007
+} while (0) 
1008
 
1009
 #define HASH_BLOOM_FREE(tbl)                                                     \
1010
 do {                                                                             \
1011
   uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \
1012
-} while (0);
1013
+} while (0) 
1014
 
1015
 #define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
1016
 #define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
1017
@@ -132,6 +144,7 @@ do {
1018
 #define HASH_BLOOM_FREE(tbl) 
1019
 #define HASH_BLOOM_ADD(tbl,hashv) 
1020
 #define HASH_BLOOM_TEST(tbl,hashv) (1)
1021
+#define HASH_BLOOM_BYTELEN 0
1022
 #endif
1023
 
1024
 #define HASH_MAKE_TABLE(hh,head)                                                 \
1025
@@ -155,13 +168,23 @@ do {
1026
 
1027
 #define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
1028
         HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
1029
+
1030
+#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced)                   \
1031
+do {                                                                             \
1032
+  replaced=NULL;                                                                 \
1033
+  HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced);                     \
1034
+  if (replaced!=NULL) {                                                          \
1035
+     HASH_DELETE(hh,head,replaced);                                              \
1036
+  };                                                                             \
1037
+  HASH_ADD(hh,head,fieldname,keylen_in,add);                                     \
1038
+} while(0)
1039
  
1040
 #define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \
1041
 do {                                                                             \
1042
  unsigned _ha_bkt;                                                               \
1043
  (add)->hh.next = NULL;                                                          \
1044
- (add)->hh.key = (char*)keyptr;                                                  \
1045
- (add)->hh.keylen = keylen_in;                                                   \
1046
+ (add)->hh.key = (char*)(keyptr);                                                \
1047
+ (add)->hh.keylen = (unsigned)(keylen_in);                                       \
1048
  if (!(head)) {                                                                  \
1049
     head = (add);                                                                \
1050
     (head)->hh.prev = NULL;                                                      \
1051
@@ -212,17 +235,17 @@ do {
1052
         _hd_hh_del = &((delptr)->hh);                                            \
1053
         if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \
1054
             (head)->hh.tbl->tail =                                               \
1055
-                (UT_hash_handle*)((char*)((delptr)->hh.prev) +                   \
1056
+                (UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +               \
1057
                 (head)->hh.tbl->hho);                                            \
1058
         }                                                                        \
1059
         if ((delptr)->hh.prev) {                                                 \
1060
-            ((UT_hash_handle*)((char*)((delptr)->hh.prev) +                      \
1061
+            ((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) +                  \
1062
                     (head)->hh.tbl->hho))->next = (delptr)->hh.next;             \
1063
         } else {                                                                 \
1064
             DECLTYPE_ASSIGN(head,(delptr)->hh.next);                             \
1065
         }                                                                        \
1066
         if (_hd_hh_del->next) {                                                  \
1067
-            ((UT_hash_handle*)((char*)_hd_hh_del->next +                         \
1068
+            ((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next +                     \
1069
                     (head)->hh.tbl->hho))->prev =                                \
1070
                     _hd_hh_del->prev;                                            \
1071
         }                                                                        \
1072
@@ -239,14 +262,20 @@ do {
1073
     HASH_FIND(hh,head,findstr,strlen(findstr),out)
1074
 #define HASH_ADD_STR(head,strfield,add)                                          \
1075
     HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
1076
+#define HASH_REPLACE_STR(head,strfield,add,replaced)                             \
1077
+  HASH_REPLACE(hh,head,strfield,strlen(add->strfield),add,replaced)
1078
 #define HASH_FIND_INT(head,findint,out)                                          \
1079
     HASH_FIND(hh,head,findint,sizeof(int),out)
1080
 #define HASH_ADD_INT(head,intfield,add)                                          \
1081
     HASH_ADD(hh,head,intfield,sizeof(int),add)
1082
+#define HASH_REPLACE_INT(head,intfield,add,replaced)                             \
1083
+    HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
1084
 #define HASH_FIND_PTR(head,findptr,out)                                          \
1085
     HASH_FIND(hh,head,findptr,sizeof(void *),out)
1086
 #define HASH_ADD_PTR(head,ptrfield,add)                                          \
1087
     HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
1088
+#define HASH_REPLACE_PTR(head,ptrfield,add)                                      \
1089
+    HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
1090
 #define HASH_DEL(head,delptr)                                                    \
1091
     HASH_DELETE(hh,head,delptr)
1092
 
1093
@@ -362,7 +391,7 @@ do {
1094
   for(_fn_i=0; _fn_i < keylen; _fn_i++)                                          \
1095
       hashv = (hashv * 16777619) ^ _hf_key[_fn_i];                               \
1096
   bkt = hashv & (num_bkts-1);                                                    \
1097
-} while(0);
1098
+} while(0) 
1099
  
1100
 #define HASH_OAT(key,keylen,num_bkts,hashv,bkt)                                  \
1101
 do {                                                                             \
1102
@@ -396,10 +425,10 @@ do {
1103
 #define HASH_JEN(key,keylen,num_bkts,hashv,bkt)                                  \
1104
 do {                                                                             \
1105
   unsigned _hj_i,_hj_j,_hj_k;                                                    \
1106
-  char *_hj_key=(char*)(key);                                                    \
1107
+  unsigned char *_hj_key=(unsigned char*)(key);                                  \
1108
   hashv = 0xfeedbeef;                                                            \
1109
   _hj_i = _hj_j = 0x9e3779b9;                                                    \
1110
-  _hj_k = keylen;                                                                \
1111
+  _hj_k = (unsigned)(keylen);                                                      \
1112
   while (_hj_k >= 12) {                                                          \
1113
     _hj_i +=    (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 )                      \
1114
         + ( (unsigned)_hj_key[2] << 16 )                                         \
1115
@@ -447,7 +476,7 @@ do {
1116
 #endif
1117
 #define HASH_SFH(key,keylen,num_bkts,hashv,bkt)                                  \
1118
 do {                                                                             \
1119
-  char *_sfh_key=(char*)(key);                                                   \
1120
+  unsigned char *_sfh_key=(unsigned char*)(key);                                 \
1121
   uint32_t _sfh_tmp, _sfh_len = keylen;                                          \
1122
                                                                                  \
1123
   int _sfh_rem = _sfh_len & 3;                                                   \
1124
@@ -457,7 +486,7 @@ do {
1125
   /* Main loop */                                                                \
1126
   for (;_sfh_len > 0; _sfh_len--) {                                              \
1127
     hashv    += get16bits (_sfh_key);                                            \
1128
-    _sfh_tmp       = (get16bits (_sfh_key+2) << 11) ^ hashv;                     \
1129
+    _sfh_tmp       = (uint32_t)(get16bits (_sfh_key+2)) << 11  ^ hashv;          \
1130
     hashv     = (hashv << 16) ^ _sfh_tmp;                                        \
1131
     _sfh_key += 2*sizeof (uint16_t);                                             \
1132
     hashv    += hashv >> 11;                                                     \
1133
@@ -467,7 +496,7 @@ do {
1134
   switch (_sfh_rem) {                                                            \
1135
     case 3: hashv += get16bits (_sfh_key);                                       \
1136
             hashv ^= hashv << 16;                                                \
1137
-            hashv ^= _sfh_key[sizeof (uint16_t)] << 18;                          \
1138
+            hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)] << 18);              \
1139
             hashv += hashv >> 11;                                                \
1140
             break;                                                               \
1141
     case 2: hashv += get16bits (_sfh_key);                                       \
1142
@@ -487,7 +516,7 @@ do {
1143
     hashv ^= hashv << 25;                                                        \
1144
     hashv += hashv >> 6;                                                         \
1145
     bkt = hashv & (num_bkts-1);                                                  \
1146
-} while(0);
1147
+} while(0) 
1148
 
1149
 #ifdef HASH_USING_NO_STRICT_ALIASING
1150
 /* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
1151
@@ -499,7 +528,7 @@ do {
1152
  *   gcc -m64 -dM -E - < /dev/null                  (on gcc)
1153
  *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)
1154
  */
1155
-#if (defined(__i386__) || defined(__x86_64__)) 
1156
+#if (defined(__i386__) || defined(__x86_64__)  || defined(_M_IX86))
1157
 #define MUR_GETBLOCK(p,i) p[i]
1158
 #else /* non intel */
1159
 #define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
1160
@@ -538,10 +567,12 @@ do {                                                                   \
1161
   uint32_t _mur_h1 = 0xf88D5353;                                       \
1162
   uint32_t _mur_c1 = 0xcc9e2d51;                                       \
1163
   uint32_t _mur_c2 = 0x1b873593;                                       \
1164
+  uint32_t _mur_k1 = 0;                                                \
1165
+  const uint8_t *_mur_tail;                                            \
1166
   const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
1167
   int _mur_i;                                                          \
1168
   for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) {                      \
1169
-    uint32_t _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);               \
1170
+    _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);                        \
1171
     _mur_k1 *= _mur_c1;                                                \
1172
     _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
1173
     _mur_k1 *= _mur_c2;                                                \
1174
@@ -550,8 +581,8 @@ do {                                                                   \
1175
     _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \
1176
     _mur_h1 = _mur_h1*5+0xe6546b64;                                    \
1177
   }                                                                    \
1178
-  const uint8_t *_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
1179
-  uint32_t _mur_k1=0;                                                  \
1180
+  _mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4);            \
1181
+  _mur_k1=0;                                                           \
1182
   switch((keylen) & 3) {                                               \
1183
     case 3: _mur_k1 ^= _mur_tail[2] << 16;                             \
1184
     case 2: _mur_k1 ^= _mur_tail[1] << 8;                              \
1185
@@ -577,10 +608,10 @@ do {
1186
  if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head));          \
1187
  else out=NULL;                                                                  \
1188
  while (out) {                                                                   \
1189
-    if (out->hh.keylen == keylen_in) {                                           \
1190
-        if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break;             \
1191
+    if ((out)->hh.keylen == keylen_in) {                                           \
1192
+        if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) break;             \
1193
     }                                                                            \
1194
-    if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
1195
+    if ((out)->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); \
1196
     else out = NULL;                                                             \
1197
  }                                                                               \
1198
 } while(0)
1199
@@ -729,18 +760,22 @@ do {
1200
                       _hs_qsize--;                                               \
1201
                   } else if ( (_hs_qsize == 0) || !(_hs_q) ) {                   \
1202
                       _hs_e = _hs_p;                                             \
1203
-                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
1204
-                              ((void*)((char*)(_hs_p->next) +                    \
1205
-                              (head)->hh.tbl->hho)) : NULL);                     \
1206
+                      if (_hs_p){                                                \
1207
+                        _hs_p = (UT_hash_handle*)((_hs_p->next) ?                \
1208
+                                ((void*)((char*)(_hs_p->next) +                  \
1209
+                                (head)->hh.tbl->hho)) : NULL);                   \
1210
+                       }                                                         \
1211
                       _hs_psize--;                                               \
1212
                   } else if ((                                                   \
1213
                       cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
1214
                              DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
1215
                              ) <= 0) {                                           \
1216
                       _hs_e = _hs_p;                                             \
1217
-                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
1218
-                              ((void*)((char*)(_hs_p->next) +                    \
1219
-                              (head)->hh.tbl->hho)) : NULL);                     \
1220
+                      if (_hs_p){                                                \
1221
+                        _hs_p = (UT_hash_handle*)((_hs_p->next) ?                \
1222
+                               ((void*)((char*)(_hs_p->next) +                   \
1223
+                               (head)->hh.tbl->hho)) : NULL);                    \
1224
+                       }                                                         \
1225
                       _hs_psize--;                                               \
1226
                   } else {                                                       \
1227
                       _hs_e = _hs_q;                                             \
1228
@@ -755,13 +790,17 @@ do {
1229
                   } else {                                                       \
1230
                       _hs_list = _hs_e;                                          \
1231
                   }                                                              \
1232
+                  if (_hs_e) {                                                   \
1233
                   _hs_e->prev = ((_hs_tail) ?                                    \
1234
                      ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL);              \
1235
+                  }                                                              \
1236
                   _hs_tail = _hs_e;                                              \
1237
               }                                                                  \
1238
               _hs_p = _hs_q;                                                     \
1239
           }                                                                      \
1240
-          _hs_tail->next = NULL;                                                 \
1241
+          if (_hs_tail){                                                         \
1242
+            _hs_tail->next = NULL;                                               \
1243
+          }                                                                      \
1244
           if ( _hs_nmerges <= 1 ) {                                              \
1245
               _hs_looping=0;                                                     \
1246
               (head)->hh.tbl->tail = _hs_tail;                                   \
1247
@@ -827,6 +866,12 @@ do {
1248
   }                                                                              \
1249
 } while(0)
1250
 
1251
+#define HASH_OVERHEAD(hh,head)                                                   \
1252
+ (size_t)((((head)->hh.tbl->num_items   * sizeof(UT_hash_handle))   +            \
1253
+           ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket))   +            \
1254
+            (sizeof(UT_hash_table))                                 +            \
1255
+            (HASH_BLOOM_BYTELEN)))
1256
+
1257
 #ifdef NO_DECLTYPE
1258
 #define HASH_ITER(hh,head,el,tmp)                                                \
1259
 for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL);       \
1260
diff --git a/include/proto/checks.h b/include/proto/checks.h
1261
index cee6dda..40f545d 100644
1262
--- a/include/proto/checks.h
1263
+++ b/include/proto/checks.h
1264
@@ -33,6 +33,10 @@ struct task *process_chk(struct task *t);
1265
 int start_checks();
1266
 void health_adjust(struct server *s, short status);
1267
 
1268
+int dns_socket_write(int);
1269
+int dns_socket_read(int);
1270
+void resolve_server(struct server*, char *);
1271
+
1272
 #endif /* _PROTO_CHECKS_H */
1273
 
1274
 /*
1275
diff --git a/include/types/global.h b/include/types/global.h
1276
index 7c5346b..a4fee7d 100644
1277
--- a/include/types/global.h
1278
+++ b/include/types/global.h
1279
@@ -97,6 +97,8 @@ struct global {
1280
 	} tune;
1281
 	struct listener stats_sock; /* unix socket listener for statistics */
1282
 	struct proxy *stats_fe;     /* the frontend holding the stats settings */
1283
+        int use_dns;    /* whether we are doing DNS look-ups */
1284
+        int dns_fd;     /* socket for DNS lookups */
1285
 };
1286
 
1287
 extern struct global global;
1288
diff --git a/include/types/server.h b/include/types/server.h
1289
index 9fbd290..b89c4a2 100644
1290
--- a/include/types/server.h
1291
+++ b/include/types/server.h
1292
@@ -38,6 +38,8 @@
1293
 #include <types/task.h>
1294
 #include <types/checks.h>
1295
 
1296
+#include <common/uthash.h>
1297
+
1298
 
1299
 /* server flags */
1300
 #define SRV_RUNNING	0x0001	/* the server is UP */
1301
@@ -111,6 +113,13 @@ struct server {
1302
 	int bind_hdr_len;			/* length of the name of the header above */
1303
 	int bind_hdr_occ;			/* occurrence number of header above: >0 = from first, <0 = from end, 0=disabled */
1304
 #endif
1305
+
1306
+        char * hostname;                        /* if !0, should be resolved at run-time */
1307
+	struct timeval dns_next_check;		/* when should the next DNS check be performed */
1308
+        int dns_id;                             /* last DNS query ID used for this server */
1309
+        UT_hash_handle hh;                      /* for being included in dns hash */
1310
+        int dns_ttl_sec;                        /* DNS TTL in m/s. Defaults to 10,000 */
1311
+
1312
 	int iface_len;				/* bind interface name length */
1313
 	char *iface_name;			/* bind interface name or NULL */
1314
 	struct port_range *sport_range;		/* optional per-server TCP source ports */
1315
diff --git a/src/cfgparse.c b/src/cfgparse.c
1316
index 09ffcd3..55a1382 100644
1317
--- a/src/cfgparse.c
1318
+++ b/src/cfgparse.c
1319
@@ -3463,6 +3463,28 @@ stats_error_parsing:
1320
 			} else
1321
 				newsrv->state |= SRV_MAPPORTS;
1322
 
1323
+                        {
1324
+                            char * dns = strstr(raddr, "@ar");
1325
+                            while (dns) {
1326
+                                char * n = strstr(dns+1, "@ar");
1327
+                                if (!n) { break; }
1328
+                                dns = n;
1329
+                            }
1330
+
1331
+                            if (dns) {
1332
+                                *dns = 0;
1333
+                                newsrv->hostname = strdup(raddr);
1334
+                                /* default DNS time out is 5 sec, man resolve.conf */
1335
+                                newsrv->dns_ttl_sec = 5;
1336
+                                if (!newsrv->hostname) {
1337
+                                    Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1338
+                                    err_code |= ERR_ALERT | ERR_ABORT;
1339
+                                    goto out;
1340
+                                }
1341
+                                global.use_dns = 1;
1342
+                            }
1343
+                        }
1344
+
1345
 			sk = str2sa(raddr);
1346
 			free(raddr);
1347
 			if (!sk) {
1348
diff --git a/src/checks.c b/src/checks.c
1349
index 021d025..66c524f 100644
1350
--- a/src/checks.c
1351
+++ b/src/checks.c
1352-
@@ -47,7 +47,55 @@
1352+
@@ -47,7 +47,56 @@
1353
 #include <proto/server.h>
1354
 #include <proto/task.h>
1355
 
1356
+#include <common/uthash.h>
1357
+
1358
+typedef struct dns_out_t {
1359
+    struct dns_out_t * next;
1360
+    struct sockaddr_in to;
1361
+    int len;
1362
+    char * data;
1363
+} dns_out_t;
1364
+
1365
+static dns_out_t * last_chunk;
1366
+static dns_out_t * first_chunk;
1367
+
1368
+struct server * dns_server_hash = 0;
1369
+
1370
+#define RESOLV_CONF "/etc/resolv.conf"
1371
+
1372
+/* we believe 512 bytes is enough for any particular
1373
+ * DNS response, if it's more than that then there is likely
1374
+ * stuff in there we don't care about anyway.
1375
+ * RFC-1035 states that UDP messages must be 512 bytes or less.
1376
+ */
1377
+static unsigned char dns_read[512];
1378
+
1379
+static int last_id = 0;
1380
+
1381
+static time_t last_rc_mod = 0;
1382
+
1383
+static char * dns_error [] = {
1384
+    "ok",
1385
+    "Format error (REPORT BUG)",
1386
+    "Server failure",
1387
+    "Name error (check your hostname)",
1388
+    "Not implemented (REPORT BUG?)",
1389
+    "Query refused"
1390
+};
1391
+
1392
+static struct sockaddr_in dns_server;
1393
+
1394
+__attribute__((constructor))
1395
+static void __dns_init(void) {
1396
+    dns_server.sin_family = AF_INET;
1397
+    dns_server.sin_port = htons(53);
1398
+}
1399
+
1400
+#define DNS_HEADER_SIZE_BYTES 12
1401
+
1402
 static int httpchk_expect(struct server *s, int done);
1403
+static char * build_full_name(int, int);
1404
+static int skip_name(int *, int *);
1405
+static int dns_socket_try_write(void *, int, struct sockaddr_in *, dns_out_t *);
1406
 
1407
 const struct check_status check_statuses[HCHK_STATUS_SIZE] = {
1408
 	[HCHK_STATUS_UNKNOWN]	= { SRV_CHK_UNKNOWN,                   "UNK",     "Unknown" },
1409
@@ -1243,6 +1291,11 @@ struct task *process_chk(struct task *t)
1410
 	int fd;
1411
 	int rv;
1412
 
1413
+        if (s->hostname && tv_islt(&s->dns_next_check, &now)) {
1414
+            resolve_server(s, 0);
1415
+            tv_sec_add(&s->dns_next_check, &now, s->dns_ttl_sec);
1416
+        }
1417
+
1418
  new_chk:
1419
 	if (attempts++ > 0) {
1420
 		/* we always fail to create a server, let's stop insisting... */
1421
@@ -1741,6 +1794,612 @@ static int httpchk_expect(struct server *s, int done)
1422
 }
1423
 
1424
 /*
1425
+ * This function is called on a write event from the DNS socket.
1426
+ * It returns 0 if the caller needs to poll before calling it again, otherwise
1427
+ * non-zero.
1428
+ */
1429
+int dns_socket_write(int s) {
1430
+
1431
+    assert(s == global.dns_fd);
1432
+
1433
+    while (first_chunk) {
1434
+
1435
+        dns_out_t * next = first_chunk->next;
1436
+
1437
+        if (!dns_socket_try_write(0, 0, 0, first_chunk)) {
1438
+            break;
1439
+        }
1440
+        
1441
+        if (first_chunk == last_chunk) {
1442
+            last_chunk = 0;
1443
+        }
1444
+
1445
+        free(first_chunk->data);
1446
+        free(first_chunk);
1447
+        first_chunk = next;
1448
+
1449
+    }
1450
+
1451
+    if (!first_chunk) {
1452
+        EV_FD_CLR(s, DIR_WR);
1453
+        return 1;
1454
+    } else {
1455
+        return 0;
1456
+    }
1457
+
1458
+}
1459
+
1460
+/*
1461
+ * Try to write DNS message, either from a buffer, or from a chunk.
1462
+ * For buffer writes, chunk must be 0, otherwise chunk will be used.
1463
+ * If data can't be written out for a buffered data, a new chunk will
1464
+ * be created, and added to the list.
1465
+ * Returns 0 if data has to be queued (and for buffer, if chunk was created),
1466
+ * otherwise returns !0
1467
+ */
1468
+int dns_socket_try_write(void * data, int len, struct sockaddr_in * to, dns_out_t * chunk) {
1469
+
1470
+    int rc;
1471
+
1472
+    if (chunk) {
1473
+        data = chunk->data;
1474
+        len = chunk->len;
1475
+        to = &chunk->to;
1476
+    }
1477
+    
1478
+    rc = sendto(global.dns_fd, data, len, 0,
1479
+        (struct sockaddr*)to, sizeof(struct sockaddr_in));
1480
+
1481
+    if (rc == -1) {
1482
+        int e = errno;
1483
+        if (e == EAGAIN || e == EWOULDBLOCK) {
1484
+            if (!chunk) {
1485
+                chunk = calloc(1, sizeof(dns_out_t));
1486
+                if (!chunk) {
1487
+                    Alert("Out of memory\n");
1488
+                    exit(1);
1489
+                }
1490
+                if (!last_chunk) {
1491
+                    last_chunk = chunk;
1492
+                    first_chunk = chunk;
1493
+                    EV_FD_SET(global.dns_fd, DIR_WR);
1494
+                } else {
1495
+                    last_chunk->next = chunk;
1496
+                    last_chunk = chunk;
1497
+                }
1498
+                chunk->data = data;
1499
+                chunk->len = len;
1500
+                memcpy(&chunk->to, to, sizeof(struct sockaddr_in));
1501
+            }
1502
+            return 0;
1503
+        }
1504
+        Warning("Failed to send DNS request : %s\n", strerror(e));
1505
+    } 
1506
+
1507
+    // we either wrote the data out, or it's a fatal error,
1508
+    // we'll need to skip.
1509
+    return 1;
1510
+
1511
+}
1512
+
1513
+/*
1514
+ * Skip over a name construct,
1515
+ * returning 0 if OK, or !0 if ran out of space
1516
+ * If !0 is returned, values of *ptr and *rem can
1517
+ * no longer be trusted, otherwise they are adjusted
1518
+ * to represent position after the construct, and
1519
+ * remainder of available bytes.
1520
+ */
1521
+int skip_name(int * ptr, int * rem) {
1522
+
1523
+    while (1) {
1524
+
1525
+        int len;
1526
+        int cc = 0;
1527
+
1528
+        if (*rem < 1) { return 1; }
1529
+
1530
+        len = dns_read[*ptr];
1531
+        if ((len&0xc0) == 0xc0) {
1532
+            len = 2;
1533
+            cc = 1;
1534
+        } else {
1535
+            len++;
1536
+        }
1537
+
1538
+        *rem -= len;
1539
+        *ptr += len;
1540
+
1541
+        if (*rem < 0) { return 1; }
1542
+        /* if we ran into 0 or cc, we are done */
1543
+        if (len == 1 || cc) { return 0; }
1544
+
1545
+    }
1546
+
1547
+}
1548
+
1549
+char * build_full_name(int mlen, int host) {
1550
+
1551
+#define MAX_REC 10 /* may be more? I don't think more is necessary here */
1552
+#define MAX_OUT 256
1553
+
1554
+#define FAIL_IF(a) do { \
1555
+    if (a) { \
1556
+        free(out); \
1557
+        return 0; \
1558
+    } \
1559
+} while(0)
1560
+
1561
+#define ENOUGH(ptr,a) do { \
1562
+    if (((ptr) + (a)) >= mlen) { \
1563
+        free(out); \
1564
+        return 0; \
1565
+    } \
1566
+} while(0)
1567
+
1568
+#define ADD_OUT(sz, str) do { \
1569
+    FAIL_IF((out_at + (sz)) >= MAX_OUT); \
1570
+    memcpy(out+out_at, str, sz); \
1571
+    out_at += sz; \
1572
+} while(0)
1573
+
1574
+    int used_addr[MAX_REC];
1575
+    int used_addr_len;
1576
+
1577
+    char * out = calloc(1, MAX_OUT+1);
1578
+    int out_at = 0;
1579
+    int ptr;
1580
+
1581
+    if (!out) {
1582
+        Alert("Out of memory\n");
1583
+        exit(1);
1584
+    }
1585
+
1586
+    assert(host < mlen);
1587
+
1588
+    used_addr_len = 0;
1589
+
1590
+    ptr = host;
1591
+
1592
+    while (1) {
1593
+
1594
+        int size;
1595
+
1596
+        ENOUGH(ptr, 1);
1597
+
1598
+        size = dns_read[ptr];
1599
+
1600
+        if (size == 0) {
1601
+            break;
1602
+        }
1603
+
1604
+        ptr++;
1605
+
1606
+        if ((size & 0xc0) == 0xc0) {
1607
+
1608
+            int j;
1609
+
1610
+            ENOUGH(ptr, 1);
1611
+            ptr = ((size&0x3f) << 8) | dns_read[ptr];
1612
+
1613
+            FAIL_IF(used_addr_len == MAX_REC);
1614
+
1615
+            for (j=0; j<used_addr_len; j++) {
1616
+                FAIL_IF(used_addr[j] == ptr);
1617
+            }
1618
+
1619
+            used_addr[used_addr_len++] = ptr;
1620
+
1621
+            continue;
1622
+        }
1623
+
1624
+        if (*out) {
1625
+            ADD_OUT(1, ".");
1626
+        }
1627
+
1628
+        ENOUGH(ptr, size);
1629
+        ADD_OUT(size, dns_read + ptr);
1630
+        ptr += size;
1631
+    }
1632
+
1633
+    return out;
1634
+
1635
+#undef FAIL_IF
1636
+#undef ENOUGH
1637
+#undef MAX_REC
1638
+#undef ADD_OUT
1639
+#undef MAX_OUT
1640
+
1641
+}
1642
+
1643
+/*
1644
+ * this function is called on a read event from the DNS socket.
1645
+ * It returns 0 if we have a high confidence that we will not be
1646
+ * able to read more data without polling first. Returns non-zero
1647
+ * otherwise.
1648
+ */
1649
+int dns_socket_read(int s) {
1650
+
1651
+/* this is to get WORD on BYTE boundary <n> */
1652
+#define D_WORD(n) \
1653
+    ((((int)dns_read[n])<<8) | ((int)dns_read[(n)+1]))
1654
+
1655
+    assert(s == global.dns_fd);
1656
+
1657
+    while (1) {
1658
+
1659
+        int rc = recv(s, dns_read, sizeof(dns_read), 0);
1660
+        int id;
1661
+        struct server * for_server;
1662
+        int aux;
1663
+        int answer_at = DNS_HEADER_SIZE_BYTES;
1664
+        char * cname = 0;
1665
+        int mlen = rc;
1666
+        int addr_ok = 0;
1667
+
1668
+        if (rc < 0) {
1669
+            int e = errno;
1670
+            if (e == EAGAIN || e == EWOULDBLOCK) {
1671
+                return 0;
1672
+            } else {
1673
+                Warning("Failed to read DNS response : %s\n", strerror(e));
1674
+                continue;
1675
+            }
1676
+        }
1677
+
1678
+        if ((rc -= DNS_HEADER_SIZE_BYTES) < 0) {
1679
+            Warning("DNS response is too small : %d\n", rc);
1680
+            continue;
1681
+        }
1682
+
1683
+        id = D_WORD(0);
1684
+
1685
+        HASH_FIND_INT(dns_server_hash, &id, for_server);
1686
+        if (!for_server) {
1687
+            Warning("Received DNS response ID %d, no matching request found\n", id);
1688
+            continue;
1689
+        }
1690
+
1691
+        HASH_DEL(dns_server_hash, for_server);
1692
+        for_server->dns_id = 0;
1693
+
1694
+        aux = D_WORD(2);
1695
+
1696
+        if (!(aux&0x8000)) {
1697
+            Warning("Received DNS message is not a response\n");
1698
+            continue;
1699
+        }
1700
+
1701
+        aux &= 0xf;
1702
+        if (aux > 5) {
1703
+            Warning("Received unknown reply code from DNS : %d\n", aux);
1704
+            continue;
1705
+        }
1706
+
1707
+        if (aux > 0) {
1708
+            Warning("DNS server returned error : %s\n", dns_error[aux]);
1709
+            continue;
1710
+        }
1711
+
1712
+        aux = D_WORD(4); /* QDCOUNT */
1713
+        while (aux) {
1714
+
1715
+            if (skip_name(&answer_at, &rc)) {
1716
+                break;
1717
+            }
1718
+
1719
+            rc -= 4;
1720
+            answer_at += 4;
1721
+
1722
+            if (rc < 0) { break; }
1723
+
1724
+            aux--;
1725
+
1726
+        }
1727
+
1728
+        if (aux) {
1729
+            Warning("Malformed DNS answer\n");
1730
+            continue;
1731
+        }
1732
+
1733
+        aux = D_WORD(6); /* ANCOUNT */
1734
+        
1735
+        while (aux) {
1736
+
1737
+            int type;
1738
+            int class;
1739
+            int rdlen;
1740
+            int ttl;
1741
+
1742
+            /* skip over domain for now, we don't need it at all? */
1743
+
1744
+            if (skip_name(&answer_at, &rc)) {
1745
+                break;
1746
+            }
1747
+
1748
+            /* we need at least 8 bytes available, for:
1749
+             * TYPE,CLASS,TTL,RDLENGTH
1750
+             */
1751
+            if (rc < 8) {
1752
+                break;
1753
+            }
1754
+
1755
+            type = D_WORD(answer_at);
1756
+            class = D_WORD(answer_at + 2);
1757
+            ttl = (D_WORD(answer_at + 4) << 16) | D_WORD(answer_at + 6);
1758
+            rdlen = D_WORD(answer_at + 8);
1759
+            
1760
+            /* this is a hack, but that would mean that TTL is so huge, it
1761
+             * won't matter much anyway */
1762
+            if (ttl < 0) {
1763
+                ttl = ((unsigned int)ttl) >> 1;
1764
+            }
1765
+
1766
+            rc -= 10;
1767
+            answer_at += 10;
1768
+
1769
+            if (rc < rdlen) {
1770
+                break;
1771
+            }
1772
+
1773
+            if (type == 5 && !cname) {
1774
+                /* CNAME */
1775
+                cname = build_full_name(mlen, answer_at);
1776
+                if (cname) {
1777
+                    Warning("Got cname %s\n", cname);
1778
+                }
1779
+            } else if (type == 1 && class == 1 && rdlen >= 4) {
1780
+                /* type A and class IN */
1781
+
1782
+                tv_sec_add(&for_server->dns_next_check, &now,
1783
+                        for_server->dns_ttl_sec = ttl);
1784
+                in_addr_t addr = (D_WORD(answer_at) << 16) | D_WORD(answer_at+2);
1785
+                for_server->addr.sin_addr.s_addr = htonl(addr);
1786
+                addr_ok = 1;
1787
+                break;
1788
+            }
1789
+
1790
+            /* otherwise we don't recognize what's there */
1791
+            rc -= rdlen;
1792
+            answer_at += rdlen;
1793
+
1794
+            if (rc < 0) { break; }
1795
+
1796
+            aux--;
1797
+
1798
+        }
1799
+
1800
+        if (cname && !addr_ok) {
1801
+            /* we need to resolve cname */
1802
+            resolve_server(for_server, cname);
1803
+        }
1804
+
1805
+        if (!cname && !addr_ok) {
1806
+            Warning("Received useless or malformed DNS response for server %s\n", for_server->id);
1807
+        }
1808
+
1809
+        if (cname) { free(cname); }
1810
+
1811
+    }
1812
+
1813
+#undef D_WORD
1814
+
1815
+}
1816
+
1817
+void resolve_server(struct server * srv, char * hostname) {
1818
+
1819
+    struct stat rc_stat;
1820
+    int no_resolver = 0;
1821
+    unsigned char * query;
1822
+    unsigned char * ptr;
1823
+    char * cname;
1824
+    int rem;
1825
+
1826
+    if (!hostname) {
1827
+        hostname = srv->hostname;
1828
+    }
1829
+
1830
+    if (!hostname) {
1831
+        /* I should not be even called in this case */
1832
+        return;
1833
+    }
1834
+
1835
+    /* default DNS time out is 5 sec, man resolve.conf */
1836
+    tv_sec_add(&srv->dns_next_check, &now, 5);
1837
+
1838
+    if (srv->dns_id) {
1839
+        struct server * aux;
1840
+        HASH_FIND_INT(dns_server_hash, &srv->dns_id, aux);
1841
+        assert(aux == srv);
1842
+        srv->dns_id = 0; /* redundant */
1843
+        HASH_DEL(dns_server_hash, aux);
1844
+    }
1845
+
1846
+    last_id = (last_id + 1) & 0xffff;
1847
+    /* avoid dns_id being 0 */
1848
+    if (!last_id) { last_id++; }
1849
+
1850
+    srv->dns_id = last_id;
1851
+    HASH_ADD_INT(dns_server_hash, dns_id, srv);
1852
+
1853
+    if (stat(RESOLV_CONF, &rc_stat)) {
1854
+        /* We shouldn't complain about it missing, as supposedly that just
1855
+         * means to try localhost */
1856
+        /* Warning("Can't stat " RESOLV_CONF " : %s\n", strerror(errno)); */
1857
+        no_resolver = 1;
1858
+    }
1859
+
1860
+    if (!no_resolver && last_rc_mod < rc_stat.st_mtime) {
1861
+
1862
+        do {
1863
+
1864
+            rem = rc_stat.st_size;
1865
+            unsigned char buf[rem];
1866
+            ptr = buf;
1867
+            int fd;
1868
+
1869
+            no_resolver = 1;
1870
+
1871
+            last_rc_mod = rc_stat.st_mtime;
1872
+
1873
+            fd = open(RESOLV_CONF, O_RDONLY);
1874
+            if (fd < 0) {
1875
+                Warning("Can't open " RESOLV_CONF " : %s\n", strerror(errno));
1876
+                break;
1877
+            }
1878
+
1879
+            while (rem) {
1880
+                int rc = read(fd, ptr, rem);
1881
+                if (rc < 0) {
1882
+                    Warning("Failed reading " RESOLV_CONF " : %s\n", strerror(errno));
1883
+                    close(fd);
1884
+                    break;
1885
+                }
1886
+
1887
+                rem -= rc;
1888
+                ptr += rc;
1889
+            }
1890
+
1891
+            close(fd);
1892
+
1893
+            ptr = buf;
1894
+            rem = rc_stat.st_size;
1895
+
1896
+            while (1) {
1897
+
1898
+                void * next;
1899
+
1900
+                /* if we have left than 12 chars left, there
1901
+                 * is no way we can fit namesever configuration */
1902
+                if (rem < 12) { break; }
1903
+
1904
+                if (!strncmp("nameserver", (char*)ptr, 10)) {
1905
+
1906
+                    int has_space = 0;
1907
+
1908
+                    /* 10 : length of "nameserver" */
1909
+                    rem -= 10;
1910
+                    ptr += 10;
1911
+
1912
+                    while (rem && isspace(*ptr)) {
1913
+                        ptr++;
1914
+                        rem--;
1915
+                        has_space = 1;
1916
+                    }
1917
+
1918
+                    if (has_space) {
1919
+
1920
+                        char buf[16];
1921
+                        int i;
1922
+                        struct in_addr addr;
1923-
+                        memset(buf, 16, 0);
1923+
1924
+                        memset(buf, 0, 16);
1925
+
1926
+                        for (i=0; i<16; i++) {
1927
+                            if (!rem || isspace(*ptr) || (*ptr == '\r') || (*ptr=='\n')) {
1928
+                                break;
1929
+                            }
1930
+                            buf[i] = *(ptr++);
1931
+                            rem--;
1932
+                        }
1933
+
1934
+                        if (inet_pton(AF_INET, buf, &addr)) {
1935
+                            no_resolver = 0;
1936
+                            dns_server.sin_addr = addr;
1937
+                            break;
1938
+                        }
1939
+
1940
+                    }
1941
+
1942
+                }
1943
+
1944
+                next = memchr(ptr, '\n', rem);
1945
+                if (!next) { break; }
1946
+
1947
+                rem -= (next+1-(void*)ptr);
1948
+                ptr = next + 1;
1949
+
1950
+                if (rem <= 0) { break; }
1951
+
1952
+            }
1953
+
1954
+        } while (0);
1955
+
1956
+    }
1957
+
1958
+    if (no_resolver) {
1959
+        dns_server.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1960
+    }
1961
+
1962
+    /* create the query */
1963
+
1964
+    /* name can pretty much fit into its strlen,
1965
+     * then 12 bytes for header, 1 byte for final 0,
1966
+     * 4 bytes for qtype/qclass, rounded as 20 */
1967
+    rem = strlen(hostname) + 20;
1968
+
1969
+    query = calloc(1, rem);
1970
+    if (!query) {
1971
+        Alert("Out of memory\n");
1972
+        exit(1);
1973
+    }
1974
+
1975
+    query[0] = (srv->dns_id >> 8) & 0xff;
1976
+    query[1] = srv->dns_id & 0xff;
1977
+    query[2] = 0x01; /* opcode=query(0),rd=1 */
1978
+    
1979
+    query[5] = 1; /* QDCOUNT = 1 */
1980
+
1981
+    ptr = query + 12;
1982
+    cname = hostname;
1983
+
1984
+    /* rest of header is 0 */
1985
+    /* write out name */
1986
+
1987
+    while (1) {
1988
+
1989
+        char * to;
1990
+        int len;
1991
+        int end = 0;
1992
+        if (!*cname || ((*cname) == '.' && !*(cname+1))) {
1993
+            /* we are at root */
1994
+            *ptr = 0;
1995
+            break;
1996
+        }
1997
+
1998
+        to = strchr(cname, '.');
1999
+        if (!to) {
2000
+            to = cname + strlen(cname);
2001
+            end = 1;
2002
+        }
2003
+        /* we need to take characters between cname(inclusive) and to(exclusive) */
2004
+        len = to - cname;
2005
+
2006
+        if (!len) { continue; } /* multiple dots? */
2007
+
2008
+        *(ptr++) = len;
2009
+        memcpy(ptr, cname, len);
2010
+        ptr += len;
2011
+        if (end) { break; }
2012
+        cname = to + 1;
2013
+
2014
+    }
2015
+
2016
+    *(ptr + 2) = 1; /* qtype=A */
2017
+    *(ptr + 4) = 1; /* qclass=IN */
2018
+
2019
+    EV_FD_COND_S(global.dns_fd, DIR_RD);
2020
+
2021
+    if (dns_socket_try_write(query, rem, &dns_server, 0)) {
2022
+        /* the data was written out if !0 was returned */
2023
+        free(query);
2024
+    }
2025
+
2026
+
2027
+
2028
+}
2029
+
2030
+/*
2031
  * Local variables:
2032
  *  c-indent-level: 8
2033
  *  c-basic-offset: 8
2034
diff --git a/src/haproxy.c b/src/haproxy.c
2035
index c163743..35dec8b 100644
2036
--- a/src/haproxy.c
2037
+++ b/src/haproxy.c
2038
@@ -631,6 +631,10 @@ void init(int argc, char **argv)
2039
 	global.maxsock += global.maxconn * 2; /* each connection needs two sockets */
2040
 	global.maxsock += global.maxpipes * 2; /* each pipe needs two FDs */
2041
 
2042
+        if (global.use_dns) {
2043
+            global.maxsock++;
2044
+        }
2045
+
2046
 	if (global.tune.maxpollevents <= 0)
2047
 		global.tune.maxpollevents = MAX_POLL_EVENTS;
2048
 
2049
@@ -681,10 +685,67 @@ void init(int argc, char **argv)
2050
 				       sizeof(struct fdinfo) * (global.maxsock));
2051
 	fdtab = (struct fdtab *)calloc(1,
2052
 				       sizeof(struct fdtab) * (global.maxsock));
2053
+
2054
+        if (!swap_buffer || !fdinfo || !fdtab) {
2055
+            Alert("Out of memory!\n");
2056
+            exit(1);
2057
+        }
2058
+
2059
 	for (i = 0; i < global.maxsock; i++) {
2060
 		fdtab[i].state = FD_STCLOSE;
2061
 	}
2062
 
2063
+        if (global.use_dns) {
2064
+
2065
+            int ok = 0;
2066
+
2067
+            do {
2068
+
2069
+                int s = socket(AF_INET, SOCK_DGRAM, 0);
2070
+                struct sockaddr_in l;
2071
+                int f;
2072
+
2073
+                l.sin_family = AF_INET;
2074
+                l.sin_addr.s_addr = INADDR_ANY;
2075
+                l.sin_port = 0;
2076
+
2077
+                if (s<0) {
2078
+                    Alert("New inet/dgram socket : %s\n", strerror(errno));
2079
+                    break;
2080
+                }
2081
+
2082
+                if (bind(s, (struct sockaddr*)&l, sizeof(struct sockaddr_in))) {
2083
+                    Alert("Binding inet/dgram socket : %s\n", strerror(errno));
2084
+                    break;
2085
+                }
2086
+
2087
+                f = fcntl(s, F_GETFL);
2088
+                if (f == -1) {
2089
+                    Alert("Can't get flags for %d: %s\n", s, strerror(errno));
2090
+                    break;
2091
+                }
2092
+
2093
+                if (fcntl(s, F_SETFL, f|O_NONBLOCK)) {
2094
+                    Alert("Can't set NON_BLK for %d: %s\n", s, strerror(errno));
2095
+                    break;
2096
+                }
2097
+
2098
+                global.dns_fd = s;
2099
+                fdtab[s].state = FD_STREADY;
2100
+                fdtab[s].cb[DIR_WR].f = dns_socket_write;
2101
+                fdtab[s].cb[DIR_RD].f = dns_socket_read;
2102
+                
2103
+                ok = 1;
2104
+
2105
+            } while(0);
2106
+
2107
+            if (!ok) {
2108
+                Alert("Failed to establish DNS reply socket\n");
2109
+                exit(1);
2110
+            }
2111
+
2112
+        }
2113
+
2114
 	/*
2115
 	 * Note: we could register external pollers here.
2116
 	 * Built-in pollers have been registered before main().
2117
diff --git a/src/time.c b/src/time.c
2118
index 342be9d..d938928 100644
2119
--- a/src/time.c
2120
+++ b/src/time.c
2121
@@ -38,6 +38,15 @@ REGPRM3 struct timeval *_tv_ms_add(struct timeval *tv, const struct timeval *fro
2122
 }
2123
 
2124
 /*
2125
+ * adds <sec> sec to <from>, set the result to <tv> and returns a pointer <tv>
2126
+ */
2127
+REGPRM3 struct timeval *_tv_sec_add(struct timeval *tv, const struct timeval *from, int sec)
2128
+{
2129
+	tv->tv_sec  = from->tv_sec  + sec;
2130
+	return tv;
2131
+}
2132
+
2133
+/*
2134
  * compares <tv1> and <tv2> modulo 1ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2
2135
  * Must not be used when either argument is eternity. Use tv_ms_cmp2() for that.
2136
  */