#include #include #include #include #include #include #include #include #include #include #include "cashmere.h" #include "message.h" #include "log.h" #include "host.h" #include "jrb.h" #include "jval.h" #include "semaphore.h" #include "chimera.h" #include "dtime.h" extern char *optarg; extern int optind; #define RAND() (lrand48()) #define SEED(s) (srand48(s)) #define OPTSTR "f:" #define USAGE "./singledriver [-f hostsfilename] numberofnodes nodelifetime runTime [exponentialPointsFile]" //if a different filename than "hosts" is to be used, -f option can be used char currentHost[100]; int stopNewNodes = 0; static int count = 0; double lasttime = 0; pthread_mutex_t lock; char *nodekeys[200]; typedef struct NodeRecord { int pid; char *key; }NodeRecord; NodeRecord nodelist[200]; int currentnetworksize = 0; char path[PATH_LENGTH][200]; int alreadypresent(int len, char *str) { int i = 0; for(i = 0; i <= len; i++) if (strcmp(str, path[i]) == 0) return 1; return 0; } void create_new_path() { int i = 0; if (lasttime != 0) { fprintf(stderr, "Rebuilding the path after %f seconds \n", getTime() - lasttime); } pthread_mutex_lock(&lock); for(i = 0; i < PATH_LENGTH; i++) { int randnum = RAND()%currentnetworksize; // ignore the first entry as its the bootstrap node with very high lifetime while(randnum == 0 || alreadypresent(i, nodelist[randnum].key)) randnum = RAND()%currentnetworksize; strcpy(path[i], nodelist[randnum].key); } pthread_mutex_unlock(&lock); fprintf(stderr, "The new path is .. \n"); for(i = 0; i < PATH_LENGTH; i++) { fprintf(stderr, "%s\n", path[i]); } lasttime = getTime(); fprintf(stderr, "lasttime is %f \n", lasttime); } int ispathalive() { pthread_mutex_lock(&lock); int i = 0; for(i = 0; i < PATH_LENGTH; i++) { int j = 0; for(j = 0; j < currentnetworksize; j++) { if (strcmp(path[i], nodelist[j].key) == 0) break; } if (j == currentnetworksize) { pthread_mutex_unlock(&lock); return 0; } } pthread_mutex_unlock(&lock); return 1; } void* send_messages(void* ) { fprintf(stderr, "building path for the first time \n"); create_new_path(); while(1) { if (ispathalive() == 0) { create_new_path(); } sleep(EVAL_MESSAGE_DELAY); } } 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", count); exit(0); } } int main(int argc, char **argv) { int numHosts = 0; int opt; char *configfile = "hosts"; //default hosts file name assumed gethostname(currentHost, 100); // get the currenthostname struct timeval t; 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 || (argc - optind) > 4) { fprintf(stderr, "usage: %s\n", USAGE); exit(1); } int numberofnodes = atoi(argv[optind]); int nodelifetime = atoi(argv[optind+1]); int runTime = atoi(argv[optind+2]); // get the run time of this driverscript int exponentialDistribution = 0; char expFileName[100] = ""; FILE *expFp = NULL; if( (argc-optind) == 4) { exponentialDistribution = 1; strcpy(expFileName, argv[optind + 3]); } fprintf(stderr, "The numberofnodes is %d \n", numberofnodes); fprintf(stderr, "The nodelifetime is %d \n", nodelifetime); fprintf(stderr, "The configfile is %s \n", configfile); fprintf(stderr, "The runtime of the script is %d \n", runTime); if (pthread_mutex_init(&lock, NULL) != 0) { fprintf(stderr, "Error initializing the lock \n"); } if (exponentialDistribution != 1) { fprintf(stderr, "The lifetime generated would be random (normal) distribution \n"); } else { fprintf(stderr, "The lifetime of nodes would be exponential distribution from the file %s \n", expFileName); expFp = fopen(expFileName, "r"); if (expFp == NULL) { fprintf(stderr, "Error reading the exp file %s \n", expFileName); exit(1); } } alarm(runTime); //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 < numberofnodes) { 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, exponentialDistribution is %d\n", numHosts, numberofnodes, exponentialDistribution); //we will create as many processes as the number of entries in the file int first = 1, i; int firstTime = 1; char bootstrapKeyPort[256]; char sshCommand[1024] = ""; char option[100]; sprintf(option, "%s", "-j"); char life[100]; char nodeexe[100] = "./singlenode"; int randomlife = 1; char tempString[256]; sprintf(life, "%d", nodelifetime); i = 0; // initialized to 0 int j = 0; count = 0; while(1) { count++; 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 ( exponentialDistribution == 0) { // if we are using normal random distribution, then do this // If X is the lifetime, choose a random number between x/2 and x+x/2 randtime = RAND()%nodelifetime + nodelifetime/2; // Pick a randome number between liftime } else { if (fgets(tempString, 256, expFp) == 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 { char nodeHost[100]; sscanf(s, "%s %s %s", nodeHost, arg[1], arg[2]); strcpy(newkey, arg[2]); 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; arg[5] = 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(5); firstTime = 0; } /* for(j=0;j<13;j++) { printf( "freeing for i = %d j = %d\n",i, j); free(arg[j]); } free(arg); */ i++; currentnetworksize++; if (i == numberofnodes) { fprintf(stderr, "Finished introducing first %d nodes\n", numberofnodes); // this should be run only once... and henc using i in the if condition above pthread_t tid; if (pthread_create (&tid, NULL, send_messages, NULL)!= 0) { fprintf(stderr, "Error creating a new thread\n"); } } if (i >= numberofnodes) { randomlife = 0; int pid, status; pid = wait(&status); int kkk = 0; char temp[200]; for(kkk = 0; kkk < currentnetworksize; kkk++) if (nodelist[kkk].pid == pid) { strcpy(temp, 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 \n", currentnetworksize, temp); break; } } } fprintf(stderr, "The number of nodes introduced was %d \n", count); fclose(fp); // close the file exit(0); printf("Driver is Sleeping!!!! and waiting for %d nodes to die gracefully \n", numberofnodes-2); int k =0; for(k = 0; k < numberofnodes-2; k++) { int pid; wait(&pid); } printf("DRIVER IS DYING!!!! \n"); // free the memory allocated above }