You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2015/07/17 00:36:24 UTC

couchdb-khash git commit: Remove the use of make_hash2

Repository: couchdb-khash
Updated Branches:
  refs/heads/master 6938d72be -> 265475d17


Remove the use of make_hash2

We were being rather naughty relying on the ability to resolve symbols
in the executable that loads the NIF. Apparently Windows has a much
different NIF loading system which prevents this from working. Given
that the patch for exposing enif_phash was never merged we're solving
the issue by removing the need from hashing terms in the NIF.

This new approach simply hashes the term in Erlang and passes the
calculated value in the NIF call. We then just store the calculated
value along with the key and value as before.

COUCHDB-2750


Project: http://git-wip-us.apache.org/repos/asf/couchdb-khash/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-khash/commit/265475d1
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-khash/tree/265475d1
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-khash/diff/265475d1

Branch: refs/heads/master
Commit: 265475d175ec9df76a2ed6ddce21184f6f83bf6e
Parents: 6938d72
Author: Paul J. Davis <pa...@gmail.com>
Authored: Tue Jul 14 01:08:26 2015 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Thu Jul 16 23:34:40 2015 +0100

----------------------------------------------------------------------
 c_src/khash.c | 72 ++++++++++++++++++++++++++++++++----------------------
 src/khash.erl | 32 ++++++++++++++++++------
 2 files changed, 67 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-khash/blob/265475d1/c_src/khash.c
----------------------------------------------------------------------
diff --git a/c_src/khash.c b/c_src/khash.c
index a2364b0..8081c3b 100644
--- a/c_src/khash.c
+++ b/c_src/khash.c
@@ -4,6 +4,7 @@
 
 #include <assert.h>
 #include <string.h>
+#include <stdint.h>
 
 #include "erl_nif.h"
 #include "hash.h"
@@ -27,6 +28,7 @@ typedef struct
 
 typedef struct
 {
+    unsigned int hval;
     ErlNifEnv* env;
     ERL_NIF_TERM key;
     ERL_NIF_TERM val;
@@ -51,13 +53,6 @@ typedef struct
 } khash_iter_t;
 
 
