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); }
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); }
//returns sock. Must unlock after usage. Otherwise the sock cannot be reused static void* notify_random_publisher(struct inotify_event *pevent, publishers_info *pub_interface) { char * instance_num = malloc(10); sprintf(instance_num, "%d", (rand()%REPLICATION_FACTOR) + 1); char * publishable = to_c_string(pevent->name, pevent->len, (pevent->len + strlen(instance_num) + 1)); strcat(publishable, instance_num); g_rw_lock_reader_lock (&lock); hash_ring_node_t *node = hash_ring_find_node(pub_interface->publisher_ring, (uint8_t*)publishable, strlen(publishable)); char *publisher = to_c_string((char*)node->name, node->nameLen, node->nameLen + 1); void* ret = g_hash_table_lookup(pub_interface->publisher_socks, publisher); void* mutex = g_hash_table_lookup(pub_interface->publisher_socks_locks, publisher); g_rw_lock_reader_unlock (&lock); free(publisher); free(publishable); free(instance_num); g_mutex_lock (mutex); notify(ret, pevent); g_mutex_unlock (mutex); return ret; }
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); }
int main() { hash_ring_t *ring = hash_ring_create(8, HASH_FUNCTION_SHA1); char *slot = malloc(10); char *keyA = "keyA"; hash_ring_node_t *node; sprintf(slot, "%d", 12313); assert(hash_ring_add_node(ring, (uint8_t*)slot, strlen(slot)) == HASH_RING_OK); free(slot); node = hash_ring_find_node(ring, (uint8_t*)keyA, strlen(keyA)); assert(node != NULL && node->nameLen == strlen(slot) && memcmp(node->name, slot, strlen(slot)) == 0); }
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); }
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); }