void testRemoveNode() { printf("Test removing a node...\n"); hash_ring_t *ring = hash_ring_create(1, HASH_FUNCTION_SHA1); hash_ring_node_t *node; char *mynode = "mynode"; char *mynode1 = "mynode1"; char *mynode2 = "mynode2"; char *mykey = "mykey"; assert(hash_ring_add_node(ring, (uint8_t*)mynode, strlen(mynode)) == HASH_RING_OK); assert(hash_ring_add_node(ring, (uint8_t*)mynode1, strlen(mynode2)) == HASH_RING_OK); assert(hash_ring_add_node(ring, (uint8_t*)mynode2, strlen(mynode2)) == HASH_RING_OK); assert(ring->numNodes == 3); node = hash_ring_find_node(ring, (uint8_t*)mykey, strlen(mykey)); assert(node != NULL && node->nameLen == strlen(mynode) && memcmp(mynode, node->name, node->nameLen) == 0); assert(hash_ring_remove_node(ring, (uint8_t*)mynode, strlen(mynode)) == HASH_RING_OK); assert(ring->numNodes == 2); assert(hash_ring_get_node(ring, (uint8_t*)mynode, strlen(mynode)) == NULL); // remove node1, and try to search for a key that went to it before, and verify it goes to node2 assert(hash_ring_remove_node(ring, (uint8_t*)mynode1, strlen(mynode1)) == HASH_RING_OK); assert(ring->numNodes == 1); node = hash_ring_find_node(ring, (uint8_t*)mykey, strlen(mykey)); assert(node != NULL && node->nameLen == strlen(mynode2) && memcmp(mynode2, node->name, node->nameLen) == 0); hash_ring_free(ring); }
int main (int argc, char *argv []) { zctx_t *ctx = zctx_new (); publishers_info *pub_interface = malloc(sizeof(publishers_info)); pub_interface->publisher_ring = hash_ring_create(REPLICATION_FACTOR, HASH_FUNCTION_SHA1); pub_interface->publisher_socks = g_hash_table_new(g_str_hash, g_str_equal); pub_interface->publisher_socks_locks = g_hash_table_new(g_str_hash, g_str_equal); //self_register(ctx, REGISTER_DISPATCHER_SANITY_CHECK, ""); void *subscriber = create_socket(ctx, ZMQ_PULL, SOCK_CONNECT, RECEIVE_ADDR); void *worker = create_socket(ctx, ZMQ_PUSH, SOCK_BIND, WORKER_SOCKET); create_parser_threads(THREAD_COUNT, ctx, pub_interface); zthread_fork(ctx, publisher_updater, pub_interface); while(true) { int size; char *string = _recv_buff(subscriber, &size); _send_string(worker, string, size); //fprintf(stderr, "\n Flush came in"); free (string); } zctx_destroy (&ctx); hash_ring_free(pub_interface->publisher_ring); return 0; }
void testKnownSlotsOnRing() { printf("Test getting known nodes on ring...\n"); hash_ring_t *ring = hash_ring_create(8, HASH_FUNCTION_SHA1); char *slotA = "slotA"; char *slotB = "slotB"; char *keyA = "keyA"; char *keyB = "keyBBBB"; char *keyC = "keyB_"; hash_ring_node_t *node; assert(hash_ring_add_node(ring, (uint8_t*)slotA, strlen(slotA)) == HASH_RING_OK); assert(hash_ring_add_node(ring, (uint8_t*)slotB, strlen(slotB)) == HASH_RING_OK); node = hash_ring_find_node(ring, (uint8_t*)keyA, strlen(keyA)); assert(node != NULL && node->nameLen == strlen(slotA) && memcmp(node->name, slotA, strlen(slotA)) == 0); node = hash_ring_find_node(ring, (uint8_t*)keyB, strlen(keyB)); assert(node != NULL && node->nameLen == strlen(slotA) && memcmp(node->name, slotA, strlen(slotA)) == 0); node = hash_ring_find_node(ring, (uint8_t*)keyC, strlen(keyC)); assert(node != NULL && node->nameLen == strlen(slotB) && memcmp(node->name, slotB, strlen(slotB)) == 0); hash_ring_free(ring); }
void testLibmemcachedCompat() { printf("Testing libmemcached compatibility mode..\n"); // make sure the mode can't be set to libmemcached if the function is not md5 hash_ring_t *ring = hash_ring_create(1, HASH_FUNCTION_SHA1); assert(hash_ring_set_mode(ring, HASH_RING_MODE_LIBMEMCACHED_COMPAT) == HASH_RING_ERR); hash_ring_free(ring); ring = hash_ring_create(1, HASH_FUNCTION_MD5); assert(hash_ring_set_mode(ring, HASH_RING_MODE_LIBMEMCACHED_COMPAT) == HASH_RING_OK); /** * TODO - Add tests to make sure libmemcached compat hashes correctly. */ hash_ring_free(ring); }
void testEmptyRingSearchReturnsNull() { printf("Test empty ring search returns null node...\n"); hash_ring_t *ring = hash_ring_create(8, HASH_FUNCTION_SHA1); char *key = "key"; assert(hash_ring_find_node(ring, (uint8_t*)key, strlen(key)) == NULL); hash_ring_free(ring); }
void testEmptyRingItemSearchReturnsNull() { printf("Test empty ring search returns null item...\n"); hash_ring_t *ring = hash_ring_create(8, HASH_FUNCTION_SHA1); assert(hash_ring_find_next_highest_item(ring, 0) == NULL); hash_ring_free(ring); }
void testAddMultipleTimes() { printf("Test adding a node multiple times...\n"); hash_ring_t *ring = hash_ring_create(1, HASH_FUNCTION_SHA1); assert(ring != NULL); char *mynode = "mynode"; hash_ring_add_node(ring, (uint8_t*)mynode, strlen(mynode)); assert(ring->numNodes == 1); assert(hash_ring_add_node(ring, (uint8_t*)mynode, strlen(mynode)) == HASH_RING_ERR); assert(ring->numNodes == 1); hash_ring_free(ring); }
void testRingSorting(int num) { printf("Test that the ring is sorted [%d item(s)]...\n", num); hash_ring_t *ring = hash_ring_create(num, HASH_FUNCTION_SHA1); char *slotA = "slotA"; assert(hash_ring_add_node(ring, (uint8_t*)slotA, strlen(slotA)) == HASH_RING_OK); int x; uint64_t cur = 0; for(x = 0; x < ring->numItems; x++) { assert(ring->items[x]->number > cur); cur = ring->items[x]->number; } hash_ring_free(ring); }
static void hash_ring_drv_stop(ErlDrvData handle) { hash_ring_data *d = (hash_ring_data*)handle; int x; for(x = 0; x < d->numRings; x++) { if(d->ring_usage[x] == 1) { hash_ring_free(d->rings[x]); } } driver_free(d->rings); driver_free(d->ring_usage); driver_free((char*)handle); }
void runBench(HASH_FUNCTION hash_fn, int numReplicas, int numNodes, int numKeys, int keySize) { char *hash = NULL; if(hash_fn == HASH_FUNCTION_MD5) hash = "MD5"; else if(hash_fn == HASH_FUNCTION_SHA1) hash = "SHA1"; printf("----------------------------------------------------\n"); printf("bench (%s): replicas = %d, nodes = %d, keys: %d, ring size: %d\n", hash, numReplicas, numNodes, numKeys, numReplicas * numNodes); printf("----------------------------------------------------\n"); hash_ring_t *ring = hash_ring_create(numReplicas, hash_fn); addNodes(ring, numNodes); uint8_t *keys = (uint8_t*)malloc(keySize * numKeys); generateKeys(keys, numKeys, keySize); printf("running...\r"); uint64_t min = 0; uint64_t max = 0; uint64_t total = 0; int times = 100; int x, y; for(y = 0; y < times; y++) { startTiming(); for(x = 0; x < numKeys; x++) { assert(hash_ring_find_node(ring, keys + (keySize * x), keySize) != NULL); } uint64_t result = endTiming(); if(result > max) max = result; if(min == 0 || result < min) min = result; total += result; } printf("stats: total = %.5fs, avg/lookup: %.5fus, min: %.5fus, max: %.5fus, ops/sec: %.0f\n", (double)total / 1000000000, (((double)(total / numKeys)) / 1000) / times, (double)min / numKeys / 1000, (double)max / numKeys / 1000, 1000000000 / ((double)(total / (numKeys * times)))); free(keys); hash_ring_free(ring); }
void testKnownNextHighestItemOnRing() { printf("Test getting next highest item on ring...\n"); hash_ring_t *ring = hash_ring_create(8, HASH_FUNCTION_SHA1); char *slotA = "slotA"; char *slotB = "slotB"; assert(hash_ring_add_node(ring, (uint8_t*)slotA, strlen(slotA)) == HASH_RING_OK); assert(hash_ring_add_node(ring, (uint8_t*)slotB, strlen(slotB)) == HASH_RING_OK); // next highest for first item should yield the second assert(hash_ring_find_next_highest_item(ring, 2351641940735260693u)->number == 2584980261350711786u); // number less than the first should yield the first assert(hash_ring_find_next_highest_item(ring, 2351641940735260692u)->number == 2351641940735260693u); // number in the middle should yield the next assert(hash_ring_find_next_highest_item(ring, 5908063426886290069u)->number == 6065789416862870789u); // number equal to the last should wrap around to the first assert(hash_ring_find_next_highest_item(ring, 17675051572751928939u)->number == 2351641940735260693u); hash_ring_free(ring); }
static void hash_ring_drv_output(ErlDrvData handle, char *buff, ErlDrvSizeT bufflen) { hash_ring_data* d = (hash_ring_data*)handle; char res = RETURN_ERR; // Check the command if(bufflen == 6 && buff[0] == COMMAND_CREATE_RING) { uint32_t numReplicas; memcpy(&numReplicas, &buff[1], 4); numReplicas = ntohl(numReplicas); int index = find_open_ring_space(d); if(index != -1) { d->ring_usage[index] = 1; d->rings[index] = hash_ring_create(numReplicas, buff[5]); index = htonl(index); driver_output(d->port, (char*)&index, 4); return; } } else if(bufflen == 5 && buff[0] == COMMAND_DELETE_RING) { uint32_t index; memcpy(&index, &buff[1], 4); index = ntohl(index); if(d->numRings > index) { if(d->ring_usage[index] == 1) { d->ring_usage[index] = 0; hash_ring_free(d->rings[index]); res = RETURN_OK; } } } else if(bufflen >= 9 && buff[0] == COMMAND_ADD_NODE) { uint32_t index = readUint32((unsigned char*)&buff[1]); uint32_t nodeLen = readUint32((unsigned char*)&buff[5]); if((bufflen - 9) == nodeLen && d->numRings > index && d->ring_usage[index] == 1) { hash_ring_add_node(d->rings[index], (unsigned char*)&buff[9], nodeLen); res = RETURN_OK; } } else if(bufflen >= 9 && buff[0] == COMMAND_REMOVE_NODE) { uint32_t index = readUint32((unsigned char*)&buff[1]); uint32_t nodeLen = readUint32((unsigned char*)&buff[5]); if((bufflen - 9) == nodeLen && d->numRings > index && d->ring_usage[index] == 1) { hash_ring_remove_node(d->rings[index], (unsigned char*)&buff[9], nodeLen); res = RETURN_OK; } } else if(bufflen >= 9 && buff[0] == COMMAND_FIND_NODE) { uint32_t index = readUint32((unsigned char*)&buff[1]); uint32_t keyLen = readUint32((unsigned char*)&buff[5]); if((bufflen - 9) == keyLen && d->numRings > index && d->ring_usage[index] == 1) { hash_ring_node_t *node = hash_ring_find_node(d->rings[index], (unsigned char*)&buff[9], keyLen); if(node != NULL) { driver_output(d->port, (char*)node->name, node->nameLen); return; } } } else if(bufflen == 6 && buff[0] == COMMAND_SET_MODE) { uint32_t index = readUint32((unsigned char*)&buff[1]); uint8_t mode = (uint8_t)buff[5]; if(d->numRings > index && d->ring_usage[index] == 1) { if(hash_ring_set_mode(d->rings[index], mode) == HASH_RING_OK) { res = RETURN_OK; } } } // default return driver_output(d->port, &res, 1); }
void testKnownMultipleSlotsOnRing() { printf("\n\nTest getting multiple known nodes on ring...\n\n"); hash_ring_t *ring = hash_ring_create(8, HASH_FUNCTION_SHA1); char *slotA = "slotA"; char *slotB = "slotB"; char *slotC = "slotC"; // hashes to a low number char *keyA = "keyA"; // hashes to high number char *keyB = "keyB*_*_*_"; int x; hash_ring_node_t *nodes[3]; assert(hash_ring_add_node(ring, (uint8_t*)slotA, strlen(slotA)) == HASH_RING_OK); assert(hash_ring_add_node(ring, (uint8_t*)slotB, strlen(slotB)) == HASH_RING_OK); x = hash_ring_find_nodes(ring, (uint8_t*)keyA, strlen(keyA), nodes, 3); assert( x == 2 && nodes[0] != NULL && nodes[0]->nameLen == strlen(slotA) && memcmp(nodes[0]->name, slotA, strlen(slotA)) == 0 && nodes[1] != NULL && nodes[1]->nameLen == strlen(slotB) && memcmp(nodes[1]->name, slotB, strlen(slotB)) == 0); x = hash_ring_find_nodes(ring, (uint8_t*)keyB, strlen(keyB), nodes, 3); assert( x == 2 && nodes[0] != NULL && nodes[0]->nameLen == strlen(slotB) && memcmp(nodes[0]->name, slotB, strlen(slotB)) == 0 && nodes[1] != NULL && nodes[1]->nameLen == strlen(slotA) && memcmp(nodes[1]->name, slotA, strlen(slotA)) == 0); assert(hash_ring_add_node(ring, (uint8_t*)slotC, strlen(slotC)) == HASH_RING_OK); x = hash_ring_find_nodes(ring, (uint8_t*)keyA, strlen(keyA), nodes, 3); assert( x == 3 && nodes[0] != NULL && nodes[0]->nameLen == strlen(slotC) && memcmp(nodes[0]->name, slotC, strlen(slotC)) == 0 && nodes[1] != NULL && nodes[1]->nameLen == strlen(slotA) && memcmp(nodes[1]->name, slotA, strlen(slotA)) == 0 && nodes[2] != NULL && nodes[2]->nameLen == strlen(slotB) && memcmp(nodes[2]->name, slotB, strlen(slotB)) == 0); x = hash_ring_find_nodes(ring, (uint8_t*)keyB, strlen(keyB), nodes, 3); assert( x == 3 && nodes[0] != NULL && nodes[0]->nameLen == strlen(slotC) && memcmp(nodes[0]->name, slotC, strlen(slotC)) == 0 && nodes[1] != NULL && nodes[1]->nameLen == strlen(slotB) && memcmp(nodes[1]->name, slotB, strlen(slotB)) == 0 && nodes[2] != NULL && nodes[2]->nameLen == strlen(slotA) && memcmp(nodes[2]->name, slotA, strlen(slotA)) == 0); hash_ring_free(ring); }