-// This is actually an internal Erlang VM function that
-// we're being a bit hacky to get access to. There's a
-// pending patch to expose this in the NIF API in newer
-// Erlangs.
-unsigned int make_hash2(ERL_NIF_TERM term);
-
-
 static inline ERL_NIF_TERM
 make_atom(ErlNifEnv* env, const char* name)
 {
@@ -145,7 +140,7 @@ hash_val_t
 khash_hash_fun(const void* obj)
 {
     khnode_t* node = (khnode_t*) obj;
-    return (hash_val_t) make_hash2(node->key);
+    return (hash_val_t) node->hval;
 }
 
 
@@ -284,9 +279,10 @@ khash_clear(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 
 
 static inline hnode_t*
-khash_lookup_int(ErlNifEnv* env, ERL_NIF_TERM key, khash_t* khash)
+khash_lookup_int(ErlNifEnv* env, uint32_t hv, ERL_NIF_TERM key, khash_t* khash)
 {
     khnode_t node;
+    node.hval = hv;
     node.env = env;
     node.key = key;
     return kl_hash_lookup(khash->h, &node);
@@ -298,12 +294,12 @@ khash_lookup(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 {
     khash_priv* priv = enif_priv_data(env);
     khash_t* khash = NULL;
-    void* res = NULL;
+    uint32_t hval;
     hnode_t* entry;
     khnode_t* node;
     ERL_NIF_TERM ret;
 
-    if(argc != 2) {
+    if(argc != 3) {
         return enif_make_badarg(env);
     }
 
@@ -317,7 +313,11 @@ khash_lookup(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
         return enif_make_badarg(env);
     }
 
-    entry = khash_lookup_int(env, argv[1], khash);
+    if(!enif_get_uint(env, argv[1], &hval)) {
+        return enif_make_badarg(env);
+    }
+
+    entry = khash_lookup_int(env, hval, argv[2], khash);
     if(entry == NULL) {
         ret = priv->atom_not_found;
     } else {
@@ -335,12 +335,12 @@ khash_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 {
     khash_priv* priv = enif_priv_data(env);
     khash_t* khash = NULL;
-    void* res = NULL;
+    uint32_t hval;
     hnode_t* entry;
     khnode_t* node;
     ERL_NIF_TERM ret;
 
-    if(argc != 3) {
+    if(argc != 4) {
         return enif_make_badarg(env);
     }
 
@@ -354,9 +354,13 @@ khash_get(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
         return enif_make_badarg(env);
     }
 
-    entry = khash_lookup_int(env, argv[1], khash);
+    if(!enif_get_uint(env, argv[1], &hval)) {
+        return enif_make_badarg(env);
+    }
+
+    entry = khash_lookup_int(env, hval, argv[2], khash);
     if(entry == NULL) {
-        ret = argv[2];
+        ret = argv[3];
     } else {
         node = (khnode_t*) kl_hnode_getkey(entry);
         ret = enif_make_copy(env, node->val);
@@ -371,11 +375,11 @@ khash_put(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 {
     khash_priv* priv = enif_priv_data(env);
     khash_t* khash = NULL;
-    void* res = NULL;
+    uint32_t hval;
     hnode_t* entry;
     khnode_t* node;
 
-    if(argc != 3) {
+    if(argc != 4) {
         return enif_make_badarg(env);
     }
 
@@ -389,18 +393,23 @@ khash_put(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
         return enif_make_badarg(env);
     }
 
-    entry = khash_lookup_int(env, argv[1], khash);
+    if(!enif_get_uint(env, argv[1], &hval)) {
+        return enif_make_badarg(env);
+    }
+
+    entry = khash_lookup_int(env, hval, argv[2], khash);
     if(entry == NULL) {
         entry = khnode_alloc(NULL);
         node = (khnode_t*) kl_hnode_getkey(entry);
-        node->key = enif_make_copy(node->env, argv[1]);
-        node->val = enif_make_copy(node->env, argv[2]);
+        node->hval = hval;
+        node->key = enif_make_copy(node->env, argv[2]);
+        node->val = enif_make_copy(node->env, argv[3]);
         kl_hash_insert(khash->h, entry, node);
     } else {
         node = (khnode_t*) kl_hnode_getkey(entry);
         enif_clear_env(node->env);
-        node->key = enif_make_copy(node->env, argv[1]);
-        node->val = enif_make_copy(node->env, argv[2]);
+        node->key = enif_make_copy(node->env, argv[2]);
+        node->val = enif_make_copy(node->env, argv[3]);
     }
 
     khash->gen += 1;
@@ -415,10 +424,11 @@ khash_del(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
     khash_priv* priv = enif_priv_data(env);
     khash_t* khash = NULL;
     void* res = NULL;
+    uint32_t hval;
     hnode_t* entry;
     ERL_NIF_TERM ret;
 
-    if(argc != 2) {
+    if(argc != 3) {
         return enif_make_badarg(env);
     }
 
@@ -432,7 +442,11 @@ khash_del(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
         return enif_make_badarg(env);
     }
 
-    entry = khash_lookup_int(env, argv[1], khash);
+    if(!enif_get_uint(env, argv[1], &hval)) {
+        return enif_make_badarg(env);
+    }
+
+    entry = khash_lookup_int(env, hval, argv[2], khash);
     if(entry == NULL) {
         ret = priv->atom_not_found;
     } else {
@@ -623,10 +637,10 @@ static ErlNifFunc funcs[] = {
     {"new", 1, khash_new},
     {"to_list", 1, khash_to_list},
     {"clear", 1, khash_clear},
-    {"lookup", 2, khash_lookup},
-    {"get", 3, khash_get},
-    {"put", 3, khash_put},
-    {"del", 2, khash_del},
+    {"lookup_int", 3, khash_lookup},
+    {"get_int", 4, khash_get},
+    {"put_int", 4, khash_put},
+    {"del_int", 3, khash_del},
     {"size", 1, khash_size},
     {"iter", 1, khash_iter},
     {"iter_next", 1, khash_iter_next}

http://git-wip-us.apache.org/repos/asf/couchdb-khash/blob/265475d1/src/khash.erl
----------------------------------------------------------------------
diff --git a/src/khash.erl b/src/khash.erl
index 7b474bd..daaf5ea 100644
--- a/src/khash.erl
+++ b/src/khash.erl
@@ -69,8 +69,8 @@ clear(_Hash) ->
 
 
 -spec lookup(khash(), any()) -> {value, any()} | not_found.
-lookup(_Hash, _Key) ->
-    ?NOT_LOADED.
+lookup(Hash, Key) ->
+    lookup_int(Hash, erlang:phash2(Key), Key).
 
 
 -spec get(khash(), any()) -> any().
@@ -79,18 +79,18 @@ get(Hash, Key) ->
 
 
 -spec get(khash(), any(), any()) -> any().
-get(_Hash, _Key, _Default) ->
-    ?NOT_LOADED.
+get(Hash, Key, Default) ->
+    get_int(Hash, erlang:phash2(Key), Key, Default).
 
 
 -spec put(khash(), any(), any()) -> ok.
-put(_Hash, _Key, _Value) ->
-    ?NOT_LOADED.
+put(Hash, Key, Value) ->
+    put_int(Hash, erlang:phash2(Key), Key, Value).
 
 
 -spec del(khash(), any()) -> ok.
-del(_Hash, _Key) ->
-    ?NOT_LOADED.
+del(Hash, Key) ->
+    del_int(Hash, erlang:phash2(Key), Key).
 
 
 -spec size(khash()) -> non_neg_integer().
@@ -137,5 +137,21 @@ init() ->
     erlang:load_nif(filename:join(PrivDir, "khash"), 0).
 
 
+lookup_int(_Hash, _HashValue, _Key) ->
+    ?NOT_LOADED.
+
+
+get_int(_Hash, _HashValue, _Key, _Default) ->
+    ?NOT_LOADED.
+
+
+put_int(_Hash, _HashValue, _Key, _Value) ->
+    ?NOT_LOADED.
+
+
+del_int(_Hash, _HashValue, _Key) ->
+    ?NOT_LOADED.
+
+
 not_loaded(Line) ->
     erlang:nif_error({not_loaded, [{module, ?MODULE}, {line, Line}]}).