Merge lp:~jake-moilanen/libmemcached/ubuntu32-build into lp:~tangent-org/libmemcached/trunk

Proposed by Jake Moilanen
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jake-moilanen/libmemcached/ubuntu32-build
Merge into: lp:~tangent-org/libmemcached/trunk
Diff against target: 4999 lines (+2532/-1181)
48 files modified
.bzrignore (+1/-0)
Makefile.am (+1/-1)
clients/ms_atomic.h (+4/-0)
clients/ms_conn.c (+13/-13)
clients/ms_memslap.h (+3/-0)
clients/ms_stats.c (+21/-0)
clients/ms_stats.h (+13/-0)
clients/ms_task.c (+6/-6)
clients/ms_thread.c (+2/-2)
configure.ac (+45/-0)
libhashkit/Makefile.am (+43/-0)
libhashkit/algorithm.h (+49/-0)
libhashkit/behavior.c (+89/-0)
libhashkit/behavior.h (+68/-0)
libhashkit/common.h (+32/-0)
libhashkit/crc32.c (+2/-3)
libhashkit/default.c (+28/-0)
libhashkit/fnv.c (+75/-0)
libhashkit/hashkit.c (+255/-226)
libhashkit/hashkit.h (+117/-0)
libhashkit/hsieh.c (+2/-2)
libhashkit/jenkins.c (+4/-4)
libhashkit/ketama.c (+113/-473)
libhashkit/md5.c (+12/-1)
libhashkit/murmur.c (+2/-2)
libhashkit/types.h (+85/-0)
libhashkit/visibility.h (+51/-0)
libmemcached/Makefile.am (+4/-13)
libmemcached/common.h (+13/-26)
libmemcached/memcached.c (+55/-4)
libmemcached/memcached.h (+6/-11)
libmemcached/memcached_behavior.c (+43/-10)
libmemcached/memcached_constants.h (+4/-7)
libmemcached/memcached_hash.c (+46/-0)
libmemcached/memcached_hash.h (+9/-0)
libmemcached/memcached_server.c (+298/-0)
libmemcached/memcached_types.h (+4/-5)
m4/pandora_have_libhashkit.m4 (+51/-0)
tests/Makefile.am (+22/-15)
tests/atomsmasher.c (+4/-4)
tests/function.c (+290/-319)
tests/hash_results.h (+115/-0)
tests/hashkit_functions.c (+363/-0)
tests/output_plus.res (+0/-5)
tests/plus.cpp (+17/-11)
tests/test.c (+38/-16)
tests/test.h (+13/-1)
tests/udp.c (+1/-1)
To merge this branch: bzr merge lp:~jake-moilanen/libmemcached/ubuntu32-build
Reviewer Review Type Date Requested Status
Libmemcached-developers Pending
Review via email: mp+16045@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jake Moilanen (jake-moilanen) wrote :

