Dick Tang avatar Dick Tang committed 14cb088

[simpledht] initial commit, simplify from dht.c and dhttest.c

Comments (0)

Files changed (3)

test/makeSimpleDHT.sh

+gcc -g -O2 -o simpledht simpledht.c -I../include -L../src -lchimera -lpthread -lcrypto
+gcc -g -O2 -o simpledht_test simpledht_test.c -I../include -L../src -lchimera -lpthread -lcrypto
+/*
+** Krishna Puttaswamy
+** A simple DHT application on top of Chimera
+** supports put/get with replications; the put/get is only for blockids, this is not a complete dht that stores blocks
+*/
+/*
+ * chirema_send is for internal use (within handlers)
+ * message_send is for external use (normal coding)
+ * no exiting procedure and no rebalancing after node down
+ * replication is 3, by default
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include "dht.h"
+#include "message.h"
+#include "log.h"
+#include "key.h"
+#include "jrb.h"
+#include "jval.h"
+#include "dtime.h"
+#include "route.h"
+
+#define USAGE "dht [ -j bootstrap:port ] port key malice_type"
+#define OPTSTR "j:"
+
+#define RAND() (lrand48())
+#define SEED(s) (srand48(s))
+
+extern char *optarg;
+extern int optind;
+
+//int malice_type = 0;
+ChimeraHost *driver = NULL;
+ChimeraState *state;
+Key key;
+char mykey[200];
+int seq = -1;
+int my_put_count = 0, my_get_count = 0;
+int ignore_dht_get_nonroot = 0, ignore_dht_get_root = 0, ignore_dht_put_nonroot = 0, ignore_dht_put_root = 0;
+int found_blocks = 0, missing_blocks = 0;
+
+/*
+Key randomKeys[TEST_NETWORK_SIZE];
+int randomKeysCount = 0;
+*/
+
+char hashTable[HASH_TABLE_SIZE][ENTRY_SIZE];
+int hashTableSize = 0;
+
+// put the block in the dht
+void dht_put(char *block)
+{
+    // current implementation is dummy... its just storing the block's Id
+    if (hashTableSize >= HASH_TABLE_SIZE)
+        fprintf(stderr, "ERROR: the hashtable is full \n");
+    else
+    {
+        strcpy(hashTable[hashTableSize++], block);
+//        fprintf(stdout, "putting %s \n", block);
+    }
+}
+
+bool dht_get(char *blockId)
+{
+    int i = 0;
+    for( i = 0; i < hashTableSize; i++)
+        if (strcmp(blockId, hashTable[i]) == 0)
+            return true;
+
+    return false;
+}
+
+void forward_handler (Key ** kp, Message ** mp, ChimeraHost ** hp)
+{
+    Message *m = *mp;
+    if (m->type == DHT_GET_ROOT || m->type == DHT_PUT_ROOT || m->type == DHT_GET_NONROOT || m->type == DHT_PUT_NONROOT)
+    { 
+        DhtMessage *dhtmsg = (DhtMessage *) (m->payload);
+        dhtmsg->hops++;
+
+        // if malicious, change the next-hop to yourself
+        /*
+	if (malice_type == MALICE_ALL_BOOTSTRAP && strcmp(mykey, m->source.keystr))
+        {
+            str_to_key(mykey, &(mp[0]->dest)); // set the destination to self
+            hp[0] = ((ChimeraGlobal *)state->chimera)->me; // and set next hop to self
+            dhtmsg->hijacked = true; //set the bool to true..this means that the message is hijacked and should be treated differently when delivered
+        }
+	*/
+        //fprintf(stderr, "source: %s hijacker: %s \n", m->source.keystr, mykey);
+    }
+}
+
+int getRandomNumber ()
+{
+    struct timeval tm;
+    gettimeofday (&tm, NULL);
+    SEED (tm.tv_sec + tm.tv_usec);
+    return RAND () % 1000;
+}
+
+// only used by broadcast_to_replicas
+Key** get_right_leafset(ChimeraState *state, int *rsize)
+{
+    int i = 0;
+    Key **rightLeafKeys;
+    RouteGlobal *routeglob = (RouteGlobal *) state->route;
+
+    pthread_mutex_lock (&routeglob->lock);
+    *rsize = leafset_size (routeglob->rightleafset);
+    rightLeafKeys = (Key **)malloc(*rsize * sizeof(Key *));
+    for (i = 0; i < *rsize; i++)
+    {
+        rightLeafKeys[i] = (Key *) malloc(sizeof(Key));
+        key_assign(rightLeafKeys[i],  routeglob->rightleafset[i]->key);
+    }
+    pthread_mutex_unlock (&routeglob->lock);
+
+    return rightLeafKeys;
+}
+
+void broadcast_to_replicas(int msg_type, int size, char *payload)
+{
+    // send it to the DHT_REPLICATION number of ppl in your right leafset
+    // The assumption is that there are DHT_REPLICATION number of ppl in your right leafset
+    RouteGlobal *routeglob = (RouteGlobal *) state->route;
+    int rsize;
+    Key **rightleafkeys = get_right_leafset(state, &rsize);
+    int i = 0;
+    for (i = 0; i < rsize && i < DHT_REPLICATION; i++)
+    {
+        Key tempKey;
+        key_assign(&tempKey, *rightleafkeys[i]);
+
+        if (msg_type == DHT_PUT_NONROOT)
+        {
+            chimera_send (state, tempKey,
+                    DHT_PUT_NONROOT, size, payload);
+        }
+        else if (msg_type == DHT_GET_NONROOT)
+        {
+            chimera_send (state, tempKey,
+                    DHT_GET_NONROOT, size, payload);
+        }
+        else
+        {
+            fprintf(stderr, "ERROR: wrong message type in broadcast to replicas \n");
+        }
+    }
+}
+
+void printResult(char *blockId, int hops)
+{
+    if (dht_get(blockId) == true)
+    {
+        fprintf(stderr, "Found the block %s in %d hops \n", blockId, hops);
+        found_blocks++;
+    }
+    else
+    {
+        fprintf(stderr, "Block %s is missing even after %d hops \n", blockId, hops);
+        missing_blocks++;
+    }
+    fflush(stderr);
+}
+
+// take care of the messages delivered to a node
+void delivery_handler(Key * key, Message * msg)
+{
+    if(msg->type == DHT_GET_ROOT || msg->type == DHT_GET_NONROOT)
+    {
+        my_get_count++;
+    }
+    if(msg->type == DHT_PUT_ROOT || msg->type == DHT_PUT_NONROOT)
+    {
+        my_put_count++;
+    }
+/*    
+    if (msg->type == DHT_GET_ROOT || msg->type == DHT_PUT_ROOT || msg->type == DHT_GET_NONROOT || msg->type == DHT_PUT_NONROOT)
+    { 
+        // only if the message is hijacked, ignore it
+        DhtMessage *dhtmessage = (DhtMessage *)msg->payload;
+        if (dhtmessage->hijacked == true)
+        {
+            if (msg->type == DHT_PUT_ROOT)
+            {
+                ignore_dht_put_root++;
+            }
+            else if (msg->type == DHT_PUT_NONROOT)
+            {
+                ignore_dht_put_nonroot++;
+            }
+            else if (msg->type == DHT_GET_ROOT)
+            {
+                ignore_dht_get_root++;
+                // reply to the source 
+            }
+            else if (msg->type == DHT_GET_NONROOT)
+            {
+                ignore_dht_get_nonroot++;
+                // reply to the source 
+            }
+            return;
+        }
+    }
+*/
+     Key newKey;
+    if (msg->type == PUT_COMMAND)
+    {
+        DhtMessage *send = get_new_dhtmessage(msg->payload);
+        str_to_key(msg->payload, &newKey);
+        chimera_send(state, newKey, DHT_PUT_ROOT, sizeof(DhtMessage), (char *)send);
+    }
+    if (msg->type == GET_COMMAND)
+    {
+        DhtMessage *send = get_new_dhtmessage(msg->payload);
+        str_to_key(msg->payload, &newKey);
+        chimera_send(state, newKey, DHT_GET_ROOT, sizeof(DhtMessage), (char *)send);
+    }
+    else if (msg->type == DHT_PUT_ROOT)
+    {
+        DhtMessage *dhtmsg = (DhtMessage *) msg->payload;
+        dht_put(dhtmsg->blockId);
+        broadcast_to_replicas(DHT_PUT_NONROOT, msg->size, msg->payload);
+    }
+    else if (msg->type == DHT_PUT_NONROOT)
+    {
+        log_message (state->log, LOG_DATA,
+             "calling dht_put_nonroot \n");
+        DhtMessage *dhtmsg = (DhtMessage *) msg->payload;
+        dht_put(dhtmsg->blockId);
+    }
+    else if (msg->type == DHT_GET_ROOT)
+    {
+        DhtMessage *dhtmsg = (DhtMessage *) msg->payload;
+        printResult(dhtmsg->blockId, dhtmsg->hops);
+        broadcast_to_replicas(DHT_GET_NONROOT, msg->size, msg->payload);
+    }
+    else if (msg->type == DHT_GET_NONROOT)
+    {
+        DhtMessage *dhtmsg = (DhtMessage *) msg->payload;
+        printResult(dhtmsg->blockId, dhtmsg->hops);
+    }
+    else if (msg->type == DHT_DUMP_STATE)
+    {
+        fprintf(stderr, "%s has %d entries in its hashtable \n", mykey, hashTableSize);
+        fprintf(stderr, "my_get_count: %d my_put_count: %d \n", my_get_count, my_put_count);
+        fprintf(stderr, "ignored counters  dht_get_root: %d dht_get_nonroot: %d dht_put_root: %d dht_put_nonroot: %d \n",
+                ignore_dht_get_root, ignore_dht_get_nonroot, ignore_dht_put_root, ignore_dht_put_nonroot);
+        fprintf(stderr, "found_blocks: %d missing_blocks: %d \n", found_blocks, missing_blocks);
+        fflush(stderr);
+    }
+}
+
+/*
+void read_hosts_entries()
+{
+    FILE *fp = fopen (HOSTS_FILE, "r");
+    if (fp == NULL)
+    {
+        perror ("unable to open the hosts file \n");
+        exit (1);
+    }
+    char hn[200], keyinput[200];
+    int port;
+    char s[1000];
+    randomKeysCount = 0;
+
+    while (fgets (s, 256, fp) != NULL)
+    {
+        if (randomKeysCount == TEST_NETWORK_SIZE-1) break;
+
+        sscanf (s, "%s %d %s", hn, &port, keyinput);
+        str_to_key (keyinput, &randomKeys[randomKeysCount]);
+        randomKeysCount++;
+    }
+    fclose (fp);
+}*/
+
+int main (int argc, char **argv)
+{
+    int opt;
+    char *hn = NULL;
+    int port, joinport;
+    ChimeraHost *join = NULL;
+    char tmp[256];
+    int i, j;
+    Message *hello;
+
+    while ((opt = getopt (argc, argv, OPTSTR)) != EOF)
+    {
+        switch ((char) opt)
+        {
+        case 'j':
+            for (i = 0; optarg[i] != ':' && i < strlen (optarg); i++);
+            optarg[i] = 0;
+            hn = optarg;
+            sscanf (optarg + (i + 1), "%d", &joinport);
+            break;
+        default:
+            fprintf (stderr, "invalid option %c\n", (char) opt);
+            fprintf (stderr, "usage: %s\n", USAGE);
+            exit (1);
+        }
+    }
+
+    if ((argc - optind) != 3)
+    {
+        fprintf (stderr, "usage: %s\n", USAGE);
+        exit (1);
+    }
+
+    port = atoi (argv[optind]);
+    str_to_key (argv[optind + 1], &key);
+    //malice_type = atoi(argv[optind + 2]);
+    state = chimera_init (port);
+    chimera_setkey (state, key);
+    strcpy(mykey, key.keystr);
+    srand (time (NULL));
+
+    if (hn != NULL)
+    {
+        join = host_get (state, hn, joinport);
+    }
+
+    //if (malice_type != MALICE_NONE)
+    //{
+    //    fprintf(stderr, "%s is malicious of type %d \n", mykey, malice_type);
+    //}
+
+    chimera_register (state, HELLO_MESSAGE, 1);
+    chimera_register (state, PUT_COMMAND, 1);
+    chimera_register (state, GET_COMMAND, 1);
+    chimera_register (state, DHT_GET_ROOT, 1);
+    chimera_register (state, DHT_GET_NONROOT, 1);
+    chimera_register (state, DHT_PUT_NONROOT, 1);
+    chimera_register (state, DHT_PUT_ROOT, 1);
+    chimera_register (state, DHT_DUMP_STATE, 1);
+
+    //char networkdebug[256], routingdebug[256];
+    //      sprintf(networkdebug, "LOG_NETWORKDEBUG_%s", keyinput.keystr); 
+    //sprintf (routingdebug, "LOG_ROUTING_%s", key.keystr);
+    //      FILE *networklogfp= fopen(networkdebug, "w");
+    //FILE *routingfp = fopen (routingdebug, "w");
+    //log_direct (state->log, LOG_ROUTING, routingfp);
+    //      log_direct(state->log, LOG_NETWORKDEBUG, networklogfp);
+
+    //char cashmeredebug[256];
+    //sprintf (cashmeredebug, "logs/LOG_DATA%s", key.keystr);
+    //FILE *cashmerefp = fopen (cashmeredebug, "w");
+    //log_direct (state->log, LOG_DATA, cashmerefp);
+
+    log_direct (state->log, LOG_WARN, stderr);
+    log_direct (state->log, LOG_ERROR, stderr);
+
+    //read_hosts_entries();
+    chimera_deliver (state, delivery_handler);
+    chimera_forward (state, forward_handler);
+
+    driver = host_get (state, "marrow", 11110);
+
+    if (join != NULL)
+    {
+        chimera_join (state, join);
+        sprintf (tmp, "%d %s joining with %s:%d", port, key.keystr, hn,
+             joinport);
+    }
+    else
+    {
+        sprintf (tmp, "%d %s starting system", port, key.keystr, hn,
+             joinport);
+    }
+
+    hello = message_create (driver->key, HELLO_MESSAGE, strlen (tmp) + 1, tmp);
+    while(!message_send (state, driver, hello, TRUE));
+    free (hello);
+
+    while (1)
+    {
+        sleep (1000);
+    }
+}

