Commits

Atte Kojo committed a550575

Replaced murmur2 C code with OCaml. Added tests for libhashkit compatibility.

  • Participants
  • Parent commits 0b49f23

Comments (0)

Files changed (14)

-Copyright (c) 2010 Atte Kojo <atte.kojo@gmail.com>
+Copyright (c) 2010-2011 Atte Kojo <atte.kojo@gmail.com>
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 
 ANNOTATE = 1
 LIBS = unix str
-SOURCES = memcached_native.c memcached.mli memcached.ml
+SOURCES = memcached_hash.mli memcached_hash.ml \
+	  memcached.mli memcached.ml
 RESULT = memcached
 
 all: bcl ncl

File memcached.ml

 (*
- * Copyright (c) 2010 Atte Kojo <atte.kojo@gmail.com>
+ * Copyright (c) 2010-2011 Atte Kojo <atte.kojo@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 open Printf
 open Str
 
-external mm_hash2 : string -> int = "mm_hash2"
-
-let hash = mm_hash2
+let hash = Memcached_hash.murmur
 
 let ws = regexp "[ \t\r\n]+"
 
     type 'a t = {
         nservers: int;
         connections: 'a ConnMap.t;
-        continuum: (int * 'a) array;
+        continuum: (int32 * 'a) array;
     }
 
     (* Internal functions *)
             match count with
             | 0 -> []
             | n ->
-                    let hash = mm_hash2 (str ^ string_of_int count) in
-                    hash :: gen_hashes str (count - 1) in
+                    let h = hash (str ^ string_of_int count) in
+                    h :: gen_hashes str (count - 1) in
         let gen_conns (name, port) conn =
             let host = name ^ string_of_int port in
             List.map (fun n -> (n, conn)) (gen_hashes host nservers) in
                  * instead of calculating the hash *)
                 snd c.continuum.(0)
             else
-                let hash = mm_hash2 key in
                 let cmp v h2 = compare v (fst h2) in
-                let idx = search cmp hash c.continuum in
+                let idx = search cmp (hash key) c.continuum in
                 snd c.continuum.(idx)
 
     let find host c =

File memcached.mli

 (*
- * Copyright (c) 2010 Atte Kojo <atte.kojo@gmail.com>
+ * Copyright (c) 2010-2011 Atte Kojo <atte.kojo@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  for details of the statistics returned. *)
 val stats: 'v t -> (string * int) -> (string * string) list
 
-val hash: string -> int
+val hash: string -> int32
 
 (** {2 Functorial interface} *)
 

File memcached_hash.ml

+(*
+ * Copyright (c) 2011 Atte Kojo <atte.kojo@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *)
+
+(*
+ * This file contains hashing algorithms compatible with the algorithms in
+ * libhashkit from libmemcached. They are mostly translations from the original
+ * libhashkit C code to OCaml code. I've kept the credits where the original C
+ * code has been credited.
+ *
+ * Because I wanted to retain compatibility with the original algorithms, even
+ * on 32-bit machines, all algorithms use the OCaml int32 datatype for the
+ * calculations and are thus slower than hashing algorithms that would use
+ * unboxed integers.
+ *
+ *  - Atte
+ *)
+
+(* Some shortcuts for the Int32 arithmetic-logical functions *)
+let (<<:) = Int32.shift_left
+let (>>:) = Int32.shift_right_logical
+let (|:) = Int32.logor
+let (^:) = Int32.logxor
+let ( *:) = Int32.mul
+
+(*
+ * "Murmur2" hash provided by Austin Appleby, tanjent@gmail.com
+ * http://murmurhash.googlepages.com/
+ *
+ * Code comments are taken from the original murmur hash C source.
+ *
+ * C-to-OCaml conversion by originally by redditor notfancy
+ * http://www.reddit.com/user/notfancy
+ *)
+let murmur key =
+  (* '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
+      | b0 :: [] -> (h ^: b0) *: m
+      | b0 :: b1 :: [] ->
+          let h = h ^: (b1 <<: 8) in
+            (h ^: b0) *: m
+      | b0 :: b1 :: b2 :: [] ->
+          let h = h ^: (b2 <<: 16) in
+          let h = h ^: (b1 <<: 8) in
+            (h ^: b0) *: m
+      | b0 :: b1 :: b2 :: b3 :: rest ->
+          let k = b0 |: (b1 <<: 8) |: (b2 <<: 16) |: (b3 <<: 24) in
+          let k = k *: m in
+          let k = k ^: (k >>: 24) in
+          let k = k *: m in
+          let h = h *: m in
+          let h = h ^: k in
+            go rest h
+  in
+  let len = Int32.of_int (String.length key) in
+  let seed = 0xdeadbeefl *: len in
+  (* Initialize the hash to a 'random' value *)
+  let h = seed ^: len in
+  (* Calculate the hash *)
+  let h = go (ints_of_string key) h in
+  (* Do a few final mixes of the hash to ensure the last few bytes are
+   * well-incorporated. *)
+  let h = h ^: (h >>: 13) in
+  let h = h *: m in
+  h ^: (h >>: 15)

File memcached_hash.mli

+val murmur: string -> int32

File memcached_native.c

-//-----------------------------------------------------------------------------
-// MurmurHash2, by Austin Appleby
-//
-// From the murmurhash www page:
-//
-// All code is released to the public domain. For business purposes, Murmurhash
-// is under the MIT license.
-// 
-
-// Note - This code makes a few assumptions about how your machine behaves -
-
-// 1. We can read a 4-byte value from any address without crashing
-// 2. sizeof(int) == 4
-
-// And it has a few limitations -
-
-// 1. It will not work incrementally.
-// 2. It will not produce the same results on little-endian and big-endian
-//    machines.
-
-#include <caml/mlvalues.h>
-#include <caml/memory.h>
-#include <stdio.h>
-
-static unsigned int Murmurhash2(const void *key, int len, unsigned int seed)
-{
-    // 'm' and 'r' are mixing constants generated offline.
-    // They're not really 'magic', they just happen to work well.
-    const unsigned int m = 0x5bd1e995;
-    const int r = 24;
-
-    // Initialize the hash to a 'random' value
-    unsigned int h = seed ^ len;
-
-    // Mix 4 bytes at a time into the hash
-    const unsigned char * data = (const unsigned char *)key;
-
-    while (len >= 4) {
-        unsigned int k = *(unsigned int *)data;
-
-        k *= m; 
-        k ^= k >> r; 
-        k *= m; 
-
-        h *= m; 
-        h ^= k;
-
-        data += 4;
-        len -= 4;
-    }
-
-    // Do a few final mixes of the hash to ensure the last few
-    // bytes are well-incorporated.
-    h ^= h >> 13;
-    h *= m;
-    h ^= h >> 15;
-
-    return h;
-} 
-
-value mm_hash2(value data)
-{
-    CAMLparam1(data);
-    int len = caml_string_length(data);
-    unsigned int h = Murmurhash2(String_val(data), len, 0);
-    CAMLreturn(Long_val(h));
-}

File test/Makefile

 export OCAMLMAKEFILE = ../OCamlMakefile
 
 PACKS = oUnit
-LIBS = oUnit str unix ../memcached
+LIBS = oUnit str ../memcached
 INCDIRS = $(shell ocamlfind query oUnit) ..
 LIBDIRS = ..
-SOURCES = memcached_test.ml
+SOURCES = memcached_hash_test.ml memcached_test.ml
 RESULT = memcached_test
 
-all: dc test
+all: nc test
 
 test:
 	./memcached_test

File test/data/genhash.c

+#include <stdio.h>
+#include <string.h>
+#include <libhashkit/hashkit.h>
+
+int main(void)
+{
+    char buf[BUFSIZ];
+
+    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);
+    }
+    return 0;
+}

