#include #include #include #include #include #include #include #include #include #include #include "message.h" #include "log.h" #include "host.h" #include "jrb.h" #include "jval.h" #include "semaphore.h" #include "dtime.h" #include "dht.h" char *optarg; int optind; #define RAND() (lrand48()) #define SEED(s) (srand48(s)) #define OPTSTR "f:" #define USAGE "./churndhtdriver [-f hostsfilename] networksize testRuntime lifetimeTraceFile" //if a different filename than "hosts" is to be used, -f option can be used char currentHost[100]; int stopNewNodes = 0; int nodecount = 0; typedef struct NodeRecord { int pid; char *key; } NodeRecord; NodeRecord nodelist[200]; int currentnetworksize = 0; void signal_handler (int sig) { if (sig == SIGALRM) { fprintf (stderr, "Got a SIGALRM signal ... Not introducing anymore nodes in to hte network\n"); stopNewNodes = 1; // just exit here itself fprintf (stderr, "The number of nodes introduced was %d \n", nodecount); exit (0); } } int main (int argc, char **argv) { int numHosts = 0; int opt; char *configfile = HOSTS_FILE; //default hosts file name assumed struct timeval t; int i = 0; gethostname (currentHost, 100); // get the currenthostname gettimeofday (&t, NULL); SEED (t.tv_sec + t.tv_usec); signal (SIGALRM, signal_handler); 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) != 3) { fprintf (stderr, "usage: %s\n", USAGE); exit (1); } /* fprintf(stderr, "%d arguments are ... ", argc); for (i = 0; i < argc; i++) { fprintf(stderr, " %s ", argv[i]); } fprintf(stderr, "\n"); fflush(stderr); */ char tracefilename[100] = ""; int networksize = atoi (argv[optind]); int testRuntime = atoi (argv[optind + 1]); // get the run time of this driverscript strcpy (tracefilename, argv[optind + 2]); FILE *tracefp = NULL; fprintf (stderr, "The networksize is %d \n", networksize); fprintf (stderr, "The configfile is %s \n", configfile); fprintf (stderr, "The runtime of the script is %d \n", testRuntime); fprintf (stderr, "Lifetime trace file is %s \n", tracefilename); tracefp = fopen (tracefilename, "r"); if (tracefp == NULL) { fprintf (stderr, "Error reading the lifetime tracefile %s \n", tracefilename); exit (1); } alarm (testRuntime); //open the file containing the hosts list //this file is expected to be of this format: //port key joinwaittime msgwaittime msgnumber ismalicious[1/0] FILE *fp = fopen (configfile, "r"); if (fp == NULL) { perror ("unable to open the file \n"); exit (1); } char s[256]; int sizeRead = 0; //how many entries in this file? while (fgets (s, 256, fp) != NULL) { numHosts++; } fclose (fp); fp = fopen (configfile, "r"); if (numHosts < networksize) { fprintf (stderr, "The number of nodes in input file is not sufficient \n"); exit (1); } fprintf (stderr, "Number of entries in the hosts file are: %d and the constant number of nodes to maintain is %d, lifetimeTracefile is %s\n", numHosts, networksize, tracefilename); //we will create as many processes as the number of entries in the file int first = 1; int firstTime = 1; char bootstrapKeyPort[256]; char sshCommand[1024] = ""; char option[100]; sprintf (option, "%s", "-j"); char nodeexe[100] = "./timeddhtnode"; int randomlife = 1; char tempString[256]; char deadnodekey[200] = ""; int uselastkey = 0; i = 0; // initialized to 0 int j = 0; nodecount = 0; while (1) { nodecount++; if (stopNewNodes == 1) { fprintf (stderr, "NO MORE NDOES WILL BE INTRODUCED \n"); break; } dsleep (0.1); char **arg = (char **) calloc (sizeof (char *) * 13, sizeof (char *)); int j; for (j = 0; j < 13; j++) { arg[j] = (char *) calloc (sizeof (char) * 256, 1); } if (fgets (s, 256, fp) == NULL) { fprintf (stderr, "The number of entries in the hosts file is over... exiting the loop \n"); break; } char *newkey = (char *) calloc (200 * sizeof (char), 1); //each process runs the node program which takes in 8 arguments. + 1 for process name, +1 for NULL //initialize this array of arguments strcpy (arg[0], nodeexe); //if not the first node, it must be given the bootstrap option //node usage is: ./node [-j bootstrap:port] port key lifetime if (!first) { char nodeHost[100]; strcpy (arg[1], option); strcpy (arg[2], bootstrapKeyPort); sscanf (s, "%s %s %s", nodeHost, arg[3], arg[4]); strcpy (newkey, arg[4]); int randtime = 0; if (fgets (tempString, 256, tracefp) == NULL) { fprintf (stderr, "The entries in the lifetime file is over \n"); } //fprintf(stderr, "The entry read from the lifetime file is %s \n", tempString); // need to pass this as an int randtime = (int) strtod (tempString, NULL); //fprintf(stderr, "randtime is %d; \n", randtime); char lifet[100]; sprintf (lifet, "%d", randtime); strcpy (arg[5], lifet); if (strcmp (nodeHost, "localhost") == 0 || strcmp (nodeHost, currentHost) == 0) { arg[6] = NULL; arg[7] = NULL; arg[8] = NULL; arg[9] = NULL; arg[10] = NULL; arg[11] = NULL; arg[12] = NULL; // running on the local machine.. be happpy } else { char temp[100]; strcpy (sshCommand, ""); arg[12] = NULL; for (j = 6; j > 0; j--) { arg[j] = arg[j - 1]; } for (j = 1; j < 12; j++) { sprintf (temp, "%s ", arg[j]); strcat (sshCommand, temp); arg[j] = NULL; } strcpy (arg[0], "ssh"); arg[1] = nodeHost; arg[2] = sshCommand; //fprintf (stderr, "Ssh command is %s \n", sshCommand); } //fprintf (stderr, //"args are: %s %s %s %s %s %s %s %s %s %s %s %s %s\n", //arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], //arg[6], arg[7], arg[8], arg[9], arg[10], arg[11], //arg[12]); } else { // for the bootstrap node, we need to pass in another parameter. Namely the file from which the keys should be read // this is passed only for the bootstrap node and not to any other nodes as the bootstrap node only sends out messages char nodeHost[100]; sscanf (s, "%s %s %s", nodeHost, arg[1], arg[2]); strcpy (newkey, arg[2]); // use the key of the last dead node strcpy (arg[3], "3000000"); //The first node will be there for a long long time first = 0; if (strcmp (nodeHost, "localhost") == 0 || strcmp (nodeHost, currentHost) == 0) { arg[4] = NULL; // running on the local machine.. be happpy sprintf (bootstrapKeyPort, "%s:%s", currentHost, arg[1]); printf ("The bootstrapkeyport is %s \n", bootstrapKeyPort); } else { sprintf (bootstrapKeyPort, "%s:%s", nodeHost, arg[1]); printf ("The bootstrapkeyport is %s \n", bootstrapKeyPort); char temp[100]; strcpy (sshCommand, ""); arg[12] = NULL; for (j = 0; j < 4; j++) { sprintf (temp, "%s ", arg[j]); strcat (sshCommand, temp); } strcpy (arg[0], "ssh"); arg[1] = nodeHost; arg[2] = sshCommand; arg[3] = NULL; //fprintf (stderr, "Ssh command is %s \n", sshCommand); } //fprintf(stderr, "args are: %s, %s, %s, %s, %s, %s, %s, %s\n", arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7]); } nodelist[currentnetworksize].pid = fork (); nodelist[currentnetworksize].key = (char *) calloc (sizeof (char) * 200, 1); strcpy (nodelist[currentnetworksize].key, newkey); if (nodelist[currentnetworksize].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 (nodeexe, arg); } fprintf (stdout, "ERROR ERROR ERROR!!!! THE EXECVP RETURNED in the driver \n"); perror (nodeexe); exit (1); } if (firstTime == 1) { sleep (2); firstTime = 0; } i++; currentnetworksize++; if (i == networksize) { fprintf (stderr, "Finished introducing first %d nodes\n", networksize); uselastkey = 1; } if (i >= networksize) { randomlife = 0; int pid, status; pid = wait (&status); int kkk = 0; for (kkk = 0; kkk < currentnetworksize; kkk++) if (nodelist[kkk].pid == pid) { strcpy (deadnodekey, nodelist[kkk].key); free (nodelist[kkk].key); int jjj = 0; for (jjj = kkk; jjj < currentnetworksize - 1; jjj++) { nodelist[jjj].pid = nodelist[jjj + 1].pid; nodelist[jjj].key = nodelist[jjj + 1].key; nodelist[jjj + 1].pid = 0; nodelist[jjj + 1].key = NULL; } currentnetworksize--; fprintf (stderr, "currentnetworksize: %d deadnodekey: %s newkey: %s\n", currentnetworksize, deadnodekey, newkey); break; } } } fprintf (stderr, "The number of nodes introduced was %d \n", nodecount); fclose (fp); // close the file exit (0); printf ("Driver is Sleeping!!!! and waiting for %d nodes to die gracefully \n", networksize - 2); int k = 0; for (k = 0; k < networksize - 2; k++) { int pid; wait (&pid); } printf ("DRIVER IS DYING!!!! \n"); // free the memory allocated above }