Commits

Atte Kojo committed cd150c3

Added CRC32 hash function.

Comments (0)

Files changed (7)

 
 uninstall: libuninstall
 
-check: all
+check:
 	cd test && make
 
 clean-test:

memcached_hash.ml

 (* Some shortcuts for the Int32 arithmetic-logical functions *)
 let (<<:) = Int32.shift_left
 let (>>:) = Int32.shift_right_logical
+let (&:) = Int32.logand
 let (|:) = Int32.logor
 let (^:) = Int32.logxor
+let (~:) = Int32.lognot
 let ( *:) = Int32.mul
 
+(* Convert a string to a list of integers *)
+let ints_of_string str =
+  let rec loop str i len =
+    if i == len then []
+    else (Int32.of_int (int_of_char str.[i])) :: loop str (i + 1) len
+  in
+    loop str 0 (String.length str)
+
+(* The crc32 functions and data was originally written by Spencer
+ * Garrett <srg@quick.com> and was gleaned from the PostgreSQL source
+ * tree via the files contrib/ltree/crc32.[ch] and from FreeBSD at
+ * src/usr.bin/cksum/crc32.c.
+ *)
+let crc32tab = [|
+  0x00000000l; 0x77073096l; 0xee0e612cl; 0x990951bal;
+  0x076dc419l; 0x706af48fl; 0xe963a535l; 0x9e6495a3l;
+  0x0edb8832l; 0x79dcb8a4l; 0xe0d5e91el; 0x97d2d988l;
+  0x09b64c2bl; 0x7eb17cbdl; 0xe7b82d07l; 0x90bf1d91l;
+  0x1db71064l; 0x6ab020f2l; 0xf3b97148l; 0x84be41del;
+  0x1adad47dl; 0x6ddde4ebl; 0xf4d4b551l; 0x83d385c7l;
+  0x136c9856l; 0x646ba8c0l; 0xfd62f97al; 0x8a65c9ecl;
+  0x14015c4fl; 0x63066cd9l; 0xfa0f3d63l; 0x8d080df5l;
+  0x3b6e20c8l; 0x4c69105el; 0xd56041e4l; 0xa2677172l;
+  0x3c03e4d1l; 0x4b04d447l; 0xd20d85fdl; 0xa50ab56bl;
+  0x35b5a8fal; 0x42b2986cl; 0xdbbbc9d6l; 0xacbcf940l;
+  0x32d86ce3l; 0x45df5c75l; 0xdcd60dcfl; 0xabd13d59l;
+  0x26d930acl; 0x51de003al; 0xc8d75180l; 0xbfd06116l;
+  0x21b4f4b5l; 0x56b3c423l; 0xcfba9599l; 0xb8bda50fl;
+  0x2802b89el; 0x5f058808l; 0xc60cd9b2l; 0xb10be924l;
+  0x2f6f7c87l; 0x58684c11l; 0xc1611dabl; 0xb6662d3dl;
+  0x76dc4190l; 0x01db7106l; 0x98d220bcl; 0xefd5102al;
+  0x71b18589l; 0x06b6b51fl; 0x9fbfe4a5l; 0xe8b8d433l;
+  0x7807c9a2l; 0x0f00f934l; 0x9609a88el; 0xe10e9818l;
+  0x7f6a0dbbl; 0x086d3d2dl; 0x91646c97l; 0xe6635c01l;
+  0x6b6b51f4l; 0x1c6c6162l; 0x856530d8l; 0xf262004el;
+  0x6c0695edl; 0x1b01a57bl; 0x8208f4c1l; 0xf50fc457l;
+  0x65b0d9c6l; 0x12b7e950l; 0x8bbeb8eal; 0xfcb9887cl;
+  0x62dd1ddfl; 0x15da2d49l; 0x8cd37cf3l; 0xfbd44c65l;
+  0x4db26158l; 0x3ab551cel; 0xa3bc0074l; 0xd4bb30e2l;
+  0x4adfa541l; 0x3dd895d7l; 0xa4d1c46dl; 0xd3d6f4fbl;
+  0x4369e96al; 0x346ed9fcl; 0xad678846l; 0xda60b8d0l;
+  0x44042d73l; 0x33031de5l; 0xaa0a4c5fl; 0xdd0d7cc9l;
+  0x5005713cl; 0x270241aal; 0xbe0b1010l; 0xc90c2086l;
+  0x5768b525l; 0x206f85b3l; 0xb966d409l; 0xce61e49fl;
+  0x5edef90el; 0x29d9c998l; 0xb0d09822l; 0xc7d7a8b4l;
+  0x59b33d17l; 0x2eb40d81l; 0xb7bd5c3bl; 0xc0ba6cadl;
+  0xedb88320l; 0x9abfb3b6l; 0x03b6e20cl; 0x74b1d29al;
+  0xead54739l; 0x9dd277afl; 0x04db2615l; 0x73dc1683l;
+  0xe3630b12l; 0x94643b84l; 0x0d6d6a3el; 0x7a6a5aa8l;
+  0xe40ecf0bl; 0x9309ff9dl; 0x0a00ae27l; 0x7d079eb1l;
+  0xf00f9344l; 0x8708a3d2l; 0x1e01f268l; 0x6906c2fel;
+  0xf762575dl; 0x806567cbl; 0x196c3671l; 0x6e6b06e7l;
+  0xfed41b76l; 0x89d32be0l; 0x10da7a5al; 0x67dd4accl;
+  0xf9b9df6fl; 0x8ebeeff9l; 0x17b7be43l; 0x60b08ed5l;
+  0xd6d6a3e8l; 0xa1d1937el; 0x38d8c2c4l; 0x4fdff252l;
+  0xd1bb67f1l; 0xa6bc5767l; 0x3fb506ddl; 0x48b2364bl;
+  0xd80d2bdal; 0xaf0a1b4cl; 0x36034af6l; 0x41047a60l;
+  0xdf60efc3l; 0xa867df55l; 0x316e8eefl; 0x4669be79l;
+  0xcb61b38cl; 0xbc66831al; 0x256fd2a0l; 0x5268e236l;
+  0xcc0c7795l; 0xbb0b4703l; 0x220216b9l; 0x5505262fl;
+  0xc5ba3bbel; 0xb2bd0b28l; 0x2bb45a92l; 0x5cb36a04l;
+  0xc2d7ffa7l; 0xb5d0cf31l; 0x2cd99e8bl; 0x5bdeae1dl;
+  0x9b64c2b0l; 0xec63f226l; 0x756aa39cl; 0x026d930al;
+  0x9c0906a9l; 0xeb0e363fl; 0x72076785l; 0x05005713l;
+  0x95bf4a82l; 0xe2b87a14l; 0x7bb12bael; 0x0cb61b38l;
+  0x92d28e9bl; 0xe5d5be0dl; 0x7cdcefb7l; 0x0bdbdf21l;
+  0x86d3d2d4l; 0xf1d4e242l; 0x68ddb3f8l; 0x1fda836el;
+  0x81be16cdl; 0xf6b9265bl; 0x6fb077e1l; 0x18b74777l;
+  0x88085ae6l; 0xff0f6a70l; 0x66063bcal; 0x11010b5cl;
+  0x8f659effl; 0xf862ae69l; 0x616bffd3l; 0x166ccf45l;
+  0xa00ae278l; 0xd70dd2eel; 0x4e048354l; 0x3903b3c2l;
+  0xa7672661l; 0xd06016f7l; 0x4969474dl; 0x3e6e77dbl;
+  0xaed16a4al; 0xd9d65adcl; 0x40df0b66l; 0x37d83bf0l;
+  0xa9bcae53l; 0xdebb9ec5l; 0x47b2cf7fl; 0x30b5ffe9l;
+  0xbdbdf21cl; 0xcabac28al; 0x53b39330l; 0x24b4a3a6l;
+  0xbad03605l; 0xcdd70693l; 0x54de5729l; 0x23d967bfl;
+  0xb3667a2el; 0xc4614ab8l; 0x5d681b02l; 0x2a6f2b94l;
+  0xb40bbe37l; 0xc30c8ea1l; 0x5a05df1bl; 0x2d02ef8dl
+|]
+
+let crc32 key =
+  let loop crc b =
+    let idx = Int32.to_int ((crc ^: b) &: 0xffl) in
+      (crc >>: 8) ^: crc32tab.(idx)
+  in
+  let crc = List.fold_left loop Int32.minus_one (ints_of_string key) in
+    ((~: crc) >>: 16) &: 0x7fffl
+
 (*
  * "Murmur2" hash provided by Austin Appleby, tanjent@gmail.com
  * http://murmurhash.googlepages.com/
   (* 'm' is a mixing constant generated offline.  It's not really 'magic', it
    * just happens to work well. *)
   let m = 0x5bd1e995l in
-  let ints_of_string str =
-    let rec loop str i len =
-      if i == len then []
-      else (Int32.of_int (int_of_char str.[i])) :: loop str (i + 1) len
-    in
-      loop str 0 (String.length str)
-  in
   let rec go key h =
     match key with
       | [] -> h

memcached_hash.mli

+val crc32: string -> int32
 val murmur: string -> int32
 export OCAMLMAKEFILE = ../OCamlMakefile
 
 PACKS = oUnit
-LIBS = oUnit str ../memcached
+LIBS = oUnit str
 INCDIRS = $(shell ocamlfind query oUnit) ..
-LIBDIRS = ..
-SOURCES = memcached_hash_test.ml memcached_test.ml
+SOURCES = ../memcached_hash.mli ../memcached_hash.ml \
+	  ../memcached.mli ../memcached.ml \
+	  memcached_hash_test.mli memcached_hash_test.ml \
+	  memcached_test.ml
 RESULT = memcached_test
 
 all: nc test

test/data/crc32.txt

+###########################################################################	32476
+{{:http://caml.inria.fr/pub/docs/manual-ocaml/libref/Marshal.html}Marshal}	5339
+href="Memcached.Value.html#TYPEt">t<\/a><\/code><\/pre><\/body><\/html>/;"	21367
+href="Memcached.S.html#TYPEt">t<\/a><\/code><\/pre><pre><span	24200
+href="Memcached.html#TYPEt">t<\/a><\/code><\/pre><pre><span	5370
+href="Memcached.html#TYPEt">t<\/a><\/code><\/pre><br>$/;"	27175
+http://www.ocaml.info/home/ocaml_sources.html	32022
+href="Memcached.S.html#TYPEvalue">value<\/a>	10928
+$(FILTERED_OXRIDL:%.oxridl=$(MLDEPDIR)/%.d)	17518
+$(FILTERED_GLADE:%.glade=$(MLDEPDIR)/%.d)	9309
+dir,$(LIBDIRS),$(CLIBS:%=$(dir)/lib%.a)))	21872
+toupper(substr($$0,1,1))substr($$0,2)}')	28722
+href="Memcached.Value.html#TYPEt">t<\/a>	13079
+$(FILTERED_IDL:%.idl=%_stubs.$(EXT_OBJ))	5557
+dir,$(LIBDIRS),$(CLIBS:%=$(dir)/%.lib)))	17919
+doc/memcached/html/Memcached.Value.html	2070
+name="2_Functorialinterface"><\/a>$/;"	26824
+list<\/code><\/pre><\/body><\/html>/;"	12902
+doc/memcached/html/Memcached.Make.html	4484
+$(FILTERED_ZOG:%.zog=$(MLDEPDIR)/%.d)	31481
+$(FILTERED_REP:%.rep=$(MLDEPDIR)/%.d)	29325
+$(FILTERED_MLY:%.mly=$(MLDEPDIR)/%.d)	13700
+$(FILTERED_MLL:%.mll=$(MLDEPDIR)/%.d)	26773
+$(FILTERED_IDL:%.idl=$(MLDEPDIR)/%.d)	10566
+$(DOC_DIR)/$(RESULT)/html/index.html:	24923
+$(OBJ_C_CXX:.$(EXT_CXX)=.$(EXT_OBJ))	17785
+name="VALdisconnect"><\/a>disconnect	30288
+libhashkit_murmur(String_val(data),	3761
+href="Memcached.S.html#TYPEt">t<\/a>	29969
+$(DOC_DIR)/$(RESULT)/html/index.html	23155
+name="2_Genericinterface"><\/a>$/;"	65
+{{:http://memcached.org/}memcached}	28722
+$(FILTERED_ML:%.ml=$(MLDEPDIR)/%.d)	17175
+doc/memcached/html/Memcached.S.html	19042
+$(DOC_DIR)/$(RESULT)/latex/doc.tex:	21106
+$(DOC_DIR)/$(RESULT)/latex/doc.pdf:	2195
+$(OCAML_DEFAULT_DIRS:%=-LIBPATH:%)	9623
+name="VALto_string"><\/a>to_string	12891
+name="VALof_string"><\/a>of_string	4440
+href="Memcached.html#TYPEt">t<\/a>	4853
+$(EXTLIBDIRS:%=-Wl,$(RPATH_FLAG)%)	19743
+$(DOC_DIR)/$(RESULT)/latex/doc.tex	28705
+$(DOC_DIR)/$(RESULT)/latex/doc.ps:	29538
+$(DOC_DIR)/$(RESULT)/latex/doc.pdf	5180
+doc/memcached/html/Memcached.html	3117
+$(DOC_DIR)/$(RESULT)/latex/doc.ps	21523
+$(FILTERED_C_CXX:.c=.$(EXT_OBJ))	31036
+/dhiebert@users.sourceforge.net/	18244
+-Wl,--allow-multiple-definition	27139
+string<\/code><\/pre><pre><span	29343
+option<\/code><\/pre><pre><span	27675
+$(MLIDEPS:%.di=$(NCDIDIR)/%.di)	3893
+$(MLIDEPS:%.di=$(BCDIDIR)/%.di)	9664
+$(FILTERED_OXRIDL:.oxridl=.mli)	7099
+$(FILTERED_IDL:%.idl=%_stubs.c)	32392
+serialization/de-serialization	21255
+profiling-native-code-library:	26362
+'$(OCAMLLIBPATH)/ocamlrun.lib'	22743
+name="VALreplace"><\/a>replace	5863
+name="VALconnect"><\/a>connect	25060
+$(FILTERED_OXRIDL:.oxridl=.ml)	9804
+$(FILTERED_OXRIDL:.oxridl=.di)	21738
+profiling-native-code-library	5745
+$(OCAML_DEFAULT_DIRS:%=-ccopt	9416
+$(IMPLO_INTF:%.mli.cmi=%.cmi)	23071
+bool<\/code><\/pre><pre><span	22512
+"--warn-undefined-variables"	22710
+profiling-byte-code-library:	27930
+$(PRE_OCAML_FIND_PREDICATES)	11858
+'$(OCAMLLIBPATH)/ocamlrun.a'	11621
+name="VALdelete"><\/a>delete	20523
+name="VALcreate"><\/a>create	21979
+$(IMPL_CMO:.cmo=.$(EXT_OBJ))	6585
+http://ctags.sourceforge.net	28364
+$(FILTERED_GLADE:.glade=.ml)	10531
+class="keyword">type<\/span>	2175
+$(space),$(comma),$(PREDS))	31727
+$(space),$(comma),$(PACKS))	10638
+$(SOURCE_DIRS:%=-LIBPATH:%)	30640
+profiling-byte-code-library	11527
+$(OCAML_DEFAULT_DIRS:%=-L%)	10104
+$(OCAML_DEFAULT_DIRS:%=-I%)	8627
+$(OBJ_C_CXX:.m=.$(EXT_OBJ))	9058
+name="TYPEvalue"><\/a><code	26313
+$(LIB_PACK_NAME).$(EXT_OBJ)	14483
+$(DOC_DIR)/$(RESULT)/latex:	7183
+class="keyword">val<\/span>	27071
+caml_string_length(data));	16749
+subproj,$(SUBPROJS),$(eval	14664
+serializing/de-serializing	285
+$(PRE_OCAML_FIND_PACKAGES)	3862
+name="VALstats"><\/a>stats	27369
+make_subproj,$(subproj))))	32419
+lib$(CLIB_BASE).$(EXT_LIB)	8107
+int<\/code><\/pre><br>$/;"	14371
+$(EXTLIBDIRS:%=-LIBPATH:%)	29658
+$(DOC_DIR)/$(RESULT)/latex	2504
+$(DOC_DIR)/$(RESULT)/html:	16744
+debug-native-code-library:	15385
+class="type"><\/code>value	12990
+$(CFRAMEWORKS:%=-framework	10109
+REAL_RESULT="$(NCRESULT)"	26673
+REAL_RESULT="$(BCRESULT)"	29197
+REAL_OCAMLC="$(OCAMLOPT)"	18985
+PRE_OCAML_FIND_PREDICATES	30817
+option<\/code><\/pre><div	10523
+$(OCAML_DEFAULT_DIRS:%=-I	12811
+hostname).h_addr_list.(0)	10198
+$(FILTERED_MLY:.mly=.mli)	12579
+$(FILTERED_IDL:.idl=.mli)	24024
+$(DOC_DIR)/$(RESULT)/html	1788
+debug-native-code-nolink:	5033
+debug-native-code-library	5582
+*************************	20729
+-Wl,--export-all-symbols	20503
+-Wl,--enable-auto-import	30617
+test_replace_nonexistent	29958
+$(RESULT)$(RES_CLIB_SUF)	16124
+PostScript-documentation	23272
+$(OCAML_FIND_PREDICATES)	30719
+name="VALincr"><\/a>incr	30455
+name="VALhash"><\/a>hash	20464
+name="VALdecr"><\/a>decr	15358
+Module:Continuum/ConnKey	15971
+Memcached.Make(Ints)$/;"	27869
+$(FILTERED_ZOG:.zog=.ml)	2097
+$(FILTERED_REP:.rep=.ml)	22158
+$(FILTERED_MLY:.mly=.ml)	13329
+$(FILTERED_MLY:.mly=.di)	18103
+$(FILTERED_MLL:.mll=.ml)	14507
+$(FILTERED_MLI:.mli=.di)	27543
+$(FILTERED_IDL:.idl=.ml)	18875
+$(FILTERED_IDL:.idl=.di)	15133
+debug-native-code-nolink	19036
+Continuum.connection_for	32023
+class="type">+'a<\/code>	1459
+$(CAMELEON_REPORT_FLAGS)	26723
+test_delete_nonexistent	32367
+$(SUBPROJS:%=subproj_%)	24013
+PRE_OCAML_FIND_PACKAGES	201
+$(OCAMLLIBPATH)/contrib	17895
+$(OCAML_LIB_INSTALL)\n"	27452
+$(OCAML_DEP_PREDICATES)	23778
+name="TYPEt"><\/a><code	11303
+list<\/code><\/pre><div	14010
+libinstall-native-code:	15337
+<libhashkit/hashkit.h>	10270
+$(LIBDIRS:%=-LIBPATH:%)	20849
+$(IMPLO_INTF:.cmo=.cmx)	19288
+$(IMPL_CMO:.cmo=.annot)	2496
+$(FILTERED_IDL:.idl=.h)	17195
+.$(EXT_CXX).$(EXT_OBJ):	28693
+$(CAMELEON_ZOGGY_FLAGS)	6117
+bool<\/code><\/pre><div	10442
+$(ALLML:%.mli=%.mli.__)	30719
+/usr/local/lib/camlp4)	4851
+test_spaces_in_key_set	12387
+test/memcached_test.ml	10195
+$(SOURCE_DIRS:%=-ccopt	19802
+profiling-native-code:	32410
+Pervasives.compare$/;"	25379
+$(OCAMLMLIB_EXISTS)),)	18095
+$(OCAML_GLADECC_FLAGS)	16946
+$(OCAML_FIND_PACKAGES)	5629
+$(OCAMLFIND_INSTFLAGS)	23390
+$(NCRESULT).$(EXT_OBJ)	16426
+$(NCRESULT).$(EXT_LIB)	5651
+name="VALset"><\/a>set	20942
+name="VALget"><\/a>get	15967
+name="VALadd"><\/a>add	11208
+Memcached.Make(Ints)]}	19122
+libinstall-native-code	27990
+class="type"><\/code>t	28220
+$(CFRAMEWORKS:%=-cclib	26507
+$(BCRESULT).$(EXT_LIB)	17701
+/usr/local/lib/ocaml)	28123
+!_TAG_PROGRAM_VERSION	16531
+$(SPECIAL_OCAMLFLAGS)	1061
+$(RESULT).$(EXT_LIB):	12372
+profiling-native-code	16808
+..\/OCamlMakefile$/;"	2268
+$(OCAML_LIB_INSTALL);	8597
+OCAML_FIND_PREDICATES	4826
+$(OCAML_FIND_LINKPKG)	28533
+$(OCAML_DEP_PACKAGES)	15010
+memcached_test.ml$/;"	9350
+Memcached_impl(struct	9875
+Map.Make(ConnKey)$/;"	10658
+$(LIB_PACK_NAME).cmx:	24670
+$(LIB_PACK_NAME).cmo:	26077
+libinstall-byte-code:	209
+$(IMPL_CMO:.cmo=.cmx)	18393
+$(IMPL_CMO:.cmo=.asm)	19677
+$(EXTLIBDIRS:%=-ccopt	2351
+CAMELEON_REPORT_FLAGS	21680
+<atte.kojo@gmail.com>	7140
+2_Functorialinterface	15877
+test_removing_server	22392
+test_get_nonexistent	10819
+!_TAG_PROGRAM_AUTHOR	15786
+$(SOURCE_DIRS:%=-L%)	22126
+$(SOURCE_DIRS:%=-I%)	20645
+$(RESULT).$(EXT_LIB)	28289
+profiling-byte-code:	17054
+$(OCAML_LIB_INSTALL)	19307
+OCAML_DEP_PREDICATES	31472
+native-code-library:	11484
+$(LIB_PACK_NAME).cmx	24895
+$(LIB_PACK_NAME).cmo	25324
+$(LIB_PACK_NAME).cmi	2959
+$(LIBINSTALL_FILES))	2950
+$(LIBINSTALL_FILES);	30783
+libinstall-byte-code	15233
+$(DOC_DIR)/$(RESULT)	2745
+connection.input$/;"	29605
+connection_finalizer	3134
+CAMLreturn(result);	19294
+CAMLlocal1(result);	17037
+caml_copy_int32(h);	11745
+CAMELEON_ZOGGY_FLAGS	7364
+####################	6181
+-Wl,--whole-archive	15147
+-Wl,$(RPATH_FLAG)%)	11991
+shutdown_connection	24467
+-short-functors$/;"	22889
+$(REAL_RESULT).dll:	13255
+profiling-byte-code	18036
+$(OCAMLMKLIB_FLAGS)	13209
+OCAML_GLADECC_FLAGS	29582
+OCAML_FIND_PACKAGES	12627
+OCAMLFIND_INSTFLAGS	29574
+native-code-nolink:	3212
+native-code-library	2795
+$(MAYBE_IDL_HEADER)	19810
+Marshal.from_string	28592
+$(LIBINSTALL_FILES)	14327
+Latex-documentation	25630
+-I'$(OCAMLLIBPATH)'	18939
+$(IMPL_CMO:.cmo=.s)	3599
+ignore(really_input	21367
+$(FIRST_DOC_FILE)`;	4923
+$(EXTLIBDIRS:%=-L%)	17617
+dll$(CLIB_BASE).dll	9770
+debug-code-library:	1090
+class="type">string	7631
+test_empty_key_set	29271
+test_empty_key_get	27000
+!_TAG_PROGRAM_NAME	16543
+SPECIAL_OCAMLFLAGS	1906
+$(SOURCE_DIRS:%=-I	4159
+Pervasives.compare	3879
+OCaml-installation	14649
+OCAML_FIND_LINKPKG	15507
+OCAML_DEP_PACKAGES	28225
+OCAML_DEFAULT_DIRS	15028
+-NODEFAULTLIB:LIBC	24913
+native-code-nolink	13578
+memcached_test$/;"	19018
+[Memcached.replace	24956
+memcached_native.c	31852
+{!Memcached.Make}.	13052
+$(LIBDIRS:%=-ccopt	31385
+$(LDFLAGS:%=-ccopt	7317
+HTML-documentation	24029
+$(FILTERED_IDL)),)	11482
+($(ELF_RPATH),yes)	6530
+dll$(CLIB_BASE).so	1494
+debug-native-code:	24860
+debug-code-nolink:	4267
+debug-code-library	5836
+CAMLparam1(data);	31967
+<caml/mlvalues.h>	26070
+$(CAMLIDLDLLFLAGS)	11493
+$(CAMELEON_REPORT)	24422
+byte-code-library:	32430
+$(ALL_OCAMLCFLAGS)	10906
+(ADDR_INET(h_addr,	17513
+2_Genericinterface	24798
+test_add_existing	11448
+!_TAG_PROGRAM_URL	18916
+!_TAG_FILE_SORTED	1720
+!_TAG_FILE_FORMAT	16271
+($(SYSTEM),win32)	14992
+($(SYSTEM),mingw)	32358
+string_of_int$/;"	27868
+$(REAL_OCAMLFIND)	138
+$(REAL_IMPL_INTF)	27250
+PDF-documentation	6025
+pack-native-code:	9681
+OCamlMakefile$/;"	21134
+OCAML_LIB_INSTALL	30330
+"\nUninstallation	17300
+$*.mli.temporary;	29560
+{!Memcached.Make}	20030
+[Memcached.delete	1559
+..\/memcached$/;"	30154
+Marshal.to_string	7122
+Map.Make(ConnKey)	21903
+language-agnostic	26351
+int_of_string$/;"	5759
+ignore(input_line	19957
+hash_murmur(value	1177
+$(ELF_RPATH_FLAG)	12291
+.DELETE_ON_ERROR:	8044
+debug-native-code	7581
+debug-code-nolink	6960
+$(CPPFLAGS_WIN32)	30096
+(ConnMap.is_empty	25082
+$(COMMON_LDFLAGS)	4011
+class="type">unit	13958
+class="info">$/;"	15039
+c.continuum.(idx)	13471
+$(CAMELEON_ZOGGY)	17458
+byte-code-nolink:	5831
+byte-code-library	4256
+-----------------	23113
+(Value.of_string	558
+\\t\\r\\n]+"$/;"	9396
+test_set_and_get	10023
+test_empty_value	13991
+pack-native-code	12781
+-out:$(RES_CLIB)	1843
+out_channel;$/;"	27670
+$(OCAMLNLDFLAGS)	21618
+OCAMLMLIB_EXISTS	8764
+OCAMLMKLIB_FLAGS	25882
+$(OCAMLMAKEFILE)	6639
+OCAMLLDFLAGS="-g	22920
+$(OCAMLLDFLAGS)"	7091
+$(OCAML_GLADECC)	28304
+$(OCAMLDOCFLAGS)	2676
+$(OCAMLBLDFLAGS)	12870
+NONINFRINGEMENT.	29427
+new_connections;	20519
+$(NCRESULT).cmxa	15376
+$(NCDIDIR)/%.di:	22113
+native-code-dll:	11318
+Module:Continuum	17885
+$*.ml.temporary;	22932
+$*.mli.temporary	11164
+$(MLDEPDIR)/%.d:	5269
+MERCHANTABILITY,	11594
+[Memcached.stats	20897
+memcached.ml$/;"	23818
+"memcached.cmxa"	11942
+MAYBE_IDL_HEADER	19123
+$(LIBS:%=%.cmxa)	32413
+$(LIB_PACK_NAME)	4381
+LIBINSTALL_FILES	13755
+$(LIBDIRS:%=-L%)	26012
+interoperability	27365
+$(INCDIRS:%=-I%)	290
+ignore(read_line	14570
+$(FOR_PACK_NAME)	28631
+$(FILTER_EXTNS),	26231
+.DELETE_ON_ERROR	14729
+Continuum.remove	20627
+connection.input	24220
+$(CLIBS:%=-cclib	23195
+$(CLIB_BASE).lib	7022
+$(CLIB_BASE).exp	13535
+$(CFRAMEWORKS))"	3145
+<caml/memory.h>	17002
+byte-code-nolink	9397
+Value.to_string	27824
+Value.of_string	23914
+type:connection	5495
+test_pool_store	27738
+test_no_servers	2733
+start_memcached	26295
+-short-functors	9753
+$(RESULT).cmxa,	22891
+$(REAL_RESULT):	5902
+$(QUIET)pp=`sed	18109
+$(QUIET)$(MAKE)	10039
+$(PIC_CPPFLAGS)	22549
+pack-byte-code:	2199
+open_connection	22670
+ocamlyacc-flags	24036
+$(OCAMLNCFLAGS)	15068
+'OcamlMakefile'	19818
+$(OCAMLLDFLAGS)	15710
+$(OCAMLCPFLAGS)	30703
+$(OCAMLBCFLAGS)	28019
+"\nUninstalling	10910
+"\nInstallation	28965
+new_connections	11769
+$(NCRESULT).exp	17646
+$(NCRESULT).dll	32643
+$(NCRESULT).cmx	30989
+$(NCRESULT).cmi	5053
+$(NCRESULT).cma	7526
+native-code-dll	1530
+$*.ml.temporary	19856
+[Memcached.incr	1417
+[Memcached.decr	31670
+"memcached.cma"	3173
+$(LIBS:%=%.cma)	16584
+in_channel;$/;"	21959
+/,$(i)),$(i))))	12754
+-I$(CAMLP4PATH)	30738
+hash_murmur$/;"	16071
+FILTERED_OXRIDL	15771
+Continuum.t$/;"	4464
+Continuum.empty	18004
+.cmxa,$(foreach	17015
+class="type">'a	15207
+class="type"><a	4689
+$(CFLAGS_WIN32)	23535
+c.continuum.(0)	19563
+$(CAMLIDLFLAGS)	1178
+CAMLIDLDLLFLAGS	29004
+CAMELEON_REPORT	19447
+$(BCRESULT).exp	24148
+$(BCRESULT).dll	25913
+$(BCRESULT).cmo	24676
+$(BCRESULT).cmi	2311
+$(BCRESULT).cma	2012
+$(BCDIDIR)/%.di	18257
+archive(native)	3776
+ALL_OCAMLCFLAGS	23839
+$(ALL_LDFLAGS))	11014
+adding/removing	5902
+?wait_time:int	1619
+%$(TOPSUFFIX):	525
+$(THREAD_FLAG)	13332
+test_underflow	19607
+successful.\n"	20149
+"$(SUBTARGET)"	4242
+(String.concat	18911
+"SERVER_ERROR"	31003
+$(RESULT).cmxa	12930
+$(RESULT).cma:	21819
+$(RESULT).cma,	8687
+representation	10709
+REAL_OCAMLFIND	15368
+$(REAL_OCAMLC)	2445
+REAL_IMPL_INTF	29730
+$(QUIET)printf	23567
+$(PRE_TARGETS)	10497
+pack-byte-code	4287
+$(OCAMLMKLIB))	3954
+"OCamlMakefile	11974
+OCAMLFLAGS="-g	25105
+$(OCAMLFLAGS)"	521
+$(OBJ_LINK)),)	8283
+["NOT_STORED"]	12931
+$(NOIDLHEADER)	2805
+.ml.$(EXT_OBJ)	15584
+.m.$(EXT_OBJ):	10537
+Memcached_test	6841
+[Memcached.set	4702
+Memcached_impl	3736
+[Memcached.get	2417
+[Memcached.add	2384
+List.fold_left	26507
+library-paths,	23284
+$(LDFLAGS:%=%)	250
+-l$(CLIB_BASE)	28012
+(int_of_string	3800
+$(INTF_OCAMLC)	911
+$(INCDIRS:%=-I	17519
+$(IMPLO_INTF))	402
+$(IMPLO_INTF),	29176
+implementation	17118
+i,$(LIBS),$(if	24540
+(gethostbyname	6023
+FIRST_DOC_FILE	18821
+FILTERED_GLADE	32746
+FILTERED_C_CXX	20019
+$(FILTERED))))	32494
+ELF_RPATH_FLAG	26109
+($(ELF_RPATH),	20804
+CREATE_LIB=yes	4967
+CPPFLAGS_WIN32	19498
+Continuum.find	3002
+ConnMap.t;$/;"	9854
+ConnMap.remove	19693
+ConnMap.empty;	23301
+connection_for	29611
+communications	11311
+COMMON_LDFLAGS	7544
+-colorize-code	22056
+.cma,$(foreach	14775
+"CLIENT_ERROR"	21953
+$(CLIBS:%=-l%)	1492
+.c.$(EXT_OBJ):	21455
+c.connections)	28312
+CAMELEON_ZOGGY	26103
+byte-code-dll:	13692
+$(AUTO_OXRIDL)	27727
+$(ALL_LDFLAGS)	15834
+$(TOPSUFFIX),	25041
+test/Makefile	385
+$(SUBTARGET);	1596
+subproj_$(1):	14838
+string_of_int	10246
+String.length	30326
+String.create	30941
+start_servers	16207

test/data/genhash.c

 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <libhashkit/hashkit.h>
 
-int main(void)
+typedef struct {
+    char *name;
+    uint32_t (*hashfunc)(const char *key, size_t key_length);
+} hashdesc_t;
+
+static hashdesc_t hashfuncs[] = {
+    { "crc32", libhashkit_crc32 },
+    { "murmur", libhashkit_murmur },
+};
+#define NHASHES (sizeof(hashfuncs) / sizeof(hashdesc_t))
+
+static void usage(void)
 {
+    int i;
+
+    printf("Usage: genhash <hashname>\n");
+    printf("Available hash functions:\n");
+    for (i = 0; i < NHASHES; i++)
+        printf("\t%s\n", hashfuncs[i].name);
+}
+
+int main(int argc, char *argv[])
+{
+    int i;
     char buf[BUFSIZ];
+    uint32_t (*hash)(const char *key, size_t key_length);
+
+    if (argc != 2) {
+        usage();
+        exit(1);
+    }
+
+    for (i = 0; i < NHASHES; i++)
+        if (!strcmp(hashfuncs[i].name, argv[1])) {
+            hash = hashfuncs[i].hashfunc;
+            break;
+        }
+
+    if (i == NHASHES) {
+        usage();
+        exit(2);
+    }
 
     while (fgets(buf, BUFSIZ, stdin) != NULL) {
         buf[strlen(buf) - 1] = '\0';
-        uint32_t hash = libhashkit_murmur(buf, strlen(buf));
-        printf("%s\t%d\n", buf, hash);
+        uint32_t h = hash(buf, strlen(buf));
+        printf("%s\t%d\n", buf, h);
     }
     return 0;
 }

test/memcached_hash_test.ml

 
 let (|>) x f = f x
 
-(* Tests for the polymorphic interface *)
-
-let setup () =
-  let input = open_in "data/murmur.txt" in
+(* Read a given hash test file. A test file contains pairs of hash key, hash
+ * value pairs; one pair per line, separated by a tab. *)
+let read_test_values hashname =
+  let input = open_in ("data/" ^ hashname ^ ".txt") in
   let read_next input =
     try
       let line = split (regexp "\t") (input_line input) in
   in
     read_all input
 
-let teardown hashes = ()
-
-let test_murmur hashes =
+(* Apply hashfunc to each key in the list of hashes and ensure that it matches
+ * the hash value *)
+let test_hash hashfunc hashes =
   let test_hash hash =
     let key = fst hash in
     let actual = snd hash in
-    let res = Memcached_hash.murmur key in
-    let err_str = sprintf "hash key: %s, should be %ld, was %ld" key actual res
+    let res = hashfunc key in
+    let err_str = sprintf "key '%s', should be %ld, was %ld" key actual res
     in
     assert_equal ~msg:err_str actual res
   in
   List.iter test_hash hashes
 
+(* Tests start here *)
+
+let test_crc32 () =
+  let hashes = read_test_values "crc32" in
+    test_hash Memcached_hash.crc32 hashes
+
+let test_murmur () =
+  let hashes = read_test_values "murmur" in
+    test_hash Memcached_hash.murmur hashes
+
 let test_hash = "" >::: [
-  "Murmur2 hash" >:: (bracket setup test_murmur teardown)
+  "CRC32" >:: test_crc32;
+  "Murmur2 hash" >:: test_murmur;
 ]