test/simpledht_test.c

+/*
+ ** Author: Krishna Puttaswamy
+ ** This test is to store and retrieve blocks in dht.
+ **   Bring up a network of specified size, insert blocks into it and finally retrieve the blocks
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include "dht.h"
+#include "chimera.h"
+#include "message.h"
+#include "log.h"
+#include "key.h"
+#include "jrb.h"
+#include "jval.h"
+#include "semaphore.h"
+#include "dtime.h"
+
+extern char *optarg;
+extern int optind;
+#define OPTSTR "f:"
+#define USAGE "./dhttest malice_percentage"
+#define EXECUTABLE_NAME "./dht"
+
+int malice_percentage;
+int announced;
+void *sem;
+Key current;
+ChimeraState *state;
+
+typedef struct
+{
+	char *hnp;
+	char *name;
+	int port;
+	Key key;
+	int pid;
+} Host;
+
+JRB read_hosts (char *fn, int *nhosts)
+{
+	FILE *fp;
+	char s[256];
+	char hn[128];
+	int port;
+	Key key;
+	JRB hosts;
+	char keyinput[64];
+
+	fp = fopen (fn, "r");
+	if (fp == NULL)
+	{
+		perror (fn);
+		exit (1);
+	}
+
+	hosts = make_jrb ();
+	*nhosts = 0;
+
+	while (fgets (s, 256, fp) != NULL)
+	{
+		sscanf (s, "%s %d %s", hn, &port, keyinput);
+		Host *host = (Host *) malloc (sizeof (Host));
+		host->name = strdup (hn);
+		host->port = port;
+
+		str_to_key (keyinput, &key);
+		key_assign (&(host->key), key);
+		sprintf (s, "%s:%d", hn, port);
+		host->hnp = strdup (s);
+		host->pid = 0;
+		jrb_insert_str (hosts, strdup (s), new_jval_v (host));
+		*nhosts++;
+	}
+	fclose (fp);
+
+	return (hosts);
+}
+
+void redirect_to_chimera(ChimeraState * chstate, Message * msg)
+{
+	fprintf(stderr, " inside redirect: \n");
+    chimera_route (chstate, &msg->dest, msg, NULL);
+}
+
+void hello (ChimeraState * chstate, Message * msg)
+{
+	fprintf (stderr, "inside hello: %s\n", msg->payload);
+	announced++;
+	sema_v (sem);
+}
+
+void start_host (Host * host, Host * join)
+{
+	char port[16], key[160];
+	char ssh[100] = "ssh";
+	memset (port, 0, 16);
+	memset (key, 0, 160);
+	char *arg[9];
+	int i;
+
+	char currentHost[256];
+	gethostname(currentHost, 100); // get the currenthostname
+	//fprintf(stderr, "The hostname is %s \n", currentHost);
+
+	sprintf (port, "%d", host->port);
+	sprintf (key, "%s", host->key.keystr);
+	//  arg[0] = "ssh";
+	//  arg[1] = host->name;
+	char sshcommand[1000];
+	int rand_num = rand()%100;
+	int malicious = 0;
+	// for now, all nodes are malicious only of type MALICE_ALL_BOOTSTRAP
+	if (rand_num < malice_percentage)
+		malicious = MALICE_ALL_BOOTSTRAP;
+	char malice[10];
+	memset (malice, 0, 10);
+	sprintf(malice, "%d", malicious);
+
+
+	arg[0] = EXECUTABLE_NAME;
+	if (join != NULL)
+	{
+		arg[1] = "-j";
+		arg[2] = join->hnp;
+		arg[3] = port;
+		arg[4] = key;
+        arg[5] = malice;
+		arg[6] = NULL;
+		sprintf(sshcommand, "%s %s %s %s %s %s", arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
+	}
+	else
+	{
+		arg[1] = port;
+		arg[2] = key;
+		arg[3] = malice;
+		arg[4] = NULL;
+		sprintf(sshcommand, "%s %s %s %s", arg[0], arg[1], arg[2], arg[3]);
+	}
+
+	//:fprintf(stderr, "nodehost is %s and currenthost is %s \n", host->name, currentHost);
+	if (strcmp(host->name, "localhost")==0 || strcmp(host->name, currentHost) == 0)
+	{
+	}
+	else
+	{
+		arg[0] = ssh;
+		arg[1] = host->name;
+		arg[2] = sshcommand;
+		arg[3] = NULL;
+		//	fprintf(stderr, "Ssh command is %s \n", sshcommand);
+	}
+	host->pid = fork ();
+
+	if (host->pid == 0)
+	{
+		if (strcmp(arg[0], "ssh") == 0)
+		{
+//		    fprintf(stderr, "The ssh command to be executed on %s is %s \n", arg[1], arg[2]);
+			execvp("/usr/bin/ssh", arg);
+		}
+		else
+		{
+			execvp (EXECUTABLE_NAME, arg);
+		}
+
+		fprintf(stderr, "ERROR ERROR ERROR!!!! THE EXECVP RETURNED in the driver \n");
+		perror (EXECUTABLE_NAME);
+		exit (1);
+	}
+
+	sema_p (sem, 0.0);
+}
+
+void key_rand (Key * key)
+{
+	int i;
+	for (i = 0; i < 5; i++)
+	{
+		key->t[i] = rand ();
+	}
+	key_to_str (key);
+}
+
+
+bool read_from_file(FILE *fp, char *block)
+{
+	// assumption is that the file contains each entry of size entry_size
+	if (fgets(block, ENTRY_SIZE, fp) == NULL)
+		return false;
+
+	int i = 0;
+	// replace new line -- just to making the output pretty
+	int len = strlen(block);
+	for(i = 0; i < len; i++)
+		if(block[i] == '\n')
+		{
+			block[i] = '\0';
+			break;;
+		}
+
+	return true;
+}
+
+int main (int argc, char **argv)
+{
+	int opt;
+	char *configfile = HOSTS_FILE;
+	JRB hosts, node, node2;
+	Host *host, *join, *me;
+	int nhosts;
+	char dest[160];
+	char msg[256];
+	Key tmp;
+	ChimeraHost ch;
+	double start;
+	int i = 0;
+
+	while ((opt = getopt (argc, argv, OPTSTR)) != EOF)
+	{
+		switch ((char) opt)
+		{
+			case 'f':
+				configfile = optarg;
+				break;
+			default:
+				fprintf (stderr, "invalid option %c\n", (char) opt);
+				fprintf (stderr, "usage: %s\n", USAGE);
+				exit (1);
+		}
+	}
+    if ((argc - optind) != 1)
+	{
+	    fprintf (stderr, "usage: %s\n", USAGE);
+	    exit (1);
+	}
+
+    malice_percentage = atoi (argv[optind]);
+	fprintf(stdout, "The network is supposed to have %d percentage of malice \n", malice_percentage);
+	fprintf(stdout, "The blocks file should have %d blocks \n", TEST_NETWORK_SIZE * BLOCKS_PER_FILE * FILES_PER_NODE);
+
+	FILE *blockFP = fopen(BLOCKS_FILE, "r");
+	int count = 0;
+	// assuming that the contents of base16 keys that are not more than 100 bytes long
+	char block[100];
+	while(fgets(block, 100, blockFP)!= NULL)
+	{
+		count++;
+	}
+	fclose(blockFP);
+
+	// if there is not enuf blocks, exit
+	if (count != (TEST_NETWORK_SIZE * BLOCKS_PER_FILE * FILES_PER_NODE))
+	{
+		fprintf(stderr, "The file doesn't contain enough IDs... please regenerate the file  \n");
+		exit(1);
+	}
+
+	sem = sema_create (0);
+	state = (ChimeraState *) malloc (sizeof (ChimeraState));
+
+	hosts = read_hosts (configfile, &nhosts);
+
+	state->log = log_init ();
+	log_direct (state->log, LOG_ERROR, stderr);
+	log_direct (state->log, LOG_WARN, stderr);
+
+	key_init ();
+	state->message = message_init (state, 11110);
+	message_handler (state, HELLO_MESSAGE, hello, 1);
+	//TODO: verify the statement below
+	message_handler (state, GET_COMMAND, redirect_to_chimera, 1);
+	message_handler (state, PUT_COMMAND, redirect_to_chimera, 1);
+	message_handler (state, DHT_DUMP_STATE, redirect_to_chimera, 1);
+
+	srand (time (NULL));
+
+	/* This part runs cashmere in different hosts */
+
+	announced = 0;
+	jrb_traverse (node, hosts)
+	{
+		if (announced == 0)
+		{
+			join = NULL;
+		}
+		else
+		{
+			i = (rand () % announced) + 1;
+			jrb_traverse (node2, hosts)
+			{
+				i--;
+				if (i == 0)
+					break;
+			}
+			join = (Host *) node2->val.v;
+		}
+		host = (Host *) node->val.v;
+
+		start_host (host, join);
+		dsleep (0.05);
+	}
+	dsleep(61);
+
+	int  k = 0;
+	blockFP = fopen(BLOCKS_FILE, "r");
+	while(1)
+	{
+		if (read_from_file(blockFP, block) == false)
+			break;
+
+		i = (rand() % announced) + 1;
+		jrb_traverse (node, hosts)
+		{
+			i--;
+			if (i == 0)
+				break;
+		}
+		host = (Host *) node->val.v;
+		ch.name = host->name;
+		ch.address = network_address (state->network, host->name);
+		ch.port = host->port;
+		key_assign (&ch.key, host->key);
+
+		// insert a block
+		Message *m = message_create (ch.key, PUT_COMMAND, strlen(block) + 1, block);
+		message_send (state, &ch, m, TRUE);
+		k++;
+	}
+	fclose(blockFP);
+	fprintf(stdout, "Inserted %d blocks into the DHT ...now looking them up\n", k);
+
+	blockFP = fopen(BLOCKS_FILE, "r");
+	int breakout = 0;
+	count = 0;
+	while(1)
+	{
+		if (breakout == 1)
+			break;
+
+		i = (rand() % announced) + 1;
+		jrb_traverse (node, hosts)
+		{
+			i--;
+			if (i == 0)
+				break;
+		}
+		host = (Host *) node->val.v;
+		ch.name = host->name;
+		ch.address = network_address (state->network, host->name);
+		ch.port = host->port;
+		key_assign (&ch.key, host->key);
+
+		// each node will lookup alls the blocks for the avg. number of files on each block
+		int k = 0;
+		for (k = 0; k < FILES_PER_NODE; k++)
+		{
+			if ( breakout == 1) break;
+
+			int j = 0;
+			for (j = 0; j < BLOCKS_PER_FILE; j++)
+			{
+				if (read_from_file(blockFP, block) == false)
+				{
+					breakout = 1;
+					break;
+				}
+
+				fprintf(stderr, "Looking for %s \n", block);
+				Message *m = message_create (ch.key, GET_COMMAND, strlen(block) + 1, block);
+				message_send (state, &ch, m, TRUE);
+				count++;
+			}
+			dsleep(.1);
+		}
+		dsleep(.2);
+	}
+	fclose(blockFP);
+	fprintf(stdout, "Lookedup %d blocks into the DHT \n", count);
+
+	// dump hashtable statistics of each node at the end of expt
+	jrb_traverse (node, hosts)
+	{
+		host = (Host *) node->val.v;
+		ch.name = host->name;
+		ch.address = network_address (state->network, host->name);
+		ch.port = host->port;
+		key_assign (&ch.key, host->key);
+		Message *m = message_create (ch.key, DHT_DUMP_STATE, strlen(host->name) + 1, host->name);
+		message_send (state, &ch, m, TRUE);
+	}
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.