File test/data/keys.txt

+###########################################################################
+{{:http://caml.inria.fr/pub/docs/manual-ocaml/libref/Marshal.html}Marshal}
+href="Memcached.Value.html#TYPEt">t<\/a><\/code><\/pre><\/body><\/html>/;"
+href="Memcached.S.html#TYPEt">t<\/a><\/code><\/pre><pre><span
+href="Memcached.html#TYPEt">t<\/a><\/code><\/pre><pre><span
+href="Memcached.html#TYPEt">t<\/a><\/code><\/pre><br>$/;"
+http://www.ocaml.info/home/ocaml_sources.html
+href="Memcached.S.html#TYPEvalue">value<\/a>
+$(FILTERED_OXRIDL:%.oxridl=$(MLDEPDIR)/%.d)
+$(FILTERED_GLADE:%.glade=$(MLDEPDIR)/%.d)
+dir,$(LIBDIRS),$(CLIBS:%=$(dir)/lib%.a)))
+toupper(substr($$0,1,1))substr($$0,2)}')
+href="Memcached.Value.html#TYPEt">t<\/a>
+$(FILTERED_IDL:%.idl=%_stubs.$(EXT_OBJ))
+dir,$(LIBDIRS),$(CLIBS:%=$(dir)/%.lib)))
+doc/memcached/html/Memcached.Value.html
+name="2_Functorialinterface"><\/a>$/;"
+list<\/code><\/pre><\/body><\/html>/;"
+doc/memcached/html/Memcached.Make.html
+$(FILTERED_ZOG:%.zog=$(MLDEPDIR)/%.d)
+$(FILTERED_REP:%.rep=$(MLDEPDIR)/%.d)
+$(FILTERED_MLY:%.mly=$(MLDEPDIR)/%.d)
+$(FILTERED_MLL:%.mll=$(MLDEPDIR)/%.d)
+$(FILTERED_IDL:%.idl=$(MLDEPDIR)/%.d)
+$(DOC_DIR)/$(RESULT)/html/index.html:
+$(OBJ_C_CXX:.$(EXT_CXX)=.$(EXT_OBJ))
+name="VALdisconnect"><\/a>disconnect
+libhashkit_murmur(String_val(data),
+href="Memcached.S.html#TYPEt">t<\/a>
+$(DOC_DIR)/$(RESULT)/html/index.html
+name="2_Genericinterface"><\/a>$/;"
+{{:http://memcached.org/}memcached}
+$(FILTERED_ML:%.ml=$(MLDEPDIR)/%.d)
+doc/memcached/html/Memcached.S.html
+$(DOC_DIR)/$(RESULT)/latex/doc.tex:
+$(DOC_DIR)/$(RESULT)/latex/doc.pdf:
+$(OCAML_DEFAULT_DIRS:%=-LIBPATH:%)
+name="VALto_string"><\/a>to_string
+name="VALof_string"><\/a>of_string
+href="Memcached.html#TYPEt">t<\/a>
+$(EXTLIBDIRS:%=-Wl,$(RPATH_FLAG)%)
+$(DOC_DIR)/$(RESULT)/latex/doc.tex
+$(DOC_DIR)/$(RESULT)/latex/doc.ps:
+$(DOC_DIR)/$(RESULT)/latex/doc.pdf
+doc/memcached/html/Memcached.html
+$(DOC_DIR)/$(RESULT)/latex/doc.ps
+$(FILTERED_C_CXX:.c=.$(EXT_OBJ))
+/dhiebert@users.sourceforge.net/
+-Wl,--allow-multiple-definition
+string<\/code><\/pre><pre><span
+option<\/code><\/pre><pre><span
+$(MLIDEPS:%.di=$(NCDIDIR)/%.di)
+$(MLIDEPS:%.di=$(BCDIDIR)/%.di)
+$(FILTERED_OXRIDL:.oxridl=.mli)
+$(FILTERED_IDL:%.idl=%_stubs.c)
+serialization/de-serialization
+profiling-native-code-library:
+'$(OCAMLLIBPATH)/ocamlrun.lib'
+name="VALreplace"><\/a>replace
+name="VALconnect"><\/a>connect
+$(FILTERED_OXRIDL:.oxridl=.ml)
+$(FILTERED_OXRIDL:.oxridl=.di)
+profiling-native-code-library
+$(OCAML_DEFAULT_DIRS:%=-ccopt
+$(IMPLO_INTF:%.mli.cmi=%.cmi)
+bool<\/code><\/pre><pre><span
+"--warn-undefined-variables"
+profiling-byte-code-library:
+$(PRE_OCAML_FIND_PREDICATES)
+'$(OCAMLLIBPATH)/ocamlrun.a'
+name="VALdelete"><\/a>delete
+name="VALcreate"><\/a>create
+$(IMPL_CMO:.cmo=.$(EXT_OBJ))
+http://ctags.sourceforge.net
+$(FILTERED_GLADE:.glade=.ml)
+class="keyword">type<\/span>
+$(space),$(comma),$(PREDS))
+$(space),$(comma),$(PACKS))
+$(SOURCE_DIRS:%=-LIBPATH:%)
+profiling-byte-code-library
+$(OCAML_DEFAULT_DIRS:%=-L%)
+$(OCAML_DEFAULT_DIRS:%=-I%)
+$(OBJ_C_CXX:.m=.$(EXT_OBJ))
+name="TYPEvalue"><\/a><code
+$(LIB_PACK_NAME).$(EXT_OBJ)
+$(DOC_DIR)/$(RESULT)/latex:
+class="keyword">val<\/span>
+caml_string_length(data));
+subproj,$(SUBPROJS),$(eval
+serializing/de-serializing
+$(PRE_OCAML_FIND_PACKAGES)
+name="VALstats"><\/a>stats
+make_subproj,$(subproj))))
+lib$(CLIB_BASE).$(EXT_LIB)
+int<\/code><\/pre><br>$/;"
+$(EXTLIBDIRS:%=-LIBPATH:%)
+$(DOC_DIR)/$(RESULT)/latex
+$(DOC_DIR)/$(RESULT)/html:
+debug-native-code-library:
+class="type"><\/code>value
+$(CFRAMEWORKS:%=-framework
+REAL_RESULT="$(NCRESULT)"
+REAL_RESULT="$(BCRESULT)"
+REAL_OCAMLC="$(OCAMLOPT)"
+PRE_OCAML_FIND_PREDICATES
+option<\/code><\/pre><div
+$(OCAML_DEFAULT_DIRS:%=-I
+hostname).h_addr_list.(0)
+$(FILTERED_MLY:.mly=.mli)
+$(FILTERED_IDL:.idl=.mli)
+$(DOC_DIR)/$(RESULT)/html
+debug-native-code-nolink:
+debug-native-code-library
+*************************
+-Wl,--export-all-symbols
+-Wl,--enable-auto-import
+test_replace_nonexistent
+$(RESULT)$(RES_CLIB_SUF)
+PostScript-documentation
+$(OCAML_FIND_PREDICATES)
+name="VALincr"><\/a>incr
+name="VALhash"><\/a>hash
+name="VALdecr"><\/a>decr
+Module:Continuum/ConnKey
+Memcached.Make(Ints)$/;"
+$(FILTERED_ZOG:.zog=.ml)
+$(FILTERED_REP:.rep=.ml)
+$(FILTERED_MLY:.mly=.ml)
+$(FILTERED_MLY:.mly=.di)
+$(FILTERED_MLL:.mll=.ml)
+$(FILTERED_MLI:.mli=.di)
+$(FILTERED_IDL:.idl=.ml)
+$(FILTERED_IDL:.idl=.di)
+debug-native-code-nolink
+Continuum.connection_for
+class="type">+'a<\/code>
+$(CAMELEON_REPORT_FLAGS)
+test_delete_nonexistent
+$(SUBPROJS:%=subproj_%)
+PRE_OCAML_FIND_PACKAGES
+$(OCAMLLIBPATH)/contrib
+$(OCAML_LIB_INSTALL)\n"
+$(OCAML_DEP_PREDICATES)
+name="TYPEt"><\/a><code
+list<\/code><\/pre><div
+libinstall-native-code:
+<libhashkit/hashkit.h>
+$(LIBDIRS:%=-LIBPATH:%)
+$(IMPLO_INTF:.cmo=.cmx)
+$(IMPL_CMO:.cmo=.annot)
+$(FILTERED_IDL:.idl=.h)
+.$(EXT_CXX).$(EXT_OBJ):
+$(CAMELEON_ZOGGY_FLAGS)
+bool<\/code><\/pre><div
+$(ALLML:%.mli=%.mli.__)
+/usr/local/lib/camlp4)
+test_spaces_in_key_set
+test/memcached_test.ml
+$(SOURCE_DIRS:%=-ccopt
+profiling-native-code:
+Pervasives.compare$/;"
+$(OCAMLMLIB_EXISTS)),)
+$(OCAML_GLADECC_FLAGS)
+$(OCAML_FIND_PACKAGES)
+$(OCAMLFIND_INSTFLAGS)
+$(NCRESULT).$(EXT_OBJ)
+$(NCRESULT).$(EXT_LIB)
+name="VALset"><\/a>set
+name="VALget"><\/a>get
+name="VALadd"><\/a>add
+Memcached.Make(Ints)]}
+libinstall-native-code
+class="type"><\/code>t
+$(CFRAMEWORKS:%=-cclib
+$(BCRESULT).$(EXT_LIB)
+/usr/local/lib/ocaml)
+!_TAG_PROGRAM_VERSION
+$(SPECIAL_OCAMLFLAGS)
+$(RESULT).$(EXT_LIB):
+profiling-native-code
+..\/OCamlMakefile$/;"
+$(OCAML_LIB_INSTALL);
+OCAML_FIND_PREDICATES
+$(OCAML_FIND_LINKPKG)
+$(OCAML_DEP_PACKAGES)
+memcached_test.ml$/;"
+Memcached_impl(struct
+Map.Make(ConnKey)$/;"
+$(LIB_PACK_NAME).cmx:
+$(LIB_PACK_NAME).cmo:
+libinstall-byte-code:
+$(IMPL_CMO:.cmo=.cmx)
+$(IMPL_CMO:.cmo=.asm)
+$(EXTLIBDIRS:%=-ccopt
+CAMELEON_REPORT_FLAGS
+<atte.kojo@gmail.com>
+2_Functorialinterface
+test_removing_server
+test_get_nonexistent
+!_TAG_PROGRAM_AUTHOR
+$(SOURCE_DIRS:%=-L%)
+$(SOURCE_DIRS:%=-I%)
+$(RESULT).$(EXT_LIB)
+profiling-byte-code:
+$(OCAML_LIB_INSTALL)
+OCAML_DEP_PREDICATES
+native-code-library:
+$(LIB_PACK_NAME).cmx
+$(LIB_PACK_NAME).cmo
+$(LIB_PACK_NAME).cmi
+$(LIBINSTALL_FILES))
+$(LIBINSTALL_FILES);
+libinstall-byte-code
+$(DOC_DIR)/$(RESULT)
+connection.input$/;"
+connection_finalizer
+CAMLreturn(result);
+CAMLlocal1(result);
+caml_copy_int32(h);
+CAMELEON_ZOGGY_FLAGS
+####################
+-Wl,--whole-archive
+-Wl,$(RPATH_FLAG)%)
+shutdown_connection
+-short-functors$/;"
+$(REAL_RESULT).dll:
+profiling-byte-code
+$(OCAMLMKLIB_FLAGS)
+OCAML_GLADECC_FLAGS
+OCAML_FIND_PACKAGES
+OCAMLFIND_INSTFLAGS
+native-code-nolink:
+native-code-library
+$(MAYBE_IDL_HEADER)
+Marshal.from_string
+$(LIBINSTALL_FILES)
+Latex-documentation
+-I'$(OCAMLLIBPATH)'
+$(IMPL_CMO:.cmo=.s)
+ignore(really_input
+$(FIRST_DOC_FILE)`;
+$(EXTLIBDIRS:%=-L%)
+dll$(CLIB_BASE).dll
+debug-code-library:
+class="type">string
+test_empty_key_set
+test_empty_key_get
+!_TAG_PROGRAM_NAME
+SPECIAL_OCAMLFLAGS
+$(SOURCE_DIRS:%=-I
+Pervasives.compare
+OCaml-installation
+OCAML_FIND_LINKPKG
+OCAML_DEP_PACKAGES
+OCAML_DEFAULT_DIRS
+-NODEFAULTLIB:LIBC
+native-code-nolink
+memcached_test$/;"
+[Memcached.replace
+memcached_native.c
+{!Memcached.Make}.
+$(LIBDIRS:%=-ccopt
+$(LDFLAGS:%=-ccopt
+HTML-documentation
+$(FILTERED_IDL)),)
+($(ELF_RPATH),yes)
+dll$(CLIB_BASE).so
+debug-native-code:
+debug-code-nolink:
+debug-code-library
+CAMLparam1(data);
+<caml/mlvalues.h>
+$(CAMLIDLDLLFLAGS)
+$(CAMELEON_REPORT)
+byte-code-library:
+$(ALL_OCAMLCFLAGS)
+(ADDR_INET(h_addr,
+2_Genericinterface
+test_add_existing
+!_TAG_PROGRAM_URL
+!_TAG_FILE_SORTED
+!_TAG_FILE_FORMAT
+($(SYSTEM),win32)
+($(SYSTEM),mingw)
+string_of_int$/;"
+$(REAL_OCAMLFIND)
+$(REAL_IMPL_INTF)
+PDF-documentation
+pack-native-code:
+OCamlMakefile$/;"
+OCAML_LIB_INSTALL
+"\nUninstallation
+$*.mli.temporary;
+{!Memcached.Make}
+[Memcached.delete
+..\/memcached$/;"
+Marshal.to_string
+Map.Make(ConnKey)
+language-agnostic
+int_of_string$/;"
+ignore(input_line
+hash_murmur(value
+$(ELF_RPATH_FLAG)
+.DELETE_ON_ERROR:
+debug-native-code
+debug-code-nolink
+$(CPPFLAGS_WIN32)
+(ConnMap.is_empty
+$(COMMON_LDFLAGS)
+class="type">unit
+class="info">$/;"
+c.continuum.(idx)
+$(CAMELEON_ZOGGY)
+byte-code-nolink:
+byte-code-library
+-----------------
+(Value.of_string
+\\t\\r\\n]+"$/;"
+test_set_and_get
+test_empty_value
+pack-native-code
+-out:$(RES_CLIB)
+out_channel;$/;"
+$(OCAMLNLDFLAGS)
+OCAMLMLIB_EXISTS
+OCAMLMKLIB_FLAGS
+$(OCAMLMAKEFILE)
+OCAMLLDFLAGS="-g
+$(OCAMLLDFLAGS)"
+$(OCAML_GLADECC)
+$(OCAMLDOCFLAGS)
+$(OCAMLBLDFLAGS)
+NONINFRINGEMENT.
+new_connections;
+$(NCRESULT).cmxa
+$(NCDIDIR)/%.di:
+native-code-dll:
+Module:Continuum
+$*.ml.temporary;
+$*.mli.temporary
+$(MLDEPDIR)/%.d:
+MERCHANTABILITY,
+[Memcached.stats
+memcached.ml$/;"
+"memcached.cmxa"
+MAYBE_IDL_HEADER
+$(LIBS:%=%.cmxa)
+$(LIB_PACK_NAME)
+LIBINSTALL_FILES
+$(LIBDIRS:%=-L%)
+interoperability
+$(INCDIRS:%=-I%)
+ignore(read_line
+$(FOR_PACK_NAME)
+$(FILTER_EXTNS),
+.DELETE_ON_ERROR
+Continuum.remove
+connection.input
+$(CLIBS:%=-cclib
+$(CLIB_BASE).lib
+$(CLIB_BASE).exp
+$(CFRAMEWORKS))"
+<caml/memory.h>
+byte-code-nolink
+Value.to_string
+Value.of_string
+type:connection
+test_pool_store
+test_no_servers
+start_memcached
+-short-functors
+$(RESULT).cmxa,
+$(REAL_RESULT):
+$(QUIET)pp=`sed
+$(QUIET)$(MAKE)
+$(PIC_CPPFLAGS)
+pack-byte-code:
+open_connection
+ocamlyacc-flags
+$(OCAMLNCFLAGS)
+'OcamlMakefile'
+$(OCAMLLDFLAGS)
+$(OCAMLCPFLAGS)
+$(OCAMLBCFLAGS)
+"\nUninstalling
+"\nInstallation
+new_connections
+$(NCRESULT).exp
+$(NCRESULT).dll
+$(NCRESULT).cmx
+$(NCRESULT).cmi
+$(NCRESULT).cma
+native-code-dll
+$*.ml.temporary
+[Memcached.incr
+[Memcached.decr
+"memcached.cma"
+$(LIBS:%=%.cma)
+in_channel;$/;"
+/,$(i)),$(i))))
+-I$(CAMLP4PATH)
+hash_murmur$/;"
+FILTERED_OXRIDL
+Continuum.t$/;"
+Continuum.empty
+.cmxa,$(foreach
+class="type">'a
+class="type"><a
+$(CFLAGS_WIN32)
+c.continuum.(0)
+$(CAMLIDLFLAGS)
+CAMLIDLDLLFLAGS
+CAMELEON_REPORT
+$(BCRESULT).exp
+$(BCRESULT).dll
+$(BCRESULT).cmo
+$(BCRESULT).cmi
+$(BCRESULT).cma
+$(BCDIDIR)/%.di
+archive(native)
+ALL_OCAMLCFLAGS
+$(ALL_LDFLAGS))
+adding/removing
+?wait_time:int
+%$(TOPSUFFIX):
+$(THREAD_FLAG)
+test_underflow
+successful.\n"
+"$(SUBTARGET)"
+(String.concat
+"SERVER_ERROR"
+$(RESULT).cmxa
+$(RESULT).cma:
+$(RESULT).cma,
+representation
+REAL_OCAMLFIND
+$(REAL_OCAMLC)
+REAL_IMPL_INTF
+$(QUIET)printf
+$(PRE_TARGETS)
+pack-byte-code
+$(OCAMLMKLIB))
+"OCamlMakefile
+OCAMLFLAGS="-g
+$(OCAMLFLAGS)"
+$(OBJ_LINK)),)
+["NOT_STORED"]
+$(NOIDLHEADER)
+.ml.$(EXT_OBJ)
+.m.$(EXT_OBJ):
+Memcached_test
+[Memcached.set
+Memcached_impl
+[Memcached.get
+[Memcached.add
+List.fold_left
+library-paths,
+$(LDFLAGS:%=%)
+-l$(CLIB_BASE)
+(int_of_string
+$(INTF_OCAMLC)
+$(INCDIRS:%=-I
+$(IMPLO_INTF))
+$(IMPLO_INTF),
+implementation
+i,$(LIBS),$(if
+(gethostbyname
+FIRST_DOC_FILE
+FILTERED_GLADE
+FILTERED_C_CXX
+$(FILTERED))))
+ELF_RPATH_FLAG
+($(ELF_RPATH),
+CREATE_LIB=yes
+CPPFLAGS_WIN32
+Continuum.find
+ConnMap.t;$/;"
+ConnMap.remove
+ConnMap.empty;
+connection_for
+communications
+COMMON_LDFLAGS
+-colorize-code
+.cma,$(foreach
+"CLIENT_ERROR"
+$(CLIBS:%=-l%)
+.c.$(EXT_OBJ):
+c.connections)
+CAMELEON_ZOGGY
+byte-code-dll:
+$(AUTO_OXRIDL)
+$(ALL_LDFLAGS)
+$(TOPSUFFIX),
+test/Makefile
+$(SUBTARGET);
+subproj_$(1):
+string_of_int
+String.length
+String.create
+start_servers

File test/data/murmur.txt

+###########################################################################	1020306811
+{{:http://caml.inria.fr/pub/docs/manual-ocaml/libref/Marshal.html}Marshal}	1640110403
+href="Memcached.Value.html#TYPEt">t<\/a><\/code><\/pre><\/body><\/html>/;"	-705314357
+href="Memcached.S.html#TYPEt">t<\/a><\/code><\/pre><pre><span	-515717670
+href="Memcached.html#TYPEt">t<\/a><\/code><\/pre><pre><span	-2078833260
+href="Memcached.html#TYPEt">t<\/a><\/code><\/pre><br>$/;"	-1210061106
+http://www.ocaml.info/home/ocaml_sources.html	1965861424
+href="Memcached.S.html#TYPEvalue">value<\/a>	-2100356866
+$(FILTERED_OXRIDL:%.oxridl=$(MLDEPDIR)/%.d)	264155290
+$(FILTERED_GLADE:%.glade=$(MLDEPDIR)/%.d)	731666306
+dir,$(LIBDIRS),$(CLIBS:%=$(dir)/lib%.a)))	1100245263
+toupper(substr($$0,1,1))substr($$0,2)}')	-1177096232
+href="Memcached.Value.html#TYPEt">t<\/a>	-1180899948
+$(FILTERED_IDL:%.idl=%_stubs.$(EXT_OBJ))	643735455
+dir,$(LIBDIRS),$(CLIBS:%=$(dir)/%.lib)))	1519600466
+doc/memcached/html/Memcached.Value.html	1217676698
+name="2_Functorialinterface"><\/a>$/;"	1883991889
+list<\/code><\/pre><\/body><\/html>/;"	2093809156
+doc/memcached/html/Memcached.Make.html	841258590
+$(FILTERED_ZOG:%.zog=$(MLDEPDIR)/%.d)	-540859574
+$(FILTERED_REP:%.rep=$(MLDEPDIR)/%.d)	97029477
+$(FILTERED_MLY:%.mly=$(MLDEPDIR)/%.d)	1653997050
+$(FILTERED_MLL:%.mll=$(MLDEPDIR)/%.d)	-2090647681
+$(FILTERED_IDL:%.idl=$(MLDEPDIR)/%.d)	1292828259
+$(DOC_DIR)/$(RESULT)/html/index.html:	-1242356011
+$(OBJ_C_CXX:.$(EXT_CXX)=.$(EXT_OBJ))	-1121163715
+name="VALdisconnect"><\/a>disconnect	-1892337842
+libhashkit_murmur(String_val(data),	2080556344
+href="Memcached.S.html#TYPEt">t<\/a>	97002319
+$(DOC_DIR)/$(RESULT)/html/index.html	794932043
+name="2_Genericinterface"><\/a>$/;"	1657813734
+{{:http://memcached.org/}memcached}	-119961755
+$(FILTERED_ML:%.ml=$(MLDEPDIR)/%.d)	831129965
+doc/memcached/html/Memcached.S.html	-128019989
+$(DOC_DIR)/$(RESULT)/latex/doc.tex:	1334224671
+$(DOC_DIR)/$(RESULT)/latex/doc.pdf:	1684431939
+$(OCAML_DEFAULT_DIRS:%=-LIBPATH:%)	-949586508
+name="VALto_string"><\/a>to_string	-918254390
+name="VALof_string"><\/a>of_string	1152395270
+href="Memcached.html#TYPEt">t<\/a>	117445922
+$(EXTLIBDIRS:%=-Wl,$(RPATH_FLAG)%)	-81877795
+$(DOC_DIR)/$(RESULT)/latex/doc.tex	1890770983
+$(DOC_DIR)/$(RESULT)/latex/doc.ps:	1959861881
+$(DOC_DIR)/$(RESULT)/latex/doc.pdf	-850519622
+doc/memcached/html/Memcached.html	-878353217
+$(DOC_DIR)/$(RESULT)/latex/doc.ps	-455249792
+$(FILTERED_C_CXX:.c=.$(EXT_OBJ))	-787116726
+/dhiebert@users.sourceforge.net/	1632248546
+-Wl,--allow-multiple-definition	1075137203
+string<\/code><\/pre><pre><span	1617856337
+option<\/code><\/pre><pre><span	-16587857
+$(MLIDEPS:%.di=$(NCDIDIR)/%.di)	2042201745
+$(MLIDEPS:%.di=$(BCDIDIR)/%.di)	-1712233560
+$(FILTERED_OXRIDL:.oxridl=.mli)	1080024804
+$(FILTERED_IDL:%.idl=%_stubs.c)	498667458
+serialization/de-serialization	1273713939
+profiling-native-code-library:	63266961
+'$(OCAMLLIBPATH)/ocamlrun.lib'	679004762
+name="VALreplace"><\/a>replace	1966356367
+name="VALconnect"><\/a>connect	1788539994
+$(FILTERED_OXRIDL:.oxridl=.ml)	1142421491
+$(FILTERED_OXRIDL:.oxridl=.di)	-694288175
+profiling-native-code-library	-1286578230
+$(OCAML_DEFAULT_DIRS:%=-ccopt	-1816825250
+$(IMPLO_INTF:%.mli.cmi=%.cmi)	-1076605946
+bool<\/code><\/pre><pre><span	307444302
+"--warn-undefined-variables"	-432882131
+profiling-byte-code-library:	-179148394
+$(PRE_OCAML_FIND_PREDICATES)	179342175
+'$(OCAMLLIBPATH)/ocamlrun.a'	1744839793
+name="VALdelete"><\/a>delete	-1997168923
+name="VALcreate"><\/a>create	-1727450010
+$(IMPL_CMO:.cmo=.$(EXT_OBJ))	-180544403
+http://ctags.sourceforge.net	183626672
+$(FILTERED_GLADE:.glade=.ml)	-656533623
+class="keyword">type<\/span>	-1642951954
+$(space),$(comma),$(PREDS))	-187076229
+$(space),$(comma),$(PACKS))	949805689
+$(SOURCE_DIRS:%=-LIBPATH:%)	-2118431659
+profiling-byte-code-library	-1051108547
+$(OCAML_DEFAULT_DIRS:%=-L%)	19263375
+$(OCAML_DEFAULT_DIRS:%=-I%)	138607382
+$(OBJ_C_CXX:.m=.$(EXT_OBJ))	-1908116898
+name="TYPEvalue"><\/a><code	762226799
+$(LIB_PACK_NAME).$(EXT_OBJ)	1542433202
+$(DOC_DIR)/$(RESULT)/latex:	-999616513
+class="keyword">val<\/span>	-67241601
+caml_string_length(data));	1743093826
+subproj,$(SUBPROJS),$(eval	1762871420
+serializing/de-serializing	1662347631
+$(PRE_OCAML_FIND_PACKAGES)	1720390544
+name="VALstats"><\/a>stats	-1947814592
+make_subproj,$(subproj))))	864581235
+lib$(CLIB_BASE).$(EXT_LIB)	1583787198
+int<\/code><\/pre><br>$/;"	-1771972545
+$(EXTLIBDIRS:%=-LIBPATH:%)	1091240412
+$(DOC_DIR)/$(RESULT)/latex	-911270766
+$(DOC_DIR)/$(RESULT)/html:	-1891406903
+debug-native-code-library:	472781356
+class="type"><\/code>value	-1414627429
+$(CFRAMEWORKS:%=-framework	1865922946
+REAL_RESULT="$(NCRESULT)"	473465866
+REAL_RESULT="$(BCRESULT)"	-1858475360
+REAL_OCAMLC="$(OCAMLOPT)"	-1952673139
+PRE_OCAML_FIND_PREDICATES	-429439021
+option<\/code><\/pre><div	1824443717
+$(OCAML_DEFAULT_DIRS:%=-I	-2028109382
+hostname).h_addr_list.(0)	726530635
+$(FILTERED_MLY:.mly=.mli)	-814253089
+$(FILTERED_IDL:.idl=.mli)	-1865126597
+$(DOC_DIR)/$(RESULT)/html	752075659
+debug-native-code-nolink:	870269385
+debug-native-code-library	407186504
+*************************	1058697849
+-Wl,--export-all-symbols	821597922
+-Wl,--enable-auto-import	1909501287
+test_replace_nonexistent	1009024885
+$(RESULT)$(RES_CLIB_SUF)	-1986872429
+PostScript-documentation	633089070
+$(OCAML_FIND_PREDICATES)	345010667
+name="VALincr"><\/a>incr	-900466393
+name="VALhash"><\/a>hash	-1188157369
+name="VALdecr"><\/a>decr	-1018216896
+Module:Continuum/ConnKey	2095988134
+Memcached.Make(Ints)$/;"	480369349
+$(FILTERED_ZOG:.zog=.ml)	-2105828973
+$(FILTERED_REP:.rep=.ml)	-661584046
+$(FILTERED_MLY:.mly=.ml)	1180853094
+$(FILTERED_MLY:.mly=.di)	51164594
+$(FILTERED_MLL:.mll=.ml)	-690570525
+$(FILTERED_MLI:.mli=.di)	1962038180
+$(FILTERED_IDL:.idl=.ml)	-1616826423
+$(FILTERED_IDL:.idl=.di)	667973233
+debug-native-code-nolink	1549600084
+Continuum.connection_for	-230503142
+class="type">+'a<\/code>	-1600314724
+$(CAMELEON_REPORT_FLAGS)	-1973536391
+test_delete_nonexistent	-1465129426
+$(SUBPROJS:%=subproj_%)	1605206028
+PRE_OCAML_FIND_PACKAGES	191369043
+$(OCAMLLIBPATH)/contrib	-1663589449
+$(OCAML_LIB_INSTALL)\n"	-1269433535
+$(OCAML_DEP_PREDICATES)	-498164905
+name="TYPEt"><\/a><code	-1367911616
+list<\/code><\/pre><div	1032515810
+libinstall-native-code:	-1881624358
+<libhashkit/hashkit.h>	-912745932
+$(LIBDIRS:%=-LIBPATH:%)	500049608
+$(IMPLO_INTF:.cmo=.cmx)	851636363
+$(IMPL_CMO:.cmo=.annot)	-1234404954
+$(FILTERED_IDL:.idl=.h)	2017251222
+.$(EXT_CXX).$(EXT_OBJ):	-1103993103
+$(CAMELEON_ZOGGY_FLAGS)	-1206782973
+bool<\/code><\/pre><div	764183031
+$(ALLML:%.mli=%.mli.__)	-1784723472
+/usr/local/lib/camlp4)	-1844855303
+test_spaces_in_key_set	-1156817548
+test/memcached_test.ml	-1256052636
+$(SOURCE_DIRS:%=-ccopt	1812322566
+profiling-native-code:	-432716225
+Pervasives.compare$/;"	-1423463026
+$(OCAMLMLIB_EXISTS)),)	1308751594
+$(OCAML_GLADECC_FLAGS)	644880460
+$(OCAML_FIND_PACKAGES)	370288926
+$(OCAMLFIND_INSTFLAGS)	-1820450606
+$(NCRESULT).$(EXT_OBJ)	-1745594923
+$(NCRESULT).$(EXT_LIB)	1634684779
+name="VALset"><\/a>set	1082276679
+name="VALget"><\/a>get	1153832362
+name="VALadd"><\/a>add	-155548416
+Memcached.Make(Ints)]}	1928981924
+libinstall-native-code	2128269107
+class="type"><\/code>t	509928159
+$(CFRAMEWORKS:%=-cclib	512333410
+$(BCRESULT).$(EXT_LIB)	583750641
+/usr/local/lib/ocaml)	-1545888080
+!_TAG_PROGRAM_VERSION	-249312110
+$(SPECIAL_OCAMLFLAGS)	-2116629110
+$(RESULT).$(EXT_LIB):	-20542193
+profiling-native-code	1787358437
+..\/OCamlMakefile$/;"	-518032703
+$(OCAML_LIB_INSTALL);	-953578590
+OCAML_FIND_PREDICATES	919536217
+$(OCAML_FIND_LINKPKG)	1518744600
+$(OCAML_DEP_PACKAGES)	-1754972905
+memcached_test.ml$/;"	316224720
+Memcached_impl(struct	351529430
+Map.Make(ConnKey)$/;"	-1393458178
+$(LIB_PACK_NAME).cmx:	844574102
+$(LIB_PACK_NAME).cmo:	1933980762
+libinstall-byte-code:	-465853743
+$(IMPL_CMO:.cmo=.cmx)	1025768377
+$(IMPL_CMO:.cmo=.asm)	1347080437
+$(EXTLIBDIRS:%=-ccopt	-1686149355
+CAMELEON_REPORT_FLAGS	-267298889
+<atte.kojo@gmail.com>	1419875395
+2_Functorialinterface	-1955409007
+test_removing_server	137135761
+test_get_nonexistent	1317332359
+!_TAG_PROGRAM_AUTHOR	576113184
+$(SOURCE_DIRS:%=-L%)	-1529367895
+$(SOURCE_DIRS:%=-I%)	1122535517
+$(RESULT).$(EXT_LIB)	1744699397
+profiling-byte-code:	-1086323049
+$(OCAML_LIB_INSTALL)	-1275589358
+OCAML_DEP_PREDICATES	-1199787409
+native-code-library:	851059429
+$(LIB_PACK_NAME).cmx	1995110297
+$(LIB_PACK_NAME).cmo	-834902292
+$(LIB_PACK_NAME).cmi	1257321806
+$(LIBINSTALL_FILES))	1263379427
+$(LIBINSTALL_FILES);	-1690467844
+libinstall-byte-code	-1659865960
+$(DOC_DIR)/$(RESULT)	1695212136
+connection.input$/;"	-97837697
+connection_finalizer	-1626598177
+CAMLreturn(result);	399397213
+CAMLlocal1(result);	1714814268
+caml_copy_int32(h);	1986842204
+CAMELEON_ZOGGY_FLAGS	-1607992282
+####################	530868931
+-Wl,--whole-archive	1494669379
+-Wl,$(RPATH_FLAG)%)	-960751745
+shutdown_connection	767086956
+-short-functors$/;"	578896789
+$(REAL_RESULT).dll:	546131385
+profiling-byte-code	-547923457
+$(OCAMLMKLIB_FLAGS)	-1843778499
+OCAML_GLADECC_FLAGS	604916047
+OCAML_FIND_PACKAGES	-1425615397
+OCAMLFIND_INSTFLAGS	722456965
+native-code-nolink:	2089950124
+native-code-library	1615213334
+$(MAYBE_IDL_HEADER)	-1216767427
+Marshal.from_string	742096855
+$(LIBINSTALL_FILES)	-994276846
+Latex-documentation	1620037639
+-I'$(OCAMLLIBPATH)'	135683113
+$(IMPL_CMO:.cmo=.s)	-1704356071
+ignore(really_input	626677392
+$(FIRST_DOC_FILE)`;	139395146
+$(EXTLIBDIRS:%=-L%)	-308964813
+dll$(CLIB_BASE).dll	2058984836
+debug-code-library:	-346063472
+class="type">string	-422251566
+test_empty_key_set	-194991160
+test_empty_key_get	-883233463
+!_TAG_PROGRAM_NAME	-1556086736
+SPECIAL_OCAMLFLAGS	100761764
+$(SOURCE_DIRS:%=-I	-370398690
+Pervasives.compare	1452371383
+OCaml-installation	648249583
+OCAML_FIND_LINKPKG	2068835399
+OCAML_DEP_PACKAGES	-3380769
+OCAML_DEFAULT_DIRS	1861186772
+-NODEFAULTLIB:LIBC	-1259653130
+native-code-nolink	1019157528
+memcached_test$/;"	618597357
+[Memcached.replace	1604106288
+memcached_native.c	-1535852634
+{!Memcached.Make}.	462152520
+$(LIBDIRS:%=-ccopt	-1718635032
+$(LDFLAGS:%=-ccopt	1666959760
+HTML-documentation	1336083765
+$(FILTERED_IDL)),)	1434106457
+($(ELF_RPATH),yes)	5174104
+dll$(CLIB_BASE).so	933750802
+debug-native-code:	693188189
+debug-code-nolink:	-1789027131
+debug-code-library	-1130528358
+CAMLparam1(data);	-1117233805
+<caml/mlvalues.h>	1252550988
+$(CAMLIDLDLLFLAGS)	1220269686
+$(CAMELEON_REPORT)	-1160556602
+byte-code-library:	-349401158
+$(ALL_OCAMLCFLAGS)	-1629749159
+(ADDR_INET(h_addr,	258759971
+2_Genericinterface	-385885062
+test_add_existing	311395375
+!_TAG_PROGRAM_URL	-149446614
+!_TAG_FILE_SORTED	1816854485
+!_TAG_FILE_FORMAT	-1338612142
+($(SYSTEM),win32)	1443373287
+($(SYSTEM),mingw)	-1629736637
+string_of_int$/;"	-687790420
+$(REAL_OCAMLFIND)	-1474436426
+$(REAL_IMPL_INTF)	-564735652
+PDF-documentation	1027549063
+pack-native-code:	622199770
+OCamlMakefile$/;"	-65960548
+OCAML_LIB_INSTALL	-1927321212
+"\nUninstallation	1782318091
+$*.mli.temporary;	178203005
+{!Memcached.Make}	-1305589371
+[Memcached.delete	-1266710703
+..\/memcached$/;"	-983199793
+Marshal.to_string	-1312898664
+Map.Make(ConnKey)	-1152316985
+language-agnostic	-163421330
+int_of_string$/;"	-30807263
+ignore(input_line	-655293544
+hash_murmur(value	704755233
+$(ELF_RPATH_FLAG)	-638427530
+.DELETE_ON_ERROR:	15348262
+debug-native-code	-1937198785
+debug-code-nolink	516699187
+$(CPPFLAGS_WIN32)	1231755856
+(ConnMap.is_empty	869654597
+$(COMMON_LDFLAGS)	-265490876
+class="type">unit	945023726
+class="info">$/;"	1257561988
+c.continuum.(idx)	-1350281321
+$(CAMELEON_ZOGGY)	8235029
+byte-code-nolink:	-934181449
+byte-code-library	1243564610
+-----------------	294629079
+(Value.of_string	2003795864
+\\t\\r\\n]+"$/;"	1340954163
+test_set_and_get	-1577597633
+test_empty_value	-1452275909
+pack-native-code	2074519530
+-out:$(RES_CLIB)	2038316077
+out_channel;$/;"	568398206
+$(OCAMLNLDFLAGS)	-690175067
+OCAMLMLIB_EXISTS	77298586
+OCAMLMKLIB_FLAGS	-1343665264
+$(OCAMLMAKEFILE)	401012399
+OCAMLLDFLAGS="-g	1202820913
+$(OCAMLLDFLAGS)"	1574256731
+$(OCAML_GLADECC)	1657637190
+$(OCAMLDOCFLAGS)	1233871356
+$(OCAMLBLDFLAGS)	-492037874
+NONINFRINGEMENT.	-1307671053
+new_connections;	937149276
+$(NCRESULT).cmxa	-109901874
+$(NCDIDIR)/%.di:	1963276021
+native-code-dll:	-1649395643
+Module:Continuum	-1577262733
+$*.ml.temporary;	-119811041
+$*.mli.temporary	487243475
+$(MLDEPDIR)/%.d:	-1946992057
+MERCHANTABILITY,	-1995882455
+[Memcached.stats	-164101520
+memcached.ml$/;"	359682116
+"memcached.cmxa"	-1093737625
+MAYBE_IDL_HEADER	-1652390890
+$(LIBS:%=%.cmxa)	1075194962
+$(LIB_PACK_NAME)	1949992606
+LIBINSTALL_FILES	-1095995645
+$(LIBDIRS:%=-L%)	1717045452
+interoperability	409368587
+$(INCDIRS:%=-I%)	-282510306
+ignore(read_line	768866682
+$(FOR_PACK_NAME)	1024691803
+$(FILTER_EXTNS),	1213958977
+.DELETE_ON_ERROR	-511662297
+Continuum.remove	691409477
+connection.input	79306681
+$(CLIBS:%=-cclib	1880230378
+$(CLIB_BASE).lib	-1925141638
+$(CLIB_BASE).exp	1363567167
+$(CFRAMEWORKS))"	1390134058
+<caml/memory.h>	353910593
+byte-code-nolink	-718581888
+Value.to_string	-705331109
+Value.of_string	1728679728
+type:connection	1186610303
+test_pool_store	-2005683276
+test_no_servers	1042675902
+start_memcached	-2027778352
+-short-functors	1892260515
+$(RESULT).cmxa,	-2061154049
+$(REAL_RESULT):	-474525874
+$(QUIET)pp=`sed	474827817
+$(QUIET)$(MAKE)	107568452
+$(PIC_CPPFLAGS)	15279852
+pack-byte-code:	-421664485
+open_connection	1229531561
+ocamlyacc-flags	755845448
+$(OCAMLNCFLAGS)	-1073835114
+'OcamlMakefile'	1636314833
+$(OCAMLLDFLAGS)	1639303728
+$(OCAMLCPFLAGS)	1373092857
+$(OCAMLBCFLAGS)	-1980140366
+"\nUninstalling	-1593396866
+"\nInstallation	83220624
+new_connections	1420990529
+$(NCRESULT).exp	-534609279
+$(NCRESULT).dll	428452856
+$(NCRESULT).cmx	-172849563
+$(NCRESULT).cmi	1339983111
+$(NCRESULT).cma	-803853100
+native-code-dll	63785297
+$*.ml.temporary	-1071833716
+[Memcached.incr	-1556761650
+[Memcached.decr	439976994
+"memcached.cma"	993181028
+$(LIBS:%=%.cma)	1109800194
+in_channel;$/;"	789481621
+/,$(i)),$(i))))	-1644069248
+-I$(CAMLP4PATH)	-1126301195
+hash_murmur$/;"	-1280451973
+FILTERED_OXRIDL	-163721828
+Continuum.t$/;"	-373315689
+Continuum.empty	-1197487616
+.cmxa,$(foreach	755357612
+class="type">'a	702465776
+class="type"><a	1680774640
+$(CFLAGS_WIN32)	-1329056116
+c.continuum.(0)	-1689550155
+$(CAMLIDLFLAGS)	-371127213
+CAMLIDLDLLFLAGS	-1675351180
+CAMELEON_REPORT	307226433
+$(BCRESULT).exp	1392726486
+$(BCRESULT).dll	-1844566173
+$(BCRESULT).cmo	-683310196
+$(BCRESULT).cmi	890927456
+$(BCRESULT).cma	-583242257
+$(BCDIDIR)/%.di	631320642
+archive(native)	2107532456
+ALL_OCAMLCFLAGS	93057105
+$(ALL_LDFLAGS))	-1942420546
+adding/removing	-1302595840
+?wait_time:int	-290570777
+%$(TOPSUFFIX):	732786698
+$(THREAD_FLAG)	766887300
+test_underflow	1924026357
+successful.\n"	-1010765118
+"$(SUBTARGET)"	-186466788
+(String.concat	-223602073
+"SERVER_ERROR"	1379460906
+$(RESULT).cmxa	427487644
+$(RESULT).cma:	1746911700
+$(RESULT).cma,	-1826520012
+representation	1117396821
+REAL_OCAMLFIND	822113169
+$(REAL_OCAMLC)	1159239711
+REAL_IMPL_INTF	-1195918398
+$(QUIET)printf	1007546699
+$(PRE_TARGETS)	1964333438
+pack-byte-code	-1178620692
+$(OCAMLMKLIB))	1978136702
+"OCamlMakefile	756511757
+OCAMLFLAGS="-g	1640771722
+$(OCAMLFLAGS)"	1569427680
+$(OBJ_LINK)),)	1495221082
+["NOT_STORED"]	-165196906
+$(NOIDLHEADER)	-2091811259
+.ml.$(EXT_OBJ)	-1631682805
+.m.$(EXT_OBJ):	320048736
+Memcached_test	557630347
+[Memcached.set	-1403334355
+Memcached_impl	1611385924
+[Memcached.get	1183890637
+[Memcached.add	-452069418
+List.fold_left	-1423420295
+library-paths,	1339999514
+$(LDFLAGS:%=%)	1495856443
+-l$(CLIB_BASE)	-1881934495
+(int_of_string	-1852391096
+$(INTF_OCAMLC)	-1933606922
+$(INCDIRS:%=-I	-69438022
+$(IMPLO_INTF))	-912048134
+$(IMPLO_INTF),	-326132435
+implementation	-492664191
+i,$(LIBS),$(if	-389043560
+(gethostbyname	1301863250
+FIRST_DOC_FILE	-1344035706
+FILTERED_GLADE	1640103076
+FILTERED_C_CXX	-308817955
+$(FILTERED))))	-1474269607
+ELF_RPATH_FLAG	-1622865238
+($(ELF_RPATH),	76108328
+CREATE_LIB=yes	-1494446444
+CPPFLAGS_WIN32	1529263669
+Continuum.find	-1504230432
+ConnMap.t;$/;"	-2023136589
+ConnMap.remove	-1702796547
+ConnMap.empty;	-1081528011
+connection_for	1716881456
+communications	-302284689
+COMMON_LDFLAGS	479101741
+-colorize-code	-95180800
+.cma,$(foreach	-1275831857
+"CLIENT_ERROR"	-559731312
+$(CLIBS:%=-l%)	-2140037502
+.c.$(EXT_OBJ):	-351381745
+c.connections)	107293049
+CAMELEON_ZOGGY	-1154587871
+byte-code-dll:	-543576300
+$(AUTO_OXRIDL)	422668599
+$(ALL_LDFLAGS)	-1965869635
+$(TOPSUFFIX),	338813996
+test/Makefile	-478904522
+$(SUBTARGET);	257337438
+subproj_$(1):	136373374
+string_of_int	673752608
+String.length	1214244514
+String.create	1788351835
+start_servers	-121498926

File test/memcached_hash_test.ml

+(*
+ * Copyright (c) 2011 Atte Kojo <atte.kojo@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *)
+
+open OUnit
+open Printf
+open Str
+
+let (|>) x f = f x
+
+(* Tests for the polymorphic interface *)
+
+let setup () =
+  let input = open_in "data/murmur.txt" in
+  let read_next input =
+    try
+      let line = split (regexp "\t") (input_line input) in
+        Some (List.hd line, Int32.of_string (List.hd (List.tl line)))
+    with End_of_file ->
+      None
+  in
+  let rec read_all input =
+    match (read_next input) with
+        Some l -> l :: read_all input
+      | None -> []
+  in
+    read_all input
+
+let teardown hashes = ()
+
+let test_murmur 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
+    in
+    assert_equal ~msg:err_str actual res
+  in
+  List.iter test_hash hashes
+
+let test_hash = "" >::: [
+  "Murmur2 hash" >:: (bracket setup test_murmur teardown)
+]

File test/memcached_hash_test.mli

+val test_hash: OUnit.test

File test/memcached_test.ml

 (*
- * Copyright (c) 2010 Atte Kojo <atte.kojo@gmail.com>
+ * Copyright (c) 2010-2011 Atte Kojo <atte.kojo@gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
 
 let base_port = 11220
 let nservers = 10
-let num_hashkeys = 500
+let num_hashkeys = 100
 
 (* Tests for the polymorphic interface *)
 
     List.iter (fun (k, v) -> ignore(Memcached.set cache k v))
         (genvalues "pool_test" num_hashkeys);
     let nitems = get_stats "curr_items" cache servers in
-    List.iter (fun i -> "0 items on a server" @? (i > 0)) nitems
+    List.iter (fun i ->
+                 printf "%d\n" i; "0 items on a server" @? (i > 0)) nitems
 
 let test_removing_server cache =
     let rec genvalues str count =
         | None -> 0 in
     let result = List.map (fun (k, v) -> read_val cache k) values in
     let valid = List.fold_left (+) 0 result in
-    "Too many keys re-hashed" @? (valid > (num_hashkeys / 5 * 4))
+    let err_str =
+      sprintf "Too many keys re-hashed, valid: %d, should be at least %d"
+        valid (num_hashkeys / 5 * 4) in
+    err_str @? (valid > (num_hashkeys / 5 * 4))
 
 let test_pool = "" >::: [
     "Test server count" >:: (bracket setup_pool test_servers teardown_pool);
 let all_tests = "Memcached tests" >::: [
     "Polymorphic interface" >: test_poly;
     "Monomorphic interface" >: test_mono;
-    "Server pool" >: test_pool
+    "Server pool" >: test_pool;
+    "Hashing functions" >: Memcached_hash_test.test_hash
     ]
 
 let _ =