cluster: STABLE3 - cman: Add improved cluster_id hash function

Christine Caulfield chrissie at fedoraproject.org
Fri Mar 19 14:00:30 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=814faae67c226f6ac9e99438096696479c8aaf2e
Commit:        814faae67c226f6ac9e99438096696479c8aaf2e
Parent:        e23761e752f496399c51d74c557f302378eb1427
Author:        Christine Caulfield <ccaulfie at redhat.com>
AuthorDate:    Fri Mar 19 13:57:50 2010 +0000
Committer:     Christine Caulfield <ccaulfie at redhat.com>
CommitterDate: Fri Mar 19 13:57:50 2010 +0000

cman: Add improved cluster_id hash function

Add a new and vastly improved function for converting the cluster name
into a 16bit ID. This is currently disabled by default but can be enabled
with the stanza

<cman hash_cluster_id="yes"/>

in cluster.conf

We might make this the default in future .. watch this space. Or some space
closely related to this one that's less intimidating to read on a Friday
afternoon before you've had tea.

Thanks to Steven Dake for finding and slightly modifying the hash function.

Signed-off-by: Christine Caulfield <ccaulfie at redhat.com>
---
 cman/daemon/cman-preconfig.c |  119 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/cman/daemon/cman-preconfig.c b/cman/daemon/cman-preconfig.c
index f27effa..3339f1d 100644
--- a/cman/daemon/cman-preconfig.c
+++ b/cman/daemon/cman-preconfig.c
@@ -49,6 +49,7 @@ static char *mcast_name;
 static char *cluster_name;
 static char error_reason[1024] = { '\0' };
 static hdb_handle_t cluster_parent_handle;
+static int use_hashed_cluster_id = 0;
 
 /*
  * Exports the interface for the service
@@ -283,6 +284,99 @@ static int add_ifaddr(struct objdb_iface_ver0 *objdb, char *mcast, char *ifaddr,
 	return ret;
 }
 
+
+/***
+ *
+ * Fowler/Noll/Vo hash
+ *
+ * The basis of this hash algorithm was taken from an idea sent
+ * as reviewer comments to the IEEE POSIX P1003.2 committee by:
+ *
+ *      Phong Vo (http://www.research.att.com/info/kpv/)
+ *      Glenn Fowler (http://www.research.att.com/~gsf/)
+ *
+ * In a subsequent ballot round:
+ *
+ *      Landon Curt Noll (http://www.isthe.com/chongo/)
+ *
+ * improved on their algorithm.  Some people tried this hash
+ * and found that it worked rather well.  In an EMail message
+ * to Landon, they named it the ``Fowler/Noll/Vo'' or FNV hash.
+ *
+ * FNV hashes are designed to be fast while maintaining a low
+ * collision rate. The FNV speed allows one to quickly hash lots
+ * of data while maintaining a reasonable collision rate.  See:
+ *
+ *      http://www.isthe.com/chongo/tech/comp/fnv/index.html
+ *
+ * for more details as well as other forms of the FNV hash.
+ ***
+ *
+ * To use the recommended 32 bit FNV-1a hash, pass FNV1_32A_INIT as the
+ * Fnv32_t hashval argument to fnv_32a_buf() or fnv_32a_str().
+ *
+ ***
+ *
+ * Please do not copyright this code.  This code is in the public domain.
+ *
+ * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
+ * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * By:
+ *	chongo <Landon Curt Noll> /\oo/\
+ *      http://www.isthe.com/chongo/
+ *
+ * Share and Enjoy!	:-)
+ */
+
+/* 
+ * Modified to be a little more simple to understand and to provide a 16 bit
+ * value rather then 32 bit for cluster id generation
+ *
+ * sdake at redhat.com
+ */
+
+/* 32 bit magic FNV-1a prime */
+#define FNV_32_PRIME ((uint32_t)0x01000193)
+
+/* Default initialization for FNV-1a */
+#define FNV_32_INIT ((uint32_t)0x811c9dc5)
+
+static uint16_t generate_hashed_cluster_id(char *str)
+{
+	unsigned char *s = (unsigned char *)str;
+	uint32_t hval = FNV_32_INIT;
+	uint32_t ret;
+
+	/*
+	* FNV-1a hash each octet in the buffer
+	*/
+	while (*s) {
+		/*
+		 * xor the bottom with the current octet
+		 */
+		hval ^= (uint32_t)*s++;
+		/*
+		 * multiply by the 32 bit FNV magic prime mod 2^32
+		 */
+		hval *= FNV_32_PRIME;
+	}
+
+	/*
+	 * Use XOR folding as recommended by authors of algorithm
+	 * to create a different hash size that is a power of two
+	 */
+	ret = (hval >> 16) ^ (hval & 0xFFFF);
+
+	sprintf(error_reason, "Generated hashed cluster id for '%s' is %d\n", str, ret);
+	return (ret);
+}
+
 static uint16_t generate_cluster_id(char *name)
 {
 	int i;
@@ -916,8 +1010,12 @@ static int set_noccs_defaults(struct objdb_iface_ver0 *objdb)
 		return -1;
 	}
 
-	if (!cluster_id)
-		cluster_id = generate_cluster_id(cluster_name);
+	if (!cluster_id) {
+	    if (use_hashed_cluster_id)
+	        cluster_id = generate_hashed_cluster_id(cluster_name);
+	    else
+	        cluster_id = generate_cluster_id(cluster_name);
+	}
 
 	if (!nodename_env) {
 		int error;
@@ -1084,6 +1182,7 @@ static int get_cman_globals(struct objdb_iface_ver0 *objdb)
 {
 	hdb_handle_t object_handle;
 	hdb_handle_t find_handle;
+	char *use_hash;
 
 	objdb_get_string(objdb, cluster_parent_handle, "name", &cluster_name);
 
@@ -1096,11 +1195,21 @@ static int get_cman_globals(struct objdb_iface_ver0 *objdb)
 		if (!key_filename)
 			objdb_get_string(objdb, object_handle, "keyfile", &key_filename);
 
+		objdb_get_string(objdb, object_handle, "hash_cluster_id", &use_hash);
+		if (use_hash) {
+		    if (strncasecmp(use_hash, "yes", 3) == 0 || strncasecmp(use_hash, "on", 2) == 0)
+		        use_hashed_cluster_id = 1;
+		}
+
 		if (!cluster_id)
 			objdb_get_int(objdb, object_handle, "cluster_id", &cluster_id, 0);
 
-		if (!cluster_id)
-			cluster_id = generate_cluster_id(cluster_name);
+		if (!cluster_id) {
+		    if (use_hashed_cluster_id)
+		        cluster_id = generate_hashed_cluster_id(cluster_name);
+		    else
+		        cluster_id = generate_cluster_id(cluster_name);
+		}
 	}
 	objdb->object_find_destroy(find_handle);
 	return 0;
@@ -1202,6 +1311,8 @@ static void setup_old_compat(struct objdb_iface_ver0 *objdb, hdb_handle_t cluste
 	hdb_handle_t totem_handle;
 	hdb_handle_t gfs_handle;
 	char *value;
+	
+	use_hashed_cluster_id = 0;
 
 	/* Set groupd to backwards compatibility mode */
 	groupd_handle = find_or_create_object(objdb, "group", cluster_handle);


More information about the cluster-commits mailing list