Here's the code to hopefully fix the ubuntu 32-bit build issue.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2009-10-01 13:45:12 +0000
3+++ .bzrignore 2009-12-11 17:27:14 +0000
4@@ -65,3 +65,4 @@
5 libmemcached-0.31-1.src.rpm
6 libmemcached-0.31-1.x86_64.rpm
7 libmemcached-?.??/
8+tests/testhashkit
9
10=== modified file 'Makefile.am'
11--- Makefile.am 2009-10-05 18:37:05 +0000
12+++ Makefile.am 2009-12-11 17:27:14 +0000
13@@ -1,6 +1,6 @@
14 ACLOCAL_AMFLAGS = -I m4
15
16-SUBDIRS = docs libmemcached support clients tests example
17+SUBDIRS = docs ${PANDORA_BUNDLED_SUBDIRS} libmemcached support clients tests example
18 EXTRA_dist = README.FIRST
19
20 check-local: test-no-outputdiff
21
22=== modified file 'clients/ms_atomic.h'
23--- clients/ms_atomic.h 2009-12-03 19:26:03 +0000
24+++ clients/ms_atomic.h 2009-12-11 17:27:14 +0000
25@@ -23,6 +23,10 @@
26 # define atomic_dec_16_nv(X) __sync_fetch_and_sub((X), 1)
27 # define atomic_dec_32_nv(X) __sync_fetch_and_sub((X), 1)
28 # define atomic_dec_64_nv(X) __sync_fetch_and_sub((X), 1)
29+
30+# define spin_lock(l) while (__sync_lock_test_and_set(l, (void *) 1) == 1) {}
31+# define spin_unlock(l) { asm volatile ("sfence":::"memory"); *(l) = 0;}
32+
33 #endif /* defined(__SUNPRO_C) */
34
35 #endif /* CLIENTS_MS_ATOMIC_H */
36
37=== modified file 'clients/ms_conn.c'
38--- clients/ms_conn.c 2009-12-06 09:02:23 +0000
39+++ clients/ms_conn.c 2009-12-11 17:27:14 +0000
40@@ -371,7 +371,7 @@
41
42 if (! (ms_setting.facebook_test && is_udp))
43 {
44- atomic_add_32(&ms_stats.active_conns, 1);
45+ ms_update_conns(&ms_stats, &ms_stats.active_conns, 1);
46 }
47
48 return 0;
49@@ -691,7 +691,7 @@
50 close(c->udpsfd);
51 }
52
53- atomic_dec_32(&ms_stats.active_conns);
54+ ms_update_conns(&ms_stats, &ms_stats.active_conns, -1);
55
56 ms_conn_free(c);
57
58@@ -1589,7 +1589,7 @@
59
60 if (res > 0)
61 {
62- atomic_add_64(&ms_stats.bytes_read, res);
63+ ms_update_stats(&ms_stats, &ms_stats.bytes_read, res);
64 c->rudpbytes+= res;
65 rbytes+= res;
66 if (res == avail)
67@@ -1623,7 +1623,7 @@
68
69 if (copybytes == -1)
70 {
71- atomic_add_64(&ms_stats.pkt_disorder, 1);
72+ ms_update_stats(&ms_stats, (uint64_t *)&ms_stats.pkt_disorder, 1);
73 }
74
75 return copybytes;
76@@ -1701,7 +1701,7 @@
77 {
78 if (! c->udp)
79 {
80- atomic_add_64(&ms_stats.bytes_read, res);
81+ ms_update_stats(&ms_stats, &ms_stats.bytes_read, res);
82 }
83 gotdata= 1;
84 c->rbytes+= res;
85@@ -1765,7 +1765,7 @@
86 if (curr_time.tv_sec - c->curr_task.item->client_time
87 > c->curr_task.item->exp_time + EXPIRE_TIME_ERROR)
88 {
89- atomic_add_64(&ms_stats.exp_get, 1);
90+ ms_update_stats(&ms_stats, &ms_stats.exp_get, 1);
91
92 if (ms_setting.verbose)
93 {
94@@ -1806,7 +1806,7 @@
95 if ((c->curr_task.item->value_size != vlen)
96 || (memcmp(orignval, value, (size_t)vlen) != 0))
97 {
98- atomic_add_64(&ms_stats.vef_failed, 1);
99+ ms_update_stats(&ms_stats, &ms_stats.vef_failed, 1);
100
101 if (ms_setting.verbose)
102 {
103@@ -2254,7 +2254,7 @@
104 res= sendmsg(c->sfd, m, 0);
105 if (res > 0)
106 {
107- atomic_add_64(&ms_stats.bytes_written, res);
108+ ms_update_stats(&ms_stats, &ms_stats.bytes_written, (int)res);
109
110 /* We've written some of the data. Remove the completed
111 * iovec entries from the list of pending writes. */
112@@ -2997,9 +2997,9 @@
113 }
114 }
115
116- atomic_add_64(&ms_stats.obj_bytes,
117- item->key_size + item->value_size);
118- atomic_add_64(&ms_stats.cmd_set, 1);
119+ ms_update_stats(&ms_stats, &ms_stats.obj_bytes,
120+ item->key_size + item->value_size);
121+ ms_update_stats(&ms_stats, &ms_stats.cmd_set, 1);
122
123 return 0;
124 } /* ms_mcd_set */
125@@ -3083,7 +3083,7 @@
126 }
127 }
128
129- atomic_add_64(&ms_stats.cmd_get, 1);
130+ ms_update_stats(&ms_stats, &ms_stats.cmd_get, 1);
131
132 return 0;
133 } /* ms_mcd_get */
134@@ -3182,7 +3182,7 @@
135 for (int i= 0; i < c->mlget_task.mlget_num; i++)
136 {
137 item= c->mlget_task.mlget_item[i].item;
138- atomic_add_64(&ms_stats.cmd_get, 1);
139+ ms_update_stats(&ms_stats, &ms_stats.cmd_get, 1);
140 }
141
142 return 0;
143
144=== modified file 'clients/ms_memslap.h'
145--- clients/ms_memslap.h 2009-12-03 19:26:03 +0000
146+++ clients/ms_memslap.h 2009-12-11 17:27:14 +0000
147@@ -28,6 +28,8 @@
148 extern "C" {
149 #endif
150
151+typedef int32_t spin_lock_t;
152+
153 /* command line option */
154 typedef enum
155 {
156@@ -85,6 +87,7 @@
157 volatile uint64_t pkt_disorder; /* disorder packages of UDP */
158 uint64_t pkt_drop; /* packages dropped of UDP */
159 uint64_t udp_timeout; /* how many times timeout of UDP happens */
160+ spin_lock_t stats_lock; /* lock to update stats structure */
161 } ms_stats_t;
162
163 /* lock adapter */
164
165=== modified file 'clients/ms_stats.c'
166--- clients/ms_stats.c 2009-12-03 20:16:27 +0000
167+++ clients/ms_stats.c 2009-12-11 17:27:14 +0000
168@@ -12,7 +12,9 @@
169 #include "config.h"
170
171 #include <inttypes.h>
172+#include "ms_memslap.h"
173 #include "ms_stats.h"
174+#include "ms_atomic.h"
175
176 #define array_size(x) (sizeof(x) / sizeof((x)[0]))
177
178@@ -305,3 +307,22 @@
179 stat->period_max_time= 0;
180 stat->pre_get_miss= stat->get_miss;
181 } /* ms_dump_format_stats */
182+
183+void ms_update_stats(struct stats * stats,
184+ uint64_t * stat,
185+ int amount)
186+{
187+ spin_lock(&stats->stats_lock);
188+ *stat += (uint64_t)amount;
189+ spin_unlock(&stats->stats_lock);
190+}
191+
192+void ms_update_conns(struct stats * stats,
193+ volatile uint32_t * num_conns,
194+ int amount)
195+{
196+ spin_lock(&stats->stats_lock);
197+ *(int32_t *)num_conns += (int32_t)amount;
198+ spin_unlock(&stats->stats_lock);
199+}
200+
201
202=== modified file 'clients/ms_stats.h'
203--- clients/ms_stats.h 2009-11-30 16:43:20 +0000
204+++ clients/ms_stats.h 2009-12-11 17:27:14 +0000
205@@ -62,6 +62,19 @@
206 int obj_size);
207
208
209+struct stats;
210+
211+/* update a stats counter */
212+void ms_update_stats(struct stats * stats,
213+ uint64_t * stat,
214+ int amount);
215+
216+/* update the number of connections */
217+void ms_update_conns(struct stats * stats,
218+ volatile uint32_t * num_conns,
219+ int amount);
220+
221+
222 #ifdef __cplusplus
223 }
224 #endif
225
226=== modified file 'clients/ms_task.c'
227--- clients/ms_task.c 2009-12-03 20:16:27 +0000
228+++ clients/ms_task.c 2009-12-11 17:27:14 +0000
229@@ -725,7 +725,7 @@
230 /* update get miss counter */
231 if (mlget_item->get_miss)
232 {
233- atomic_add_64(&ms_stats.get_misses, 1);
234+ ms_update_stats(&ms_stats, &ms_stats.get_misses, 1);
235 }
236
237 /* get nothing from server for this task item */
238@@ -741,7 +741,7 @@
239 if (curr_time.tv_sec - item->client_time
240 < item->exp_time - EXPIRE_TIME_ERROR)
241 {
242- atomic_add_64(&ms_stats.unexp_unget, 1);
243+ ms_update_stats(&ms_stats, &ms_stats.unexp_unget, 1);
244
245 if (ms_setting.verbose)
246 {
247@@ -779,7 +779,7 @@
248 }
249 else
250 {
251- atomic_add_64(&ms_stats.vef_miss, 1);
252+ ms_update_stats(&ms_stats, &ms_stats.vef_miss, 1);
253
254 if (ms_setting.verbose)
255 {
256@@ -829,7 +829,7 @@
257 /* update get miss counter */
258 if ((c->precmd.cmd == CMD_GET) && c->curr_task.get_miss)
259 {
260- atomic_add_64(&ms_stats.get_misses, 1);
261+ ms_update_stats(&ms_stats, &ms_stats.get_misses, 1);
262 }
263
264 /* get nothing from server for this task item */
265@@ -846,7 +846,7 @@
266 if (curr_time.tv_sec - item->client_time
267 < item->exp_time - EXPIRE_TIME_ERROR)
268 {
269- atomic_add_64(&ms_stats.unexp_unget, 1);
270+ ms_update_stats(&ms_stats, &ms_stats.unexp_unget, 1);
271
272 if (ms_setting.verbose)
273 {
274@@ -884,7 +884,7 @@
275 }
276 else
277 {
278- atomic_add_64(&ms_stats.vef_miss, 1);
279+ ms_update_stats(&ms_stats, &ms_stats.vef_miss, 1);
280
281 if (ms_setting.verbose)
282 {
283
284=== modified file 'clients/ms_thread.c'
285--- clients/ms_thread.c 2009-12-06 09:02:23 +0000
286+++ clients/ms_thread.c 2009-12-11 17:27:14 +0000
287@@ -69,10 +69,10 @@
288 /* calculate dropped packets count */
289 if (c->recvpkt > 0)
290 {
291- atomic_add_64(&ms_stats.pkt_drop, c->packets - c->recvpkt);
292+ ms_update_stats(&ms_stats, &ms_stats.pkt_drop, c->packets - c->recvpkt);
293 }
294
295- atomic_add_64(&ms_stats.udp_timeout, 1);
296+ ms_update_stats(&ms_stats, &ms_stats.udp_timeout, 1);
297 ms_reset_conn(c, true);
298 }
299 }
300
301=== modified file 'configure.ac'
302--- configure.ac 2009-12-05 13:11:26 +0000
303+++ configure.ac 2009-12-11 17:27:14 +0000
304@@ -14,6 +14,49 @@
305
306 PANDORA_CANONICAL_TARGET
307
308+#shared library versioning
309+MEMCACHED_LIBRARY_VERSION=3:0:0
310+# | | |
311+# +------+ | +---+
312+# | | |
313+# current:revision:age
314+# | | |
315+# | | +- increment if interfaces have been added
316+# | | set to zero if interfaces have been removed or changed
317+# | +- increment if source code has changed
318+# | set to zero if current is incremented
319+# +- increment if interfaces have been added, removed or changed
320+AC_SUBST(MEMCACHED_LIBRARY_VERSION)
321+MEMCACHEDUTIL_LIBRARY_VERSION=0:0:0
322+AC_SUBST(MEMCACHEDUTIL_LIBRARY_VERSION)
323+MEMCACHEDPROTOCOL_LIBRARY_VERSION=0:0:0
324+AC_SUBST(MEMCACHEDPROTOCOL_LIBRARY_VERSION)
325+HASHKIT_LIBRARY_VERSION=0:0:0
326+AC_SUBST(HASHKIT_LIBRARY_VERSION)
327+
328+
329+# libmemcached versioning when linked with GNU ld.
330+if test "$lt_cv_prog_gnu_ld" = "yes"
331+then
332+ LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmemcached/libmemcached.ver"
333+ LD_UTIL_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmemcached/util/libmemcachedutil.ver"
334+ LD_PROTOCOL_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmemcached/protocol/libmemcachedprotocol.ver"
335+fi
336+AC_SUBST(LD_VERSION_SCRIPT)
337+AC_SUBST(LD_UTIL_VERSION_SCRIPT)
338+AC_SUBST(LD_PROTOCOL_VERSION_SCRIPT)
339+
340+
341+#--------------------------------------------------------------------
342+# Check for libpthread
343+#--------------------------------------------------------------------
344+
345+ACX_PTHREAD(,AC_MSG_ERROR(could not find libpthread))
346+LIBS="${PTHREAD_LIBS} ${LIBS}"
347+CFLAGS="${PTHREAD_CFLAGS} ${CFLAGS}"
348+CC="$PTHREAD_CC"
349+
350+
351 AC_SEARCH_LIBS(getopt_long, gnugetopt)
352 AC_SEARCH_LIBS(gethostbyname, nsl)
353
354@@ -35,6 +78,7 @@
355 ENABLE_DEPRECATED
356 PANDORA_HAVE_LIBINNODB
357 PANDORA_PRINT_CALLSTACK
358+PANDORA_BUNDLE_LIBHASHKIT
359
360 AC_CONFIG_FILES([
361 Makefile
362@@ -48,6 +92,7 @@
363 support/libmemcached.pc
364 support/libmemcached.spec
365 support/libmemcached-fc.spec
366+ libhashkit/Makefile
367 ])
368 AC_OUTPUT
369
370
371=== added directory 'libhashkit'
372=== added file 'libhashkit/Makefile.am'
373--- libhashkit/Makefile.am 1970-01-01 00:00:00 +0000
374+++ libhashkit/Makefile.am 2009-12-11 17:27:14 +0000
375@@ -0,0 +1,43 @@
376+# HashKit
377+# Copyright (C) 2009 Brian Aker
378+# All rights reserved.
379+#
380+# Use and distribution licensed under the BSD license. See
381+# the COPYING file in the parent directory for full text.
382+
383+lib_LTLIBRARIES= libhashkit.la
384+
385+libhashkitincludedir= ${includedir}/libhashkit
386+
387+dist_libhashkitinclude_HEADERS= \
388+ algorithm.h \
389+ behavior.h \
390+ hashkit.h \
391+ types.h \
392+ visibility.h
393+
394+noinst_HEADERS= \
395+ common.h
396+
397+libhashkit_la_SOURCES= \
398+ crc32.c \
399+ behavior.c \
400+ default.c \
401+ fnv.c \
402+ hashkit.c \
403+ jenkins.c \
404+ ketama.c \
405+ md5.c \
406+ murmur.c
407+
408+if INCLUDE_HSIEH_SRC
409+libhashkit_la_SOURCES+= hsieh.c
410+endif
411+
412+libhashkit_la_CFLAGS= \
413+ ${AM_CFLAGS} \
414+ -DBUILDING_HASHKIT
415+
416+libhashkit_la_LDFLAGS= \
417+ -version-info \
418+ $(HASHKIT_LIBRARY_VERSION)
419
420=== added file 'libhashkit/algorithm.h'
421--- libhashkit/algorithm.h 1970-01-01 00:00:00 +0000
422+++ libhashkit/algorithm.h 2009-12-11 17:27:14 +0000
423@@ -0,0 +1,49 @@
424+/* HashKit
425+ * Copyright (C) 2009 Brian Aker
426+ * All rights reserved.
427+ *
428+ * Use and distribution licensed under the BSD license. See
429+ * the COPYING file in the parent directory for full text.
430+ */
431+
432+/**
433+ * @file
434+ * @brief HashKit Header
435+ */
436+
437+#ifndef HASHKIT_ALGORITHM_H
438+#define HASHKIT_ALGORITHM_H
439+
440+#ifdef __cplusplus
441+extern "C" {
442+#endif
443+
444+HASHKIT_API
445+uint32_t hashkit_default(const char *key, size_t key_length);
446+HASHKIT_API
447+uint32_t hashkit_fnv1_64(const char *key, size_t key_length);
448+HASHKIT_API
449+uint32_t hashkit_fnv1a_64(const char *key, size_t key_length);
450+HASHKIT_API
451+uint32_t hashkit_fnv1_32(const char *key, size_t key_length);
452+HASHKIT_API
453+uint32_t hashkit_fnv1a_32(const char *key, size_t key_length);
454+HASHKIT_API
455+uint32_t hashkit_crc32(const char *key, size_t key_length);
456+HASHKIT_API
457+#ifdef HAVE_HSIEH_HASH
458+HASHKIT_API
459+uint32_t hashkit_hsieh(const char *key, size_t key_length);
460+#endif
461+HASHKIT_API
462+uint32_t hashkit_murmur(const char *key, size_t key_length);
463+HASHKIT_API
464+uint32_t hashkit_jenkins(const char *key, size_t key_length);
465+HASHKIT_API
466+uint32_t hashkit_md5(const char *key, size_t key_length);
467+
468+#ifdef __cplusplus
469+}
470+#endif
471+
472+#endif /* HASHKIT_ALGORITHM_H */
473
474=== added file 'libhashkit/behavior.c'
475--- libhashkit/behavior.c 1970-01-01 00:00:00 +0000
476+++ libhashkit/behavior.c 2009-12-11 17:27:14 +0000
477@@ -0,0 +1,89 @@
478+/* HashKit
479+ * Copyright (C) 2009 Brian Aker
480+ * All rights reserved.
481+ *
482+ * Use and distribution licensed under the BSD license. See
483+ * the COPYING file in the parent directory for full text.
484+ */
485+
486+#include "common.h"
487+
488+void hashkit_set_distribution(hashkit_st *hashkit, hashkit_distribution_t distribution)
489+{
490+ hashkit->distribution= distribution;
491+}
492+
493+hashkit_distribution_t hashkit_get_distribution(hashkit_st *hashkit)
494+{
495+ return hashkit->distribution;
496+}
497+
498+
499+void hashkit_set_hash_fn(hashkit_st *hashkit, hashkit_fn *function)
500+{
501+ hashkit->hash_fn= function;
502+}
503+
504+hashkit_fn * hashkit_get_hash_fn(hashkit_st *hashkit)
505+{
506+ return hashkit->hash_fn;
507+}
508+
509+
510+void hashkit_set_active_fn(hashkit_st *hashkit, hashkit_active_fn *function)
511+{
512+ hashkit->active_fn= function;
513+}
514+
515+
516+hashkit_active_fn * hashkit_get_active_fn(hashkit_st *hashkit)
517+{
518+ return hashkit->active_fn;
519+}
520+
521+
522+void hashkit_set_continuum_hash_fn(hashkit_st *hashkit, hashkit_fn *function)
523+{
524+ hashkit->continuum_hash_fn= function;
525+}
526+
527+
528+hashkit_fn * hashkit_get_continuum_hash_fn(hashkit_st *hashkit)
529+{
530+ return hashkit->continuum_hash_fn;
531+}
532+
533+
534+void hashkit_set_continuum_key_fn(hashkit_st *hashkit, hashkit_key_fn *function)
535+{
536+ hashkit->continuum_key_fn= function;
537+}
538+
539+hashkit_key_fn * hashkit_get_continuum_key_fn(hashkit_st *hashkit)
540+{
541+ return hashkit->continuum_key_fn;
542+}
543+
544+
545+void hashkit_set_sort_fn(hashkit_st *hashkit, hashkit_sort_fn *function)
546+{
547+ hashkit->sort_fn= function;
548+}
549+
550+
551+hashkit_sort_fn * hashkit_get_sort_fn(hashkit_st *hashkit)
552+{
553+ return hashkit->sort_fn;
554+}
555+
556+
557+void hashkit_set_weight_fn(hashkit_st *hashkit, hashkit_weight_fn *function)
558+{
559+ hashkit->weight_fn= function;
560+}
561+
562+
563+hashkit_weight_fn * hashkit_get_weight_fn(hashkit_st *hashkit)
564+{
565+ return hashkit->weight_fn;
566+}
567
568=== added file 'libhashkit/behavior.h'
569--- libhashkit/behavior.h 1970-01-01 00:00:00 +0000
570+++ libhashkit/behavior.h 2009-12-11 17:27:14 +0000
571@@ -0,0 +1,68 @@
572+/* HashKit
573+ * Copyright (C) 2009 Brian Aker
574+ * All rights reserved.
575+ *
576+ * Use and distribution licensed under the BSD license. See
577+ * the COPYING file in the parent directory for full text.
578+ */
579+
580+/**
581+ * @file
582+ * @brief HashKit Header
583+ */
584+
585+#ifndef HASHKIT_BEHAVIOR_H
586+#define HASHKIT_BEHAVIORH
587+
588+#ifdef __cplusplus
589+extern "C" {
590+#endif
591+
592+
593+HASHKIT_API
594+void hashkit_set_distribution(hashkit_st *hash, hashkit_distribution_t distribution);
595+
596+HASHKIT_API
597+hashkit_distribution_t hashkit_get_distribution(hashkit_st *hash);
598+
599+HASHKIT_API
600+void hashkit_set_hash_fn(hashkit_st *hash, hashkit_fn *function);
601+
602+HASHKIT_API
603+hashkit_fn * hashkit_get_hash_fn(hashkit_st *hash);
604+
605+HASHKIT_API
606+void hashkit_set_active_fn(hashkit_st *hash, hashkit_active_fn *function);
607+
608+HASHKIT_API
609+hashkit_active_fn * hashkit_get_active_fn(hashkit_st *hash);
610+
611+HASHKIT_API
612+void hashkit_set_continuum_hash_fn(hashkit_st *hash, hashkit_fn *function);
613+
614+HASHKIT_API
615+hashkit_fn * hashkit_get_continuum_hash_fn(hashkit_st *hash);
616+
617+HASHKIT_API
618+void hashkit_set_continuum_key_fn(hashkit_st *hash, hashkit_key_fn *function);
619+
620+HASHKIT_API
621+hashkit_key_fn * hashkit_get_continuum_key_fn(hashkit_st *hash);
622+
623+HASHKIT_API
624+void hashkit_set_sort_fn(hashkit_st *hash, hashkit_sort_fn *function);
625+
626+HASHKIT_API
627+hashkit_sort_fn * hashkit_get_sort_fn(hashkit_st *hash);
628+
629+HASHKIT_API
630+void hashkit_set_weight_fn(hashkit_st *hash, hashkit_weight_fn *function);
631+
632+HASHKIT_API
633+hashkit_weight_fn * hashkit_get_weight_fn(hashkit_st *hash);
634+
635+#ifdef __cplusplus
636+}
637+#endif
638+
639+#endif /* HASHKIT_BEHAVIOR_H */
640
641=== added file 'libhashkit/common.h'
642--- libhashkit/common.h 1970-01-01 00:00:00 +0000
643+++ libhashkit/common.h 2009-12-11 17:27:14 +0000
644@@ -0,0 +1,32 @@
645+/* HashKit
646+ * Copyright (C) 2009 Brian Aker
647+ * All rights reserved.
648+ *
649+ * Use and distribution licensed under the BSD license. See
650+ * the COPYING file in the parent directory for full text.
651+ */
652+
653+/**
654+ * @file
655+ * @brief System Include Files
656+ */
657+
658+#ifndef HASHKIT_COMMON_H
659+#define HASHKIT_COMMON_H
660+
661+#include "config.h"
662+
663+#include <assert.h>
664+#include <errno.h>
665+#include <stdio.h>
666+#include <stdlib.h>
667+
668+#include "hashkit.h"
669+
670+HASHKIT_LOCAL
671+void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result);
672+
673+HASHKIT_LOCAL
674+int update_continuum(hashkit_st *hashkit);
675+
676+#endif /* HASHKIT_COMMON_H */
677
678=== renamed file 'libmemcached/crc.c' => 'libhashkit/crc32.c'
679--- libmemcached/crc.c 2009-09-30 03:51:54 +0000
680+++ libhashkit/crc32.c 2009-12-11 17:27:14 +0000
681@@ -73,8 +73,7 @@
682 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
683 };
684
685-
686-uint32_t hash_crc32(const char *key, size_t key_length)
687+uint32_t hashkit_crc32(const char *key, size_t key_length)
688 {
689 uint64_t x;
690 uint32_t crc= UINT32_MAX;
691@@ -82,5 +81,5 @@
692 for (x= 0; x < key_length; x++)
693 crc= (crc >> 8) ^ crc32tab[(crc ^ (uint64_t)key[x]) & 0xff];
694
695- return ~crc;
696+ return ((~crc) >> 16) & 0x7fff;
697 }
698
699=== added file 'libhashkit/default.c'
700--- libhashkit/default.c 1970-01-01 00:00:00 +0000
701+++ libhashkit/default.c 2009-12-11 17:27:14 +0000
702@@ -0,0 +1,28 @@
703+/* HashKit
704+ * Copyright (C) 2009 Brian Aker
705+ * All rights reserved.
706+ *
707+ * Use and distribution licensed under the BSD license. See
708+ * the COPYING file in the parent directory for full text.
709+ */
710+
711+#include "common.h"
712+
713+uint32_t hashkit_default(const char *key, size_t key_length)
714+{
715+ const char *ptr= key;
716+ uint32_t value= 0;
717+
718+ while (key_length--)
719+ {
720+ uint32_t val= (uint32_t) *ptr++;
721+ value += val;
722+ value += (value << 10);
723+ value ^= (value >> 6);
724+ }
725+ value += (value << 3);
726+ value ^= (value >> 11);
727+ value += (value << 15);
728+
729+ return value;
730+}
731
732=== added file 'libhashkit/fnv.c'
733--- libhashkit/fnv.c 1970-01-01 00:00:00 +0000
734+++ libhashkit/fnv.c 2009-12-11 17:27:14 +0000
735@@ -0,0 +1,75 @@
736+/* HashKit
737+ * Copyright (C) 2009 Brian Aker
738+ * All rights reserved.
739+ *
740+ * Use and distribution licensed under the BSD license. See
741+ * the COPYING file in the parent directory for full text.
742+ */
743+
744+#include "common.h"
745+
746+/* FNV hash'es lifted from Dustin Sallings work */
747+static uint64_t FNV_64_INIT= UINT64_C(0xcbf29ce484222325);
748+static uint64_t FNV_64_PRIME= UINT64_C(0x100000001b3);
749+static uint32_t FNV_32_INIT= 2166136261UL;
750+static uint32_t FNV_32_PRIME= 16777619;
751+
752+uint32_t hashkit_fnv1_64(const char *key, size_t key_length)
753+{
754+ /* Thanks to pierre@demartines.com for the pointer */
755+ uint64_t hash= FNV_64_INIT;
756+ size_t x= 0;
757+
758+ for (x= 0; x < key_length; x++)
759+ {
760+ hash *= FNV_64_PRIME;
761+ hash ^= (uint64_t)key[x];
762+ }
763+
764+ return (uint32_t)hash;
765+}
766+
767+uint32_t hashkit_fnv1a_64(const char *key, size_t key_length)
768+{
769+ uint32_t hash= (uint32_t) FNV_64_INIT;
770+ size_t x= 0;
771+
772+ for (x= 0; x < key_length; x++)
773+ {
774+ uint32_t val= (uint32_t)key[x];
775+ hash ^= val;
776+ hash *= (uint32_t) FNV_64_PRIME;
777+ }
778+
779+ return hash;
780+}
781+
782+uint32_t hashkit_fnv1_32(const char *key, size_t key_length)
783+{
784+ uint32_t hash= FNV_32_INIT;
785+ size_t x= 0;
786+
787+ for (x= 0; x < key_length; x++)
788+ {
789+ uint32_t val= (uint32_t)key[x];
790+ hash *= FNV_32_PRIME;
791+ hash ^= val;
792+ }
793+
794+ return hash;
795+}
796+
797+uint32_t hashkit_fnv1a_32(const char *key, size_t key_length)
798+{
799+ uint32_t hash= FNV_32_INIT;
800+ size_t x= 0;
801+
802+ for (x= 0; x < key_length; x++)
803+ {
804+ uint32_t val= (uint32_t)key[x];
805+ hash ^= val;
806+ hash *= FNV_32_PRIME;
807+ }
808+
809+ return hash;
810+}
811
812=== renamed file 'libmemcached/memcached_hash.c' => 'libhashkit/hashkit.c'
813--- libmemcached/memcached_hash.c 2009-11-03 13:09:13 +0000
814+++ libhashkit/hashkit.c 2009-12-11 17:27:14 +0000
815@@ -1,234 +1,263 @@
816+/* HashKit
817+ * Copyright (C) 2009 Brian Aker
818+ * All rights reserved.
819+ *
820+ * Use and distribution licensed under the BSD license. See
821+ * the COPYING file in the parent directory for full text.
822+ */
823+
824 #include "common.h"
825
826-
827-/* Defines */
828-static uint64_t FNV_64_INIT= UINT64_C(0xcbf29ce484222325);
829-static uint64_t FNV_64_PRIME= UINT64_C(0x100000001b3);
830-
831-static uint32_t FNV_32_INIT= 2166136261UL;
832-static uint32_t FNV_32_PRIME= 16777619;
833-
834-/* Prototypes */
835-static uint32_t internal_generate_hash(const char *key, size_t key_length);
836-static uint32_t internal_generate_md5(const char *key, size_t key_length);
837-
838-uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash hash_algorithm)
839-{
840- uint32_t hash= 1; /* Just here to remove compile warning */
841- uint32_t x= 0;
842-
843+inline static bool _is_allocated(const hashkit_st *hashk)
844+{
845+ return hashk->options.is_allocated == true;
846+}
847+
848+inline static bool _is_initialized(const hashkit_st *hashk)
849+{
850+ return hashk->options.is_initialized == true;
851+}
852+
853+/**
854+ @note We make no assumptions that "hashk" has been, or not been allocated from heap/stack. We just know we didn't do it.
855+*/
856+hashkit_st *hashkit_create(hashkit_st *hashk)
857+{
858+ if (hashk == NULL)
859+ {
860+ hashk= (hashkit_st *)malloc(sizeof(hashkit_st));
861+ if (hashk == NULL)
862+ {
863+ hashk->options.is_initialized= false;
864+
865+ return NULL;
866+ }
867+
868+ hashk->options.is_allocated= true;
869+ }
870+ else
871+ {
872+ hashk->options.is_allocated= false;
873+ }
874+
875+ hashk->options.is_initialized= true;
876+
877+ hashk->distribution= HASHKIT_DISTRIBUTION_MODULA;
878+ hashk->continuum_count= 0;
879+ hashk->continuum_points_count= 0;
880+ hashk->list_size= 0;
881+ hashk->context_size= 0;
882+ hashk->continuum= NULL;
883+ hashk->hash_fn= NULL;
884+ hashk->active_fn= NULL;
885+ hashk->continuum_hash_fn= NULL;
886+ hashk->continuum_key_fn= NULL;
887+ hashk->sort_fn= NULL;
888+ hashk->weight_fn= NULL;
889+ hashk->list= NULL;
890+
891+ return hashk;
892+}
893+
894+
895+void hashkit_free(hashkit_st *hashk)
896+{
897+ assert(_is_initialized(hashk) == true);
898+
899+ if (hashk->continuum != NULL)
900+ {
901+ free(hashk->continuum);
902+ }
903+
904+ /**
905+ We don't know if hashk is pointing to something else,
906+ so we go on and set is_initialized.
907+ */
908+ hashk->options.is_initialized= false;
909+
910+ if (_is_allocated(hashk))
911+ {
912+ free(hashk);
913+ }
914+}
915+
916+bool hashkit_is_allocated(const hashkit_st *hashk)
917+{
918+ return _is_allocated(hashk);
919+}
920+
921+bool hashkit_is_initialized(const hashkit_st *hashk)
922+{
923+ return _is_initialized(hashk);
924+}
925+
926+
927+/**
928+ @note We do assume source is valid. If source does not exist, we allocate.
929+*/
930+hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *source)
931+{
932+ hashkit_st *new_clone;
933+
934+ if (source == NULL)
935+ {
936+ return hashkit_create(destination);
937+ }
938+ else
939+ {
940+ assert(_is_initialized(source) == true);
941+ }
942+
943+ /* new_clone will be a pointer to destination */
944+ new_clone= hashkit_create(destination);
945+ assert((destination ? ((_is_allocated(new_clone) == false)) : (_is_allocated(new_clone) == true)));
946+
947+ // Should only happen on allocation failure.
948+ if (new_clone == NULL)
949+ {
950+ return NULL;
951+ }
952+
953+ // For the moment we will not clone this.
954+ new_clone->continuum= NULL;
955+
956+ new_clone->distribution= source->distribution;
957+ new_clone->continuum_count= source->continuum_count;
958+ new_clone->continuum_points_count= source->continuum_points_count;
959+ new_clone->list_size= source->list_size;
960+ new_clone->context_size= source->context_size;
961+
962+
963+ new_clone->hash_fn= source->hash_fn;
964+ new_clone->active_fn= source->active_fn;
965+ new_clone->continuum_hash_fn= source->continuum_hash_fn;
966+ new_clone->continuum_key_fn= source->continuum_key_fn;
967+ new_clone->sort_fn= source->sort_fn;
968+ new_clone->weight_fn= source->weight_fn;
969+ new_clone->list= source->list;
970+
971+ return new_clone;
972+}
973+
974+
975+void hashkit_set_list(hashkit_st *hashkit, void *list, size_t list_size, size_t context_size)
976+{
977+ hashkit->list= list;
978+ hashkit->list_size= list_size;
979+ hashkit->context_size= context_size;
980+}
981+
982+
983+uint32_t hashkit_value(hashkit_st *hashkit, const char *key, size_t key_length)
984+{
985+ if (hashkit->hash_fn == NULL)
986+ return hashkit_default(key, key_length);
987+
988+ return hashkit->hash_fn(key, key_length);
989+}
990+
991+
992+uint32_t hashkit_index(hashkit_st *hashkit, uint32_t hash_value)
993+{
994+ if (hashkit->list_size == 1)
995+ return 0;
996+
997+ switch (hashkit->distribution)
998+ {
999+ case HASHKIT_DISTRIBUTION_MODULA:
1000+ return hash_value % (uint32_t)hashkit->list_size;
1001+
1002+ case HASHKIT_DISTRIBUTION_RANDOM:
1003+ return (uint32_t)random() % (uint32_t)hashkit->list_size;
1004+
1005+ case HASHKIT_DISTRIBUTION_KETAMA:
1006+ {
1007+ hashkit_continuum_point_st *begin, *end, *left, *right, *middle;
1008+ begin= left= hashkit->continuum;
1009+ end= right= hashkit->continuum + hashkit->continuum_points_count;
1010+
1011+ while (left < right)
1012+ {
1013+ middle= left + (right - left) / 2;
1014+ if (middle->value < hash_value)
1015+ left= middle + 1;
1016+ else
1017+ right= middle;
1018+ }
1019+ if (right == end)
1020+ right= begin;
1021+ return right->index;
1022+ }
1023+
1024+ case HASHKIT_DISTRIBUTION_MAX:
1025+ default:
1026+ /* We have added a distribution without extending the logic */
1027+ return hash_value % (uint32_t)hashkit->list_size;
1028+ }
1029+
1030+ /* NOTREACHED */
1031+}
1032+
1033+
1034+int hashkit_run_distribution(hashkit_st *hashkit)
1035+{
1036+ switch (hashkit->distribution)
1037+ {
1038+ case HASHKIT_DISTRIBUTION_MODULA:
1039+ if (hashkit->sort_fn != NULL && hashkit->list_size > 1)
1040+ hashkit->sort_fn(hashkit->list, hashkit->list_size);
1041+ break;
1042+ case HASHKIT_DISTRIBUTION_RANDOM:
1043+ break;
1044+ case HASHKIT_DISTRIBUTION_KETAMA:
1045+ return update_continuum(hashkit);
1046+ case HASHKIT_DISTRIBUTION_MAX:
1047+ default:
1048+ /* We have added a distribution without extending the logic */
1049+ break;
1050+ }
1051+
1052+ return 0;
1053+}
1054+
1055+
1056+uint32_t hashkit_generate_value(const char *key, size_t key_length, hashkit_hash_t hash_algorithm)
1057+{
1058 switch (hash_algorithm)
1059 {
1060- case MEMCACHED_HASH_DEFAULT:
1061- hash= internal_generate_hash(key, key_length);
1062- break;
1063- case MEMCACHED_HASH_MD5:
1064- hash= internal_generate_md5(key, key_length);
1065- break;
1066- case MEMCACHED_HASH_CRC:
1067- hash= ((hash_crc32(key, key_length) >> 16) & 0x7fff);
1068- if (hash == 0)
1069- hash= 1;
1070- break;
1071- /* FNV hash'es lifted from Dustin Sallings work */
1072- case MEMCACHED_HASH_FNV1_64:
1073- {
1074- /* Thanks to pierre@demartines.com for the pointer */
1075- uint64_t temp_hash;
1076-
1077- temp_hash= FNV_64_INIT;
1078- for (x= 0; x < key_length; x++)
1079- {
1080- temp_hash *= FNV_64_PRIME;
1081- temp_hash ^= (uint64_t)key[x];
1082- }
1083- hash= (uint32_t)temp_hash;
1084- }
1085- break;
1086- case MEMCACHED_HASH_FNV1A_64:
1087- {
1088- hash= (uint32_t) FNV_64_INIT;
1089- for (x= 0; x < key_length; x++)
1090- {
1091- uint32_t val= (uint32_t)key[x];
1092- hash ^= val;
1093- hash *= (uint32_t) FNV_64_PRIME;
1094- }
1095- }
1096- break;
1097- case MEMCACHED_HASH_FNV1_32:
1098- {
1099- hash= FNV_32_INIT;
1100- for (x= 0; x < key_length; x++)
1101- {
1102- uint32_t val= (uint32_t)key[x];
1103- hash *= FNV_32_PRIME;
1104- hash ^= val;
1105- }
1106- }
1107- break;
1108- case MEMCACHED_HASH_FNV1A_32:
1109- {
1110- hash= FNV_32_INIT;
1111- for (x= 0; x < key_length; x++)
1112- {
1113- uint32_t val= (uint32_t)key[x];
1114- hash ^= val;
1115- hash *= FNV_32_PRIME;
1116- }
1117- }
1118- break;
1119- case MEMCACHED_HASH_HSIEH:
1120- {
1121+ case HASHKIT_HASH_DEFAULT:
1122+ return hashkit_default(key, key_length);
1123+ case HASHKIT_HASH_MD5:
1124+ return hashkit_md5(key, key_length);
1125+ case HASHKIT_HASH_CRC:
1126+ return hashkit_crc32(key, key_length);
1127+ case HASHKIT_HASH_FNV1_64:
1128+ return hashkit_fnv1_64(key, key_length);
1129+ case HASHKIT_HASH_FNV1A_64:
1130+ return hashkit_fnv1a_64(key, key_length);
1131+ case HASHKIT_HASH_FNV1_32:
1132+ return hashkit_fnv1_32(key, key_length);
1133+ case HASHKIT_HASH_FNV1A_32:
1134+ return hashkit_fnv1a_32(key, key_length);
1135+ case HASHKIT_HASH_HSIEH:
1136 #ifdef HAVE_HSIEH_HASH
1137- hash= hsieh_hash(key, key_length);
1138+ return hashkit_hsieh(key, key_length);
1139+#else
1140+ return 1;
1141 #endif
1142- break;
1143- }
1144- case MEMCACHED_HASH_MURMUR:
1145- {
1146- hash= murmur_hash(key, key_length);
1147- break;
1148- }
1149- case MEMCACHED_HASH_JENKINS:
1150- {
1151- hash=jenkins_hash(key, key_length, 13);
1152- break;
1153- }
1154- default:
1155- {
1156- WATCHPOINT_ASSERT(hash_algorithm);
1157- break;
1158- }
1159- }
1160- return hash;
1161-}
1162-
1163-uint32_t generate_hash(memcached_st *ptr, const char *key, size_t key_length)
1164-{
1165- uint32_t hash= 1; /* Just here to remove compile warning */
1166-
1167-
1168- WATCHPOINT_ASSERT(ptr->number_of_hosts);
1169-
1170- if (ptr->number_of_hosts == 1)
1171- return 0;
1172-
1173- hash= memcached_generate_hash_value(key, key_length, ptr->hash);
1174- WATCHPOINT_ASSERT(hash);
1175- return hash;
1176-}
1177-
1178-static uint32_t dispatch_host(memcached_st *ptr, uint32_t hash)
1179-{
1180- switch (ptr->distribution)
1181- {
1182- case MEMCACHED_DISTRIBUTION_CONSISTENT:
1183- case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
1184- case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
1185- {
1186- uint32_t num= ptr->continuum_points_counter;
1187- WATCHPOINT_ASSERT(ptr->continuum);
1188-
1189- hash= hash;
1190- memcached_continuum_item_st *begin, *end, *left, *right, *middle;
1191- begin= left= ptr->continuum;
1192- end= right= ptr->continuum + num;
1193-
1194- while (left < right)
1195- {
1196- middle= left + (right - left) / 2;
1197- if (middle->value < hash)
1198- left= middle + 1;
1199- else
1200- right= middle;
1201- }
1202- if (right == end)
1203- right= begin;
1204- return right->index;
1205- }
1206- case MEMCACHED_DISTRIBUTION_MODULA:
1207- return hash % ptr->number_of_hosts;
1208- case MEMCACHED_DISTRIBUTION_RANDOM:
1209- return (uint32_t) random() % ptr->number_of_hosts;
1210+ case HASHKIT_HASH_MURMUR:
1211+ return hashkit_murmur(key, key_length);
1212+ case HASHKIT_HASH_JENKINS:
1213+ return hashkit_jenkins(key, key_length);
1214+ case HASHKIT_HASH_MAX:
1215 default:
1216- WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
1217- return hash % ptr->number_of_hosts;
1218- }
1219-
1220- /* NOTREACHED */
1221-}
1222-
1223-/*
1224- One day make this public, and have it return the actual memcached_server_st
1225- to the calling application.
1226-*/
1227-uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_length)
1228-{
1229- uint32_t hash= 1; /* Just here to remove compile warning */
1230-
1231- WATCHPOINT_ASSERT(ptr->number_of_hosts);
1232-
1233- if (ptr->number_of_hosts == 1)
1234- return 0;
1235-
1236- if (ptr->flags & MEM_HASH_WITH_PREFIX_KEY)
1237- {
1238- size_t temp_length= ptr->prefix_key_length + key_length;
1239- char temp[temp_length];
1240-
1241- if (temp_length > MEMCACHED_MAX_KEY -1)
1242- return 0;
1243-
1244- strncpy(temp, ptr->prefix_key, ptr->prefix_key_length);
1245- strncpy(temp + ptr->prefix_key_length, key, key_length);
1246- hash= generate_hash(ptr, temp, temp_length);
1247- }
1248- else
1249- {
1250- hash= generate_hash(ptr, key, key_length);
1251- }
1252-
1253- WATCHPOINT_ASSERT(hash);
1254-
1255- if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS) && ptr->next_distribution_rebuild) {
1256- struct timeval now;
1257-
1258- if (gettimeofday(&now, NULL) == 0 &&
1259- now.tv_sec > ptr->next_distribution_rebuild)
1260- run_distribution(ptr);
1261- }
1262-
1263- return dispatch_host(ptr, hash);
1264-}
1265-
1266-static uint32_t internal_generate_hash(const char *key, size_t key_length)
1267-{
1268- const char *ptr= key;
1269- uint32_t value= 0;
1270-
1271- while (key_length--)
1272- {
1273- uint32_t val= (uint32_t) *ptr++;
1274- value += val;
1275- value += (value << 10);
1276- value ^= (value >> 6);
1277- }
1278- value += (value << 3);
1279- value ^= (value >> 11);
1280- value += (value << 15);
1281-
1282- return value == 0 ? 1 : (uint32_t) value;
1283-}
1284-
1285-static uint32_t internal_generate_md5(const char *key, size_t key_length)
1286-{
1287- unsigned char results[16];
1288-
1289- md5_signature((unsigned char*)key, (unsigned int)key_length, results);
1290-
1291- return ((uint32_t) (results[3] & 0xFF) << 24)
1292- | ((uint32_t) (results[2] & 0xFF) << 16)
1293- | ((uint32_t) (results[1] & 0xFF) << 8)
1294- | (results[0] & 0xFF);
1295+#ifdef HAVE_DEBUG
1296+ fprintf(stderr, "hashkit_hash_t was extended but hashkit_generate_value was not updated\n");
1297+ fflush(stderr);
1298+ assert(0);
1299+#endif
1300+ break;
1301+ }
1302+
1303+ return 1;
1304 }
1305
1306=== added file 'libhashkit/hashkit.h'
1307--- libhashkit/hashkit.h 1970-01-01 00:00:00 +0000
1308+++ libhashkit/hashkit.h 2009-12-11 17:27:14 +0000
1309@@ -0,0 +1,117 @@
1310+/* HashKit
1311+ * Copyright (C) 2009 Brian Aker
1312+ * All rights reserved.
1313+ *
1314+ * Use and distribution licensed under the BSD license. See
1315+ * the COPYING file in the parent directory for full text.
1316+ */
1317+
1318+/**
1319+ * @file
1320+ * @brief HashKit Header
1321+ */
1322+
1323+#ifndef HASHKIT_H
1324+#define HASHKIT_H
1325+
1326+#if !defined(__cplusplus)
1327+# include <stdbool.h>
1328+#endif
1329+#include <inttypes.h>
1330+#include <sys/types.h>
1331+#include <libhashkit/visibility.h>
1332+#include <libhashkit/types.h>
1333+#include <libhashkit/algorithm.h>
1334+#include <libhashkit/behavior.h>
1335+
1336+#ifdef __cplusplus
1337+extern "C" {
1338+#endif
1339+
1340+/**
1341+ * @addtogroup hashkit_constants Constants
1342+ * @ingroup hashkit
1343+ * @{
1344+ */
1345+
1346+/* Defines. */
1347+#define HASHKIT_MAX_KEY 251
1348+#define HASHKIT_POINTS_PER_NODE 100
1349+#define HASHKIT_POINTS_PER_NODE_WEIGHTED 160
1350+#define HASHKIT_CONTINUUM_ADDITION 10
1351+#define HASHKIT_CONTINUUM_KEY_SIZE 86
1352+
1353+/** @} */
1354+
1355+/**
1356+ * @ingroup hashkit
1357+ */
1358+struct hashkit_st
1359+{
1360+ hashkit_options_st options;
1361+ hashkit_distribution_t distribution;
1362+ uint32_t continuum_count;
1363+ uint32_t continuum_points_count;
1364+ size_t list_size;
1365+ size_t context_size;
1366+ hashkit_continuum_point_st *continuum;
1367+ hashkit_fn *hash_fn;
1368+ hashkit_active_fn *active_fn;
1369+ hashkit_fn *continuum_hash_fn;
1370+ hashkit_key_fn *continuum_key_fn;
1371+ hashkit_sort_fn *sort_fn;
1372+ hashkit_weight_fn *weight_fn;
1373+ void *list;
1374+};
1375+
1376+/**
1377+ * @ingroup hashkit
1378+ */
1379+struct hashkit_continuum_point_st
1380+{
1381+ uint32_t index;
1382+ uint32_t value;
1383+};
1384+
1385+/**
1386+ * @addtogroup hashkit Pandora Hash Declarations
1387+ * @{
1388+ */
1389+
1390+HASHKIT_API
1391+hashkit_st *hashkit_create(hashkit_st *hash);
1392+
1393+HASHKIT_API
1394+hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *ptr);
1395+
1396+HASHKIT_API
1397+void hashkit_free(hashkit_st *hash);
1398+
1399+HASHKIT_API
1400+bool hashkit_is_allocated(const hashkit_st *hash);
1401+
1402+HASHKIT_API
1403+bool hashkit_is_initialized(const hashkit_st *hash);
1404+
1405+HASHKIT_API
1406+void hashkit_set_list(hashkit_st *hash, void *list, size_t list_size,
1407+ size_t context_size);
1408+
1409+HASHKIT_API
1410+uint32_t hashkit_value(hashkit_st *hash, const char *key, size_t key_length);
1411+HASHKIT_API
1412+uint32_t hashkit_index(hashkit_st *hash, uint32_t value);
1413+HASHKIT_API
1414+int hashkit_run_distribution(hashkit_st *hash);
1415+
1416+
1417+HASHKIT_API
1418+uint32_t hashkit_generate_value(const char *key, size_t key_length, hashkit_hash_t hash_algorithm);
1419+
1420+/** @} */
1421+
1422+#ifdef __cplusplus
1423+}
1424+#endif
1425+
1426+#endif /* HASHKIT_H */
1427
1428=== renamed file 'libmemcached/hsieh_hash.c' => 'libhashkit/hsieh.c'
1429--- libmemcached/hsieh_hash.c 2009-03-11 20:06:43 +0000
1430+++ libhashkit/hsieh.c 2009-12-11 17:27:14 +0000
1431@@ -5,7 +5,7 @@
1432 * http://www.azillionmonkeys.com/qed/hash.html
1433 */
1434
1435-#include "common.h"
1436+#include "hash_common.h"
1437
1438 #undef get16bits
1439 #if (defined(__GNUC__) && defined(__i386__))
1440@@ -17,7 +17,7 @@
1441 +(uint32_t)(((const uint8_t *)(d))[0]) )
1442 #endif
1443
1444-uint32_t hsieh_hash(const char *key, size_t key_length)
1445+uint32_t hashkit_hsieh(const char *key, size_t key_length)
1446 {
1447 uint32_t hash = 0, tmp;
1448 int rem;
1449
1450=== renamed file 'libmemcached/jenkins_hash.c' => 'libhashkit/jenkins.c'
1451--- libmemcached/jenkins_hash.c 2009-12-02 03:09:57 +0000
1452+++ libhashkit/jenkins.c 2009-12-11 17:27:14 +0000
1453@@ -38,6 +38,8 @@
1454 c ^= b; c -= rot(b,24); \
1455 }
1456
1457+#define JENKINS_INITVAL 13
1458+
1459 /*
1460 jenkins_hash() -- hash a variable-length key into a 32-bit value
1461 k : the key (the unaligned variable-length array of bytes)
1462@@ -54,13 +56,13 @@
1463 In which case, the hash table should have hashsize(10) elements.
1464 */
1465
1466-uint32_t jenkins_hash(const void *key, size_t length, uint32_t initval)
1467+uint32_t hashkit_jenkins(const char *key, size_t length)
1468 {
1469 uint32_t a,b,c; /* internal state */
1470 union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
1471
1472 /* Set up the internal state */
1473- a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
1474+ a = b = c = 0xdeadbeef + ((uint32_t)length) + JENKINS_INITVAL;
1475
1476 u.ptr = key;
1477 #ifndef WORDS_BIGENDIAN
1478@@ -209,5 +211,3 @@
1479 final(a,b,c);
1480 return c;
1481 }
1482-
1483-
1484
1485=== renamed file 'libmemcached/memcached_hosts.c' => 'libhashkit/ketama.c'
1486--- libmemcached/memcached_hosts.c 2009-11-03 13:09:13 +0000
1487+++ libhashkit/ketama.c 2009-12-11 17:27:14 +0000
1488@@ -1,82 +1,6 @@
1489 #include "common.h"
1490 #include <math.h>
1491
1492-/* Protoypes (static) */
1493-static memcached_return server_add(memcached_st *ptr, const char *hostname,
1494- unsigned int port,
1495- uint32_t weight,
1496- memcached_connection type);
1497-memcached_return update_continuum(memcached_st *ptr);
1498-
1499-static int compare_servers(const void *p1, const void *p2)
1500-{
1501- int return_value;
1502- memcached_server_st *a= (memcached_server_st *)p1;
1503- memcached_server_st *b= (memcached_server_st *)p2;
1504-
1505- return_value= strcmp(a->hostname, b->hostname);
1506-
1507- if (return_value == 0)
1508- {
1509- return_value= (int) (a->port - b->port);
1510- }
1511-
1512- return return_value;
1513-}
1514-
1515-static void sort_hosts(memcached_st *ptr)
1516-{
1517- if (ptr->number_of_hosts)
1518- {
1519- qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers);
1520- ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
1521- }
1522-}
1523-
1524-
1525-memcached_return run_distribution(memcached_st *ptr)
1526-{
1527- switch (ptr->distribution)
1528- {
1529- case MEMCACHED_DISTRIBUTION_CONSISTENT:
1530- case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
1531- case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
1532- return update_continuum(ptr);
1533- case MEMCACHED_DISTRIBUTION_MODULA:
1534- if (ptr->flags & MEM_USE_SORT_HOSTS)
1535- sort_hosts(ptr);
1536- break;
1537- case MEMCACHED_DISTRIBUTION_RANDOM:
1538- break;
1539- default:
1540- WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
1541- }
1542-
1543- ptr->last_disconnected_server = NULL;
1544-
1545- return MEMCACHED_SUCCESS;
1546-}
1547-
1548-void server_list_free(memcached_st *ptr, memcached_server_st *servers)
1549-{
1550- unsigned int x;
1551-
1552- if (servers == NULL)
1553- return;
1554-
1555- for (x= 0; x < servers->count; x++)
1556- if (servers[x].address_info)
1557- {
1558- freeaddrinfo(servers[x].address_info);
1559- servers[x].address_info= NULL;
1560- }
1561-
1562- if (ptr)
1563- ptr->call_free(ptr, servers);
1564- else
1565- free(servers);
1566-}
1567-
1568 static uint32_t ketama_server_hash(const char *key, unsigned int key_length, int alignment)
1569 {
1570 unsigned char results[16];
1571@@ -88,13 +12,11 @@
1572 | (results[0 + alignment * 4] & 0xFF);
1573 }
1574
1575-static int continuum_item_cmp(const void *t1, const void *t2)
1576+static int continuum_points_cmp(const void *t1, const void *t2)
1577 {
1578- memcached_continuum_item_st *ct1= (memcached_continuum_item_st *)t1;
1579- memcached_continuum_item_st *ct2= (memcached_continuum_item_st *)t2;
1580+ hashkit_continuum_point_st *ct1= (hashkit_continuum_point_st *)t1;
1581+ hashkit_continuum_point_st *ct2= (hashkit_continuum_point_st *)t2;
1582
1583- /* Why 153? Hmmm... */
1584- WATCHPOINT_ASSERT(ct1->value != 153);
1585 if (ct1->value == ct2->value)
1586 return 0;
1587 else if (ct1->value > ct2->value)
1588@@ -103,412 +25,130 @@
1589 return -1;
1590 }
1591
1592-memcached_return update_continuum(memcached_st *ptr)
1593+int update_continuum(hashkit_st *hashkit)
1594 {
1595- uint32_t host_index;
1596+ uint32_t count;
1597 uint32_t continuum_index= 0;
1598 uint32_t value;
1599- memcached_server_st *list;
1600- uint32_t pointer_index;
1601- uint32_t pointer_counter= 0;
1602- uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER;
1603- uint32_t pointer_per_hash= 1;
1604+ uint32_t points_index;
1605+ uint32_t points_count= 0;
1606+ uint32_t points_per_server;
1607+ uint32_t points_per_hash;
1608 uint64_t total_weight= 0;
1609- uint64_t is_ketama_weighted= 0;
1610- uint64_t is_auto_ejecting= 0;
1611- uint32_t points_per_server= 0;
1612- uint32_t live_servers= 0;
1613- struct timeval now;
1614-
1615- if (gettimeofday(&now, NULL) != 0)
1616- {
1617- ptr->cached_errno = errno;
1618- return MEMCACHED_ERRNO;
1619- }
1620-
1621- list = ptr->hosts;
1622-
1623- /* count live servers (those without a retry delay set) */
1624- is_auto_ejecting= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS);
1625- if (is_auto_ejecting)
1626+ uint32_t live_servers;
1627+ uint8_t *context;
1628+
1629+ if (hashkit->active_fn != NULL || hashkit->weight_fn != NULL)
1630 {
1631 live_servers= 0;
1632- ptr->next_distribution_rebuild= 0;
1633- for (host_index= 0; host_index < ptr->number_of_hosts; ++host_index)
1634+
1635+ for (count= 0, context= hashkit->list; count < hashkit->list_size;
1636+ count++, context+= hashkit->context_size)
1637 {
1638- if (list[host_index].next_retry <= now.tv_sec)
1639- live_servers++;
1640- else
1641+ if (hashkit->active_fn != NULL)
1642 {
1643- if (ptr->next_distribution_rebuild == 0 || list[host_index].next_retry < ptr->next_distribution_rebuild)
1644- ptr->next_distribution_rebuild= list[host_index].next_retry;
1645+ if (hashkit->active_fn(context))
1646+ live_servers++;
1647+ else
1648+ continue;
1649 }
1650+
1651+ if (hashkit->weight_fn != NULL)
1652+ total_weight+= hashkit->weight_fn(context);
1653 }
1654 }
1655- else
1656- live_servers= ptr->number_of_hosts;
1657
1658- is_ketama_weighted= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED);
1659- points_per_server= (uint32_t) (is_ketama_weighted ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER);
1660+ if (hashkit->active_fn == NULL)
1661+ live_servers= (uint32_t)hashkit->list_size;
1662
1663 if (live_servers == 0)
1664- return MEMCACHED_SUCCESS;
1665-
1666- if (live_servers > ptr->continuum_count)
1667- {
1668- memcached_continuum_item_st *new_ptr;
1669-
1670- new_ptr= ptr->call_realloc(ptr, ptr->continuum,
1671- sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server);
1672-
1673- if (new_ptr == 0)
1674- return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
1675-
1676- ptr->continuum= new_ptr;
1677- ptr->continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION;
1678- }
1679-
1680- if (is_ketama_weighted)
1681- {
1682- for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index)
1683- {
1684- if (list[host_index].weight == 0)
1685- {
1686- list[host_index].weight = 1;
1687- }
1688- if (!is_auto_ejecting || list[host_index].next_retry <= now.tv_sec)
1689- total_weight += list[host_index].weight;
1690- }
1691- }
1692-
1693- for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index)
1694- {
1695- if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec)
1696+ return 0;
1697+
1698+ if (hashkit->weight_fn == NULL)
1699+ {
1700+ points_per_server= HASHKIT_POINTS_PER_NODE;
1701+ points_per_hash= 1;
1702+ }
1703+ else
1704+ {
1705+ points_per_server= HASHKIT_POINTS_PER_NODE_WEIGHTED;
1706+ points_per_hash= 4;
1707+ }
1708+
1709+ if (live_servers > hashkit->continuum_count)
1710+ {
1711+ hashkit_continuum_point_st *new_continuum;
1712+
1713+ new_continuum= realloc(hashkit->continuum,
1714+ sizeof(hashkit_continuum_point_st) *
1715+ (live_servers + HASHKIT_CONTINUUM_ADDITION) *
1716+ points_per_server);
1717+
1718+ if (new_continuum == NULL)
1719+ return ENOMEM;
1720+
1721+ hashkit->continuum= new_continuum;
1722+ hashkit->continuum_count= live_servers + HASHKIT_CONTINUUM_ADDITION;
1723+ }
1724+
1725+ for (count= 0, context= hashkit->list; count < hashkit->list_size;
1726+ count++, context+= hashkit->context_size)
1727+ {
1728+ if (hashkit->active_fn != NULL && hashkit->active_fn(context) == false)
1729 continue;
1730
1731- if (is_ketama_weighted)
1732- {
1733- float pct = (float)list[host_index].weight / (float)total_weight;
1734- pointer_per_server= (uint32_t) ((floorf((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4);
1735- pointer_per_hash= 4;
1736-#ifdef DEBUG
1737- printf("ketama_weighted:%s|%d|%llu|%u\n",
1738- list[host_index].hostname,
1739- list[host_index].port,
1740- (unsigned long long)list[host_index].weight,
1741- pointer_per_server);
1742-#endif
1743- }
1744-
1745-
1746- if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY)
1747- {
1748- for (pointer_index= 0;
1749- pointer_index < pointer_per_server / pointer_per_hash;
1750- pointer_index++)
1751- {
1752- char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
1753- size_t sort_host_length;
1754-
1755- // Spymemcached ketema key format is: hostname/ip:port-index
1756- // If hostname is not available then: /ip:port-index
1757- sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
1758- "/%s:%d-%d",
1759- list[host_index].hostname,
1760- list[host_index].port,
1761- pointer_index);
1762-#ifdef DEBUG
1763- printf("update_continuum: key is %s\n", sort_host);
1764-#endif
1765-
1766- WATCHPOINT_ASSERT(sort_host_length);
1767-
1768- if (is_ketama_weighted)
1769- {
1770- unsigned int i;
1771- for (i = 0; i < pointer_per_hash; i++)
1772- {
1773- value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
1774- ptr->continuum[continuum_index].index= host_index;
1775- ptr->continuum[continuum_index++].value= value;
1776- }
1777- }
1778- else
1779- {
1780- value= memcached_generate_hash_value(sort_host, sort_host_length, ptr->hash_continuum);
1781- ptr->continuum[continuum_index].index= host_index;
1782- ptr->continuum[continuum_index++].value= value;
1783- }
1784- }
1785- }
1786- else
1787- {
1788- for (pointer_index= 1;
1789- pointer_index <= pointer_per_server / pointer_per_hash;
1790- pointer_index++)
1791- {
1792- char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
1793- size_t sort_host_length;
1794-
1795- if (list[host_index].port == MEMCACHED_DEFAULT_PORT)
1796- {
1797- sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
1798- "%s-%d",
1799- list[host_index].hostname,
1800- pointer_index - 1);
1801- }
1802- else
1803- {
1804- sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
1805- "%s:%d-%d",
1806- list[host_index].hostname,
1807- list[host_index].port, pointer_index - 1);
1808- }
1809-
1810- WATCHPOINT_ASSERT(sort_host_length);
1811-
1812- if (is_ketama_weighted)
1813- {
1814- unsigned int i;
1815- for (i = 0; i < pointer_per_hash; i++)
1816- {
1817- value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
1818- ptr->continuum[continuum_index].index= host_index;
1819- ptr->continuum[continuum_index++].value= value;
1820- }
1821- }
1822- else
1823- {
1824- value= memcached_generate_hash_value(sort_host, sort_host_length, ptr->hash_continuum);
1825- ptr->continuum[continuum_index].index= host_index;
1826- ptr->continuum[continuum_index++].value= value;
1827- }
1828- }
1829- }
1830-
1831- pointer_counter+= pointer_per_server;
1832- }
1833-
1834- WATCHPOINT_ASSERT(ptr);
1835- WATCHPOINT_ASSERT(ptr->continuum);
1836- WATCHPOINT_ASSERT(ptr->number_of_hosts * MEMCACHED_POINTS_PER_SERVER <= MEMCACHED_CONTINUUM_SIZE);
1837- ptr->continuum_points_counter= pointer_counter;
1838- qsort(ptr->continuum, ptr->continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp);
1839-
1840-#ifdef DEBUG
1841- for (pointer_index= 0; ptr->number_of_hosts && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++)
1842- {
1843- WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value);
1844- }
1845-#endif
1846-
1847- return MEMCACHED_SUCCESS;
1848-}
1849-
1850-
1851-memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
1852-{
1853- unsigned int x;
1854- uint16_t count;
1855- memcached_server_st *new_host_list;
1856-
1857- if (!list)
1858- return MEMCACHED_SUCCESS;
1859-
1860- count= list[0].count;
1861- new_host_list= ptr->call_realloc(ptr, ptr->hosts,
1862- sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
1863-
1864- if (!new_host_list)
1865- return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
1866-
1867- ptr->hosts= new_host_list;
1868-
1869- for (x= 0; x < count; x++)
1870- {
1871- if ((ptr->flags & MEM_USE_UDP && list[x].type != MEMCACHED_CONNECTION_UDP)
1872- || ((list[x].type == MEMCACHED_CONNECTION_UDP)
1873- && ! (ptr->flags & MEM_USE_UDP)) )
1874- return MEMCACHED_INVALID_HOST_PROTOCOL;
1875-
1876- WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
1877- memcached_server_create(ptr, &ptr->hosts[ptr->number_of_hosts]);
1878- /* TODO check return type */
1879- (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname,
1880- list[x].port, list[x].weight, list[x].type);
1881- ptr->number_of_hosts++;
1882- }
1883- ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
1884-
1885- return run_distribution(ptr);
1886-}
1887-
1888-memcached_return memcached_server_add_unix_socket(memcached_st *ptr,
1889- const char *filename)
1890-{
1891- return memcached_server_add_unix_socket_with_weight(ptr, filename, 0);
1892-}
1893-
1894-memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
1895- const char *filename,
1896- uint32_t weight)
1897-{
1898- if (!filename)
1899- return MEMCACHED_FAILURE;
1900-
1901- return server_add(ptr, filename, 0, weight, MEMCACHED_CONNECTION_UNIX_SOCKET);
1902-}
1903-
1904-memcached_return memcached_server_add_udp(memcached_st *ptr,
1905- const char *hostname,
1906- unsigned int port)
1907-{
1908- return memcached_server_add_udp_with_weight(ptr, hostname, port, 0);
1909-}
1910-
1911-memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr,
1912- const char *hostname,
1913- unsigned int port,
1914- uint32_t weight)
1915-{
1916- if (!port)
1917- port= MEMCACHED_DEFAULT_PORT;
1918-
1919- if (!hostname)
1920- hostname= "localhost";
1921-
1922- return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_UDP);
1923-}
1924-
1925-memcached_return memcached_server_add(memcached_st *ptr,
1926- const char *hostname,
1927- unsigned int port)
1928-{
1929- return memcached_server_add_with_weight(ptr, hostname, port, 0);
1930-}
1931-
1932-memcached_return memcached_server_add_with_weight(memcached_st *ptr,
1933- const char *hostname,
1934- unsigned int port,
1935- uint32_t weight)
1936-{
1937- if (!port)
1938- port= MEMCACHED_DEFAULT_PORT;
1939-
1940- if (!hostname)
1941- hostname= "localhost";
1942-
1943- return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_TCP);
1944-}
1945-
1946-static memcached_return server_add(memcached_st *ptr, const char *hostname,
1947- unsigned int port,
1948- uint32_t weight,
1949- memcached_connection type)
1950-{
1951- memcached_server_st *new_host_list;
1952-
1953- if ( (ptr->flags & MEM_USE_UDP && type != MEMCACHED_CONNECTION_UDP)
1954- || ( (type == MEMCACHED_CONNECTION_UDP) && !(ptr->flags & MEM_USE_UDP) ) )
1955- return MEMCACHED_INVALID_HOST_PROTOCOL;
1956-
1957- new_host_list= ptr->call_realloc(ptr, ptr->hosts,
1958- sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
1959-
1960- if (new_host_list == NULL)
1961- return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
1962-
1963- ptr->hosts= new_host_list;
1964-
1965- /* TODO: Check return type */
1966- (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], hostname, port, weight, type);
1967- ptr->number_of_hosts++;
1968- ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
1969-
1970- return run_distribution(ptr);
1971-}
1972-
1973-memcached_return memcached_server_remove(memcached_server_st *st_ptr)
1974-{
1975- uint32_t x, host_index;
1976- memcached_st *ptr= st_ptr->root;
1977- memcached_server_st *list= ptr->hosts;
1978-
1979- for (x= 0, host_index= 0; x < ptr->number_of_hosts; x++)
1980- {
1981- if (strncmp(list[x].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH) != 0 || list[x].port != st_ptr->port)
1982- {
1983- if (host_index != x)
1984- memcpy(list+host_index, list+x, sizeof(memcached_server_st));
1985- host_index++;
1986- }
1987- }
1988- ptr->number_of_hosts= host_index;
1989-
1990- if (st_ptr->address_info)
1991- {
1992- freeaddrinfo(st_ptr->address_info);
1993- st_ptr->address_info= NULL;
1994- }
1995- run_distribution(ptr);
1996-
1997- return MEMCACHED_SUCCESS;
1998-}
1999-
2000-memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
2001- const char *hostname, unsigned int port,
2002- memcached_return *error)
2003-{
2004- return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error);
2005-}
2006-
2007-memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr,
2008- const char *hostname, unsigned int port,
2009- uint32_t weight,
2010- memcached_return *error)
2011-{
2012- unsigned int count;
2013- memcached_server_st *new_host_list;
2014-
2015- if (hostname == NULL || error == NULL)
2016- return NULL;
2017-
2018- if (!port)
2019- port= MEMCACHED_DEFAULT_PORT;
2020-
2021- /* Increment count for hosts */
2022- count= 1;
2023- if (ptr != NULL)
2024- {
2025- count+= ptr[0].count;
2026- }
2027-
2028- new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
2029- if (!new_host_list)
2030- {
2031- *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
2032- return NULL;
2033- }
2034-
2035- /* TODO: Check return type */
2036- memcached_server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, MEMCACHED_CONNECTION_TCP);
2037-
2038- /* Backwards compatibility hack */
2039- new_host_list[0].count= (uint16_t) count;
2040-
2041- *error= MEMCACHED_SUCCESS;
2042- return new_host_list;
2043-}
2044-
2045-unsigned int memcached_server_list_count(memcached_server_st *ptr)
2046-{
2047- if (ptr == NULL)
2048- return 0;
2049-
2050- return ptr[0].count;
2051-}
2052-
2053-void memcached_server_list_free(memcached_server_st *ptr)
2054-{
2055- server_list_free(NULL, ptr);
2056+ if (hashkit->weight_fn != NULL)
2057+ {
2058+ float pct = (float)hashkit->weight_fn(context) / (float)total_weight;
2059+ points_per_server= (uint32_t) ((floorf((float) (pct * HASHKIT_POINTS_PER_NODE_WEIGHTED / 4 * (float)live_servers + 0.0000000001))) * 4);
2060+ }
2061+
2062+ for (points_index= 0;
2063+ points_index < points_per_server / points_per_hash;
2064+ points_index++)
2065+ {
2066+ char sort_host[HASHKIT_CONTINUUM_KEY_SIZE]= "";
2067+ size_t sort_host_length;
2068+
2069+ if (hashkit->continuum_key_fn == NULL)
2070+ {
2071+ sort_host_length= (size_t) snprintf(sort_host, HASHKIT_CONTINUUM_KEY_SIZE, "%d",
2072+ points_index);
2073+ }
2074+ else
2075+ {
2076+ sort_host_length= hashkit->continuum_key_fn(sort_host, HASHKIT_CONTINUUM_KEY_SIZE,
2077+ points_index, context);
2078+ }
2079+
2080+ if (hashkit->weight_fn == NULL)
2081+ {
2082+ if (hashkit->continuum_hash_fn == NULL)
2083+ value= hashkit_default(sort_host, sort_host_length);
2084+ else
2085+ value= hashkit->continuum_hash_fn(sort_host, sort_host_length);
2086+
2087+ hashkit->continuum[continuum_index].index= count;
2088+ hashkit->continuum[continuum_index++].value= value;
2089+ }
2090+ else
2091+ {
2092+ unsigned int i;
2093+ for (i = 0; i < points_per_hash; i++)
2094+ {
2095+ value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
2096+ hashkit->continuum[continuum_index].index= count;
2097+ hashkit->continuum[continuum_index++].value= value;
2098+ }
2099+ }
2100+ }
2101+
2102+ points_count+= points_per_server;
2103+ }
2104+
2105+ hashkit->continuum_points_count= points_count;
2106+ qsort(hashkit->continuum, hashkit->continuum_points_count, sizeof(hashkit_continuum_point_st),
2107+ continuum_points_cmp);
2108+
2109+ return 0;
2110 }
2111
2112=== renamed file 'libmemcached/md5.c' => 'libhashkit/md5.c'
2113--- libmemcached/md5.c 2009-05-13 09:53:59 +0000
2114+++ libhashkit/md5.c 2009-12-11 17:27:14 +0000
2115@@ -29,7 +29,6 @@
2116 documentation and/or software.
2117 */
2118
2119-
2120 #include "common.h"
2121
2122 #include <string.h>
2123@@ -352,3 +351,15 @@
2124 output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
2125 (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
2126 }
2127+
2128+uint32_t hashkit_md5(const char *key, size_t key_length)
2129+{
2130+ unsigned char results[16];
2131+
2132+ md5_signature((unsigned char*)key, (unsigned int)key_length, results);
2133+
2134+ return ((uint32_t) (results[3] & 0xFF) << 24)
2135+ | ((uint32_t) (results[2] & 0xFF) << 16)
2136+ | ((uint32_t) (results[1] & 0xFF) << 8)
2137+ | (results[0] & 0xFF);
2138+}
2139
2140=== renamed file 'libmemcached/murmur_hash.c' => 'libhashkit/murmur.c'
2141--- libmemcached/murmur_hash.c 2009-08-11 18:56:12 +0000
2142+++ libhashkit/murmur.c 2009-12-11 17:27:14 +0000
2143@@ -17,7 +17,7 @@
2144
2145 #include "common.h"
2146
2147-uint32_t murmur_hash(const char *key, size_t length)
2148+uint32_t hashkit_murmur(const char *key, size_t length)
2149 {
2150 /*
2151 'm' and 'r' are mixing constants generated offline. They're not
2152@@ -72,5 +72,5 @@
2153 h *= m;
2154 h ^= h >> 15;
2155
2156- return (uint32_t) h;
2157+ return h;
2158 }
2159
2160=== added file 'libhashkit/types.h'
2161--- libhashkit/types.h 1970-01-01 00:00:00 +0000
2162+++ libhashkit/types.h 2009-12-11 17:27:14 +0000
2163@@ -0,0 +1,85 @@
2164+
2165+/* HashKit
2166+ * Copyright (C) 2009 Brian Aker
2167+ * All rights reserved.
2168+ *
2169+ * Use and distribution licensed under the BSD license. See
2170+ * the COPYING file in the parent directory for full text.
2171+ */
2172+
2173+/**
2174+ * @file
2175+ * @brief HashKit Header
2176+ */
2177+
2178+#ifndef HASHKIT_TYPES_H
2179+#define HASHKIT_TYPES_H
2180+
2181+#ifdef __cplusplus
2182+extern "C" {
2183+#endif
2184+
2185+/**
2186+ * @addtogroup hashkit_types Types
2187+ * @ingroup hashkit
2188+ * @{
2189+ */
2190+
2191+/**
2192+ @todo hashkit_options_t is for future use, currently we do not define any user options.
2193+ */
2194+
2195+typedef enum
2196+{
2197+ HASHKIT_OPTION_MAX
2198+} hashkit_options_t;
2199+
2200+typedef struct
2201+{
2202+ /* We use the following for internal book keeping. */
2203+ bool is_initialized:1;
2204+ bool is_allocated:1;
2205+} hashkit_options_st;
2206+
2207+typedef enum {
2208+ HASHKIT_HASH_DEFAULT= 0,
2209+ HASHKIT_HASH_MD5,
2210+ HASHKIT_HASH_CRC,
2211+ HASHKIT_HASH_FNV1_64,
2212+ HASHKIT_HASH_FNV1A_64,
2213+ HASHKIT_HASH_FNV1_32,
2214+ HASHKIT_HASH_FNV1A_32,
2215+ HASHKIT_HASH_HSIEH,
2216+ HASHKIT_HASH_MURMUR,
2217+ HASHKIT_HASH_JENKINS,
2218+ HASHKIT_HASH_MAX
2219+} hashkit_hash_t;
2220+
2221+/**
2222+ * Hash distributions that are available to use.
2223+ */
2224+typedef enum
2225+{
2226+ HASHKIT_DISTRIBUTION_MODULA,
2227+ HASHKIT_DISTRIBUTION_RANDOM,
2228+ HASHKIT_DISTRIBUTION_KETAMA,
2229+ HASHKIT_DISTRIBUTION_MAX /* Always add new values before this. */
2230+} hashkit_distribution_t;
2231+
2232+
2233+typedef struct hashkit_st hashkit_st;
2234+typedef struct hashkit_continuum_point_st hashkit_continuum_point_st;
2235+typedef bool (hashkit_active_fn)(void *context);
2236+typedef uint32_t (hashkit_fn)(const char *key, size_t key_length);
2237+typedef size_t (hashkit_key_fn)(char *key, size_t key_length, uint32_t point_index, void *context);
2238+typedef void (hashkit_sort_fn)(void *context, size_t count);
2239+typedef uint32_t (hashkit_weight_fn)(void *context);
2240+
2241+/** @} */
2242+
2243+
2244+#ifdef __cplusplus
2245+}
2246+#endif
2247+
2248+#endif /* HASHKIT_TYPES_H */
2249
2250=== added file 'libhashkit/visibility.h'
2251--- libhashkit/visibility.h 1970-01-01 00:00:00 +0000
2252+++ libhashkit/visibility.h 2009-12-11 17:27:14 +0000
2253@@ -0,0 +1,51 @@
2254+/*
2255+ * Summary: interface for HashKit functions
2256+ * Description: visibitliy macros for HashKit library
2257+ *
2258+ * Use and distribution licensed under the BSD license. See
2259+ * the COPYING file in this directory for full text.
2260+ *
2261+ * Author: Monty Taylor
2262+ */
2263+
2264+/**
2265+ * @file
2266+ * @brief Visibility control macros
2267+ */
2268+
2269+#ifndef HASHKIT_VISIBILITY_H
2270+#define HASHKIT_VISIBILITY_H
2271+
2272+/**
2273+ *
2274+ * HASHKIT_API is used for the public API symbols. It either DLL imports or
2275+ * DLL exports (or does nothing for static build).
2276+ *
2277+ * HASHKIT_LOCAL is used for non-api symbols.
2278+ */
2279+
2280+#if defined(BUILDING_HASHKIT)
2281+# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
2282+# define HASHKIT_API __attribute__ ((visibility("default")))
2283+# define HASHKIT_LOCAL __attribute__ ((visibility("hidden")))
2284+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
2285+# define HASHKIT_API __global
2286+# define HASHKIT_LOCAL __hidden
2287+# elif defined(_MSC_VER)
2288+# define HASHKIT_API extern __declspec(dllexport)
2289+# define HASHKIT_LOCAL
2290+# else
2291+# define HASHKIT_API
2292+# define HASHKIT_LOCAL
2293+# endif /* defined(HAVE_VISIBILITY) */
2294+#else /* defined(BUILDING_HASHKIT) */
2295+# if defined(_MSC_VER)
2296+# define HASHKIT_API extern __declspec(dllimport)
2297+# define HASHKIT_LOCAL
2298+# else
2299+# define HASHKIT_API
2300+# define HASHKIT_LOCAL
2301+# endif /* defined(_MSC_VER) */
2302+#endif /* defined(BUILDING_HASHKIT) */
2303+
2304+#endif /* HASHKIT_VISIBILITY_H */
2305
2306=== modified file 'libmemcached/Makefile.am'
2307--- libmemcached/Makefile.am 2009-12-02 04:43:41 +0000
2308+++ libmemcached/Makefile.am 2009-12-11 17:27:14 +0000
2309@@ -24,6 +24,7 @@
2310 memcached_configure.h \
2311 memcached_constants.h \
2312 memcached_get.h \
2313+ memcached_hash.h \
2314 memcached_result.h \
2315 memcached_server.h \
2316 memcached_storage.h \
2317@@ -51,8 +52,7 @@
2318 libmemcachedcallbacks_la_SOURCES = memcached_callback.c
2319
2320 libmemcached_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION}
2321-libmemcached_la_SOURCES = crc.c \
2322- memcached.c \
2323+libmemcached_la_SOURCES = memcached.c \
2324 memcached_auto.c \
2325 memcached_analyze.c \
2326 memcached_behavior.c \
2327@@ -64,11 +64,9 @@
2328 memcached_flush.c \
2329 memcached_get.c \
2330 memcached_hash.c \
2331- memcached_hosts.c \
2332 memcached_io.c \
2333 memcached_purge.c \
2334 memcached_flush_buffers.c \
2335- md5.c \
2336 memcached_key.c \
2337 memcached_quit.c \
2338 memcached_parse.c \
2339@@ -81,18 +79,11 @@
2340 memcached_strerror.c \
2341 memcached_verbosity.c \
2342 memcached_version.c \
2343- murmur_hash.c \
2344- jenkins_hash.c \
2345 memcached_allocators.c
2346
2347-
2348-if INCLUDE_HSIEH_SRC
2349-libmemcached_la_SOURCES += hsieh_hash.c
2350-endif
2351-
2352 libmemcached_la_DEPENDENCIES= libmemcachedcallbacks.la
2353-libmemcached_la_LIBADD= $(LIBM) libmemcachedcallbacks.la
2354-libmemcached_la_LDFLAGS= ${AM_LDFLAGS} -version-info 3:0:0
2355+libmemcached_la_LIBADD= $(LIBM) libmemcachedcallbacks.la $(LIBHASHKIT_LINK)
2356+libmemcached_la_LDFLAGS = -version-info $(MEMCACHED_LIBRARY_VERSION) $(LD_VERSION_SCRIPT) $(LIBM)
2357
2358 if BUILD_LIBMEMCACHEDUTIL
2359 pkginclude_HEADERS+= memcached_util.h memcached_pool.h
2360
2361=== modified file 'libmemcached/common.h'
2362--- libmemcached/common.h 2009-11-27 10:40:32 +0000
2363+++ libmemcached/common.h 2009-12-11 17:27:14 +0000
2364@@ -39,7 +39,6 @@
2365 */
2366 #define BUILDING_LIBMEMCACHED 1
2367
2368-
2369 #include "libmemcached/memcached.h"
2370 #include "libmemcached/memcached_watchpoint.h"
2371
2372@@ -50,13 +49,6 @@
2373 #include "libmemcached/memcached/protocol_binary.h"
2374 #include "libmemcached/byteorder.h"
2375
2376-/* string value */
2377-struct memcached_continuum_item_st {
2378- uint32_t index;
2379- uint32_t value;
2380-};
2381-
2382-
2383 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
2384
2385 #define likely(x) if((x))
2386@@ -97,21 +89,10 @@
2387 MEM_RANDOMIZE_REPLICA_READ= (1 << 17)
2388 } memcached_flags;
2389
2390-/* Hashing algo */
2391-
2392-LIBMEMCACHED_LOCAL
2393-void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result);
2394-LIBMEMCACHED_LOCAL
2395-uint32_t hash_crc32(const char *data,
2396- size_t data_len);
2397-#ifdef HAVE_HSIEH_HASH
2398-LIBMEMCACHED_LOCAL
2399-uint32_t hsieh_hash(const char *key, size_t key_length);
2400-#endif
2401-LIBMEMCACHED_LOCAL
2402-uint32_t murmur_hash(const char *key, size_t key_length);
2403-LIBMEMCACHED_LOCAL
2404-uint32_t jenkins_hash(const void *key, size_t length, uint32_t initval);
2405+LIBMEMCACHED_LOCAL
2406+extern hashkit_fn *memcached_hash_fn_map[MEMCACHED_HASH_MAX];
2407+LIBMEMCACHED_LOCAL
2408+extern hashkit_distribution_t memcached_distribution_map[MEMCACHED_DISTRIBUTION_MAX];
2409
2410 LIBMEMCACHED_LOCAL
2411 memcached_return memcached_connect(memcached_server_st *ptr);
2412@@ -143,9 +124,6 @@
2413
2414
2415 LIBMEMCACHED_LOCAL
2416-uint32_t generate_hash(memcached_st *ptr, const char *key, size_t key_length);
2417-
2418-LIBMEMCACHED_LOCAL
2419 memcached_return memcached_purge(memcached_server_st *ptr);
2420
2421 static inline memcached_return memcached_validate_key_length(size_t key_length,
2422@@ -167,4 +145,13 @@
2423 return MEMCACHED_SUCCESS;
2424 }
2425
2426+LIBMEMCACHED_LOCAL
2427+bool memcached_server_active(void *context);
2428+LIBMEMCACHED_LOCAL
2429+uint32_t memcached_server_weight(void *context);
2430+LIBMEMCACHED_LOCAL
2431+void memcached_server_sort(void *context, size_t count);
2432+LIBMEMCACHED_LOCAL
2433+size_t memcached_server_key(char *key, size_t key_length, uint32_t point_index, void *context);
2434+
2435 #endif /* LIBMEMCACHED_COMMON_H */
2436
2437=== modified file 'libmemcached/memcached.c'
2438--- libmemcached/memcached.c 2009-06-14 18:52:39 +0000
2439+++ libmemcached/memcached.c 2009-12-11 17:27:14 +0000
2440@@ -3,6 +3,33 @@
2441 */
2442 #include "common.h"
2443
2444+hashkit_fn *memcached_hash_fn_map[MEMCACHED_HASH_MAX]=
2445+{
2446+ hashkit_default,
2447+ hashkit_md5,
2448+ hashkit_crc32,
2449+ hashkit_fnv1_64,
2450+ hashkit_fnv1a_64,
2451+ hashkit_fnv1_32,
2452+ hashkit_fnv1a_32,
2453+#ifdef HAVE_HSIEH_HASH
2454+ hashkit_hsieh,
2455+#else
2456+ NULL,
2457+#endif
2458+ hashkit_murmur,
2459+ hashkit_jenkins
2460+};
2461+
2462+hashkit_distribution_t memcached_distribution_map[MEMCACHED_DISTRIBUTION_MAX]=
2463+{
2464+ HASHKIT_DISTRIBUTION_MODULA,
2465+ HASHKIT_DISTRIBUTION_KETAMA,
2466+ HASHKIT_DISTRIBUTION_KETAMA,
2467+ HASHKIT_DISTRIBUTION_RANDOM,
2468+ HASHKIT_DISTRIBUTION_KETAMA
2469+};
2470+
2471 memcached_st *memcached_create(memcached_st *ptr)
2472 {
2473 memcached_result_st *result_ptr;
2474@@ -29,6 +56,8 @@
2475 ptr->connect_timeout= MEMCACHED_DEFAULT_TIMEOUT;
2476 ptr->retry_timeout= 0;
2477 ptr->distribution= MEMCACHED_DISTRIBUTION_MODULA;
2478+ hashkit_create(&ptr->hashkit);
2479+ hashkit_set_continuum_key_fn(&ptr->hashkit, memcached_server_key);
2480
2481 /* TODO, Document why we picked these defaults */
2482 ptr->io_msg_watermark= 500;
2483@@ -47,8 +76,7 @@
2484 if (ptr->on_cleanup)
2485 ptr->on_cleanup(ptr);
2486
2487- if (ptr->continuum)
2488- ptr->call_free(ptr, ptr->continuum);
2489+ hashkit_free(&ptr->hashkit);
2490
2491 if (ptr->is_allocated)
2492 ptr->call_free(ptr, ptr);
2493@@ -67,7 +95,9 @@
2494 memcached_st *new_clone;
2495
2496 if (source == NULL)
2497+ {
2498 return memcached_create(clone);
2499+ }
2500
2501 if (clone && clone->is_allocated)
2502 {
2503@@ -86,8 +116,13 @@
2504 new_clone->connect_timeout= source->connect_timeout;
2505 new_clone->retry_timeout= source->retry_timeout;
2506 new_clone->distribution= source->distribution;
2507- new_clone->hash= source->hash;
2508- new_clone->hash_continuum= source->hash_continuum;
2509+ hashkit_set_distribution(&new_clone->hashkit,
2510+ memcached_distribution_map[new_clone->distribution]);
2511+ new_clone->hash_type= source->hash_type;
2512+ hashkit_set_hash_fn(&new_clone->hashkit, memcached_hash_fn_map[new_clone->hash_type]);
2513+ new_clone->continuum_hash_type= source->continuum_hash_type;
2514+ hashkit_set_continuum_hash_fn(&new_clone->hashkit,
2515+ memcached_hash_fn_map[new_clone->continuum_hash_type]);
2516 new_clone->user_data= source->user_data;
2517
2518 new_clone->snd_timeout= source->snd_timeout;
2519@@ -148,3 +183,19 @@
2520 ptr->user_data= data;
2521 return ret;
2522 }
2523+
2524+memcached_return run_distribution(memcached_st *ptr)
2525+{
2526+ if (gettimeofday(&ptr->now, NULL) == 0 && ptr->now.tv_sec > ptr->next_distribution_rebuild)
2527+ ptr->next_distribution_rebuild= 0;
2528+
2529+ if (hashkit_run_distribution(&ptr->hashkit) != 0)
2530+ {
2531+ ptr->cached_errno= errno;
2532+ return MEMCACHED_ERRNO;
2533+ }
2534+
2535+ ptr->last_disconnected_server = NULL;
2536+
2537+ return MEMCACHED_SUCCESS;
2538+}
2539
2540=== modified file 'libmemcached/memcached.h'
2541--- libmemcached/memcached.h 2009-12-02 22:04:02 +0000
2542+++ libmemcached/memcached.h 2009-12-11 17:27:14 +0000
2543@@ -18,11 +18,13 @@
2544 #include <sys/types.h>
2545 #include <netinet/in.h>
2546
2547+#include <libhashkit/hashkit.h>
2548 #include <libmemcached/visibility.h>
2549 #include <libmemcached/memcached_configure.h>
2550 #include <libmemcached/memcached_constants.h>
2551 #include <libmemcached/memcached_types.h>
2552 #include <libmemcached/memcached_get.h>
2553+#include <libmemcached/memcached_hash.h>
2554 #include <libmemcached/memcached_server.h>
2555 #include <libmemcached/memcached_string.h>
2556 #include <libmemcached/memcached_result.h>
2557@@ -76,8 +78,6 @@
2558 uint8_t purging;
2559 bool is_allocated;
2560 uint8_t distribution;
2561- uint8_t hash;
2562- uint32_t continuum_points_counter;
2563 memcached_server_st *hosts;
2564 memcached_server_st *last_disconnected_server;
2565 int32_t snd_timeout;
2566@@ -93,15 +93,14 @@
2567 int32_t poll_timeout;
2568 int32_t connect_timeout;
2569 int32_t retry_timeout;
2570- uint32_t continuum_count;
2571 int send_size;
2572 int recv_size;
2573 void *user_data;
2574 time_t next_distribution_rebuild;
2575 size_t prefix_key_length;
2576- memcached_hash hash_continuum;
2577+ memcached_hash hash_type;
2578+ memcached_hash continuum_hash_type;
2579 memcached_result_st result;
2580- memcached_continuum_item_st *continuum;
2581 memcached_clone_func on_clone;
2582 memcached_cleanup_func on_cleanup;
2583 memcached_free_function call_free;
2584@@ -110,9 +109,11 @@
2585 memcached_calloc_function call_calloc;
2586 memcached_trigger_key get_key_failure;
2587 memcached_trigger_delete_key delete_trigger;
2588+ hashkit_st hashkit;
2589 char prefix_key[MEMCACHED_PREFIX_KEY_MAX_SIZE];
2590 uint32_t number_of_replicas;
2591 memcached_callback_st *callbacks;
2592+ struct timeval now;
2593 };
2594
2595 LIBMEMCACHED_API
2596@@ -214,12 +215,6 @@
2597 LIBMEMCACHED_API
2598 uint64_t memcached_behavior_get(memcached_st *ptr, memcached_behavior flag);
2599
2600-/* The two public hash bits */
2601-LIBMEMCACHED_API
2602-uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash hash_algorithm);
2603-LIBMEMCACHED_API
2604-uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_length);
2605-
2606 LIBMEMCACHED_API
2607 memcached_return memcached_flush_buffers(memcached_st *mem);
2608
2609
2610=== modified file 'libmemcached/memcached_behavior.c'
2611--- libmemcached/memcached_behavior.c 2009-11-27 19:46:16 +0000
2612+++ libmemcached/memcached_behavior.c 2009-12-11 17:27:14 +0000
2613@@ -75,6 +75,7 @@
2614 case MEMCACHED_BEHAVIOR_DISTRIBUTION:
2615 {
2616 ptr->distribution= (memcached_server_distribution)(data);
2617+ hashkit_set_distribution(&ptr->hashkit, memcached_distribution_map[data]);
2618 if (ptr->distribution == MEMCACHED_DISTRIBUTION_RANDOM)
2619 {
2620 srandom((uint32_t) time(NULL));
2621@@ -86,21 +87,31 @@
2622 {
2623 if (data)
2624 {
2625- ptr->hash= MEMCACHED_HASH_MD5;
2626+ ptr->hash_type= MEMCACHED_HASH_MD5;
2627+ hashkit_set_hash_fn(&ptr->hashkit, hashkit_md5);
2628 ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
2629+ hashkit_set_distribution(&ptr->hashkit, HASHKIT_DISTRIBUTION_KETAMA);
2630 }
2631 else
2632 {
2633- ptr->hash= 0;
2634+ ptr->hash_type= 0;
2635+ hashkit_set_hash_fn(&ptr->hashkit, NULL);
2636 ptr->distribution= 0;
2637+ hashkit_set_distribution(&ptr->hashkit, HASHKIT_DISTRIBUTION_MODULA);
2638 }
2639 run_distribution(ptr);
2640 break;
2641 }
2642 case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
2643 {
2644- ptr->hash= MEMCACHED_HASH_MD5;
2645+ ptr->hash_type= MEMCACHED_HASH_MD5;
2646+ hashkit_set_hash_fn(&ptr->hashkit, hashkit_md5);
2647 ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
2648+ hashkit_set_distribution(&ptr->hashkit, HASHKIT_DISTRIBUTION_KETAMA);
2649+ if (data)
2650+ hashkit_set_weight_fn(&ptr->hashkit, memcached_server_weight);
2651+ else
2652+ hashkit_set_weight_fn(&ptr->hashkit, NULL);
2653 set_behavior_flag(ptr, MEM_KETAMA_WEIGHTED, data);
2654 run_distribution(ptr);
2655 break;
2656@@ -109,12 +120,16 @@
2657 switch (data)
2658 {
2659 case MEMCACHED_KETAMA_COMPAT_LIBMEMCACHED:
2660- ptr->hash= MEMCACHED_HASH_MD5;
2661+ ptr->hash_type= MEMCACHED_HASH_MD5;
2662+ hashkit_set_hash_fn(&ptr->hashkit, hashkit_md5);
2663 ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
2664+ hashkit_set_distribution(&ptr->hashkit, HASHKIT_DISTRIBUTION_KETAMA);
2665 break;
2666 case MEMCACHED_KETAMA_COMPAT_SPY:
2667- ptr->hash= MEMCACHED_HASH_MD5;
2668+ ptr->hash_type= MEMCACHED_HASH_MD5;
2669+ hashkit_set_hash_fn(&ptr->hashkit, hashkit_md5);
2670 ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY;
2671+ hashkit_set_distribution(&ptr->hashkit, HASHKIT_DISTRIBUTION_KETAMA);
2672 break;
2673 default:
2674 return MEMCACHED_FAILURE;
2675@@ -122,14 +137,24 @@
2676 run_distribution(ptr);
2677 break;
2678 case MEMCACHED_BEHAVIOR_HASH:
2679+ if ((memcached_hash)data >= MEMCACHED_HASH_MAX)
2680+ return MEMCACHED_FAILURE;
2681 #ifndef HAVE_HSIEH_HASH
2682- if ((memcached_hash)(data) == MEMCACHED_HASH_HSIEH)
2683+ else if ((memcached_hash)data == MEMCACHED_HASH_HSIEH)
2684 return MEMCACHED_FAILURE;
2685 #endif
2686- ptr->hash= (memcached_hash)(data);
2687+ ptr->hash_type= (memcached_hash)data;
2688+ hashkit_set_hash_fn(&ptr->hashkit, memcached_hash_fn_map[(memcached_hash)data]);
2689 break;
2690 case MEMCACHED_BEHAVIOR_KETAMA_HASH:
2691- ptr->hash_continuum= (memcached_hash)(data);
2692+ if ((memcached_hash)data >= MEMCACHED_HASH_MAX)
2693+ return MEMCACHED_FAILURE;
2694+#ifndef HAVE_HSIEH_HASH
2695+ else if ((memcached_hash)data == MEMCACHED_HASH_HSIEH)
2696+ return MEMCACHED_FAILURE;
2697+#endif
2698+ ptr->continuum_hash_type= (memcached_hash)(data);
2699+ hashkit_set_continuum_hash_fn(&ptr->hashkit, memcached_hash_fn_map[(memcached_hash)data]);
2700 run_distribution(ptr);
2701 break;
2702 case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
2703@@ -143,6 +168,10 @@
2704 break;
2705 case MEMCACHED_BEHAVIOR_SORT_HOSTS:
2706 {
2707+ if (data)
2708+ hashkit_set_sort_fn(&ptr->hashkit, memcached_server_sort);
2709+ else
2710+ hashkit_set_sort_fn(&ptr->hashkit, NULL);
2711 set_behavior_flag(ptr, MEM_USE_SORT_HOSTS, data);
2712 run_distribution(ptr);
2713
2714@@ -174,6 +203,10 @@
2715 set_behavior_flag(ptr, MEM_NOREPLY, data);
2716 break;
2717 case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
2718+ if (data)
2719+ hashkit_set_active_fn(&ptr->hashkit, memcached_server_active);
2720+ else
2721+ hashkit_set_active_fn(&ptr->hashkit, NULL);
2722 set_behavior_flag(ptr, MEM_AUTO_EJECT_HOSTS, data);
2723 break;
2724 case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
2725@@ -247,9 +280,9 @@
2726 }
2727 /* NOTREACHED */
2728 case MEMCACHED_BEHAVIOR_HASH:
2729- return ptr->hash;
2730+ return ptr->hash_type;
2731 case MEMCACHED_BEHAVIOR_KETAMA_HASH:
2732- return ptr->hash_continuum;
2733+ return ptr->continuum_hash_type;
2734 case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
2735 return ptr->server_failure_limit;
2736 case MEMCACHED_BEHAVIOR_SORT_HOSTS:
2737
2738=== modified file 'libmemcached/memcached_constants.h'
2739--- libmemcached/memcached_constants.h 2009-11-27 10:40:32 +0000
2740+++ libmemcached/memcached_constants.h 2009-12-11 17:27:14 +0000
2741@@ -14,13 +14,8 @@
2742 #define MEMCACHED_MAX_KEY 251 /* We add one to have it null terminated */
2743 #define MEMCACHED_MAX_BUFFER 8196
2744 #define MEMCACHED_MAX_HOST_LENGTH 64
2745-#define MEMCACHED_MAX_HOST_SORT_LENGTH 86 /* Used for Ketama */
2746-#define MEMCACHED_POINTS_PER_SERVER 100
2747-#define MEMCACHED_POINTS_PER_SERVER_KETAMA 160
2748-#define MEMCACHED_CONTINUUM_SIZE MEMCACHED_POINTS_PER_SERVER*100 /* This would then set max hosts to 100 */
2749 #define MEMCACHED_STRIDE 4
2750 #define MEMCACHED_DEFAULT_TIMEOUT 1000
2751-#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
2752 #define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
2753 #define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
2754
2755@@ -72,7 +67,8 @@
2756 MEMCACHED_DISTRIBUTION_CONSISTENT,
2757 MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA,
2758 MEMCACHED_DISTRIBUTION_RANDOM,
2759- MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
2760+ MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY,
2761+ MEMCACHED_DISTRIBUTION_MAX
2762 } memcached_server_distribution;
2763
2764 typedef enum {
2765@@ -137,7 +133,8 @@
2766 MEMCACHED_HASH_FNV1A_32,
2767 MEMCACHED_HASH_HSIEH,
2768 MEMCACHED_HASH_MURMUR,
2769- MEMCACHED_HASH_JENKINS
2770+ MEMCACHED_HASH_JENKINS,
2771+ MEMCACHED_HASH_MAX
2772 } memcached_hash;
2773
2774 typedef enum {
2775
2776=== added file 'libmemcached/memcached_hash.c'
2777--- libmemcached/memcached_hash.c 1970-01-01 00:00:00 +0000
2778+++ libmemcached/memcached_hash.c 2009-12-11 17:27:14 +0000
2779@@ -0,0 +1,46 @@
2780+/*
2781+ Memcached library
2782+*/
2783+#include "common.h"
2784+
2785+uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash hash_algorithm)
2786+{
2787+ return hashkit_generate_value(key, key_length, (hashkit_hash_t)hash_algorithm);
2788+
2789+}
2790+
2791+uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_length)
2792+{
2793+ uint32_t hash_value= 1; /* Just here to remove compile warning */
2794+
2795+ WATCHPOINT_ASSERT(ptr->number_of_hosts);
2796+
2797+ if (ptr->number_of_hosts == 1)
2798+ return 0;
2799+
2800+ if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS) &&
2801+ ptr->next_distribution_rebuild)
2802+ {
2803+ if (gettimeofday(&ptr->now, NULL) == 0 && ptr->now.tv_sec > ptr->next_distribution_rebuild)
2804+ run_distribution(ptr);
2805+ }
2806+
2807+ if (ptr->flags & MEM_HASH_WITH_PREFIX_KEY)
2808+ {
2809+ size_t temp_length= ptr->prefix_key_length + key_length;
2810+ char temp[temp_length];
2811+
2812+ if (temp_length > MEMCACHED_MAX_KEY -1)
2813+ return 0;
2814+
2815+ strncpy(temp, ptr->prefix_key, ptr->prefix_key_length);
2816+ strncpy(temp + ptr->prefix_key_length, key, key_length);
2817+ hash_value= hashkit_value(&ptr->hashkit, temp, temp_length);
2818+ }
2819+ else
2820+ hash_value= hashkit_value(&ptr->hashkit, key, key_length);
2821+
2822+ WATCHPOINT_ASSERT(hash_value);
2823+
2824+ return hashkit_index(&ptr->hashkit, hash_value);
2825+}
2826
2827=== added file 'libmemcached/memcached_hash.h'
2828--- libmemcached/memcached_hash.h 1970-01-01 00:00:00 +0000
2829+++ libmemcached/memcached_hash.h 2009-12-11 17:27:14 +0000
2830@@ -0,0 +1,9 @@
2831+/*
2832+ Memcached library
2833+*/
2834+
2835+/* The two public hash bits */
2836+LIBMEMCACHED_API
2837+uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash hash_algorithm);
2838+LIBMEMCACHED_API
2839+uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_length);
2840
2841=== modified file 'libmemcached/memcached_server.c'
2842--- libmemcached/memcached_server.c 2009-10-10 11:57:03 +0000
2843+++ libmemcached/memcached_server.c 2009-12-11 17:27:14 +0000
2844@@ -3,6 +3,12 @@
2845 */
2846 #include "common.h"
2847
2848+/* Protoypes (static) */
2849+static memcached_return server_add(memcached_st *ptr, const char *hostname,
2850+ unsigned int port,
2851+ uint32_t weight,
2852+ memcached_connection type);
2853+
2854 memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr)
2855 {
2856 if (ptr == NULL)
2857@@ -159,3 +165,295 @@
2858 {
2859 return ptr->last_disconnected_server;
2860 }
2861+
2862+void server_list_free(memcached_st *ptr, memcached_server_st *servers)
2863+{
2864+ unsigned int x;
2865+
2866+ if (servers == NULL)
2867+ return;
2868+
2869+ for (x= 0; x < servers->count; x++)
2870+ if (servers[x].address_info)
2871+ {
2872+ freeaddrinfo(servers[x].address_info);
2873+ servers[x].address_info= NULL;
2874+ }
2875+
2876+ if (ptr)
2877+ ptr->call_free(ptr, servers);
2878+ else
2879+ free(servers);
2880+}
2881+
2882+memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
2883+{
2884+ unsigned int x;
2885+ uint16_t count;
2886+ memcached_server_st *new_host_list;
2887+
2888+ if (!list)
2889+ return MEMCACHED_SUCCESS;
2890+
2891+ count= list[0].count;
2892+ new_host_list= ptr->call_realloc(ptr, ptr->hosts,
2893+ sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
2894+
2895+ if (!new_host_list)
2896+ return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
2897+
2898+ ptr->hosts= new_host_list;
2899+ hashkit_set_list(&ptr->hashkit, ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st));
2900+
2901+ for (x= 0; x < count; x++)
2902+ {
2903+ if ((ptr->flags & MEM_USE_UDP && list[x].type != MEMCACHED_CONNECTION_UDP)
2904+ || ((list[x].type == MEMCACHED_CONNECTION_UDP)
2905+ && ! (ptr->flags & MEM_USE_UDP)) )
2906+ return MEMCACHED_INVALID_HOST_PROTOCOL;
2907+
2908+ WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
2909+ memcached_server_create(ptr, &ptr->hosts[ptr->number_of_hosts]);
2910+ /* TODO check return type */
2911+ (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname,
2912+ list[x].port, list[x].weight, list[x].type);
2913+ ptr->number_of_hosts++;
2914+ hashkit_set_list(&ptr->hashkit, ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st));
2915+ }
2916+ ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
2917+
2918+ return run_distribution(ptr);
2919+}
2920+
2921+memcached_return memcached_server_add_unix_socket(memcached_st *ptr,
2922+ const char *filename)
2923+{
2924+ return memcached_server_add_unix_socket_with_weight(ptr, filename, 0);
2925+}
2926+
2927+memcached_return memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
2928+ const char *filename,
2929+ uint32_t weight)
2930+{
2931+ if (!filename)
2932+ return MEMCACHED_FAILURE;
2933+
2934+ return server_add(ptr, filename, 0, weight, MEMCACHED_CONNECTION_UNIX_SOCKET);
2935+}
2936+
2937+memcached_return memcached_server_add_udp(memcached_st *ptr,
2938+ const char *hostname,
2939+ unsigned int port)
2940+{
2941+ return memcached_server_add_udp_with_weight(ptr, hostname, port, 0);
2942+}
2943+
2944+memcached_return memcached_server_add_udp_with_weight(memcached_st *ptr,
2945+ const char *hostname,
2946+ unsigned int port,
2947+ uint32_t weight)
2948+{
2949+ if (!port)
2950+ port= MEMCACHED_DEFAULT_PORT;
2951+
2952+ if (!hostname)
2953+ hostname= "localhost";
2954+
2955+ return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_UDP);
2956+}
2957+
2958+memcached_return memcached_server_add(memcached_st *ptr,
2959+ const char *hostname,
2960+ unsigned int port)
2961+{
2962+ return memcached_server_add_with_weight(ptr, hostname, port, 0);
2963+}
2964+
2965+memcached_return memcached_server_add_with_weight(memcached_st *ptr,
2966+ const char *hostname,
2967+ unsigned int port,
2968+ uint32_t weight)
2969+{
2970+ if (!port)
2971+ port= MEMCACHED_DEFAULT_PORT;
2972+
2973+ if (!hostname)
2974+ hostname= "localhost";
2975+
2976+ return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_TCP);
2977+}
2978+
2979+static memcached_return server_add(memcached_st *ptr, const char *hostname,
2980+ unsigned int port,
2981+ uint32_t weight,
2982+ memcached_connection type)
2983+{
2984+ memcached_server_st *new_host_list;
2985+
2986+ if ( (ptr->flags & MEM_USE_UDP && type != MEMCACHED_CONNECTION_UDP)
2987+ || ( (type == MEMCACHED_CONNECTION_UDP) && !(ptr->flags & MEM_USE_UDP) ) )
2988+ return MEMCACHED_INVALID_HOST_PROTOCOL;
2989+
2990+ new_host_list= ptr->call_realloc(ptr, ptr->hosts,
2991+ sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
2992+
2993+ if (new_host_list == NULL)
2994+ return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
2995+
2996+ ptr->hosts= new_host_list;
2997+
2998+ /* TODO: Check return type */
2999+ (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], hostname, port, weight, type);
3000+ ptr->number_of_hosts++;
3001+ ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
3002+
3003+ hashkit_set_list(&ptr->hashkit, ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st));
3004+
3005+ return run_distribution(ptr);
3006+}
3007+
3008+memcached_return memcached_server_remove(memcached_server_st *st_ptr)
3009+{
3010+ uint32_t x, host_index;
3011+ memcached_st *ptr= st_ptr->root;
3012+ memcached_server_st *list= ptr->hosts;
3013+
3014+ for (x= 0, host_index= 0; x < ptr->number_of_hosts; x++)
3015+ {
3016+ if (strncmp(list[x].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH) != 0 || list[x].port != st_ptr->port)
3017+ {
3018+ if (host_index != x)
3019+ memcpy(list+host_index, list+x, sizeof(memcached_server_st));
3020+ host_index++;
3021+ }
3022+ }
3023+ ptr->number_of_hosts= host_index;
3024+
3025+ if (st_ptr->address_info)
3026+ {
3027+ freeaddrinfo(st_ptr->address_info);
3028+ st_ptr->address_info= NULL;
3029+ }
3030+ run_distribution(ptr);
3031+
3032+ return MEMCACHED_SUCCESS;
3033+}
3034+
3035+memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
3036+ const char *hostname, unsigned int port,
3037+ memcached_return *error)
3038+{
3039+ return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error);
3040+}
3041+
3042+memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr,
3043+ const char *hostname, unsigned int port,
3044+ uint32_t weight,
3045+ memcached_return *error)
3046+{
3047+ unsigned int count;
3048+ memcached_server_st *new_host_list;
3049+
3050+ if (hostname == NULL || error == NULL)
3051+ return NULL;
3052+
3053+ if (!port)
3054+ port= MEMCACHED_DEFAULT_PORT;
3055+
3056+ /* Increment count for hosts */
3057+ count= 1;
3058+ if (ptr != NULL)
3059+ {
3060+ count+= ptr[0].count;
3061+ }
3062+
3063+ new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
3064+ if (!new_host_list)
3065+ {
3066+ *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
3067+ return NULL;
3068+ }
3069+
3070+ /* TODO: Check return type */
3071+ memcached_server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, MEMCACHED_CONNECTION_TCP);
3072+
3073+ /* Backwards compatibility hack */
3074+ new_host_list[0].count= (uint16_t) count;
3075+
3076+ *error= MEMCACHED_SUCCESS;
3077+ return new_host_list;
3078+}
3079+
3080+unsigned int memcached_server_list_count(memcached_server_st *ptr)
3081+{
3082+ if (ptr == NULL)
3083+ return 0;
3084+
3085+ return ptr[0].count;
3086+}
3087+
3088+void memcached_server_list_free(memcached_server_st *ptr)
3089+{
3090+ server_list_free(NULL, ptr);
3091+}
3092+
3093+bool memcached_server_active(void *context)
3094+{
3095+ memcached_server_st *ptr= (memcached_server_st *)context;
3096+
3097+ if (ptr->next_retry <= ptr->root->now.tv_sec)
3098+ return true;
3099+ else if (ptr->root->next_distribution_rebuild == 0 ||
3100+ ptr->next_retry < ptr->root->next_distribution_rebuild)
3101+ {
3102+ ptr->root->next_distribution_rebuild= ptr->next_retry;
3103+ }
3104+
3105+ return false;
3106+}
3107+
3108+uint32_t memcached_server_weight(void *context)
3109+{
3110+ memcached_server_st *ptr= (memcached_server_st *)context;
3111+
3112+ if (ptr->weight == 0)
3113+ ptr->weight= 1;
3114+
3115+ return ptr->weight;
3116+}
3117+
3118+static int compare_servers(const void *p1, const void *p2)
3119+{
3120+ int return_value;
3121+ memcached_server_st *a= (memcached_server_st *)p1;
3122+ memcached_server_st *b= (memcached_server_st *)p2;
3123+
3124+ return_value= strcmp(a->hostname, b->hostname);
3125+
3126+ if (return_value == 0)
3127+ {
3128+ return_value= (int) (a->port - b->port);
3129+ }
3130+
3131+ return return_value;
3132+}
3133+
3134+void memcached_server_sort(void *context, size_t count)
3135+{
3136+ memcached_server_st *ptr= (memcached_server_st *)context;
3137+
3138+ qsort(context, count, sizeof(memcached_server_st), compare_servers);
3139+ ptr[0].count= (uint16_t) count;
3140+}
3141+
3142+size_t memcached_server_key(char *key, size_t key_length, uint32_t point_index, void *context)
3143+{
3144+ memcached_server_st *ptr= (memcached_server_st *)context;
3145+
3146+ if (ptr->root->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY)
3147+ return (size_t)snprintf(key, key_length, "/%s:%d-%d", ptr->hostname, ptr->port, point_index);
3148+ else if (ptr->port == MEMCACHED_DEFAULT_PORT)
3149+ return (size_t)snprintf(key, key_length, "%s-%d", ptr->hostname, point_index);
3150+
3151+ return (size_t)snprintf(key, key_length, "%s:%d-%d", ptr->hostname, ptr->port, point_index);
3152+}
3153
3154=== modified file 'libmemcached/memcached_types.h'
3155--- libmemcached/memcached_types.h 2009-10-13 10:05:51 +0000
3156+++ libmemcached/memcached_types.h 2009-12-11 17:27:14 +0000
3157@@ -19,7 +19,6 @@
3158 typedef struct memcached_result_st memcached_result_st;
3159 typedef struct memcached_string_st memcached_string_st;
3160 typedef struct memcached_server_st memcached_server_st;
3161-typedef struct memcached_continuum_item_st memcached_continuum_item_st;
3162 typedef memcached_return (*memcached_clone_func)(memcached_st *parent, memcached_st *clone);
3163 typedef memcached_return (*memcached_cleanup_func)(memcached_st *ptr);
3164 typedef void (*memcached_free_function)(memcached_st *ptr, void *mem);
3165@@ -28,13 +27,13 @@
3166 typedef void *(*memcached_calloc_function)(memcached_st *ptr, size_t nelem, const size_t elsize);
3167 typedef memcached_return (*memcached_execute_function)(memcached_st *ptr, memcached_result_st *result, void *context);
3168 typedef memcached_return (*memcached_server_function)(memcached_st *ptr, memcached_server_st *server, void *context);
3169-typedef memcached_return (*memcached_trigger_key)(memcached_st *ptr,
3170- const char *key, size_t key_length,
3171+typedef memcached_return (*memcached_trigger_key)(memcached_st *ptr,
3172+ const char *key, size_t key_length,
3173 memcached_result_st *result);
3174-typedef memcached_return (*memcached_trigger_delete_key)(memcached_st *ptr,
3175+typedef memcached_return (*memcached_trigger_delete_key)(memcached_st *ptr,
3176 const char *key, size_t key_length);
3177
3178-typedef memcached_return (*memcached_dump_func)(memcached_st *ptr,
3179+typedef memcached_return (*memcached_dump_func)(memcached_st *ptr,
3180 const char *key, size_t key_length, void *context);
3181
3182 typedef struct {
3183
3184=== added file 'm4/pandora_have_libhashkit.m4'
3185--- m4/pandora_have_libhashkit.m4 1970-01-01 00:00:00 +0000
3186+++ m4/pandora_have_libhashkit.m4 2009-12-11 17:27:14 +0000
3187@@ -0,0 +1,51 @@
3188+dnl Copyright (C) 2009 Sun Microsystems
3189+dnl This file is free software; Sun Microsystems
3190+dnl gives unlimited permission to copy and/or distribute it,
3191+dnl with or without modifications, as long as this notice is preserved.
3192+
3193+AC_DEFUN([_PANDORA_SEARCH_LIBHASHKIT],[
3194+ AC_REQUIRE([AC_LIB_PREFIX])
3195+
3196+ dnl --------------------------------------------------------------------
3197+ dnl Check for libhashkit
3198+ dnl --------------------------------------------------------------------
3199+
3200+ AC_ARG_ENABLE([libhashkit],
3201+ [AS_HELP_STRING([--disable-libhashkit],
3202+ [Build with libhashkit support @<:@default=on@:>@])],
3203+ [ac_enable_libhashkit="$enableval"],
3204+ [ac_enable_libhashkit="yes"])
3205+
3206+ AS_IF([test "x$ac_enable_libhashkit" = "xyes"],[
3207+ AC_LIB_HAVE_LINKFLAGS(hashkit,,[
3208+ #include <libhashkit/hashkit.h>
3209+ ],[
3210+ hashkit_st hashkit;
3211+ hashkit_create(&hashkit);
3212+ ])
3213+ ],[
3214+ ac_cv_libhashkit="no"
3215+ ])
3216+
3217+ AM_CONDITIONAL(HAVE_LIBHASHKIT, [test "x${ac_cv_libhashkit}" = "xyes"])
3218+])
3219+
3220+AC_DEFUN([PANDORA_HAVE_LIBHASHKIT],[
3221+ AC_REQUIRE([_PANDORA_SEARCH_LIBHASHKIT])
3222+])
3223+
3224+AC_DEFUN([PANDORA_REQUIRE_LIBHASHKIT],[
3225+ AC_REQUIRE([PANDORA_HAVE_LIBHASHKIT])
3226+ AS_IF([test "x${ac_cv_libhashkit}" = "xno"],
3227+ AC_MSG_ERROR([libhashkit is required for ${PACKAGE}]))
3228+])
3229+
3230+AC_DEFUN([PANDORA_BUNDLE_LIBHASHKIT],[
3231+ AC_REQUIRE([PANDORA_HAVE_LIBHASHKIT])
3232+ AS_IF([test "x${ac_cv_libhashkit}" = "xno"],
3233+ PANDORA_BUNDLED_SUBDIRS="${PANDORA_BUNDLED_SUBDIRS} libhashkit"
3234+ LIBHASHKIT_LINK="\$(top_builddir)/libhashkit/libhashkit.la",
3235+ LIBHASHKIT_LINK="${LTLIBHASHKIT}")
3236+ AC_SUBST(PANDORA_BUNDLED_SUBDIRS)
3237+ AC_SUBST(LIBHASHKIT_LINK)
3238+])
3239
3240=== modified file 'tests/Makefile.am'
3241--- tests/Makefile.am 2009-11-10 03:57:08 +0000
3242+++ tests/Makefile.am 2009-12-11 17:27:14 +0000
3243@@ -18,8 +18,11 @@
3244
3245 LIBS =
3246
3247+clean-local:
3248+ -rm -r ketama_keys.txt
3249+
3250 noinst_HEADERS = test.h server.h ketama_test_cases.h ketama_test_cases_spy.h
3251-noinst_PROGRAMS = testapp testplus udptest atomsmasher startservers
3252+noinst_PROGRAMS = testapp testplus udptest atomsmasher startservers testhashkit
3253 noinst_LTLIBRARIES= libserver.la libtest.la
3254
3255 libserver_la_SOURCES= server.c
3256@@ -27,7 +30,11 @@
3257
3258 testapp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
3259 testapp_SOURCES = function.c
3260-testapp_LDADD = $(top_builddir)/clients/libgenexec.la libtest.la libserver.la $(LDADDS)
3261+testapp_LDADD = $(top_builddir)/clients/libgenexec.la libtest.la libserver.la $(LDADDS) $(LIBHASHKIT_LINK)
3262+
3263+testhashkit_CFLAGS=$(AM_CFLAGS)
3264+testhashkit_SOURCES= hashkit_functions.c
3265+testhashkit_LDADD = libtest.la $(LDADDS) $(LIBHASHKIT_LINK)
3266
3267 testplus_SOURCES = plus.cpp
3268 testplus_LDADD = libtest.la libserver.la $(LDADDS)
3269@@ -41,10 +48,6 @@
3270 startservers_SOURCES = start.c
3271 startservers_LDADD = libserver.la $(LDADDS)
3272
3273-record:
3274- ./testapp > output.res
3275- ./testplus > output_plus.res
3276-
3277 client-record:
3278 sh t/memcat.test > r/memcat.res
3279 sh t/memcp.test > r/memcp.res
3280@@ -52,17 +55,15 @@
3281 sh t/memslap.test > r/memslap.res
3282 sh t/memstat.test > r/memstat.res
3283
3284-record-extended:
3285- ./testapp extended > output2.res
3286-
3287-test: testapp testplus library_test memcapable
3288+test: testapp testhashkit testplus libmemcached_test libmhashkit_test memcapable
3289 echo "Tests completed"
3290
3291-library_test:
3292- ./testapp > output.cmp
3293- diff output.res output.cmp
3294-# ./testplus > output_plus.cmp
3295-# diff output_plus.res output_plus.cmp
3296+libmhashkit_test:
3297+ ./testhashkit
3298+
3299+libmemcached_test:
3300+ ./testapp
3301+# ./testplus
3302
3303 memcapable:
3304 @MEMC_BINARY@ -d -P /tmp/Xumemc.pid -p 12555
3305@@ -86,6 +87,12 @@
3306 cat /tmp/Xumemc.pid | xargs kill
3307 rm /tmp/Xumemc.pid
3308
3309+gdb-hash:
3310+ $(LIBTOOL) --mode=execute gdb testhashkit
3311+
3312+valgrind-hash:
3313+ $(LIBTOOL) --mode=execute valgrind testhashkit
3314+
3315 valgrind:
3316 libtool --mode=execute valgrind --leak-check=yes --show-reachable=yes testapp
3317
3318
3319=== modified file 'tests/atomsmasher.c'
3320--- tests/atomsmasher.c 2009-11-25 08:21:57 +0000
3321+++ tests/atomsmasher.c 2009-12-11 17:27:14 +0000
3322@@ -199,10 +199,10 @@
3323 }
3324
3325 test_st smash_tests[] ={
3326- {"generate_pairs", 1, generate_pairs },
3327- {"drizzle", 1, drizzle },
3328- {"cleanup", 1, cleanup_pairs },
3329- {"many_adds", 1, many_adds },
3330+ {"generate_pairs", 1, (test_execution_fn *)generate_pairs },
3331+ {"drizzle", 1, (test_execution_fn *)drizzle },
3332+ {"cleanup", 1, (test_execution_fn *)cleanup_pairs },
3333+ {"many_adds", 1, (test_execution_fn *)many_adds },
3334 {0, 0, 0}
3335 };
3336
3337
3338=== modified file 'tests/function.c'
3339--- tests/function.c 2009-12-02 23:07:20 +0000
3340+++ tests/function.c 2009-12-11 17:27:14 +0000
3341@@ -1,3 +1,11 @@
3342+/* libMemcached Functions Test
3343+ * Copyright (C) 2006-2009 Brian Aker
3344+ * All rights reserved.
3345+ *
3346+ * Use and distribution licensed under the BSD license. See
3347+ * the COPYING file in the parent directory for full text.
3348+ */
3349+
3350 /*
3351 Sample test application.
3352 */
3353@@ -33,6 +41,8 @@
3354 #include "libmemcached/memcached_util.h"
3355 #endif
3356
3357+#include "hash_results.h"
3358+
3359 #define GLOBAL_COUNT 10000
3360 #define GLOBAL2_COUNT 100
3361 #define SERVERS_TO_CREATE 5
3362@@ -223,8 +233,8 @@
3363 test_truth(memc_clone->distribution == memc->distribution);
3364 test_truth(memc_clone->flags == memc->flags);
3365 test_truth(memc_clone->get_key_failure == memc->get_key_failure);
3366- test_truth(memc_clone->hash == memc->hash);
3367- test_truth(memc_clone->hash_continuum == memc->hash_continuum);
3368+ test_truth(memc_clone->hash_type == memc->hash_type);
3369+ test_truth(memc_clone->continuum_hash_type == memc->continuum_hash_type);
3370 test_truth(memc_clone->io_bytes_watermark == memc->io_bytes_watermark);
3371 test_truth(memc_clone->io_msg_watermark == memc->io_msg_watermark);
3372 test_truth(memc_clone->io_key_prefetch == memc->io_key_prefetch);
3373@@ -1625,18 +1635,18 @@
3374
3375 static test_return_t get_stats_keys(memcached_st *memc)
3376 {
3377- char **list;
3378+ char **stat_list;
3379 char **ptr;
3380 memcached_stat_st memc_stat;
3381 memcached_return rc;
3382
3383- list= memcached_stat_get_keys(memc, &memc_stat, &rc);
3384+ stat_list= memcached_stat_get_keys(memc, &memc_stat, &rc);
3385 test_truth(rc == MEMCACHED_SUCCESS);
3386- for (ptr= list; *ptr; ptr++)
3387+ for (ptr= stat_list; *ptr; ptr++)
3388 test_truth(*ptr);
3389 fflush(stdout);
3390
3391- free(list);
3392+ free(stat_list);
3393
3394 return TEST_SUCCESS;
3395 }
3396@@ -1655,7 +1665,7 @@
3397 static test_return_t get_stats(memcached_st *memc)
3398 {
3399 unsigned int x;
3400- char **list;
3401+ char **stat_list;
3402 char **ptr;
3403 memcached_return rc;
3404 memcached_stat_st *memc_stat;
3405@@ -1668,11 +1678,11 @@
3406
3407 for (x= 0; x < memcached_server_count(memc); x++)
3408 {
3409- list= memcached_stat_get_keys(memc, memc_stat+x, &rc);
3410+ stat_list= memcached_stat_get_keys(memc, memc_stat+x, &rc);
3411 test_truth(rc == MEMCACHED_SUCCESS);
3412- for (ptr= list; *ptr; ptr++);
3413+ for (ptr= stat_list; *ptr; ptr++);
3414
3415- free(list);
3416+ free(stat_list);
3417 }
3418
3419 memcached_stat_free(NULL, memc_stat);
3420@@ -2699,7 +2709,7 @@
3421 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
3422 * us test the boundary wraparound.
3423 */
3424- test_truth(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->continuum[0].index);
3425+ test_truth(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->hashkit.continuum[0].index);
3426
3427 /* verify the standard ketama set. */
3428 for (x= 0; x < 99; x++)
3429@@ -3368,7 +3378,7 @@
3430
3431 static memcached_return pre_hash_fnv1_64(memcached_st *memc)
3432 {
3433- memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, (uint64_t)MEMCACHED_HASH_FNV1_64);
3434+ memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, (uint64_t)HASHKIT_HASH_MURMUR);
3435
3436 return MEMCACHED_SUCCESS;
3437 }
3438@@ -3759,19 +3769,19 @@
3439 switch (count)
3440 {
3441 case 0:
3442- ret=memcached_add(memc, key, len, key, len, 0, 0);
3443+ ret= memcached_add(memc, key, len, key, len, 0, 0);
3444 break;
3445 case 1:
3446- ret=memcached_replace(memc, key, len, key, len, 0, 0);
3447+ ret= memcached_replace(memc, key, len, key, len, 0, 0);
3448 break;
3449 case 2:
3450- ret=memcached_set(memc, key, len, key, len, 0, 0);
3451+ ret= memcached_set(memc, key, len, key, len, 0, 0);
3452 break;
3453 case 3:
3454- ret=memcached_append(memc, key, len, key, len, 0, 0);
3455+ ret= memcached_append(memc, key, len, key, len, 0, 0);
3456 break;
3457 case 4:
3458- ret=memcached_prepend(memc, key, len, key, len, 0, 0);
3459+ ret= memcached_prepend(memc, key, len, key, len, 0, 0);
3460 break;
3461 default:
3462 test_truth(count);
3463@@ -3923,7 +3933,7 @@
3464 }
3465
3466 #ifdef HAVE_LIBMEMCACHEDUTIL
3467-static void* connection_release(void *arg)
3468+static void* connection_release(void *arg)
3469 {
3470 struct {
3471 memcached_pool_st* pool;
3472@@ -4170,7 +4180,7 @@
3473 rc= memcached_set(memc, keys[x], len[x], "1", 1, 0, 0);
3474 test_truth(rc == MEMCACHED_SUCCESS);
3475 }
3476-
3477+
3478 memcached_quit(memc);
3479
3480 for (int x=0; x< 7; ++x) {
3481@@ -4567,25 +4577,55 @@
3482 {
3483 test_st current_op;
3484 test_st mixed_io_ops [] ={
3485- {"udp_set_test", 0, udp_set_test},
3486- {"udp_set_too_big_test", 0, udp_set_too_big_test},
3487- {"udp_delete_test", 0, udp_delete_test},
3488- {"udp_verbosity_test", 0, udp_verbosity_test},
3489- {"udp_quit_test", 0, udp_quit_test},
3490- {"udp_flush_test", 0, udp_flush_test},
3491- {"udp_incr_test", 0, udp_incr_test},
3492- {"udp_decr_test", 0, udp_decr_test},
3493- {"udp_version_test", 0, udp_version_test}
3494+ {"udp_set_test", 0,
3495+ (test_execution_fn *)udp_set_test},
3496+ {"udp_set_too_big_test", 0,
3497+ (test_execution_fn *)udp_set_too_big_test},
3498+ {"udp_delete_test", 0,
3499+ (test_execution_fn *)udp_delete_test},
3500+ {"udp_verbosity_test", 0,
3501+ (test_execution_fn *)udp_verbosity_test},
3502+ {"udp_quit_test", 0,
3503+ (test_execution_fn *)udp_quit_test},
3504+ {"udp_flush_test", 0,
3505+ (test_execution_fn *)udp_flush_test},
3506+ {"udp_incr_test", 0,
3507+ (test_execution_fn *)udp_incr_test},
3508+ {"udp_decr_test", 0,
3509+ (test_execution_fn *)udp_decr_test},
3510+ {"udp_version_test", 0,
3511+ (test_execution_fn *)udp_version_test}
3512 };
3513 unsigned int x= 0;
3514 for (x= 0; x < 500; x++)
3515 {
3516 current_op= mixed_io_ops[random() % 9];
3517- test_truth(current_op.function(memc) == TEST_SUCCESS);
3518+ test_truth(current_op.test_fn(memc) == TEST_SUCCESS);
3519 }
3520 return TEST_SUCCESS;
3521 }
3522
3523+static test_return_t hash_sanity_test (memcached_st *memc)
3524+{
3525+ (void)memc;
3526+
3527+ assert(HASHKIT_HASH_DEFAULT == MEMCACHED_HASH_DEFAULT);
3528+ assert(HASHKIT_HASH_MD5 == MEMCACHED_HASH_MD5);
3529+ assert(HASHKIT_HASH_CRC == MEMCACHED_HASH_CRC);
3530+ assert(HASHKIT_HASH_FNV1_64 == MEMCACHED_HASH_FNV1_64);
3531+ assert(HASHKIT_HASH_FNV1A_64 == MEMCACHED_HASH_FNV1A_64);
3532+ assert(HASHKIT_HASH_FNV1_32 == MEMCACHED_HASH_FNV1_32);
3533+ assert(HASHKIT_HASH_FNV1A_32 == MEMCACHED_HASH_FNV1A_32);
3534+#ifdef HAVE_HSIEH_HASH
3535+ assert(HASHKIT_HASH_HSIEH == MEMCACHED_HASH_HSIEH);
3536+#endif
3537+ assert(HASHKIT_HASH_MURMUR == MEMCACHED_HASH_MURMUR);
3538+ assert(HASHKIT_HASH_JENKINS == MEMCACHED_HASH_JENKINS);
3539+ assert(HASHKIT_HASH_MAX == MEMCACHED_HASH_MAX);
3540+
3541+ return TEST_SUCCESS;
3542+}
3543+
3544 static test_return_t hsieh_avaibility_test (memcached_st *memc)
3545 {
3546 memcached_return expected_rc= MEMCACHED_FAILURE;
3547@@ -4598,55 +4638,17 @@
3548 return TEST_SUCCESS;
3549 }
3550
3551-static const char *list[]=
3552-{
3553- "apple",
3554- "beat",
3555- "carrot",
3556- "daikon",
3557- "eggplant",
3558- "flower",
3559- "green",
3560- "hide",
3561- "ick",
3562- "jack",
3563- "kick",
3564- "lime",
3565- "mushrooms",
3566- "nectarine",
3567- "orange",
3568- "peach",
3569- "quant",
3570- "ripen",
3571- "strawberry",
3572- "tang",
3573- "up",
3574- "volumne",
3575- "when",
3576- "yellow",
3577- "zip",
3578- NULL
3579-};
3580-
3581 static test_return_t md5_run (memcached_st *memc __attribute__((unused)))
3582 {
3583 uint32_t x;
3584 const char **ptr;
3585- uint32_t values[]= { 3195025439U, 2556848621U, 3724893440U, 3332385401U,
3586- 245758794U, 2550894432U, 121710495U, 3053817768U,
3587- 1250994555U, 1862072655U, 2631955953U, 2951528551U,
3588- 1451250070U, 2820856945U, 2060845566U, 3646985608U,
3589- 2138080750U, 217675895U, 2230934345U, 1234361223U,
3590- 3968582726U, 2455685270U, 1293568479U, 199067604U,
3591- 2042482093U };
3592-
3593-
3594- for (ptr= list, x= 0; *ptr; ptr++, x++)
3595+
3596+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3597 {
3598 uint32_t hash_val;
3599
3600 hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_MD5);
3601- test_truth(values[x] == hash_val);
3602+ test_truth(md5_values[x] == hash_val);
3603 }
3604
3605 return TEST_SUCCESS;
3606@@ -4656,17 +4658,13 @@
3607 {
3608 uint32_t x;
3609 const char **ptr;
3610- uint32_t values[]= { 10542U, 22009U, 14526U, 19510U, 19432U, 10199U, 20634U,
3611- 9369U, 11511U, 10362U, 7893U, 31289U, 11313U, 9354U,
3612- 7621U, 30628U, 15218U, 25967U, 2695U, 9380U,
3613- 17300U, 28156U, 9192U, 20484U, 16925U };
3614
3615- for (ptr= list, x= 0; *ptr; ptr++, x++)
3616+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3617 {
3618 uint32_t hash_val;
3619
3620 hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_CRC);
3621- assert(values[x] == hash_val);
3622+ assert(crc_values[x] == hash_val);
3623 }
3624
3625 return TEST_SUCCESS;
3626@@ -4676,20 +4674,13 @@
3627 {
3628 uint32_t x;
3629 const char **ptr;
3630- uint32_t values[]= { 473199127U, 4148981457U, 3971873300U, 3257986707U,
3631- 1722477987U, 2991193800U, 4147007314U, 3633179701U,
3632- 1805162104U, 3503289120U, 3395702895U, 3325073042U,
3633- 2345265314U, 3340346032U, 2722964135U, 1173398992U,
3634- 2815549194U, 2562818319U, 224996066U, 2680194749U,
3635- 3035305390U, 246890365U, 2395624193U, 4145193337U,
3636- 1801941682U };
3637
3638- for (ptr= list, x= 0; *ptr; ptr++, x++)
3639+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3640 {
3641 uint32_t hash_val;
3642
3643 hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_FNV1_64);
3644- assert(values[x] == hash_val);
3645+ assert(fnv1_64_values[x] == hash_val);
3646 }
3647
3648 return TEST_SUCCESS;
3649@@ -4699,20 +4690,13 @@
3650 {
3651 uint32_t x;
3652 const char **ptr;
3653- uint32_t values[]= { 1488911807U, 2500855813U, 1510099634U, 1390325195U,
3654- 3647689787U, 3241528582U, 1669328060U, 2604311949U,
3655- 734810122U, 1516407546U, 560948863U, 1767346780U,
3656- 561034892U, 4156330026U, 3716417003U, 3475297030U,
3657- 1518272172U, 227211583U, 3938128828U, 126112909U,
3658- 3043416448U, 3131561933U, 1328739897U, 2455664041U,
3659- 2272238452U };
3660
3661- for (ptr= list, x= 0; *ptr; ptr++, x++)
3662+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3663 {
3664 uint32_t hash_val;
3665
3666 hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_FNV1A_64);
3667- assert(values[x] == hash_val);
3668+ assert(fnv1a_64_values[x] == hash_val);
3669 }
3670
3671 return TEST_SUCCESS;
3672@@ -4722,21 +4706,14 @@
3673 {
3674 uint32_t x;
3675 const char **ptr;
3676- uint32_t values[]= { 67176023U, 1190179409U, 2043204404U, 3221866419U,
3677- 2567703427U, 3787535528U, 4147287986U, 3500475733U,
3678- 344481048U, 3865235296U, 2181839183U, 119581266U,
3679- 510234242U, 4248244304U, 1362796839U, 103389328U,
3680- 1449620010U, 182962511U, 3554262370U, 3206747549U,
3681- 1551306158U, 4127558461U, 1889140833U, 2774173721U,
3682- 1180552018U };
3683-
3684-
3685- for (ptr= list, x= 0; *ptr; ptr++, x++)
3686+
3687+
3688+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3689 {
3690 uint32_t hash_val;
3691
3692 hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_FNV1_32);
3693- assert(values[x] == hash_val);
3694+ assert(fnv1_32_values[x] == hash_val);
3695 }
3696
3697 return TEST_SUCCESS;
3698@@ -4746,20 +4723,13 @@
3699 {
3700 uint32_t x;
3701 const char **ptr;
3702- uint32_t values[]= { 280767167U, 2421315013U, 3072375666U, 855001899U,
3703- 459261019U, 3521085446U, 18738364U, 1625305005U,
3704- 2162232970U, 777243802U, 3323728671U, 132336572U,
3705- 3654473228U, 260679466U, 1169454059U, 2698319462U,
3706- 1062177260U, 235516991U, 2218399068U, 405302637U,
3707- 1128467232U, 3579622413U, 2138539289U, 96429129U,
3708- 2877453236U };
3709
3710- for (ptr= list, x= 0; *ptr; ptr++, x++)
3711+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3712 {
3713 uint32_t hash_val;
3714
3715 hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_FNV1A_32);
3716- assert(values[x] == hash_val);
3717+ assert(fnv1a_32_values[x] == hash_val);
3718 }
3719
3720 return TEST_SUCCESS;
3721@@ -4769,22 +4739,13 @@
3722 {
3723 uint32_t x;
3724 const char **ptr;
3725-#ifdef HAVE_HSIEH_HASH
3726- uint32_t values[]= { 3738850110, 3636226060, 3821074029, 3489929160, 3485772682, 80540287,
3727- 1805464076, 1895033657, 409795758, 979934958, 3634096985, 1284445480,
3728- 2265380744, 707972988, 353823508, 1549198350, 1327930172, 9304163,
3729- 4220749037, 2493964934, 2777873870, 2057831732, 1510213931, 2027828987,
3730- 3395453351 };
3731-#else
3732- uint32_t values[]= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
3733-#endif
3734
3735- for (ptr= list, x= 0; *ptr; ptr++, x++)
3736+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3737 {
3738 uint32_t hash_val;
3739
3740 hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_HSIEH);
3741- assert(values[x] == hash_val);
3742+ assert(hsieh_values[x] == hash_val);
3743 }
3744
3745 return TEST_SUCCESS;
3746@@ -4794,20 +4755,13 @@
3747 {
3748 uint32_t x;
3749 const char **ptr;
3750- uint32_t values[]= { 473199127U, 4148981457U, 3971873300U, 3257986707U,
3751- 1722477987U, 2991193800U, 4147007314U, 3633179701U,
3752- 1805162104U, 3503289120U, 3395702895U, 3325073042U,
3753- 2345265314U, 3340346032U, 2722964135U, 1173398992U,
3754- 2815549194U, 2562818319U, 224996066U, 2680194749U,
3755- 3035305390U, 246890365U, 2395624193U, 4145193337U,
3756- 1801941682U };
3757
3758- for (ptr= list, x= 0; *ptr; ptr++, x++)
3759+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3760 {
3761 uint32_t hash_val;
3762
3763- hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_FNV1_64);
3764- assert(values[x] == hash_val);
3765+ hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_MURMUR);
3766+ assert(murmur_values[x] == hash_val);
3767 }
3768
3769 return TEST_SUCCESS;
3770@@ -4817,21 +4771,14 @@
3771 {
3772 uint32_t x;
3773 const char **ptr;
3774- uint32_t values[]= { 1442444624U, 4253821186U, 1885058256U, 2120131735U,
3775- 3261968576U, 3515188778U, 4232909173U, 4288625128U,
3776- 1812047395U, 3689182164U, 2502979932U, 1214050606U,
3777- 2415988847U, 1494268927U, 1025545760U, 3920481083U,
3778- 4153263658U, 3824871822U, 3072759809U, 798622255U,
3779- 3065432577U, 1453328165U, 2691550971U, 3408888387U,
3780- 2629893356U };
3781-
3782-
3783- for (ptr= list, x= 0; *ptr; ptr++, x++)
3784+
3785+
3786+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
3787 {
3788 uint32_t hash_val;
3789
3790 hash_val= memcached_generate_hash_value(*ptr, strlen(*ptr), MEMCACHED_HASH_JENKINS);
3791- assert(values[x] == hash_val);
3792+ assert(jenkins_values[x] == hash_val);
3793 }
3794
3795 return TEST_SUCCESS;
3796@@ -4881,7 +4828,7 @@
3797 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
3798 * us test the boundary wraparound.
3799 */
3800- assert(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->continuum[0].index);
3801+ assert(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->hashkit.continuum[0].index);
3802
3803 /* verify the standard ketama set. */
3804 for (x= 0; x < 99; x++)
3805@@ -4940,7 +4887,7 @@
3806 /* VDEAAAAA hashes to fffcd1b5, after the last continuum point, and lets
3807 * us test the boundary wraparound.
3808 */
3809- assert(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->continuum[0].index);
3810+ assert(memcached_generate_hash(memc, (char *)"VDEAAAAA", 8) == memc->hashkit.continuum[0].index);
3811
3812 /* verify the standard ketama set. */
3813 for (x= 0; x < 99; x++)
3814@@ -5393,140 +5340,157 @@
3815 }
3816
3817 test_st udp_setup_server_tests[] ={
3818- {"set_udp_behavior_test", 0, set_udp_behavior_test},
3819- {"add_tcp_server_udp_client_test", 0, add_tcp_server_udp_client_test},
3820- {"add_udp_server_tcp_client_test", 0, add_udp_server_tcp_client_test},
3821+ {"set_udp_behavior_test", 0,
3822+ (test_execution_fn *)set_udp_behavior_test},
3823+ {"add_tcp_server_udp_client_test", 0,
3824+ (test_execution_fn *)add_tcp_server_udp_client_test},
3825+ {"add_udp_server_tcp_client_test", 0,
3826+ (test_execution_fn *)add_udp_server_tcp_client_test},
3827 {0, 0, 0}
3828 };
3829
3830 test_st upd_io_tests[] ={
3831- {"udp_set_test", 0, udp_set_test},
3832- {"udp_buffered_set_test", 0, udp_buffered_set_test},
3833- {"udp_set_too_big_test", 0, udp_set_too_big_test},
3834- {"udp_delete_test", 0, udp_delete_test},
3835- {"udp_buffered_delete_test", 0, udp_buffered_delete_test},
3836- {"udp_verbosity_test", 0, udp_verbosity_test},
3837- {"udp_quit_test", 0, udp_quit_test},
3838- {"udp_flush_test", 0, udp_flush_test},
3839- {"udp_incr_test", 0, udp_incr_test},
3840- {"udp_decr_test", 0, udp_decr_test},
3841- {"udp_stat_test", 0, udp_stat_test},
3842- {"udp_version_test", 0, udp_version_test},
3843- {"udp_get_test", 0, udp_get_test},
3844- {"udp_mixed_io_test", 0, udp_mixed_io_test},
3845+ {"udp_set_test", 0,
3846+ (test_execution_fn *)udp_set_test},
3847+ {"udp_buffered_set_test", 0,
3848+ (test_execution_fn *)udp_buffered_set_test},
3849+ {"udp_set_too_big_test", 0,
3850+ (test_execution_fn *)udp_set_too_big_test},
3851+ {"udp_delete_test", 0,
3852+ (test_execution_fn *)udp_delete_test},
3853+ {"udp_buffered_delete_test", 0,
3854+ (test_execution_fn *)udp_buffered_delete_test},
3855+ {"udp_verbosity_test", 0,
3856+ (test_execution_fn *)udp_verbosity_test},
3857+ {"udp_quit_test", 0,
3858+ (test_execution_fn *)udp_quit_test},
3859+ {"udp_flush_test", 0,
3860+ (test_execution_fn *)udp_flush_test},
3861+ {"udp_incr_test", 0,
3862+ (test_execution_fn *)udp_incr_test},
3863+ {"udp_decr_test", 0,
3864+ (test_execution_fn *)udp_decr_test},
3865+ {"udp_stat_test", 0,
3866+ (test_execution_fn *)udp_stat_test},
3867+ {"udp_version_test", 0,
3868+ (test_execution_fn *)udp_version_test},
3869+ {"udp_get_test", 0,
3870+ (test_execution_fn *)udp_get_test},
3871+ {"udp_mixed_io_test", 0,
3872+ (test_execution_fn *)udp_mixed_io_test},
3873 {0, 0, 0}
3874 };
3875
3876 /* Clean the server before beginning testing */
3877 test_st tests[] ={
3878- {"flush", 0, flush_test },
3879- {"init", 0, init_test },
3880- {"allocation", 0, allocation_test },
3881- {"server_list_null_test", 0, server_list_null_test},
3882- {"server_unsort", 0, server_unsort_test},
3883- {"server_sort", 0, server_sort_test},
3884- {"server_sort2", 0, server_sort2_test},
3885- {"clone_test", 0, clone_test },
3886- {"connection_test", 0, connection_test},
3887- {"callback_test", 0, callback_test},
3888- {"behavior_test", 0, behavior_test},
3889- {"userdata_test", 0, userdata_test},
3890- {"error", 0, error_test },
3891- {"set", 0, set_test },
3892- {"set2", 0, set_test2 },
3893- {"set3", 0, set_test3 },
3894- {"dump", 1, dump_test},
3895- {"add", 1, add_test },
3896- {"replace", 1, replace_test },
3897- {"delete", 1, delete_test },
3898- {"get", 1, get_test },
3899- {"get2", 0, get_test2 },
3900- {"get3", 0, get_test3 },
3901- {"get4", 0, get_test4 },
3902- {"partial mget", 0, get_test5 },
3903- {"stats_servername", 0, stats_servername_test },
3904- {"increment", 0, increment_test },
3905- {"increment_with_initial", 1, increment_with_initial_test },
3906- {"decrement", 0, decrement_test },
3907- {"decrement_with_initial", 1, decrement_with_initial_test },
3908- {"increment_by_key", 0, increment_by_key_test },
3909- {"increment_with_initial_by_key", 1, increment_with_initial_by_key_test },
3910- {"decrement_by_key", 0, decrement_by_key_test },
3911- {"decrement_with_initial_by_key", 1, decrement_with_initial_by_key_test },
3912- {"quit", 0, quit_test },
3913- {"mget", 1, mget_test },
3914- {"mget_result", 1, mget_result_test },
3915- {"mget_result_alloc", 1, mget_result_alloc_test },
3916- {"mget_result_function", 1, mget_result_function },
3917- {"mget_execute", 1, mget_execute },
3918- {"mget_end", 0, mget_end },
3919- {"get_stats", 0, get_stats },
3920- {"add_host_test", 0, add_host_test },
3921- {"add_host_test_1", 0, add_host_test1 },
3922- {"get_stats_keys", 0, get_stats_keys },
3923- {"behavior_test", 0, get_stats_keys },
3924- {"callback_test", 0, get_stats_keys },
3925- {"version_string_test", 0, version_string_test},
3926- {"bad_key", 1, bad_key_test },
3927- {"memcached_server_cursor", 1, memcached_server_cursor_test },
3928- {"read_through", 1, read_through },
3929- {"delete_through", 1, delete_through },
3930- {"noreply", 1, noreply_test},
3931- {"analyzer", 1, analyzer_test},
3932+ {"flush", 0, (test_execution_fn *)flush_test },
3933+ {"init", 0, (test_execution_fn *)init_test },
3934+ {"allocation", 0, (test_execution_fn *)allocation_test },
3935+ {"server_list_null_test", 0, (test_execution_fn *)server_list_null_test},
3936+ {"server_unsort", 0, (test_execution_fn *)server_unsort_test},
3937+ {"server_sort", 0, (test_execution_fn *)server_sort_test},
3938+ {"server_sort2", 0, (test_execution_fn *)server_sort2_test},
3939+ {"clone_test", 0, (test_execution_fn *)clone_test },
3940+ {"connection_test", 0, (test_execution_fn *)connection_test},
3941+ {"callback_test", 0, (test_execution_fn *)callback_test},
3942+ {"behavior_test", 0, (test_execution_fn *)behavior_test},
3943+ {"userdata_test", 0, (test_execution_fn *)userdata_test},
3944+ {"error", 0, (test_execution_fn *)error_test },
3945+ {"set", 0, (test_execution_fn *)set_test },
3946+ {"set2", 0, (test_execution_fn *)set_test2 },
3947+ {"set3", 0, (test_execution_fn *)set_test3 },
3948+ {"dump", 1, (test_execution_fn *)dump_test},
3949+ {"add", 1, (test_execution_fn *)add_test },
3950+ {"replace", 1, (test_execution_fn *)replace_test },
3951+ {"delete", 1, (test_execution_fn *)delete_test },
3952+ {"get", 1, (test_execution_fn *)get_test },
3953+ {"get2", 0, (test_execution_fn *)get_test2 },
3954+ {"get3", 0, (test_execution_fn *)get_test3 },
3955+ {"get4", 0, (test_execution_fn *)get_test4 },
3956+ {"partial mget", 0, (test_execution_fn *)get_test5 },
3957+ {"stats_servername", 0, (test_execution_fn *)stats_servername_test },
3958+ {"increment", 0, (test_execution_fn *)increment_test },
3959+ {"increment_with_initial", 1, (test_execution_fn *)increment_with_initial_test },
3960+ {"decrement", 0, (test_execution_fn *)decrement_test },
3961+ {"decrement_with_initial", 1, (test_execution_fn *)decrement_with_initial_test },
3962+ {"increment_by_key", 0, (test_execution_fn *)increment_by_key_test },
3963+ {"increment_with_initial_by_key", 1, (test_execution_fn *)increment_with_initial_by_key_test },
3964+ {"decrement_by_key", 0, (test_execution_fn *)decrement_by_key_test },
3965+ {"decrement_with_initial_by_key", 1, (test_execution_fn *)decrement_with_initial_by_key_test },
3966+ {"quit", 0, (test_execution_fn *)quit_test },
3967+ {"mget", 1, (test_execution_fn *)mget_test },
3968+ {"mget_result", 1, (test_execution_fn *)mget_result_test },
3969+ {"mget_result_alloc", 1, (test_execution_fn *)mget_result_alloc_test },
3970+ {"mget_result_function", 1, (test_execution_fn *)mget_result_function },
3971+ {"mget_execute", 1, (test_execution_fn *)mget_execute },
3972+ {"mget_end", 0, (test_execution_fn *)mget_end },
3973+ {"get_stats", 0, (test_execution_fn *)get_stats },
3974+ {"add_host_test", 0, (test_execution_fn *)add_host_test },
3975+ {"add_host_test_1", 0, (test_execution_fn *)add_host_test1 },
3976+ {"get_stats_keys", 0, (test_execution_fn *)get_stats_keys },
3977+ {"behavior_test", 0, (test_execution_fn *)get_stats_keys },
3978+ {"callback_test", 0, (test_execution_fn *)get_stats_keys },
3979+ {"version_string_test", 0, (test_execution_fn *)version_string_test},
3980+ {"bad_key", 1, (test_execution_fn *)bad_key_test },
3981+ {"memcached_server_cursor", 1, (test_execution_fn *)memcached_server_cursor_test },
3982+ {"read_through", 1, (test_execution_fn *)read_through },
3983+ {"delete_through", 1, (test_execution_fn *)delete_through },
3984+ {"noreply", 1, (test_execution_fn *)noreply_test},
3985+ {"analyzer", 1, (test_execution_fn *)analyzer_test},
3986 #ifdef HAVE_LIBMEMCACHEDUTIL
3987- {"connectionpool", 1, connection_pool_test },
3988+ {"connectionpool", 1, (test_execution_fn *)connection_pool_test },
3989 #endif
3990- {"test_get_last_disconnect", 1, test_get_last_disconnect},
3991+ {"test_get_last_disconnect", 1, (test_execution_fn *)test_get_last_disconnect},
3992 {0, 0, 0}
3993 };
3994
3995 test_st async_tests[] ={
3996- {"add", 1, add_wrapper },
3997+ {"add", 1, (test_execution_fn *)add_wrapper },
3998 {0, 0, 0}
3999 };
4000
4001 test_st string_tests[] ={
4002- {"string static with null", 0, string_static_null },
4003- {"string alloc with null", 0, string_alloc_null },
4004- {"string alloc with 1K", 0, string_alloc_with_size },
4005- {"string alloc with malloc failure", 0, string_alloc_with_size_toobig },
4006- {"string append", 0, string_alloc_append },
4007- {"string append failure (too big)", 0, string_alloc_append_toobig },
4008- {0, 0, 0}
4009+ {"string static with null", 0, (test_execution_fn *)string_static_null },
4010+ {"string alloc with null", 0, (test_execution_fn *)string_alloc_null },
4011+ {"string alloc with 1K", 0, (test_execution_fn *)string_alloc_with_size },
4012+ {"string alloc with malloc failure", 0, (test_execution_fn *)string_alloc_with_size_toobig },
4013+ {"string append", 0, (test_execution_fn *)string_alloc_append },
4014+ {"string append failure (too big)", 0, (test_execution_fn *)string_alloc_append_toobig },
4015+ {0, 0, (test_execution_fn *)0}
4016 };
4017
4018 test_st result_tests[] ={
4019- {"result static", 0, result_static},
4020- {"result alloc", 0, result_alloc},
4021- {0, 0, 0}
4022+ {"result static", 0, (test_execution_fn *)result_static},
4023+ {"result alloc", 0, (test_execution_fn *)result_alloc},
4024+ {0, 0, (test_execution_fn *)0}
4025 };
4026
4027 test_st version_1_2_3[] ={
4028- {"append", 0, append_test },
4029- {"prepend", 0, prepend_test },
4030- {"cas", 0, cas_test },
4031- {"cas2", 0, cas2_test },
4032- {"append_binary", 0, append_binary_test },
4033- {0, 0, 0}
4034+ {"append", 0, (test_execution_fn *)append_test },
4035+ {"prepend", 0, (test_execution_fn *)prepend_test },
4036+ {"cas", 0, (test_execution_fn *)cas_test },
4037+ {"cas2", 0, (test_execution_fn *)cas2_test },
4038+ {"append_binary", 0, (test_execution_fn *)append_binary_test },
4039+ {0, 0, (test_execution_fn *)0}
4040 };
4041
4042 test_st user_tests[] ={
4043- {"user_supplied_bug1", 0, user_supplied_bug1 },
4044- {"user_supplied_bug2", 0, user_supplied_bug2 },
4045- {"user_supplied_bug3", 0, user_supplied_bug3 },
4046- {"user_supplied_bug4", 0, user_supplied_bug4 },
4047- {"user_supplied_bug5", 1, user_supplied_bug5 },
4048- {"user_supplied_bug6", 1, user_supplied_bug6 },
4049- {"user_supplied_bug7", 1, user_supplied_bug7 },
4050- {"user_supplied_bug8", 1, user_supplied_bug8 },
4051- {"user_supplied_bug9", 1, user_supplied_bug9 },
4052- {"user_supplied_bug10", 1, user_supplied_bug10 },
4053- {"user_supplied_bug11", 1, user_supplied_bug11 },
4054- {"user_supplied_bug12", 1, user_supplied_bug12 },
4055- {"user_supplied_bug13", 1, user_supplied_bug13 },
4056- {"user_supplied_bug14", 1, user_supplied_bug14 },
4057- {"user_supplied_bug15", 1, user_supplied_bug15 },
4058- {"user_supplied_bug16", 1, user_supplied_bug16 },
4059+ {"user_supplied_bug1", 0, (test_execution_fn *)user_supplied_bug1 },
4060+ {"user_supplied_bug2", 0, (test_execution_fn *)user_supplied_bug2 },
4061+ {"user_supplied_bug3", 0, (test_execution_fn *)user_supplied_bug3 },
4062+ {"user_supplied_bug4", 0, (test_execution_fn *)user_supplied_bug4 },
4063+ {"user_supplied_bug5", 1, (test_execution_fn *)user_supplied_bug5 },
4064+ {"user_supplied_bug6", 1, (test_execution_fn *)user_supplied_bug6 },
4065+ {"user_supplied_bug7", 1, (test_execution_fn *)user_supplied_bug7 },
4066+ {"user_supplied_bug8", 1, (test_execution_fn *)user_supplied_bug8 },
4067+ {"user_supplied_bug9", 1, (test_execution_fn *)user_supplied_bug9 },
4068+ {"user_supplied_bug10", 1, (test_execution_fn *)user_supplied_bug10 },
4069+ {"user_supplied_bug11", 1, (test_execution_fn *)user_supplied_bug11 },
4070+ {"user_supplied_bug12", 1, (test_execution_fn *)user_supplied_bug12 },
4071+ {"user_supplied_bug13", 1, (test_execution_fn *)user_supplied_bug13 },
4072+ {"user_supplied_bug14", 1, (test_execution_fn *)user_supplied_bug14 },
4073+ {"user_supplied_bug15", 1, (test_execution_fn *)user_supplied_bug15 },
4074+ {"user_supplied_bug16", 1, (test_execution_fn *)user_supplied_bug16 },
4075 #ifndef __sun
4076 /*
4077 ** It seems to be something weird with the character sets..
4078@@ -5535,23 +5499,23 @@
4079 ** to run the test in a specific locale (I tried zh_CN.UTF-8 without success,
4080 ** so just disable the code for now...).
4081 */
4082- {"user_supplied_bug17", 1, user_supplied_bug17 },
4083+ {"user_supplied_bug17", 1, (test_execution_fn *)user_supplied_bug17 },
4084 #endif
4085- {"user_supplied_bug18", 1, user_supplied_bug18 },
4086- {"user_supplied_bug19", 1, user_supplied_bug19 },
4087- {"user_supplied_bug20", 1, user_supplied_bug20 },
4088- {"user_supplied_bug21", 1, user_supplied_bug21 },
4089- {"wrong_failure_counter_test", 1, wrong_failure_counter_test},
4090- {0, 0, 0}
4091+ {"user_supplied_bug18", 1, (test_execution_fn *)user_supplied_bug18 },
4092+ {"user_supplied_bug19", 1, (test_execution_fn *)user_supplied_bug19 },
4093+ {"user_supplied_bug20", 1, (test_execution_fn *)user_supplied_bug20 },
4094+ {"user_supplied_bug21", 1, (test_execution_fn *)user_supplied_bug21 },
4095+ {"wrong_failure_counter_test", 1, (test_execution_fn *)wrong_failure_counter_test},
4096+ {0, 0, (test_execution_fn *)0}
4097 };
4098
4099 test_st replication_tests[]= {
4100- {"set", 1, replication_set_test },
4101- {"get", 0, replication_get_test },
4102- {"mget", 0, replication_mget_test },
4103- {"delete", 0, replication_delete_test },
4104- {"rand_mget", 0, replication_randomize_mget_test },
4105- {0, 0, 0}
4106+ {"set", 1, (test_execution_fn *)replication_set_test },
4107+ {"get", 0, (test_execution_fn *)replication_get_test },
4108+ {"mget", 0, (test_execution_fn *)replication_mget_test },
4109+ {"delete", 0, (test_execution_fn *)replication_delete_test },
4110+ {"rand_mget", 0, (test_execution_fn *)replication_randomize_mget_test },
4111+ {0, 0, (test_execution_fn *)0}
4112 };
4113
4114 /*
4115@@ -5561,82 +5525,88 @@
4116 * http://bugs.launchpad.net/libmemcached
4117 */
4118 test_st regression_tests[]= {
4119- {"lp:434484", 1, regression_bug_434484 },
4120- {"lp:434843", 1, regression_bug_434843 },
4121- {"lp:434843 buffered", 1, regression_bug_434843_buffered },
4122- {"lp:421108", 1, regression_bug_421108 },
4123- {"lp:442914", 1, regression_bug_442914 },
4124- {"lp:447342", 1, regression_bug_447342 },
4125- {"lp:463297", 1, regression_bug_463297 },
4126- {0, 0, 0}
4127+ {"lp:434484", 1, (test_execution_fn *)regression_bug_434484 },
4128+ {"lp:434843", 1, (test_execution_fn *)regression_bug_434843 },
4129+ {"lp:434843 buffered", 1, (test_execution_fn *)regression_bug_434843_buffered },
4130+ {"lp:421108", 1, (test_execution_fn *)regression_bug_421108 },
4131+ {"lp:442914", 1, (test_execution_fn *)regression_bug_442914 },
4132+ {"lp:447342", 1, (test_execution_fn *)regression_bug_447342 },
4133+ {"lp:463297", 1, (test_execution_fn *)regression_bug_463297 },
4134+ {0, 0, (test_execution_fn *)0}
4135 };
4136
4137 test_st ketama_compatibility[]= {
4138- {"libmemcached", 1, ketama_compatibility_libmemcached },
4139- {"spymemcached", 1, ketama_compatibility_spymemcached },
4140- {0, 0, 0}
4141+ {"libmemcached", 1, (test_execution_fn *)ketama_compatibility_libmemcached },
4142+ {"spymemcached", 1, (test_execution_fn *)ketama_compatibility_spymemcached },
4143+ {0, 0, (test_execution_fn *)0}
4144 };
4145
4146 test_st generate_tests[] ={
4147- {"generate_pairs", 1, generate_pairs },
4148- {"generate_data", 1, generate_data },
4149- {"get_read", 0, get_read },
4150- {"delete_generate", 0, delete_generate },
4151- {"generate_buffer_data", 1, generate_buffer_data },
4152- {"delete_buffer", 0, delete_buffer_generate},
4153- {"generate_data", 1, generate_data },
4154- {"mget_read", 0, mget_read },
4155- {"mget_read_result", 0, mget_read_result },
4156- {"mget_read_function", 0, mget_read_function },
4157- {"cleanup", 1, cleanup_pairs },
4158- {"generate_large_pairs", 1, generate_large_pairs },
4159- {"generate_data", 1, generate_data },
4160- {"generate_buffer_data", 1, generate_buffer_data },
4161- {"cleanup", 1, cleanup_pairs },
4162- {0, 0, 0}
4163+ {"generate_pairs", 1, (test_execution_fn *)generate_pairs },
4164+ {"generate_data", 1, (test_execution_fn *)generate_data },
4165+ {"get_read", 0, (test_execution_fn *)get_read },
4166+ {"delete_generate", 0, (test_execution_fn *)delete_generate },
4167+ {"generate_buffer_data", 1, (test_execution_fn *)generate_buffer_data },
4168+ {"delete_buffer", 0, (test_execution_fn *)delete_buffer_generate},
4169+ {"generate_data", 1, (test_execution_fn *)generate_data },
4170+ {"mget_read", 0, (test_execution_fn *)mget_read },
4171+ {"mget_read_result", 0, (test_execution_fn *)mget_read_result },
4172+ {"mget_read_function", 0, (test_execution_fn *)mget_read_function },
4173+ {"cleanup", 1, (test_execution_fn *)cleanup_pairs },
4174+ {"generate_large_pairs", 1, (test_execution_fn *)generate_large_pairs },
4175+ {"generate_data", 1, (test_execution_fn *)generate_data },
4176+ {"generate_buffer_data", 1, (test_execution_fn *)generate_buffer_data },
4177+ {"cleanup", 1, (test_execution_fn *)cleanup_pairs },
4178+ {0, 0, (test_execution_fn *)0}
4179 };
4180
4181 test_st consistent_tests[] ={
4182- {"generate_pairs", 1, generate_pairs },
4183- {"generate_data", 1, generate_data },
4184- {"get_read", 0, get_read_count },
4185- {"cleanup", 1, cleanup_pairs },
4186- {0, 0, 0}
4187+ {"generate_pairs", 1, (test_execution_fn *)generate_pairs },
4188+ {"generate_data", 1, (test_execution_fn *)generate_data },
4189+ {"get_read", 0, (test_execution_fn *)get_read_count },
4190+ {"cleanup", 1, (test_execution_fn *)cleanup_pairs },
4191+ {0, 0, (test_execution_fn *)0}
4192 };
4193
4194 test_st consistent_weighted_tests[] ={
4195- {"generate_pairs", 1, generate_pairs },
4196- {"generate_data", 1, generate_data_with_stats },
4197- {"get_read", 0, get_read_count },
4198- {"cleanup", 1, cleanup_pairs },
4199- {0, 0, 0}
4200+ {"generate_pairs", 1, (test_execution_fn *)generate_pairs },
4201+ {"generate_data", 1, (test_execution_fn *)generate_data_with_stats },
4202+ {"get_read", 0, (test_execution_fn *)get_read_count },
4203+ {"cleanup", 1, (test_execution_fn *)cleanup_pairs },
4204+ {0, 0, (test_execution_fn *)0}
4205 };
4206
4207 test_st hsieh_availability[] ={
4208- {"hsieh_avaibility_test",0,hsieh_avaibility_test},
4209- {0, 0, 0}
4210+ {"hsieh_avaibility_test", 0, (test_execution_fn *)hsieh_avaibility_test},
4211+ {0, 0, (test_execution_fn *)0}
4212+};
4213+
4214+test_st hash_sanity[] ={
4215+ {"hash sanity", 0, (test_execution_fn *)hash_sanity_test},
4216+ {0, 0, (test_execution_fn *)0}
4217 };
4218
4219 test_st ketama_auto_eject_hosts[] ={
4220- {"auto_eject_hosts", 1, auto_eject_hosts },
4221- {"output_ketama_weighted_keys", 1, output_ketama_weighted_keys },
4222- {0, 0, 0}
4223+ {"auto_eject_hosts", 1, (test_execution_fn *)auto_eject_hosts },
4224+ {"output_ketama_weighted_keys", 1, (test_execution_fn *)output_ketama_weighted_keys },
4225+ {0, 0, (test_execution_fn *)0}
4226 };
4227
4228 test_st hash_tests[] ={
4229- {"md5", 0, md5_run },
4230- {"crc", 0, crc_run },
4231- {"fnv1_64", 0, fnv1_64_run },
4232- {"fnv1a_64", 0, fnv1a_64_run },
4233- {"fnv1_32", 0, fnv1_32_run },
4234- {"fnv1a_32", 0, fnv1a_32_run },
4235- {"hsieh", 0, hsieh_run },
4236- {"murmur", 0, murmur_run },
4237- {"jenkis", 0, jenkins_run },
4238- {0, 0, 0}
4239+ {"md5", 0, (test_execution_fn *)md5_run },
4240+ {"crc", 0, (test_execution_fn *)crc_run },
4241+ {"fnv1_64", 0, (test_execution_fn *)fnv1_64_run },
4242+ {"fnv1a_64", 0, (test_execution_fn *)fnv1a_64_run },
4243+ {"fnv1_32", 0, (test_execution_fn *)fnv1_32_run },
4244+ {"fnv1a_32", 0, (test_execution_fn *)fnv1a_32_run },
4245+ {"hsieh", 0, (test_execution_fn *)hsieh_run },
4246+ {"murmur", 0, (test_execution_fn *)murmur_run },
4247+ {"jenkis", 0, (test_execution_fn *)jenkins_run },
4248+ {0, 0, (test_execution_fn *)0}
4249 };
4250
4251 collection_st collection[] ={
4252+ {"hash_sanity", 0, 0, hash_sanity},
4253 {"hsieh_availability",0,0,hsieh_availability},
4254 {"udp_setup", init_udp, 0, udp_setup_server_tests},
4255 {"udp_io", init_udp, 0, upd_io_tests},
4256@@ -5725,4 +5695,5 @@
4257 world->collections= collection;
4258 world->create= world_create;
4259 world->destroy= world_destroy;
4260+ world->is_libmemcached= true;
4261 }
4262
4263=== added file 'tests/hash_results.h'
4264--- tests/hash_results.h 1970-01-01 00:00:00 +0000
4265+++ tests/hash_results.h 2009-12-11 17:27:14 +0000
4266@@ -0,0 +1,115 @@
4267+/*
4268+ * Copyright (C) 2006-2009 Brian Aker
4269+ * All rights reserved.
4270+ *
4271+ * Use and distribution licensed under the BSD license. See
4272+ * the COPYING file in the parent directory for full text.
4273+ */
4274+
4275+/**
4276+ @brief We list strings and results for testing different hashing algo in
4277+ this file.
4278+*/
4279+
4280+
4281+static const char *list_to_hash[]=
4282+{
4283+ "apple",
4284+ "beat",
4285+ "carrot",
4286+ "daikon",
4287+ "eggplant",
4288+ "flower",
4289+ "green",
4290+ "hide",
4291+ "ick",
4292+ "jack",
4293+ "kick",
4294+ "lime",
4295+ "mushrooms",
4296+ "nectarine",
4297+ "orange",
4298+ "peach",
4299+ "quant",
4300+ "ripen",
4301+ "strawberry",
4302+ "tang",
4303+ "up",
4304+ "volumne",
4305+ "when",
4306+ "yellow",
4307+ "zip",
4308+ NULL
4309+};
4310+
4311+static uint32_t md5_values[]= { 3195025439U, 2556848621U, 3724893440U, 3332385401U,
4312+ 245758794U, 2550894432U, 121710495U, 3053817768U,
4313+ 1250994555U, 1862072655U, 2631955953U, 2951528551U,
4314+ 1451250070U, 2820856945U, 2060845566U, 3646985608U,
4315+ 2138080750U, 217675895U, 2230934345U, 1234361223U,
4316+ 3968582726U, 2455685270U, 1293568479U, 199067604U,
4317+ 2042482093U };
4318+
4319+static uint32_t crc_values[]= { 10542U, 22009U, 14526U, 19510U, 19432U, 10199U, 20634U,
4320+ 9369U, 11511U, 10362U, 7893U, 31289U, 11313U, 9354U,
4321+ 7621U, 30628U, 15218U, 25967U, 2695U, 9380U,
4322+ 17300U, 28156U, 9192U, 20484U, 16925U };
4323+
4324+static uint32_t fnv1_64_values[]= { 473199127U, 4148981457U, 3971873300U, 3257986707U,
4325+ 1722477987U, 2991193800U, 4147007314U, 3633179701U,
4326+ 1805162104U, 3503289120U, 3395702895U, 3325073042U,
4327+ 2345265314U, 3340346032U, 2722964135U, 1173398992U,
4328+ 2815549194U, 2562818319U, 224996066U, 2680194749U,
4329+ 3035305390U, 246890365U, 2395624193U, 4145193337U,
4330+ 1801941682U };
4331+
4332+static uint32_t fnv1a_64_values[]= { 1488911807U, 2500855813U, 1510099634U, 1390325195U,
4333+ 3647689787U, 3241528582U, 1669328060U, 2604311949U,
4334+ 734810122U, 1516407546U, 560948863U, 1767346780U,
4335+ 561034892U, 4156330026U, 3716417003U, 3475297030U,
4336+ 1518272172U, 227211583U, 3938128828U, 126112909U,
4337+ 3043416448U, 3131561933U, 1328739897U, 2455664041U,
4338+ 2272238452U };
4339+
4340+static uint32_t fnv1_32_values[]= { 67176023U, 1190179409U, 2043204404U, 3221866419U,
4341+ 2567703427U, 3787535528U, 4147287986U, 3500475733U,
4342+ 344481048U, 3865235296U, 2181839183U, 119581266U,
4343+ 510234242U, 4248244304U, 1362796839U, 103389328U,
4344+ 1449620010U, 182962511U, 3554262370U, 3206747549U,
4345+ 1551306158U, 4127558461U, 1889140833U, 2774173721U,
4346+ 1180552018U };
4347+
4348+static uint32_t fnv1a_32_values[]= { 280767167U, 2421315013U, 3072375666U, 855001899U,
4349+ 459261019U, 3521085446U, 18738364U, 1625305005U,
4350+ 2162232970U, 777243802U, 3323728671U, 132336572U,
4351+ 3654473228U, 260679466U, 1169454059U, 2698319462U,
4352+ 1062177260U, 235516991U, 2218399068U, 405302637U,
4353+ 1128467232U, 3579622413U, 2138539289U, 96429129U,
4354+ 2877453236U };
4355+
4356+#ifdef HAVE_HSIEH_HASH
4357+static uint32_t hsieh_values[]= { 3738850110U, 3636226060U, 3821074029U, 3489929160U, 3485772682U, 80540287U,
4358+ 1805464076U, 1895033657U, 409795758U, 979934958U, 3634096985U, 1284445480U,
4359+ 2265380744U, 707972988U, 353823508U, 1549198350U, 1327930172U, 9304163U,
4360+ 4220749037U, 2493964934U, 2777873870U, 2057831732U, 1510213931U, 2027828987U,
4361+ 3395453351U };
4362+#else
4363+static uint32_t hsieh_values[]= { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
4364+#endif
4365+
4366+static uint32_t murmur_values[]= { 4142305122U, 734504955U, 3802834688U, 4076891445U,
4367+ 387802650U, 560515427U, 3274673488U, 3150339524U,
4368+ 1527441970U, 2728642900U, 3613992239U, 2938419259U,
4369+ 2321988328U, 1145154116U, 4038540960U, 2224541613U,
4370+ 264013145U, 3995512858U, 2400956718U, 2346666219U,
4371+ 926327338U, 442757446U, 1770805201U, 560483147U,
4372+ 3902279934U };
4373+
4374+static uint32_t jenkins_values[]= { 1442444624U, 4253821186U, 1885058256U, 2120131735U,
4375+ 3261968576U, 3515188778U, 4232909173U, 4288625128U,
4376+ 1812047395U, 3689182164U, 2502979932U, 1214050606U,
4377+ 2415988847U, 1494268927U, 1025545760U, 3920481083U,
4378+ 4153263658U, 3824871822U, 3072759809U, 798622255U,
4379+ 3065432577U, 1453328165U, 2691550971U, 3408888387U,
4380+ 2629893356U };
4381+
4382
4383=== added file 'tests/hashkit_functions.c'
4384--- tests/hashkit_functions.c 1970-01-01 00:00:00 +0000
4385+++ tests/hashkit_functions.c 2009-12-11 17:27:14 +0000
4386@@ -0,0 +1,363 @@
4387+/* libHashKit Functions Test
4388+ * Copyright (C) 2006-2009 Brian Aker
4389+ * All rights reserved.
4390+ *
4391+ * Use and distribution licensed under the BSD license. See
4392+ * the COPYING file in the parent directory for full text.
4393+ */
4394+
4395+#include <assert.h>
4396+#include <stdio.h>
4397+#include <stdlib.h>
4398+#include <string.h>
4399+
4400+#include <libhashkit/hashkit.h>
4401+
4402+#include "test.h"
4403+
4404+#include "hash_results.h"
4405+
4406+static hashkit_st global_hashk;
4407+
4408+/**
4409+ @brief hash_test_st is a structure we use in testing. It is currently empty.
4410+*/
4411+typedef struct hash_test_st hash_test_st;
4412+
4413+struct hash_test_st
4414+{
4415+ bool _unused;
4416+};
4417+
4418+static test_return_t init_test(void *not_used __attribute__((unused)))
4419+{
4420+ hashkit_st hashk;
4421+ hashkit_st *hashk_ptr;
4422+
4423+ hashk_ptr= hashkit_create(&hashk);
4424+ test_truth(hashk_ptr);
4425+ test_truth(hashk_ptr == &hashk);
4426+ test_truth(hashkit_is_initialized(&hashk) == true);
4427+ test_truth(hashkit_is_allocated(hashk_ptr) == false);
4428+
4429+ hashkit_free(hashk_ptr);
4430+
4431+ test_truth(hashkit_is_initialized(&hashk) == false);
4432+
4433+ return TEST_SUCCESS;
4434+}
4435+
4436+static test_return_t allocation_test(void *not_used __attribute__((unused)))
4437+{
4438+ hashkit_st *hashk_ptr;
4439+
4440+ hashk_ptr= hashkit_create(NULL);
4441+ test_truth(hashk_ptr);
4442+ test_truth(hashkit_is_allocated(hashk_ptr) == true);
4443+ test_truth(hashkit_is_initialized(hashk_ptr) == true);
4444+ hashkit_free(hashk_ptr);
4445+
4446+ return TEST_SUCCESS;
4447+}
4448+
4449+static test_return_t clone_test(hashkit_st *hashk)
4450+{
4451+ // First we make sure that the testing system is giving us what we expect.
4452+ assert(&global_hashk == hashk);
4453+
4454+ // Second we test if hashk is even valid
4455+ test_truth(hashkit_is_initialized(hashk) == true);
4456+
4457+ /* All null? */
4458+ {
4459+ hashkit_st *hashk_ptr;
4460+ hashk_ptr= hashkit_clone(NULL, NULL);
4461+ test_truth(hashk_ptr);
4462+ test_truth(hashkit_is_allocated(hashk_ptr) == true);
4463+ test_truth(hashkit_is_initialized(hashk_ptr) == true);
4464+ hashkit_free(hashk_ptr);
4465+ }
4466+
4467+ /* Can we init from null? */
4468+ {
4469+ hashkit_st *hashk_ptr;
4470+
4471+ hashk_ptr= hashkit_clone(NULL, hashk);
4472+
4473+ test_truth(hashk_ptr);
4474+ test_truth(hashkit_is_allocated(hashk_ptr) == true);
4475+ test_truth(hashkit_is_initialized(hashk_ptr) == true);
4476+
4477+ test_truth(hashk_ptr->distribution == hashk->distribution);
4478+ test_truth(hashk_ptr->continuum_count == hashk->continuum_count);
4479+ test_truth(hashk_ptr->continuum_points_count == hashk->continuum_points_count);
4480+ test_truth(hashk_ptr->list_size == hashk->list_size);
4481+ test_truth(hashk_ptr->context_size == hashk->context_size);
4482+ test_truth(hashk_ptr->continuum == NULL);
4483+ test_truth(hashk_ptr->hash_fn == hashk->hash_fn);
4484+ test_truth(hashk_ptr->active_fn == hashk->active_fn);
4485+ test_truth(hashk_ptr->continuum_hash_fn == hashk->continuum_hash_fn);
4486+ test_truth(hashk_ptr->continuum_key_fn == hashk->continuum_key_fn);
4487+ test_truth(hashk_ptr->sort_fn == hashk->sort_fn);
4488+ test_truth(hashk_ptr->weight_fn == hashk->weight_fn);
4489+ test_truth(hashk_ptr->list == hashk->list);
4490+
4491+ hashkit_free(hashk_ptr);
4492+ }
4493+
4494+ /* Can we init from struct? */
4495+ {
4496+ hashkit_st declared_clone;
4497+ hashkit_st *hash_clone;
4498+
4499+ hash_clone= hashkit_clone(&declared_clone, NULL);
4500+ test_truth(hash_clone);
4501+
4502+ hashkit_free(hash_clone);
4503+ }
4504+
4505+ /* Can we init from struct? */
4506+ {
4507+ hashkit_st declared_clone;
4508+ hashkit_st *hash_clone;
4509+ memset(&declared_clone, 0 , sizeof(hashkit_st));
4510+ hash_clone= hashkit_clone(&declared_clone, hashk);
4511+ test_truth(hash_clone);
4512+ hashkit_free(hash_clone);
4513+ }
4514+
4515+ return TEST_SUCCESS;
4516+}
4517+
4518+
4519+static test_return_t md5_run (hashkit_st *hashk __attribute__((unused)))
4520+{
4521+ uint32_t x;
4522+ const char **ptr;
4523+
4524+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4525+ {
4526+ uint32_t hash_val;
4527+
4528+ hash_val= hashkit_md5(*ptr, strlen(*ptr));
4529+ test_truth(md5_values[x] == hash_val);
4530+ }
4531+
4532+ return TEST_SUCCESS;
4533+}
4534+
4535+static test_return_t crc_run (hashkit_st *hashk __attribute__((unused)))
4536+{
4537+ uint32_t x;
4538+ const char **ptr;
4539+
4540+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4541+ {
4542+ uint32_t hash_val;
4543+
4544+ hash_val= hashkit_crc32(*ptr, strlen(*ptr));
4545+ assert(crc_values[x] == hash_val);
4546+ }
4547+
4548+ return TEST_SUCCESS;
4549+}
4550+
4551+static test_return_t fnv1_64_run (hashkit_st *hashk __attribute__((unused)))
4552+{
4553+ uint32_t x;
4554+ const char **ptr;
4555+
4556+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4557+ {
4558+ uint32_t hash_val;
4559+
4560+ hash_val= hashkit_fnv1_64(*ptr, strlen(*ptr));
4561+ assert(fnv1_64_values[x] == hash_val);
4562+ }
4563+
4564+ return TEST_SUCCESS;
4565+}
4566+
4567+static test_return_t fnv1a_64_run (hashkit_st *hashk __attribute__((unused)))
4568+{
4569+ uint32_t x;
4570+ const char **ptr;
4571+
4572+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4573+ {
4574+ uint32_t hash_val;
4575+
4576+ hash_val= hashkit_fnv1a_64(*ptr, strlen(*ptr));
4577+ assert(fnv1a_64_values[x] == hash_val);
4578+ }
4579+
4580+ return TEST_SUCCESS;
4581+}
4582+
4583+static test_return_t fnv1_32_run (hashkit_st *hashk __attribute__((unused)))
4584+{
4585+ uint32_t x;
4586+ const char **ptr;
4587+
4588+
4589+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4590+ {
4591+ uint32_t hash_val;
4592+
4593+ hash_val= hashkit_fnv1_32(*ptr, strlen(*ptr));
4594+ assert(fnv1_32_values[x] == hash_val);
4595+ }
4596+
4597+ return TEST_SUCCESS;
4598+}
4599+
4600+static test_return_t fnv1a_32_run (hashkit_st *hashk __attribute__((unused)))
4601+{
4602+ uint32_t x;
4603+ const char **ptr;
4604+
4605+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4606+ {
4607+ uint32_t hash_val;
4608+
4609+ hash_val= hashkit_fnv1a_32(*ptr, strlen(*ptr));
4610+ assert(fnv1a_32_values[x] == hash_val);
4611+ }
4612+
4613+ return TEST_SUCCESS;
4614+}
4615+
4616+static test_return_t hsieh_run (hashkit_st *hashk __attribute__((unused)))
4617+{
4618+ uint32_t x;
4619+ const char **ptr;
4620+
4621+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4622+ {
4623+ uint32_t hash_val;
4624+
4625+#ifdef HAVE_HSIEH_HASH
4626+ hash_val= hashkit_hsieh(*ptr, strlen(*ptr));
4627+#else
4628+ hash_val= 1;
4629+#endif
4630+ assert(hsieh_values[x] == hash_val);
4631+ }
4632+
4633+ return TEST_SUCCESS;
4634+}
4635+
4636+static test_return_t murmur_run (hashkit_st *hashk __attribute__((unused)))
4637+{
4638+ uint32_t x;
4639+ const char **ptr;
4640+
4641+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4642+ {
4643+ uint32_t hash_val;
4644+
4645+ hash_val= hashkit_murmur(*ptr, strlen(*ptr));
4646+ assert(murmur_values[x] == hash_val);
4647+ }
4648+
4649+ return TEST_SUCCESS;
4650+}
4651+
4652+static test_return_t jenkins_run (hashkit_st *hashk __attribute__((unused)))
4653+{
4654+ uint32_t x;
4655+ const char **ptr;
4656+
4657+
4658+ for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
4659+ {
4660+ uint32_t hash_val;
4661+
4662+ hash_val= hashkit_jenkins(*ptr, strlen(*ptr));
4663+ assert(jenkins_values[x] == hash_val);
4664+ }
4665+
4666+ return TEST_SUCCESS;
4667+}
4668+
4669+
4670+
4671+
4672+/**
4673+ @brief now we list out the tests.
4674+*/
4675+
4676+test_st allocation[]= {
4677+ {"init", 0, (test_execution_fn *)init_test},
4678+ {"create and free", 0, (test_execution_fn *)allocation_test},
4679+ {"clone", 0, (test_execution_fn *)clone_test},
4680+ {0, 0, 0}
4681+};
4682+
4683+test_st hash_tests[] ={
4684+ {"md5", 0, (test_execution_fn *)md5_run },
4685+ {"crc", 0, (test_execution_fn *)crc_run },
4686+ {"fnv1_64", 0, (test_execution_fn *)fnv1_64_run },
4687+ {"fnv1a_64", 0, (test_execution_fn *)fnv1a_64_run },
4688+ {"fnv1_32", 0, (test_execution_fn *)fnv1_32_run },
4689+ {"fnv1a_32", 0, (test_execution_fn *)fnv1a_32_run },
4690+ {"hsieh", 0, (test_execution_fn *)hsieh_run },
4691+ {"murmur", 0, (test_execution_fn *)murmur_run },
4692+ {"jenkis", 0, (test_execution_fn *)jenkins_run },
4693+ {0, 0, (test_execution_fn *)0}
4694+};
4695+
4696+/*
4697+ * The following test suite is used to verify that we don't introduce
4698+ * regression bugs. If you want more information about the bug / test,
4699+ * you should look in the bug report at
4700+ * http://bugs.launchpad.net/libmemcached
4701+ */
4702+test_st regression[]= {
4703+ {0, 0, 0}
4704+};
4705+
4706+collection_st collection[] ={
4707+ {"allocation", 0, 0, allocation},
4708+ {"regression", 0, 0, regression},
4709+ {"hashing", 0, 0, hash_tests},
4710+ {0, 0, 0, 0}
4711+};
4712+
4713+/* Prototypes for functions we will pass to test framework */
4714+void *world_create(void);
4715+void world_destroy(void *p);
4716+
4717+void *world_create(void)
4718+{
4719+ hashkit_st *hashk_ptr;
4720+
4721+ hashk_ptr= hashkit_create(&global_hashk);
4722+
4723+ assert(hashk_ptr == &global_hashk);
4724+
4725+ // First we test if hashk is even valid
4726+ assert(hashkit_is_initialized(hashk_ptr) == true);
4727+ assert(hashkit_is_allocated(hashk_ptr) == false);
4728+ assert(hashk_ptr->continuum == NULL);
4729+
4730+ return hashk_ptr;
4731+}
4732+
4733+
4734+void world_destroy(void *p)
4735+{
4736+ hashkit_st *hashk= (hashkit_st *)p;
4737+
4738+ // Did we get back what we expected?
4739+ assert(hashkit_is_initialized(hashk) == true);
4740+ assert(hashkit_is_allocated(hashk) == false);
4741+ hashkit_free(&global_hashk);
4742+}
4743+
4744+void get_world(world_st *world)
4745+{
4746+ world->collections= collection;
4747+ world->create= world_create;
4748+ world->destroy= world_destroy;
4749+}
4750
4751=== modified file 'tests/output_plus.res'
4752--- tests/output_plus.res 2009-07-15 22:13:28 +0000
4753+++ tests/output_plus.res 2009-12-11 17:27:14 +0000
4754@@ -1,5 +0,0 @@
4755-servers localhost:11221,
4756- localhost : 11221
4757-
4758-
4759-retvalue 1
4760
4761=== modified file 'tests/plus.cpp'
4762--- tests/plus.cpp 2009-11-19 22:46:49 +0000
4763+++ tests/plus.cpp 2009-12-11 17:27:14 +0000
4764@@ -30,7 +30,7 @@
4765 test_return_t basic_behavior(memcached_st *memc);
4766 test_return_t mget_test(memcached_st *memc);
4767 memcached_return callback_counter(memcached_st *,
4768- memcached_result_st *,
4769+ memcached_result_st *,
4770 void *context);
4771 void *world_create(void);
4772 void world_destroy(void *p);
4773@@ -65,7 +65,7 @@
4774
4775 assert((memcmp(&test_value[0], &value[0], test_value.size()) == 0));
4776
4777- /*
4778+ /*
4779 * Simple test of the exceptions here...this should throw an exception
4780 * saying that the key is empty.
4781 */
4782@@ -109,7 +109,7 @@
4783
4784 int_inc_value= uint64_t(atol(inc_value.c_str()));
4785 int_ret_value= uint64_t(atol(ret_string.c_str()));
4786- assert(int_ret_value == int_inc_value);
4787+ assert(int_ret_value == int_inc_value);
4788
4789 rc= mcach.increment(key, 1, &int_ret_value);
4790 assert(rc == true);
4791@@ -153,7 +153,7 @@
4792
4793 /* Count the results */
4794 memcached_return callback_counter(memcached_st *,
4795- memcached_result_st *,
4796+ memcached_result_st *,
4797 void *context)
4798 {
4799 unsigned int *counter= static_cast<unsigned int *>(context);
4800@@ -199,7 +199,7 @@
4801
4802 callbacks[0]= &callback_counter;
4803 counter= 0;
4804- rc= mc.fetchExecute(callbacks, static_cast<void *>(&counter), 1);
4805+ rc= mc.fetchExecute(callbacks, static_cast<void *>(&counter), 1);
4806
4807 assert(counter == 3);
4808
4809@@ -274,12 +274,18 @@
4810 }
4811
4812 test_st tests[] ={
4813- { "basic", 0, basic_test },
4814- { "basic_master_key", 0, basic_master_key_test },
4815- { "increment_test", 0, increment_test },
4816- { "mget", 1, mget_test },
4817- { "mget_result_function", 1, mget_result_function },
4818- { "basic_behavior", 0, basic_behavior },
4819+ { "basic", 0,
4820+ reinterpret_cast<test_execution_fn *>(basic_test) },
4821+ { "basic_master_key", 0,
4822+ reinterpret_cast<test_execution_fn *>(basic_master_key_test) },
4823+ { "increment_test", 0,
4824+ reinterpret_cast<test_execution_fn *>(increment_test) },
4825+ { "mget", 1,
4826+ reinterpret_cast<test_execution_fn *>(mget_test) },
4827+ { "mget_result_function", 1,
4828+ reinterpret_cast<test_execution_fn *>(mget_result_function) },
4829+ { "basic_behavior", 0,
4830+ reinterpret_cast<test_execution_fn *>(basic_behavior) },
4831 {0, 0, 0}
4832 };
4833
4834
4835=== modified file 'tests/test.c'
4836--- tests/test.c 2009-12-05 12:53:58 +0000
4837+++ tests/test.c 2009-12-11 17:27:14 +0000
4838@@ -1,3 +1,11 @@
4839+/* uTest
4840+ * Copyright (C) 2006-2009 Brian Aker
4841+ * All rights reserved.
4842+ *
4843+ * Use and distribution licensed under the BSD license. See
4844+ * the COPYING file in the parent directory for full text.
4845+ */
4846+
4847 /*
4848 Sample test application.
4849 */
4850@@ -57,7 +65,7 @@
4851 char *collection_to_run= NULL;
4852 char *wildcard= NULL;
4853 server_startup_st *startup_ptr;
4854- memcached_server_st *servers;
4855+ memcached_server_st *servers= NULL;
4856 world_st world;
4857 collection_st *collection;
4858 collection_st *next;
4859@@ -72,8 +80,11 @@
4860 else
4861 world_ptr= NULL;
4862
4863- startup_ptr= (server_startup_st *)world_ptr;
4864- servers= (memcached_server_st *)startup_ptr->servers;
4865+ if (world.is_libmemcached)
4866+ {
4867+ startup_ptr= (server_startup_st *)world_ptr;
4868+ servers= (memcached_server_st *)startup_ptr->servers;
4869+ }
4870
4871 if (argc > 1)
4872 collection_to_run= argv[1];
4873@@ -94,7 +105,7 @@
4874 for (x= 0; run->name; run++)
4875 {
4876 unsigned int loop;
4877- memcached_st *memc;
4878+ memcached_st *memc= NULL;
4879 memcached_return rc;
4880 struct timeval start_time, end_time;
4881 long int load_time;
4882@@ -104,22 +115,31 @@
4883
4884 fprintf(stderr, "Testing %s", run->name);
4885
4886- memc= memcached_create(NULL);
4887- test_truth(memc);
4888+ if (world.is_libmemcached)
4889+ {
4890+ memc= memcached_create(NULL);
4891+ test_truth(memc);
4892
4893- rc= memcached_server_push(memc, servers);
4894- test_truth(rc == MEMCACHED_SUCCESS);
4895+ rc= memcached_server_push(memc, servers);
4896+ test_truth(rc == MEMCACHED_SUCCESS);
4897+ }
4898
4899 if (run->requires_flush)
4900 {
4901- memcached_flush(memc, 0);
4902- memcached_quit(memc);
4903+ if (world.is_libmemcached)
4904+ {
4905+ memcached_flush(memc, 0);
4906+ memcached_quit(memc);
4907+ }
4908 }
4909
4910- for (loop= 0; loop < memcached_server_list_count(servers); loop++)
4911+ if (world.is_libmemcached)
4912 {
4913- test_truth(memc->hosts[loop].fd == -1);
4914- test_truth(memc->hosts[loop].cursor_active == 0);
4915+ for (loop= 0; loop < memcached_server_list_count(servers); loop++)
4916+ {
4917+ test_truth(memc->hosts[loop].fd == -1);
4918+ test_truth(memc->hosts[loop].cursor_active == 0);
4919+ }
4920 }
4921
4922 if (next->pre)
4923@@ -134,7 +154,7 @@
4924 }
4925
4926 gettimeofday(&start_time, NULL);
4927- failed= run->function(memc);
4928+ failed= run->test_fn(world.is_libmemcached ? memc : world_ptr);
4929 gettimeofday(&end_time, NULL);
4930 load_time= timedif(end_time, start_time);
4931
4932@@ -144,9 +164,11 @@
4933 if (next->post)
4934 (void)next->post(memc);
4935
4936- test_truth(memc);
4937+ if (world.is_libmemcached)
4938+ assert(memc);
4939 error:
4940- memcached_free(memc);
4941+ if (world.is_libmemcached)
4942+ memcached_free(memc);
4943 }
4944 }
4945
4946
4947=== modified file 'tests/test.h'
4948--- tests/test.h 2009-12-03 15:22:16 +0000
4949+++ tests/test.h 2009-12-11 17:27:14 +0000
4950@@ -1,6 +1,15 @@
4951+/* uTest
4952+ * Copyright (C) 2006-2009 Brian Aker
4953+ * All rights reserved.
4954+ *
4955+ * Use and distribution licensed under the BSD license. See
4956+ * the COPYING file in the parent directory for full text.
4957+ */
4958+
4959 /*
4960 Structures for generic tests.
4961 */
4962+
4963 #ifdef __cplusplus
4964 extern "C" {
4965 #endif
4966@@ -20,10 +29,12 @@
4967 TEST_MAXIMUM_RETURN /* Always add new error code before */
4968 } test_return_t;
4969
4970+typedef test_return_t (test_execution_fn)(void *context);
4971+
4972 struct test_st {
4973 const char *name;
4974 unsigned int requires_flush;
4975- test_return_t (*function)(memcached_st *memc);
4976+ test_execution_fn *test_fn;
4977 };
4978
4979 struct collection_st {
4980@@ -37,6 +48,7 @@
4981 collection_st *collections;
4982 void *(*create)(void);
4983 void (*destroy)(void *collection_object);
4984+ bool is_libmemcached; // This will eventually go away
4985 };
4986
4987 /* How we make all of this work :) */
4988
4989=== modified file 'tests/udp.c'
4990--- tests/udp.c 2009-11-25 08:21:57 +0000
4991+++ tests/udp.c 2009-12-11 17:27:14 +0000
4992@@ -34,7 +34,7 @@
4993 }
4994
4995 test_st tests[] ={
4996- {"set", 1, set_test },
4997+ {"set", 1, (test_execution_fn *)set_test },
4998 {0, 0, 0}
4999 };
5000

Subscribers

People subscribed via source and target branches

to all changes: