Changes to make charmrun recover in the SMP mode.
[charm.git] / src / arch / net / charmrun / charmrun.c
1 #include "converse.h"
2
3 #include "../sockRoutines.h"
4 #include "../sockRoutines.c"
5 #include "../ccs-auth.h"
6 #include "../ccs-auth.c"
7 #include "../ccs-server.h"
8 #include "../ccs-server.c"
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <errno.h>
14 #include <setjmp.h>
15 #include <stdlib.h>
16 #include <signal.h>
17 #include <fcntl.h>
18 #include <time.h>
19 #include <assert.h>
20 #include <math.h>
21 #if CMK_BPROC
22 #include <sys/bproc.h>
23 #endif
24 #if CMK_USE_POLL
25 #include <poll.h>
26 #endif
27 #include <sys/stat.h>
28
29
30 #if defined(_WIN32) && !defined(__CYGWIN__)
31 /*Win32 has screwy names for the standard UNIX calls:*/
32 #define getcwd _getcwd
33 #define strdup _strdup
34 #define unlink _unlink
35 #define open _open
36 #define fdopen _fdopen
37 #define ftruncate _chsize
38 #include <winbase.h>
39 #include <direct.h>
40 #include <io.h>
41 #include <sys/timeb.h>
42 #include <process.h>
43 #define DIRSEP "\\"
44 #define SIGBUS -1  /*These signals don't exist in Win32*/
45 #define SIGKILL -1
46 #define SIGQUIT -1
47
48
49 #else /*UNIX*/
50 #include <pwd.h>   /*getcwd*/
51 #include <unistd.h>
52 #define DIRSEP "/"
53 #endif
54
55 #if CMK_RSH_NOT_NEEDED /*No RSH-- use daemon to start node-programs*/
56 #  define CMK_USE_RSH 0
57
58 #else /*Use RSH to start node-programs*/
59 #  define CMK_USE_RSH 1
60 #ifdef __MINGW_H
61 #  include <rpc.h>
62 #elif !defined(__CYGWIN__)
63 #  include <rpc/rpc.h>
64 #else
65 #  include <w32api/rpc.h>
66 #endif
67 #  if CMK_RSH_IS_A_COMMAND
68 #    define RSH_CMD "rsh"
69 #  endif
70
71 #  if CMK_RSH_USE_REMSH
72 #    define RSH_CMD "remsh"
73 #  endif
74 #endif
75
76 #include "daemon.h"
77
78 /*#define DEBUGF(x) printf x*/
79 #define DEBUGF(x) 
80
81 #ifndef MAXPATHLEN
82 #define MAXPATHLEN 1024
83 #endif
84
85
86 //#define HSTART
87 #ifdef HSTART
88 /*Hierarchical-start routines*/
89 int mynodes_start ;     /* To keep a global node numbering */
90
91 #endif
92
93 static double ftTimer;
94
95 double start_timer;
96
97 int *rsh_pids=NULL;
98                                                                                 
99 double GetClock(void)
100 {
101 #if defined(_WIN32) && !defined(__CYGWIN__)
102   struct _timeb tv;
103   _ftime(&tv);
104   return (tv.time * 1.0 + tv.millitm * 1.0E-3);
105 #else
106   struct timeval tv; int ok;
107   ok = gettimeofday(&tv, NULL);
108   if (ok<0) { perror("gettimeofday"); exit(1); }
109   return (tv.tv_sec * 1.0 + tv.tv_usec * 1.0E-6);
110 #endif
111 }
112
113
114 int probefile(path)
115     char *path;
116 {
117         FILE *f=fopen(path,"r");
118         if (f==NULL) return 0;
119         fclose(f);
120         return 1;
121 }
122
123 char *mylogin(void)
124 {
125 #if defined(_WIN32) && !defined(__CYGWIN__)
126         static char name[100]={'d','u','n','n','o',0};
127         int len=100;
128         GetUserName(name,&len);
129         return name;
130 #else /*UNIX*/
131   struct passwd *self;
132
133   self = getpwuid(getuid());
134   if (self==0) { 
135 #if CMK_HAS_POPEN
136     char cmd[16];
137     char uname[64];
138     FILE *p;
139     sprintf(cmd, "id -u -n");
140     p = popen(cmd, "r");
141     if (p){
142         fscanf(p, "%s", uname);
143         pclose(p);
144         return strdup(uname);
145     }
146     else
147         return "unknown"; 
148 #else
149     return "unknown"; 
150 #endif
151   }
152   return self->pw_name;
153 #endif
154
155
156 /**************************************************************************
157  *
158  * ping_developers
159  *
160  * Sends a single UDP packet to the charm developers notifying them
161  * that charm is in use.
162  *
163  **************************************************************************/
164
165 void ping_developers()
166 {
167 #ifdef NOTIFY
168   char               info[1000];
169   /*This is the resolved IP address of elegance.cs.uiuc.edu */
170   skt_ip_t destination_ip=skt_lookup_ip("128.174.241.211");
171   unsigned int destination_port=6571;
172   struct sockaddr_in addr=skt_build_addr(destination_ip,destination_port);
173   SOCKET             skt;
174   
175   skt = socket(AF_INET, SOCK_DGRAM, 0);
176   if (skt == INVALID_SOCKET) return;
177
178   sprintf(info,"%s",mylogin());
179   
180   sendto(skt, info, strlen(info), 0, (struct sockaddr *)&addr, sizeof(addr));
181   skt_close(skt);
182 #endif /* NOTIFY */
183 }
184
185 /**************************************************************************
186  *
187  * Pathfix : alters a path according to a set of rewrite rules
188  *
189  *************************************************************************/
190
191 typedef struct pathfixlist {
192   char *s1;
193   char *s2;
194   struct pathfixlist *next;
195 } *pathfixlist;
196
197 pathfixlist pathfix_append(char *s1, char *s2, pathfixlist l)
198 {
199   pathfixlist pf = (pathfixlist)malloc(sizeof(struct pathfixlist));
200   pf->s1 = s1;
201   pf->s2 = s2;
202   pf->next = l;
203   return pf;
204 }
205
206 char *pathfix(char *path, pathfixlist fixes)
207 {
208   char buffer[MAXPATHLEN]; pathfixlist l; 
209   char buf2[MAXPATHLEN]; 
210   char *offs; int mod, len;
211   strcpy(buffer,path);
212   mod = 1;
213   while (mod) {
214     mod = 0;
215     for (l=fixes; l; l=l->next) {
216       len = strlen(l->s1);
217       offs = strstr(buffer, l->s1);
218       if (offs) {
219         offs[0]=0;
220         sprintf(buf2,"%s%s%s",buffer,l->s2,offs+len);
221         strcpy(buffer,buf2);
222         mod = 1;
223       }
224     }
225   }
226   return strdup(buffer);
227 }
228
229 char *pathextfix(char *path, pathfixlist fixes, char *ext)
230 {
231   char *newpath = pathfix(path, fixes);
232   char *ret;
233   if (ext == NULL) return newpath;
234   ret = (char *)malloc(strlen(newpath)+strlen(ext)+2);
235   strcpy(ret, newpath);
236   strcat(ret, ext);
237   return ret;
238 }
239
240 /****************************************************************************
241  *
242  * Miscellaneous minor routines.
243  *
244  ****************************************************************************/
245
246 int is_quote(char c)
247 {
248   return (c=='\'' || c == '"');
249 }
250
251 void zap_newline(char *s)
252 {
253   char *p;
254   p = s + strlen(s)-1;
255   if (*p == '\n') *p = '\0';
256   /* in case of DOS ^m */
257   p--;
258   if (*p == '\15') *p = '\0';
259 }
260
261 /* get substring from lo to hi, remove quote chars */
262 char *substr(char *lo, char *hi)
263 {
264   int len;
265   char *res;
266   if (is_quote(*lo)) lo++;
267   if (is_quote(*(hi-1))) hi--;
268   len = hi-lo;
269   res = (char *)malloc(1+len);
270   memcpy(res, lo, len);
271   res[len]=0;
272   return res;
273 }
274
275 int subeqs(char *lo, char *hi, char *str)
276 {
277   int len = strlen(str);
278   if (hi-lo != len) return 0;
279   if (memcmp(lo, str, len)) return 0;
280   return 1;
281 }
282
283 /* advance pointer over blank characters */
284 char *skipblanks(char *p)
285 {
286   while ((*p==' ')||(*p=='\t')) p++;
287   return p;
288 }
289
290 /* advance pointer over nonblank characters and a quoted string */
291 char *skipstuff(char *p)
292 {
293   char quote = 0;
294   if (*p && (*p=='\'' || *p=='"')) { quote=*p; p++; }
295   if (quote != 0) {
296     while (*p&&*p!=quote) p++;
297     if (*p!=quote) {
298       fprintf(stderr, "ERROR> Unmatched quote in nodelist file.\n");
299       exit(1);
300     }
301     p++;
302   }
303   else
304     while ((*p)&&(*p!=' ')&&(*p!='\t')) p++;
305   return p;
306 }
307
308 #if CMK_USE_RSH
309 char *getenv_rsh()
310 {
311   char *e;
312
313   e = getenv("CONV_RSH");
314   return e ? e : RSH_CMD;
315 }
316 #endif
317
318 #if !defined(_WIN32) || defined(__CYGWIN__)
319 char *getenv_display()
320 {
321   static char result[100],ipBuf[200];
322   char *e, *p;
323   
324   e = getenv("DISPLAY");
325   if (e==0) return NULL;
326   p = strrchr(e, ':');
327   if (p==0) return NULL;
328   if ((e[0]==':')||(strncmp(e,"unix:",5)==0)) {
329     sprintf(result,"%s:%s",skt_print_ip(ipBuf,skt_my_ip()),p+1);
330   }
331   else strcpy(result, e);
332   return result;
333 }
334 char *getenv_display_no_tamper()
335 {
336   static char result[100],ipBuf[200];
337   char *e, *p;
338   
339   e = getenv("DISPLAY");
340   if (e==0) return NULL;
341   p = strrchr(e, ':');
342   if (p==0) return NULL;
343   strcpy(result, e);
344   return result;
345 }
346
347 #endif
348
349 /*****************************************************************************
350  *                                                                           *
351  * PPARAM - obtaining "program parameters" from the user.                    *
352  *                                                                           *
353  *****************************************************************************/
354
355 typedef struct ppdef
356 {
357   union {
358       int *i;
359       double *r;
360       char **s;
361       int *f;
362     } where;/*Where to store result*/
363   const char *lname; /*Argument name on command line*/
364   const char *doc;
365   char  type; /*One of i, r, s, f.*/
366   struct ppdef *next;
367 }
368 *ppdef;
369
370 static ppdef ppdefs;
371
372 static int     pparam_pos;
373 static char  **pparam_argv;
374 static char    pparam_optc='-';
375 char           pparam_error[100];
376
377 static ppdef pparam_find(lname)
378     const char *lname;
379 {
380   ppdef def;
381   for (def=ppdefs; def; def=def->next)
382     if (strcmp(def->lname, lname)==0)
383       return def;
384   return 0;
385 }
386
387 static ppdef pparam_cell(lname)
388     const char *lname;
389 {
390   ppdef def = pparam_find(lname);
391   if (def) return def;
392   def = (ppdef)malloc(sizeof(struct ppdef));
393   def->lname = lname;
394   def->type  = 's';
395   def->doc   = "(undocumented)";
396   def->next  = ppdefs;
397   ppdefs = def;
398   return def;
399 }
400
401
402
403 void pparam_int(int *where,int defValue,
404                                    const char *arg,const char *doc)
405 {
406   ppdef def = pparam_cell(arg);
407   def->type  = 'i';
408   def->where.i = where; *where=defValue;
409   def->lname=arg;
410   def->doc=doc;
411 }
412
413 void pparam_flag(int *where,int defValue,
414                                    const char *arg,const char *doc)
415 {
416   ppdef def = pparam_cell(arg);
417   def->type  = 'f';
418   def->where.f = where; *where=defValue;
419   def->lname=arg;
420   def->doc=doc;
421 }
422
423 void pparam_real(double *where,double defValue,
424                                    const char *arg,const char *doc)
425 {
426   ppdef def = pparam_cell(arg);
427   def->type  = 'r';
428   def->where.r = where; *where=defValue;
429   def->lname=arg;
430   def->doc=doc;
431 }
432 void pparam_str(char **where,char *defValue,
433                                    const char *arg,const char *doc)
434 {
435   ppdef def = pparam_cell(arg);
436   def->type  = 's';
437   def->where.s = where; *where=defValue;
438   def->lname=arg;
439   def->doc=doc;
440 }
441
442 static int pparam_setdef(def, value)
443     ppdef def; char *value;
444 {
445   char *p;
446   switch(def->type)
447     {
448     case 'i' :
449       *def->where.i = strtol(value, &p, 10);
450       if (*p) return -1;
451       return 0;
452     case 'r' :
453       *def->where.r = strtod(value, &p);
454       if (*p) return -1;
455       return 0;
456     case 's' :
457       *def->where.s = strdup(value);
458       return 0;
459     case 'f' :
460       *def->where.f = strtol(value, &p, 10);
461       if (*p) return -1;
462       return 0;
463     }
464   return -1;
465 }
466
467 int pparam_set(lname, value)
468     char *lname; char *value;
469 {
470   ppdef def = pparam_cell(lname);
471   return pparam_setdef(def, value);
472 }
473
474 char *pparam_getdef(def)
475     ppdef def;
476 {
477   static char result[100];
478   switch(def->type)
479     {
480     case 'i': sprintf(result,"%d", *def->where.i); return result;
481     case 'r': sprintf(result,"%f",*def->where.r); return result;
482     case 's': return *def->where.s?*def->where.s:"";
483     case 'f': sprintf(result,"%d", *def->where.f); return result;
484     }
485   return NULL;
486 }
487
488 void pparam_printdocs()
489 {
490   ppdef def; int len, maxname, maxdoc;
491   maxname = 0;
492   maxdoc = 0;
493   for (def=ppdefs; def; def=def->next)
494     {
495       len = strlen(def->lname);
496       if (len>maxname) maxname=len;
497       len = strlen(def->doc);
498       if (len>maxdoc) maxdoc=len;
499     }
500   fprintf(stderr,"\n");
501   fprintf(stderr,"Charmrun Command-line Parameters:\n");
502   for (def=ppdefs; def; def=def->next)
503     {
504       fprintf(stderr,"  %c%c%-*s ",pparam_optc,pparam_optc,maxname,def->lname);
505       fprintf(stderr,"  %-*s [%s]\n",maxdoc,def->doc,pparam_getdef(def));
506     }
507   fprintf(stderr,"\n");
508 }
509
510 void pparam_delarg(i)
511     int i;
512 {
513   int j;
514   for (j=i; pparam_argv[j]; j++)
515     pparam_argv[j]=pparam_argv[j+1];
516 }
517
518 int pparam_countargs(argv)
519     char **argv;
520 {
521   int argc;
522   for (argc=0; argv[argc]; argc++);
523   return argc;
524 }
525
526 int pparam_parseopt()
527 {
528   int ok; ppdef def=NULL;
529   char *opt = pparam_argv[pparam_pos];
530   /* handle ++ by skipping to end */
531   if ((opt[1]=='+')&&(opt[2]==0))
532     {
533       pparam_delarg(pparam_pos);
534       while (pparam_argv[pparam_pos]) pparam_pos++;
535       return 0;
536     }
537   /* handle + by itself - an error */
538   if (opt[1]==0) 
539     {
540       sprintf(pparam_error,"Illegal option +\n");
541       return -1;
542     }
543   /* look up option definition */
544   if (opt[1]=='+') def = pparam_find(opt+2);
545   else
546     {
547       char name[2];
548       name[0]=opt[1];
549       if (strlen(opt)<=2 || !isalpha(opt[2]))
550       {
551       name[1]=0;
552       def = pparam_find(name);
553       }
554     }
555   if (def==NULL)
556   {
557     if (opt[1]=='+')
558     {
559        sprintf(pparam_error,"Option %s not recognized.",opt);
560        return -1;
561     } else {
562            /*Unrecognized + option-- skip it.*/
563            pparam_pos++;
564            return 0;
565         }
566   }
567   /* handle flag-options */
568   if ((def->type=='f')&&(opt[1]!='+')&&(opt[2]))
569     {
570       sprintf(pparam_error,"Option %s should not include a value",opt);
571       return -1;
572     }
573   if (def->type=='f')
574     {
575       *def->where.f = 1;
576       pparam_delarg(pparam_pos);
577       return 0;
578     }
579   /* handle non-flag options */
580   if ((opt[1]=='+')||(opt[2]==0))
581     {
582       pparam_delarg(pparam_pos);
583       opt = pparam_argv[pparam_pos];
584     }
585   else opt+=2;
586   if ((opt == 0)||(opt[0] == 0))
587     {
588       sprintf(pparam_error,"%s must be followed by a value.",opt);
589       return -1;
590     }
591   ok = pparam_setdef(def, opt);
592   pparam_delarg(pparam_pos);
593   if (ok<0)
594     {
595       sprintf(pparam_error,"Illegal value for %s",opt);
596       return -1;
597     }
598   return 0;
599 }
600
601 int pparam_parsecmd(optchr, argv)
602     char optchr; char **argv;
603 {
604   pparam_error[0]=0;
605   pparam_argv = argv;
606   pparam_optc = optchr;
607   pparam_pos  = 0;
608   while(1)
609     {
610       char *opt = pparam_argv[pparam_pos];
611       if (opt==0) break;
612       if (opt[0]!=optchr) pparam_pos++;
613       else if (pparam_parseopt()<0) return -1;
614     }
615   return 0;
616 }
617
618 #ifdef HSTART
619 char **
620 dupargv (argv)
621      char **argv;
622 {
623   int argc;
624   char **copy;
625   
626   if (argv == NULL)
627     return NULL;
628   
629   /* the vector */
630   for (argc = 0; argv[argc] != NULL; argc++);
631   copy = (char **) malloc ((argc +2) * sizeof (char *));
632   if (copy == NULL)
633     return NULL;
634   
635   /* the strings */
636   for (argc = 0; argv[argc] != NULL; argc++)
637     {
638       int len = strlen (argv[argc]);
639       copy[argc] = malloc (sizeof (char ) * (len + 1));
640       strcpy (copy[argc], argv[argc]);
641     }
642   copy[argc] = NULL;
643   return copy;
644 }
645
646 #endif
647
648 /****************************************************************************
649  * 
650  * ARG
651  *
652  * The following module computes a whole bunch of miscellaneous values, which
653  * are all constant throughout the program.  Naturally, this includes the
654  * value of the command-line arguments.
655  *
656  *****************************************************************************/
657
658
659 #define MAX_NODES 1000
660 #define MAX_LINE_LENGTH 1000
661
662 char **arg_argv;
663 int    arg_argc;
664
665 int   arg_requested_pes;
666 int   arg_timeout;
667 int   arg_verbose;
668 char *arg_nodelist;
669 char *arg_nodegroup;
670 char *arg_runscript; /* script to run the node-program with */
671 char *arg_charmrunip;
672 #if CONVERSE_VERSION_VMI
673 char *arg_vmispecfile;
674 #endif
675
676 int   arg_debug;
677 int   arg_debug_no_pause;
678 int   arg_debug_no_xrdb;
679 int   arg_charmdebug;
680 char *arg_debug_commands; /* commands that are provided by a ++debug-commands flag. These are passed into gdb. */
681
682 int   arg_local;        /* start node programs directly by exec on localhost */
683 int   arg_batch_spawn;  /* control starting node programs, several at a time */
684 int   arg_scalable_start;
685
686 #ifdef HSTART
687 int       arg_hierarchical_start;
688 int       arg_child_charmrun;
689 #endif
690 int   arg_help;         /* print help message */
691 int   arg_ppn;          /* pes per node */
692 int   arg_usehostname;
693
694 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
695 int     arg_read_pes=0;
696 #endif
697
698 #if CMK_USE_RSH
699 int   arg_maxrsh;
700 char *arg_shell;
701 int   arg_in_xterm;
702 char *arg_debugger;
703 char *arg_xterm;
704 char *arg_display;
705 int arg_ssh_display;
706 char *arg_mylogin;
707 #endif
708 int   arg_mpiexec;
709 int   arg_no_va_rand;
710
711 char *arg_nodeprog_a;
712 char *arg_nodeprog_r;
713 char *arg_currdir_a;
714 char *arg_currdir_r;
715
716 int   arg_server;
717 int   arg_server_port=0;
718 char *arg_server_auth=NULL;
719 int   replay_single=0;
720
721 #if CMK_BPROC
722 int   arg_startpe;
723 int   arg_endpe;
724 int   arg_singlemaster;
725 int   arg_skipmaster;
726 #endif
727
728 void arg_init(int argc, char **argv)
729 {
730   static char buf[1024];
731   
732   int i, local_def=0;
733 #if CMK_CHARMRUN_LOCAL
734   local_def=1; /*++local is the default*/
735 #endif
736   
737   pparam_int(&arg_requested_pes, 1, "p",             "number of processes to create");
738   pparam_int(&arg_timeout,      60, "timeout",       "seconds to wait per host connection");
739   pparam_flag(&arg_verbose,      0, "verbose",       "Print diagnostic messages");
740   pparam_str(&arg_nodelist,      0, "nodelist",      "file containing list of nodes");
741   pparam_str(&arg_nodegroup,"main", "nodegroup",     "which group of nodes to use");
742 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
743         pparam_int(&arg_read_pes, 0, "readpe",             "number of host names to read into the host table");
744 #endif
745
746 #if CMK_CCS_AVAILABLE
747   pparam_flag(&arg_server,       0, "server",        "Enable client-server (CCS) mode");
748   pparam_int(&arg_server_port,   0, "server-port",   "Port to listen for CCS requests");
749   pparam_str(&arg_server_auth,   0, "server-auth",   "CCS Authentication file");
750 #endif
751   pparam_flag(&arg_local,       local_def, "local", "Start node programs locally without daemon");
752   pparam_int(&arg_batch_spawn,   0, "batch", "Rsh several node programs at a time, avoiding overloading charmrun pe");
753   pparam_flag(&arg_scalable_start, 0, "scalable-start", "scalable start");
754 #ifdef HSTART
755   pparam_flag(&arg_hierarchical_start, 0, "hierarchical-start", "hierarchical start");
756   pparam_flag(&arg_child_charmrun, 0, "child-charmrun", "child charmrun");
757 #endif
758   pparam_flag(&arg_usehostname,  0, "usehostname", "Send nodes our symbolic hostname instead of IP address");
759   pparam_str(&arg_charmrunip,    0, "useip",      "Use IP address provided for charmrun IP");
760   pparam_flag(&arg_mpiexec,          0, "mpiexec",   "use mpiexec to start jobs");
761 #if CMK_USE_RSH
762   pparam_flag(&arg_debug,         0, "debug",         "Run each node under gdb in an xterm window");
763   pparam_flag(&arg_debug_no_pause,0, "debug-no-pause","Like debug, except doesn't pause at beginning");
764   pparam_str(&arg_debug_commands,   0, "debug-commands",   "Commands to be run inside gdb at startup");
765   pparam_flag(&arg_debug_no_xrdb,0, "no-xrdb","Don't check xrdb");
766
767   /* When the ++charmdebug flag is used, charmrun listens from its stdin for
768      commands, and forwards them to the gdb info program (a child), or to the
769      processor gdbs. The stderr is redirected to the stdout, so the two streams
770      are mixed together. The channel for stderr is reused to forward the replies
771      of gdb back to the java debugger. */
772 #if !defined(_WIN32)
773   pparam_flag(&arg_charmdebug,    0, "charmdebug",    "Used only when charmrun is started by charmdebug");
774 #endif
775
776   pparam_int(&arg_maxrsh,        16, "maxrsh",        "Maximum number of rsh's to run at a time");
777   pparam_str(&arg_shell,          0, "remote-shell",  "which remote shell to use");
778   pparam_str(&arg_debugger,       0, "debugger",      "which debugger to use");
779   pparam_str(&arg_display,        0, "display",       "X Display for xterm");
780   pparam_flag(&arg_ssh_display,   0, "ssh-display",   "use own X Display for each ssh session");
781   pparam_flag(&arg_in_xterm,      0, "in-xterm",      "Run each node in an xterm window");
782   pparam_str(&arg_xterm,          0, "xterm",         "which xterm to use");
783 #endif
784 #ifdef CMK_BPROC
785   /* options for Scyld */
786   pparam_int(&arg_startpe,   0, "startpe",   "first pe to start job(SCYLD)");
787   pparam_int(&arg_endpe,  1000000, "endpe",   "last pe to start job(SCYLD)");
788   pparam_flag(&arg_singlemaster, 0, "singlemaster", "Only assign one process to master node(SCYLD)");
789   pparam_flag(&arg_skipmaster, 0, "skipmaster", "Donot assign any process to master node(SCYLD)");
790   if (arg_skipmaster && arg_singlemaster) {
791     printf("Charmrun> 'singlemaster' is ignored due to 'skipmaster'. \n");
792     arg_singlemaster = 0;
793   }
794   pparam_flag(&arg_debug,         0, "debug",         "turn on more verbose debug print");
795 #endif
796 #ifdef CONVERSE_VERSION_VMI
797   pparam_str (&arg_vmispecfile, 0, "specfile", "device specfile to load (VMI)");
798 #endif
799   pparam_str(&arg_runscript,    0, "runscript", "script to run node-program with");
800   pparam_flag(&arg_help,        0, "help", "print help messages");
801   pparam_int(&arg_ppn,          0, "ppn",             "number of pes per node");
802   pparam_flag(&arg_no_va_rand,   0, "no-va-randomization",   "Disables randomization of the virtual address  space");
803 #ifdef HSTART
804   arg_argv = dupargv(argv);
805 #endif
806
807   if (pparam_parsecmd('+', argv) < 0) {
808     fprintf(stderr,"ERROR> syntax: %s\n",pparam_error);
809     pparam_printdocs();
810     exit(1);
811   }
812   
813   /* Check for (but do *not* remove) the "-?", "-h", or "--help" flags */
814   for (i=0;argv[i];i++) {
815         if (0==strcmp(argv[i],"-?") ||
816             0==strcmp(argv[i],"-h") ||
817             0==strcmp(argv[i],"--help")) 
818                 arg_help=1;
819   }
820   if (arg_help) {
821     pparam_printdocs();
822     /*exit(0);*/
823   }
824
825 #ifdef HSTART
826   if (!arg_hierarchical_start || arg_child_charmrun)
827 #endif
828   arg_argv = argv+1; /*Skip over charmrun (0) here and program name (1) later*/
829   arg_argc = pparam_countargs(arg_argv);
830   if (arg_argc<1) {
831     fprintf(stderr,"ERROR> You must specify a node-program.\n");
832     pparam_printdocs();
833     exit(1);
834   }
835
836 #ifdef HSTART
837         if (!arg_hierarchical_start || arg_child_charmrun){
838                 //Removing nodeprogram from the list
839                 arg_argv++; arg_argc--;
840         }
841         else{
842                 //Removing charmrun from parameters     
843                 arg_argv++;arg_argc--;
844                 
845                 arg_argv[arg_argc]=malloc(sizeof(char) * strlen("++child-charmrun"));
846                 strcpy(arg_argv[arg_argc++],"++child-charmrun");
847                 arg_argv[arg_argc] = NULL;
848         }
849 #else
850   arg_argv++; arg_argc--;
851 #endif
852                                         
853   if (arg_server_port || arg_server_auth) arg_server=1;
854
855   if (arg_debug || arg_debug_no_pause) {
856         arg_verbose=1;
857         /*Pass ++debug along to program (used by machine.c)*/
858         arg_argv[arg_argc++]="++debug";
859   }
860
861   /* Check for +replay-detail to know we have to load only one single processor */
862   for (i=0;argv[i];i++) {
863     if (0==strcmp(argv[i],"+replay-detail")) {
864       replay_single = 1;
865       arg_requested_pes = 1;
866     }
867   }
868   
869 #ifdef CMK_BPROC
870   if (arg_local) {
871     fprintf(stderr,"Warning> ++local cannot be used in bproc version, ignored!\n");
872     arg_local = 0;
873   }
874 #endif
875
876 #if CMK_USE_RSH
877   /* Find the current value of the CONV_RSH variable */
878   if(!arg_shell) {
879     if (arg_mpiexec)
880       arg_shell = "mpiexec";
881     else
882       arg_shell = getenv_rsh();
883   }
884
885   /* Find the current value of the DISPLAY variable */
886   if(!arg_display)
887     arg_display = getenv_display_no_tamper();
888   if ((arg_debug || arg_debug_no_pause || arg_in_xterm) && (arg_display==0)) {
889     fprintf(stderr,"ERROR> DISPLAY must be set to use debugging mode\n");
890     exit(1);
891   }
892   if (arg_debug || arg_debug_no_pause) 
893     arg_timeout=8*60*60; /* Wait 8 hours for ++debug */
894
895   /* default debugger is gdb */
896   if(!arg_debugger)
897     arg_debugger = "gdb" ;
898   /* default xterm is xterm */
899   if(!arg_xterm)
900     arg_xterm = "xterm" ;
901
902   arg_mylogin = mylogin();
903 #endif
904
905 #if CONVERSE_VERSION_VMI
906   if (!arg_vmispecfile) {
907     arg_vmispecfile = getenv ("VMI_SPECFILE");
908   }
909
910   if (!arg_vmispecfile) {
911     fprintf (stderr, "ERROR> ++specfile not specified and VMI_SPECFILE not given in environment\n");
912     exit (1);
913   }
914 #endif
915
916   /* find the current directory, absolute version */
917   getcwd(buf, 1023);
918   arg_currdir_a = strdup(buf);
919     
920   /* find the node-program, absolute version */
921   arg_nodeprog_r = argv[1];
922
923   if (arg_nodeprog_r[0]=='-' || arg_nodeprog_r[0]=='+') 
924   { /*If it starts with - or +, it ain't a node program.
925       Chances are, the user screwed up and passed some unknown flag to charmrun*/
926      printf("Charmrun does not recognize the flag '%s'.\n",arg_nodeprog_r);
927      if (arg_nodeprog_r[0]=='+')
928        printf("Charm++'s flags need to be placed *after* the program name.\n");
929      pparam_printdocs();
930      exit(1);
931   }
932
933
934 #if defined(_WIN32) && !defined(__CYGWIN__)
935   if (argv[1][1]==':' || argv[1][0]=='\\' && argv[1][1]=='\\') { /*E.g.: "C:\foo\bar.exe*/
936 #else
937   if (argv[1][0]=='/') { /*E.g.: "\foo\bar"*/
938 #endif
939           /*Absolute path to node-program*/
940     arg_nodeprog_a = argv[1];
941   } else {
942     sprintf(buf,"%s%s%s",arg_currdir_a,DIRSEP,arg_nodeprog_r);
943     arg_nodeprog_a = strdup(buf);
944   }
945   if (arg_scalable_start) {
946     printf("Charmrun> scalable start enabled. \n");
947     if (arg_debug || arg_debug_no_pause) {
948       fprintf(stderr, "Charmrun> Error: ++scalable-start does not support debugging mode. \n");
949       exit(1);
950     }
951 }
952
953 #ifdef HSTART
954   if (arg_hierarchical_start) {
955     printf("Charmrun> Hierarchical scalable start enabled. \n");
956     if (arg_debug || arg_debug_no_pause) {
957       fprintf(stderr, "Charmrun> Error: ++hierarchial-start does not support debugging mode. \n");
958       exit(1);
959     }
960    if (arg_verbose) {
961       fprintf(stderr, "Charmrun> Warning: you have enabled verbose output with Hierarchical startup, you may get inconsistent verbose outputs. \n++hierarchial-start does not support verbose mode. \n");
962     }
963
964         }
965   else if(arg_child_charmrun) {
966       fprintf(stderr, "Charmrun> Error: ++child-charmrun is not a user-specified flag. \n");
967       exit(1);
968     }
969 #endif
970 }
971
972 /****************************************************************************
973  *                                                                           
974  * NODETAB:  The nodes file and nodes table.
975  *
976  ****************************************************************************/
977
978 static int portOk = 1;
979 static const char *nodetab_tempName=NULL;
980 char *nodetab_file_find()
981 {
982   char buffer[MAXPATHLEN];
983
984   /* Find a nodes-file as specified by ++nodelist */
985   if (arg_nodelist) {
986     char *path = arg_nodelist;
987     if (probefile(path)) return strdup(path);
988     fprintf(stderr,"ERROR> No such nodelist file %s\n",path);
989     exit(1);
990   }
991   /* Find a nodes-file as specified by getenv("NODELIST") */
992   if (getenv("NODELIST")) {
993     char *path = getenv("NODELIST");        
994     if (path && probefile(path)) return strdup(path);
995     fprintf(stderr,"ERROR> Cannot find nodelist file %s\n",path);
996     exit(1);
997   }
998   /* Find a nodes-file by looking under 'nodelist' in the current directory */
999   if (probefile("./nodelist")) return strdup("./nodelist");
1000 #if defined(_WIN32) && !defined(__CYGWIN__)
1001   tmpnam(buffer);
1002   nodetab_tempName=strdup(buffer);
1003 #else /*UNIX*/
1004   if (getenv("HOME")) {
1005     sprintf(buffer,"%s/.nodelist",getenv("HOME"));
1006   }
1007 #endif
1008   if (!probefile(buffer)) 
1009   {
1010     /*Create a simple nodelist in the user's home*/
1011     FILE *f=fopen(buffer,"w");
1012     if (f==NULL) {
1013       fprintf(stderr,"ERROR> Cannot create a 'nodelist' file.\n");
1014       exit(1);
1015     }
1016     fprintf(f,"group main\nhost localhost\n");
1017     fclose(f);
1018   }
1019   return strdup(buffer);
1020 }
1021
1022 typedef struct nodetab_host {
1023   char    *name;  /*Host DNS name*/
1024   skt_ip_t ip; /*IP address of host*/
1025   pathfixlist pathfixes;
1026   char    *ext;  /*FIXME: What the heck is this?  OSL 9/8/00*/
1027   int      cpus;  /* # of physical CPUs*/
1028   int      rank;  /*Rank of this CPU*/
1029   double   speed; /*Relative speed of each CPU*/
1030   int      nice;  /* process priority */
1031   int      forks; /* number of processes to fork on remote node */
1032   /*These fields are set during node-startup*/
1033   int     dataport;/*UDP port number*/
1034   SOCKET  ctrlfd;/*Connection to control port*/
1035 #if CMK_USE_RSH
1036   char    *shell;  /*Rsh to use*/
1037   char    *debugger ; /*Debugger to use*/
1038   char    *xterm ;  /*Xterm to use*/
1039   char    *login;  /*User login name to use*/
1040   char    *passwd;  /*User login password*/
1041   char    *setup;  /*Commands to execute on login*/
1042 #endif
1043
1044 #if CMK_USE_IBVERBS
1045         ChInfiAddr *qpData;
1046 #endif
1047 #if CMK_USE_IBUD
1048         ChInfiAddr qp;
1049 #endif
1050
1051
1052 } nodetab_host;
1053
1054 nodetab_host **nodetab_table;
1055 int           nodetab_max;
1056 int           nodetab_size;
1057 int          *nodetab_rank0_table;
1058 int           nodetab_rank0_size;
1059
1060 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1061 int                     loaded_max_pe;
1062 #endif
1063
1064 void nodetab_reset(nodetab_host *h)
1065 {
1066   h->name="SET_H->NAME";
1067   h->ip=_skt_invalid_ip;
1068   h->pathfixes = 0;
1069   h->ext = NULL;
1070   h->speed = 1.0;
1071   h->cpus = 1;
1072   h->rank = 0;
1073   h->nice=-100;
1074   h->forks = 0;
1075   h->dataport=-1;
1076   h->ctrlfd=-1;
1077 #if CMK_USE_RSH
1078   h->shell = arg_shell;
1079   h->debugger = arg_debugger;
1080   h->xterm = arg_xterm;
1081   h->login = arg_mylogin;
1082   h->passwd = "*";
1083   h->setup = "*";
1084 #endif
1085 }
1086
1087 void nodetab_add(nodetab_host *h)
1088 {
1089   if (h->rank == 0)
1090     nodetab_rank0_table[nodetab_rank0_size++] = nodetab_size;
1091   nodetab_table[nodetab_size] = (nodetab_host *) malloc(sizeof(nodetab_host));
1092
1093   if (arg_verbose) {
1094     char ips[200];
1095     skt_print_ip(ips,h->ip);
1096     printf("Charmrun> adding client %d: \"%s\", IP:%s\n", nodetab_size, h->name, ips);
1097   }
1098
1099   *nodetab_table[nodetab_size++] = *h;
1100 }
1101
1102 void nodetab_makehost(char *name,nodetab_host *h)
1103 {
1104   h->name=strdup(name);
1105   h->ip = skt_innode_lookup_ip(name);
1106   if (skt_ip_match(h->ip,_skt_invalid_ip)) {
1107 #ifdef CMK_BPROC
1108     /* only the master node is used */
1109     if (!(1 == arg_requested_pes && atoi(name)==-1))
1110 #endif
1111     {
1112     fprintf(stderr,"ERROR> Cannot obtain IP address of %s\n", name);
1113     exit(1);
1114     }
1115   }
1116   if (nodetab_size == nodetab_max) return;
1117   nodetab_add(h);
1118 }
1119
1120 char *nodetab_args(char *args,nodetab_host *h)
1121 {
1122   if (arg_ppn>0) h->cpus = arg_ppn;
1123   while(*args != 0) {
1124     char *b1 = skipblanks(args), *e1 = skipstuff(b1);
1125     char *b2 = skipblanks(e1), *e2 = skipstuff(b2);
1126     while (*b1=='+') b1++;/*Skip over "++" on parameters*/
1127 #if CMK_USE_RSH
1128     if (subeqs(b1,e1,"login")) h->login = substr(b2,e2);
1129     else if (subeqs(b1,e1,"passwd")) h->passwd = substr(b2,e2);
1130     else if (subeqs(b1,e1,"setup")) h->setup = strdup(b2);
1131     else if (subeqs(b1,e1,"shell")) h->shell = substr(b2,e2);
1132     else if (subeqs(b1,e1,"debugger")) h->debugger = substr(b2,e2);
1133     else if (subeqs(b1,e1,"xterm")) h->xterm = substr(b2,e2);
1134     else 
1135 #endif
1136     if (subeqs(b1,e1,"speed")) h->speed = atof(b2);
1137     else if (subeqs(b1,e1,"cpus")) {
1138       if (arg_ppn==0) h->cpus = atol(b2);       /* ignore if there is ++ppn */
1139     }
1140     else if (subeqs(b1,e1,"pathfix")) {
1141       char *b3 = skipblanks(e2), *e3 = skipstuff(b3);
1142       args = skipblanks(e3);
1143       h->pathfixes=pathfix_append(substr(b2,e2),substr(b3,e3),h->pathfixes);
1144       e2 = e3;       /* for the skipblanks at the end */
1145     } 
1146     else if (subeqs(b1,e1,"ext"))  h->ext = substr(b2,e2);
1147     else if (subeqs(b1,e1,"nice"))  h->nice = atoi(b2);
1148     else return args;
1149     args = skipblanks(e2);
1150   }
1151 #if CMK_SHARED_VARS_UNAVAILABLE
1152   if (h->cpus != 1) {
1153     fprintf(stderr,"Warning> Invalid cpus %d in nodelist ignored.\n", h->cpus);
1154     h->cpus = 1;
1155   }
1156 #endif
1157   return args;
1158 }
1159
1160 /*  setup nodetab as localhost only */
1161 void nodetab_init_for_local()
1162 {
1163   int tablesize, i, done=0;
1164   nodetab_host group;
1165
1166 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1167     if(arg_read_pes == 0){
1168         arg_read_pes = arg_requested_pes;
1169     }
1170 #endif
1171
1172   tablesize = arg_requested_pes;
1173   nodetab_table=(nodetab_host**)malloc(tablesize*sizeof(nodetab_host*));
1174   nodetab_rank0_table=(int*)malloc(tablesize*sizeof(int));
1175   nodetab_max=tablesize;
1176
1177   nodetab_reset(&group);
1178   if (arg_ppn==0) arg_ppn=1;
1179 #if CMK_SHARED_VARS_UNAVAILABLE
1180   if (arg_ppn > 1) {
1181     fprintf(stderr,"Warning> Invalid ppn %d in nodelist ignored.\n", arg_ppn);
1182     arg_ppn=1;
1183   }
1184 #endif
1185   group.cpus = arg_ppn;
1186   i = 0;
1187   while (!done) {
1188     char *hostname = "127.0.0.1";
1189     for (group.rank = 0; group.rank<arg_ppn; group.rank++) {
1190       nodetab_makehost(hostname, &group);
1191       if (++i == arg_requested_pes) { done = 1; break; }
1192     }
1193   }
1194 }
1195
1196
1197 #ifdef HSTART
1198 /* Sets the parent field of hosts to point to their parent charmrun. The root charmrun will create children for all hosts which are parent of at least one other host*/
1199 int branchfactor;
1200 int nodes_per_child;
1201 int * nodetab_unique_table;
1202 int nodetab_unique_size;
1203 char  *nodetab_name(int i);
1204 void nodetab_init_hierarchical_start(void)
1205 {
1206         int node_start = 0;
1207         char * node_name;
1208         nodetab_unique_size = 0;
1209         nodetab_unique_table = (int *)malloc(nodetab_rank0_size * sizeof(int));
1210         while(node_start<nodetab_rank0_size)
1211         {
1212                         nodetab_unique_table[nodetab_unique_size++] = node_start;
1213                         node_name = nodetab_name(node_start);
1214                         do{
1215                                         node_start++;
1216             }
1217                         while(node_start<nodetab_rank0_size&&(!strcmp(nodetab_name(node_start),node_name)));
1218                                 
1219         }
1220         branchfactor = ceil(sqrt(nodetab_unique_size));
1221         nodes_per_child = round(nodetab_unique_size*1.0/branchfactor);
1222 }
1223 #endif
1224
1225 void nodetab_init()
1226 {
1227   FILE *f,*fopen();
1228   char *nodesfile; 
1229   nodetab_host global,group,host;
1230   char input_line[MAX_LINE_LENGTH];
1231   int rightgroup, basicsize, i, remain;
1232   
1233   /* if arg_local is set, ignore the nodelist file */
1234   if (arg_local || arg_mpiexec) {
1235     nodetab_init_for_local();
1236     goto fin;
1237   }
1238
1239   /* Open the NODES_FILE. */
1240   nodesfile = nodetab_file_find();
1241   if(arg_verbose)
1242     fprintf(stderr, "Charmrun> using %s as nodesfile\n", nodesfile);
1243   if (!(f = fopen(nodesfile,"r"))) {
1244     fprintf(stderr,"ERROR> Cannot read %s: %s\n",nodesfile,strerror(errno));
1245     exit(1);
1246   }
1247  
1248 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1249         if(arg_read_pes == 0){
1250         arg_read_pes = arg_requested_pes;
1251     }
1252         nodetab_table=(nodetab_host**)malloc(arg_read_pes*sizeof(nodetab_host*));
1253         nodetab_rank0_table=(int*)malloc(arg_read_pes*sizeof(int));
1254         nodetab_max=arg_read_pes;
1255     fprintf(stderr,"arg_read_pes %d arg_requested_pes %d\n",arg_read_pes,arg_requested_pes);
1256 #else
1257         nodetab_table=(nodetab_host**)malloc(arg_requested_pes*sizeof(nodetab_host*));
1258         nodetab_rank0_table=(int*)malloc(arg_requested_pes*sizeof(int));
1259         nodetab_max=arg_requested_pes;
1260 #endif
1261  
1262   
1263   nodetab_reset(&global);
1264   group=global;
1265   rightgroup = (strcmp(arg_nodegroup,"main")==0);
1266   
1267   while(fgets(input_line,sizeof(input_line)-1,f)!=0) {
1268 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1269         if (nodetab_size == arg_read_pes) break;
1270 #else
1271     if (nodetab_size == arg_requested_pes) break;
1272 #endif
1273     if (input_line[0]=='#') continue;
1274     zap_newline(input_line);
1275         if (!nodetab_args(input_line,&global)) {
1276                 /*An option line-- also add options to current group*/
1277                 nodetab_args(input_line,&group);
1278         }
1279         else {/*Not an option line*/
1280                 char *b1 = skipblanks(input_line), *e1 = skipstuff(b1);
1281                 char *b2 = skipblanks(e1), *e2 = skipstuff(b2);
1282                 char *b3 = skipblanks(e2);
1283                 if (subeqs(b1,e1,"host")) {
1284                         if (rightgroup) {
1285                                 host=group;
1286                                 nodetab_args(b3,&host);
1287                                 for (host.rank=0; host.rank<host.cpus; host.rank++)
1288                                         nodetab_makehost(substr(b2,e2),&host);
1289                         }
1290                 } else if (subeqs(b1,e1, "group")) {
1291                         group=global;
1292                         nodetab_args(b3,&group);
1293                         rightgroup = subeqs(b2,e2,arg_nodegroup);
1294                 } else if (b1!=b3) {
1295                         fprintf(stderr,"ERROR> unrecognized command in nodesfile:\n");
1296                         fprintf(stderr,"ERROR> %s\n", input_line);
1297                         exit(1);
1298                 }
1299         }
1300   }
1301   fclose(f);
1302   if (nodetab_tempName!=NULL) unlink(nodetab_tempName);
1303
1304   /*Wrap nodes in table around if there aren't enough yet*/
1305   basicsize = nodetab_size;
1306   if (basicsize==0) {
1307     fprintf(stderr,"ERROR> No hosts in group %s\n", arg_nodegroup);
1308     exit(1);
1309   }
1310   while ((nodetab_size < arg_requested_pes)&&(arg_requested_pes!=MAX_NODES))
1311      nodetab_add(nodetab_table[nodetab_size%basicsize]);
1312   
1313 fin:
1314   /*Clip off excess CPUs at end*/
1315   for (i=0; i<nodetab_size; i++) {
1316     if (nodetab_table[i]->rank == 0)
1317       remain = nodetab_size - i;
1318     if (nodetab_table[i]->cpus > remain)
1319       nodetab_table[i]->cpus = remain;
1320   }
1321
1322 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
1323         loaded_max_pe = arg_requested_pes-1;
1324 #endif
1325 #ifdef HSTART
1326         if(arg_hierarchical_start) 
1327                 nodetab_init_hierarchical_start();              
1328 #endif
1329
1330 }
1331
1332 /* Given a processor number, look up the nodetab info: */
1333 nodetab_host *nodetab_getinfo(int i)
1334 {
1335   if (nodetab_table==0) {
1336     fprintf(stderr,"ERROR> Node table not initialized.\n");
1337     exit(1);
1338   }
1339   return nodetab_table[i];
1340 }
1341
1342 /* Given a node number, look up the nodetab info: */
1343 nodetab_host *nodetab_getnodeinfo(int i)
1344 {
1345   return nodetab_getinfo(nodetab_rank0_table[i]);
1346 }
1347
1348 /*These routines all take *PE* numbers (NOT node numbers!)*/
1349 char        *nodetab_name(int i)     { return nodetab_getinfo(i)->name; }
1350 pathfixlist  nodetab_pathfixes(int i){ return nodetab_getinfo(i)->pathfixes; }
1351 char        *nodetab_ext(int i)      { return nodetab_getinfo(i)->ext; }
1352 skt_ip_t     nodetab_ip(int i)       { return nodetab_getinfo(i)->ip; }
1353 unsigned int nodetab_cpus(int i)     { return nodetab_getinfo(i)->cpus; }
1354 unsigned int nodetab_rank(int i)     { return nodetab_getinfo(i)->rank; }
1355 int          nodetab_dataport(int i) { return nodetab_getinfo(i)->dataport; }
1356 int          nodetab_nice(int i)     { return nodetab_getinfo(i)->nice; }
1357 SOCKET      nodetab_ctrlfd(int i)    { return nodetab_getinfo(i)->ctrlfd;}
1358 #if CMK_USE_RSH
1359 char        *nodetab_setup(int i)    { return nodetab_getinfo(i)->setup; }
1360 char        *nodetab_shell(int i)    { return nodetab_getinfo(i)->shell; }
1361 char        *nodetab_debugger(int i) { return nodetab_getinfo(i)->debugger; }
1362 char        *nodetab_xterm(int i)    { return nodetab_getinfo(i)->xterm; }
1363 char        *nodetab_login(int i)    { return nodetab_getinfo(i)->login; }
1364 char        *nodetab_passwd(int i)   { return nodetab_getinfo(i)->passwd; }
1365 #endif
1366
1367 /****************************************************************************
1368  *
1369  * Nodeinfo
1370  *
1371  * The global list of node PEs, IPs, and port numbers.
1372  * Stored in ChMachineInt_t format so the table can easily be sent
1373  * back to the nodes.
1374  *
1375  ****************************************************************************/
1376
1377 static ChNodeinfo *nodeinfo_arr;/*Indexed by node number.*/
1378
1379 void nodeinfo_allocate(void)
1380 {
1381         nodeinfo_arr=(ChNodeinfo *)malloc(nodetab_rank0_size*sizeof(ChNodeinfo));
1382 }
1383 void nodeinfo_add(const ChSingleNodeinfo *in,SOCKET ctrlfd)
1384 {
1385         int node=ChMessageInt(in->nodeNo);
1386         ChNodeinfo i=in->info;
1387         unsigned int nt;
1388         unsigned int pe;
1389         unsigned int dataport;
1390         int lid,qpn,psn;
1391         if (node<0 || node>=nodetab_rank0_size)
1392                 {fprintf(stderr,"Unexpected node %d registered!\n",node);exit(1);}
1393         nt=nodetab_rank0_table[node];/*Nodetable index for this node*/  
1394         i.nPE=ChMessageInt_new(nodetab_cpus(nt));
1395         if (arg_mpiexec)
1396            nodetab_getinfo(nt)->ip = i.IP;   /* get IP */
1397         i.IP=nodetab_ip(nt);
1398 #if CMK_USE_IBVERBS 
1399         nodeinfo_arr[node] = i;
1400         for (pe=0;pe<nodetab_cpus(nt);pe++){
1401                 nodetab_table[nt+pe]->ctrlfd=ctrlfd;
1402         }
1403         /* printf("Charmrun> client %d connected\n", nt); */
1404 #else
1405         dataport = ChMessageInt(i.dataport);
1406         if (0==dataport)
1407                 {fprintf(stderr,"Node %d could not initialize network!\n",node);exit(1);}
1408         nodeinfo_arr[node]=i;
1409         for (pe=0;pe<nodetab_cpus(nt);pe++)
1410           {
1411             nodetab_table[nt+pe]->dataport=dataport;
1412             nodetab_table[nt+pe]->ctrlfd=ctrlfd;
1413 #if CMK_USE_IBUD
1414             nodetab_table[nt+pe]->qp=i.qp;
1415 #endif
1416           }
1417         if (arg_verbose) {
1418           char ips[200];
1419           skt_print_ip(ips,nodetab_ip(nt));
1420           printf("Charmrun> client %d connected (IP=%s data_port=%d)\n", nt, ips, dataport);
1421 #if CMK_USE_IBUD
1422           printf("Charmrun> client %d lid=%d qpn=%i psn=%i\n",nt,ChMessageInt(i.qp.lid),ChMessageInt(i.qp.qpn),ChMessageInt(i.qp.psn));
1423 #endif
1424         }
1425 #endif
1426 }
1427
1428 /****************************************************************************
1429  *
1430  * input handling
1431  *
1432  * You can use this module to read the standard input.  It supports
1433  * one odd function, input_scanf_chars, which is what makes it useful.
1434  * if you use this module, you may not read stdin yourself.
1435  *
1436  * void input_init(void)
1437  * char *input_gets(void)
1438  * char *input_scanf_chars(char *fmt)
1439  *
1440  ****************************************************************************/
1441
1442 char *input_buffer;
1443
1444 void input_extend()
1445 {
1446   char line[1024];
1447   int len = input_buffer?strlen(input_buffer):0;
1448   fflush(stdout);
1449   if (fgets(line, 1023, stdin)==0) { 
1450     fprintf(stderr,"end-of-file on stdin");
1451     exit(1);
1452   }
1453   input_buffer = realloc(input_buffer, len + strlen(line) + 1);
1454   strcpy(input_buffer+len, line);
1455 }
1456
1457 void input_init()
1458 {
1459   input_buffer = strdup("");
1460 }
1461
1462 char *input_extract(nchars)
1463     int nchars;
1464 {
1465   char *res = substr(input_buffer, input_buffer+nchars);
1466   char *tmp = substr(input_buffer+nchars, input_buffer+strlen(input_buffer));
1467   free(input_buffer);
1468   input_buffer = tmp;
1469   return res;
1470 }
1471
1472 char *input_gets()
1473 {
1474   char *p, *res; int len;
1475   while(1) {
1476     p = strchr(input_buffer,'\n');
1477     if (p) break;
1478     input_extend();
1479   }
1480   len = p-input_buffer;
1481   res = input_extract(len+1);
1482   res[len]=0;
1483   return res;
1484 }
1485
1486 /*FIXME: I am terrified by this routine. OSL 9/8/00*/
1487 char *input_scanf_chars(fmt)
1488     char *fmt;
1489 {
1490   char buf[8192]; int len, pos;
1491   static int fd; static FILE *file;
1492   fflush(stdout);
1493   if (file==0) {
1494 #if CMK_USE_MKSTEMP
1495     char tmp[128];
1496     strcpy(tmp, "/tmp/fnordXXXXXX");
1497     mkstemp(tmp);
1498 #else
1499     char *tmp=tmpnam(NULL);/*This was once /tmp/fnord*/
1500 #endif
1501     unlink(tmp);
1502     fd = open(tmp,O_RDWR | O_CREAT | O_TRUNC, 0664);
1503     if (fd<0) { 
1504       fprintf(stderr,"cannot open temp file /tmp/fnord");
1505       exit(1);
1506     }
1507     file = fdopen(fd, "r+");
1508     unlink(tmp);
1509   }
1510   while (1) {
1511     len = strlen(input_buffer);
1512     rewind(file);
1513     fwrite(input_buffer, len, 1, file);
1514     fflush(file);
1515     rewind(file);
1516     ftruncate(fd, len);
1517     fscanf(file, fmt, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf, buf);
1518     pos = ftell(file);
1519     if (pos<len) break;
1520     input_extend();
1521   }
1522   return input_extract(pos);
1523 }
1524
1525 /***************************************************************************
1526 CCS Interface:
1527   Charmrun forwards CCS requests on to the node-programs' control
1528 sockets.
1529 ***************************************************************************/
1530
1531 #if CMK_CCS_AVAILABLE
1532
1533 /*The Ccs Server socket became active-- 
1534 rec'v the message and respond to the request,
1535 by forwarding the request to the appropriate node.
1536  */
1537 void req_ccs_connect(void)
1538 {
1539   const void *bufs[3]; int lens[3];
1540   struct {
1541    ChMessageHeader ch;/*Make a charmrun header*/
1542    CcsImplHeader hdr;/*Ccs internal header*/
1543   } h;
1544   void *reqData;/*CCS request data*/
1545   int pe,reqBytes;
1546   if (0==CcsServer_recvRequest(&h.hdr,&reqData))
1547     return;/*Malformed request*/
1548   pe=ChMessageInt(h.hdr.pe);
1549   reqBytes=ChMessageInt(h.hdr.len);
1550
1551   if (pe == -1) {
1552     /*Treat -1 as broadcast and sent to 0 as root of the spanning tree*/
1553     pe = 0;
1554   }
1555   if ((pe<=-nodetab_size || pe>=nodetab_size) && 0==replay_single) {
1556     /*Treat out of bound values as errors. Helps detecting bugs*/
1557     /* But when virtualized with Bigemulator, we can have more pes than nodetabs */
1558     /* TODO: We should somehow check boundaries also for bigemulator... */
1559 #if ! CMK_BLUEGENE_CHARM
1560     if (pe==-nodetab_size) fprintf(stderr,"Invalid processor index in CCS request: are you trying to do a broadcast instead?");
1561     else fprintf(stderr,"Invalid processor index in CCS request.");
1562     CcsServer_sendReply(&h.hdr,0,0);
1563     free(reqData);
1564     return;
1565 #endif
1566   }
1567   else if (pe < -1) {
1568     /*Treat negative values as multicast to a number of processors specified by -pe.
1569       The pes to multicast to follows sits at the beginning of reqData*/
1570     reqBytes -= pe * sizeof(ChMessageInt_t);
1571     pe = ChMessageInt(*(ChMessageInt_t*)reqData);
1572   }
1573   
1574   if (! check_stdio_header(&h.hdr)) {
1575
1576 #define LOOPBACK 0
1577 #if LOOPBACK /*Immediately reply "there's nothing!" (for performance testing)*/
1578   CcsServer_sendReply(&h.hdr,0,0);
1579 #else
1580     int destpe = pe;
1581 #if CMK_BLUEGENE_CHARM
1582     destpe = destpe % nodetab_size;
1583 #endif
1584     if (replay_single) destpe = 0;
1585     /*Fill out the charmrun header & forward the CCS request*/
1586     ChMessageHeader_new("req_fw",sizeof(h.hdr)+reqBytes,&h.ch);  
1587
1588     bufs[0]=&h; lens[0]=sizeof(h);
1589     bufs[1]=reqData; lens[1]=reqBytes;
1590     skt_sendV(nodetab_ctrlfd(destpe),2,bufs,lens);
1591
1592 #endif
1593   }
1594   free(reqData);
1595 }
1596
1597 /*
1598 Forward the CCS reply (if any) from this client back to the 
1599 original network requestor, on the original request socket.
1600  */
1601 int req_ccs_reply_fw(ChMessage *msg,SOCKET srcFd) {
1602   int len=msg->len; /* bytes of data remaining to receive */
1603   
1604   /* First pull down the CCS header sent by the client. */
1605   CcsImplHeader hdr;
1606   skt_recvN(srcFd,&hdr,sizeof(hdr)); len-=sizeof(hdr);
1607   
1608 #define m (4*1024) /* packets of message to recv/send at once */
1609   if (len<m || hdr.attr.auth) 
1610   { /* short or authenticated message: grab the whole thing first */
1611      void *data=malloc(len);
1612      skt_recvN(srcFd,data,len);
1613      CcsServer_sendReply(&hdr,len,data);
1614      free(data);
1615   } 
1616   else 
1617   { /* long messages: packetize (for pipelined sending; a 2x bandwidth improvement!) */
1618     ChMessageInt_t outLen;
1619     int destFd; /* destination for data */
1620     skt_abortFn old=skt_set_abort(reply_abortFn);
1621     int destErrs=0;
1622     
1623     destFd=ChMessageInt(hdr.replyFd);
1624     outLen=ChMessageInt_new(len);
1625     skt_sendN(destFd,&outLen,sizeof(outLen)); /* first comes the length */
1626     while(len>0) {
1627        char buf[m];
1628        int r=m; if (r>len) r=len;
1629        skt_recvN(srcFd,buf,r);
1630        if (0==destErrs) /* don't keep sending to dead clients, but *do* clean out srcFd */
1631           destErrs|=skt_sendN(destFd,buf,r);
1632        len-=m;
1633 #undef m
1634     }
1635     skt_close(destFd);
1636   
1637     skt_set_abort(old); 
1638   }
1639   return 0;
1640 }
1641
1642 #else
1643 int req_ccs_reply_fw(ChMessage *msg,SOCKET srcFd) {
1644   
1645 }
1646 #endif /*CMK_CCS_AVAILABLE*/
1647
1648 /****************************************************************************
1649  *
1650  * REQUEST SERVICER
1651  *
1652  * The request servicer accepts connections on a TCP port.  The client
1653  * sends a sequence of commands (each is one line).  It then closes the
1654  * connection.  The server must then contact the client, sending replies.
1655  *
1656  ****************************************************************************/
1657  /** Macro to switch on the case when charmrun stays up even if
1658  one of the processor crashes*/
1659 /*#define __FAULT__*/
1660
1661 SOCKET *req_clients; /*TCP request sockets for each node*/
1662 #ifdef HSTART
1663 SOCKET *charmrun_fds;
1664 #endif
1665 int  req_nClients;/*Number of entries in above list (==nodetab_rank0_size)*/
1666 int             req_ending=0;
1667
1668 /* socket and std streams for the gdb info program */
1669 int gdb_info_pid=0;
1670 int gdb_info_std[3];
1671 FILE *gdb_stream=NULL;
1672
1673 #define REQ_OK 0
1674 #define REQ_FAILED -1
1675
1676 #ifdef HSTART
1677 int req_reply_child(SOCKET fd, char *type, 
1678               const char *data, int dataLen)
1679 {
1680
1681                 int status = req_reply(fd, type, data, dataLen);
1682                 if(status != REQ_OK) return status;
1683             SOCKET clientFd ;
1684                 skt_recvN(fd, (const char *)&clientFd, sizeof(SOCKET));
1685             skt_sendN(fd, (const char *)&clientFd, sizeof(fd)); 
1686                 return status;
1687 }
1688 #endif
1689 /**
1690  * @brief This is the only place where charmrun talks back to anyone. 
1691  */
1692 int req_reply(SOCKET fd, char *type, 
1693               const char *data, int dataLen)
1694 {
1695         ChMessageHeader msg;
1696         if (fd == INVALID_SOCKET) return REQ_FAILED;
1697         ChMessageHeader_new(type,dataLen,&msg);
1698         skt_sendN(fd,(const char *)&msg,sizeof(msg));
1699         skt_sendN(fd,data,dataLen);
1700         return REQ_OK;
1701 }
1702
1703 /* Request handlers:
1704 When a client asks us to do something, these are the
1705 routines that actually respond to the request.
1706 */
1707 /*Stash this new node's control and data ports.
1708  */
1709 int req_handle_initnode(ChMessage *msg,SOCKET fd)
1710 {
1711 #if CMK_USE_IBVERBS
1712         int i;
1713         ChSingleNodeinfo *nodeInfo = (ChSingleNodeinfo *)msg->data;
1714 //      printf("Charmrun> msg->len %d sizeof(ChSingleNodeinfo) %d sizeof(ChInfiAddr) %d \n",msg->len,sizeof(ChSingleNodeinfo),sizeof(ChInfiAddr));
1715         if(msg->len != sizeof(ChSingleNodeinfo) + (nodetab_rank0_size-1)*sizeof(ChInfiAddr)){
1716     fprintf(stderr,"Charmrun: Bad initnode data length. Aborting\n");
1717                 exit(1);
1718         }
1719         nodeInfo->info.qpList = malloc(sizeof(ChInfiAddr)*(nodetab_rank0_size-1));
1720         memcpy((char *)nodeInfo->info.qpList,&msg->data[sizeof(ChSingleNodeinfo)],sizeof(ChInfiAddr)*(nodetab_rank0_size-1));
1721 /*      for(i=0;i<nodetab_rank0_size-1;i++){
1722                 printf("i %d  0x%0x 0x%0x 0x%0x\n",i,ChMessageInt(nodeInfo->info.qpList[i].lid),ChMessageInt(nodeInfo->info.qpList[i].qpn),ChMessageInt(nodeInfo->info.qpList[i].psn));
1723         }*/
1724 #else
1725   if (msg->len!=sizeof(ChSingleNodeinfo)) {
1726     fprintf(stderr,"Charmrun: Bad initnode data length. Aborting\n");
1727     fprintf(stderr,"Charmrun: possibly because: %s.\n", msg->data);
1728     exit(1);
1729   }
1730 #endif  
1731   nodeinfo_add((ChSingleNodeinfo *)msg->data,fd);
1732   return REQ_OK;
1733 }
1734
1735 /**
1736  * @brief Gets the array of node numbers, IPs, and ports. This is used by the node-programs 
1737  * to talk to one another.
1738  */
1739 int req_handle_initnodetab(ChMessage *msg,SOCKET fd)
1740 {
1741         ChMessageHeader hdr;
1742         ChMessageInt_t nNodes=ChMessageInt_new(nodetab_rank0_size);
1743         ChMessageHeader_new("initnodetab",sizeof(ChMessageInt_t)+
1744                             sizeof(ChNodeinfo)*nodetab_rank0_size,&hdr);
1745         skt_sendN(fd,(const char *)&hdr,sizeof(hdr));
1746         skt_sendN(fd,(const char *)&nNodes,sizeof(nNodes));
1747         skt_sendN(fd,(const char *)nodeinfo_arr,
1748                   sizeof(ChNodeinfo)*nodetab_rank0_size);
1749                         
1750         return REQ_OK;
1751 }
1752
1753 #ifdef HSTART
1754 /* Used for fault tolerance with hierarchical start */
1755 int req_handle_initnodetab1(ChMessage *msg,SOCKET fd)
1756 {
1757         ChMessageHeader hdr;
1758         ChMessageInt_t nNodes=ChMessageInt_new(nodetab_rank0_size);
1759         ChMessageHeader_new("initnttab",sizeof(ChMessageInt_t)+
1760                             sizeof(ChNodeinfo)*nodetab_rank0_size,&hdr);
1761         skt_sendN(fd,(const char *)&hdr,sizeof(hdr));
1762         skt_sendN(fd,(const char *)&nNodes,sizeof(nNodes));
1763         skt_sendN(fd,(const char *)nodeinfo_arr,
1764                   sizeof(ChNodeinfo)*nodetab_rank0_size);
1765         
1766         return REQ_OK;
1767 }
1768 /*Get the array of node numbers, IPs, and ports.
1769 This is used by the node-programs to talk to one another.
1770 */
1771 static int parent_charmrun_fd = -1;
1772 int req_handle_initnodedistribution(ChMessage *msg,SOCKET fd, int client)
1773 {
1774         int nodes_to_fork = nodes_per_child; /* rounding should help in better load distribution*/
1775         int rank0_start = nodetab_unique_table[client*nodes_per_child];
1776         int rank0_finish;
1777         if(client == branchfactor -1)
1778         {
1779                 nodes_to_fork = nodetab_unique_size- client*nodes_per_child;
1780                 rank0_finish = nodetab_rank0_size;
1781         }
1782         else
1783                         rank0_finish = nodetab_unique_table[client*nodes_per_child + nodes_to_fork];
1784         int k;
1785         ChMessageInt_t * nodemsg = (ChMessageInt_t *)malloc((rank0_finish - rank0_start)*sizeof(ChMessageInt_t)); 
1786         for(k =0; k <rank0_finish- rank0_start; k++)
1787                         nodemsg[k] = ChMessageInt_new(nodetab_rank0_table[rank0_start+k]);
1788         ChMessageHeader hdr;
1789         ChMessageInt_t nNodes=ChMessageInt_new(rank0_finish- rank0_start);
1790         ChMessageInt_t nTotalNodes=ChMessageInt_new(nodetab_rank0_size);
1791         ChMessageHeader_new("initnodetab",sizeof(ChMessageInt_t)*2+
1792                             sizeof(ChMessageInt_t)*(rank0_finish- rank0_start),&hdr);
1793         skt_sendN(fd,(const char *)&hdr,sizeof(hdr));
1794         skt_sendN(fd,(const char *)&nNodes,sizeof(nNodes));
1795         skt_sendN(fd,(const char *)&nTotalNodes,sizeof(nTotalNodes));
1796         skt_sendN(fd,(const char *)nodemsg,(rank0_finish- rank0_start)*sizeof(ChMessageInt_t));
1797         free(nodemsg);          
1798         return REQ_OK;
1799 }
1800
1801 ChSingleNodeinfo * myNodesInfo;
1802 int     send_myNodeInfo_to_parent()
1803 {
1804         ChMessageHeader hdr;
1805         ChMessageInt_t nNodes=ChMessageInt_new(nodetab_rank0_size);
1806         ChMessageHeader_new("initnodetab",sizeof(ChMessageInt_t)+
1807                             sizeof(ChSingleNodeinfo)*nodetab_rank0_size,&hdr);
1808         skt_sendN(parent_charmrun_fd,(const char *)&hdr,sizeof(hdr));
1809         skt_sendN(parent_charmrun_fd,(const char *)&nNodes,sizeof(nNodes));
1810         skt_sendN(parent_charmrun_fd,(const char *)myNodesInfo,
1811                   sizeof(ChSingleNodeinfo)*nodetab_rank0_size);
1812
1813         return REQ_OK;
1814 }
1815 void forward_nodetab_to_children()
1816 {
1817         /*it just needs to receive and copy the nodetab info if required and send it as it is to its nodes */   
1818 if (!skt_select1(parent_charmrun_fd,1200*1000)){
1819         exit(0);
1820         }
1821 ChMessage msg;
1822 ChMessage_recv(parent_charmrun_fd,&msg);
1823
1824 ChMessageInt_t * nodelistmsg = (ChMessageInt_t *)msg.data;                      
1825 int nodetab_Nodes = ChMessageInt(nodelistmsg[0]);
1826 int client;
1827 for (client=0;client<nodetab_rank0_size;client++)       {
1828         SOCKET fd = req_clients[client];
1829         ChMessageHeader hdr;
1830         ChMessageInt_t nNodes=ChMessageInt_new(nodetab_Nodes);
1831         ChMessageHeader_new("initnodetab",sizeof(ChMessageInt_t)+
1832                             sizeof(ChNodeinfo)*nodetab_Nodes,&hdr);
1833         skt_sendN(fd,(const char *)&hdr,sizeof(hdr));
1834         skt_sendN(fd,(const char *)&nNodes,sizeof(nNodes));
1835         skt_sendN(fd,(const char *)(nodelistmsg+1),
1836                   sizeof(ChNodeinfo)*nodetab_Nodes);
1837 }
1838 }
1839 /*Parent Charmrun receives the nodetab from child and processes it. msg contain array of ChSingleNodeInfo*/
1840 void receive_nodeset_from_child(ChMessage *msg, SOCKET fd)
1841 {
1842         ChMessageInt_t * n32 = (ChMessageInt_t *)msg->data;     
1843     int numOfNodes =ChMessageInt(n32[0]); 
1844     ChSingleNodeinfo *childNodeInfo = (ChSingleNodeinfo*) (n32+1);
1845         int k;
1846         for(k = 0; k<numOfNodes; k++)
1847                         nodeinfo_add(childNodeInfo+k,fd);
1848 }
1849
1850 void set_sockets_list(ChMessage *msg, SOCKET fd)
1851 {
1852         ChMessageInt_t * n32 = (ChMessageInt_t *)msg->data;     
1853     int node_start =ChMessageInt(n32[0]); 
1854         charmrun_fds[node_start/nodes_per_child] = fd;
1855 }
1856 #endif
1857 /* Check this return code from "printf". */
1858 static void checkPrintfError(int err) {
1859   if (err<0) {
1860     static int warned=0;
1861     if (!warned) {
1862       perror("charmrun WARNING> error in printf");
1863       warned=1;
1864     }
1865   }
1866 }
1867
1868 int req_handle_print(ChMessage *msg,SOCKET fd)
1869 {
1870   checkPrintfError(printf("%s",msg->data));
1871   checkPrintfError(fflush(stdout));
1872   write_stdio_duplicate(msg->data);
1873   return REQ_OK;
1874 }
1875
1876
1877 int req_handle_printerr(ChMessage *msg,SOCKET fd)
1878 {
1879   fprintf(stderr,"%s",msg->data);
1880   fflush(stderr);
1881   write_stdio_duplicate(msg->data);
1882   return REQ_OK;
1883 }
1884
1885
1886 int req_handle_printsyn(ChMessage *msg,SOCKET fd)
1887 {
1888   checkPrintfError(printf("%s",msg->data));
1889   checkPrintfError(fflush(stdout));
1890   write_stdio_duplicate(msg->data);
1891 #ifdef HSTART
1892   if(arg_hierarchical_start) 
1893                   req_reply_child(fd, "printdone", "", 1);
1894   else
1895 #endif
1896   req_reply(fd, "printdone", "", 1);
1897   return REQ_OK;
1898 }
1899
1900
1901 int req_handle_printerrsyn(ChMessage *msg,SOCKET fd)
1902 {
1903   fprintf(stderr,"%s",msg->data);
1904   fflush(stderr);
1905   write_stdio_duplicate(msg->data);
1906 #ifdef HSTART
1907  if(arg_hierarchical_start) 
1908                   req_reply_child(fd, "printdone", "", 1);
1909 else
1910 #endif
1911   req_reply(fd, "printdone", "", 1);
1912   return REQ_OK;
1913 }
1914
1915
1916 int req_handle_ending(ChMessage *msg,SOCKET fd)
1917 {  
1918   int i;
1919   req_ending++;
1920
1921 #if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))    
1922         if (req_ending == nodetab_size)
1923 #else
1924         if(req_ending == arg_requested_pes)
1925 #endif
1926   {
1927     for (i=0;i<req_nClients;i++)
1928       skt_close(req_clients[i]);
1929     if (arg_verbose) printf("Charmrun> Graceful exit.\n");
1930     exit(0);
1931   }
1932   return REQ_OK;
1933 }
1934
1935 int req_handle_barrier(ChMessage *msg,SOCKET fd)
1936 {
1937   int i;
1938   static int barrier_count = 0;
1939   static int barrier_phase = 0;
1940   barrier_count ++;
1941 #ifdef HSTART
1942   if (barrier_count == arg_requested_pes) 
1943 #else
1944   if (barrier_count == req_nClients) 
1945 #endif
1946   {
1947     barrier_count = 0;
1948         barrier_phase ++;
1949         for (i=0;i<req_nClients;i++)
1950           if (REQ_OK != req_reply(req_clients[i], "barrier", "", 1))
1951           {
1952                 fprintf(stderr, "req_handle_barrier socket error: %d\n", i);
1953         abort();
1954           }
1955   }
1956   return REQ_OK;
1957 }
1958
1959 int req_handle_barrier0(ChMessage *msg,SOCKET fd)
1960 {
1961   int i;
1962   static int count = 0;
1963   static SOCKET fd0;
1964   int pe = atoi(msg->data);
1965   if (pe == 0) fd0 = fd;
1966   count ++;
1967 #ifdef HSTART
1968   if (count == arg_requested_pes) 
1969 #else
1970   if (count == req_nClients) 
1971 #endif
1972   {
1973         req_reply(fd0, "barrier0", "", 1);     /* only send to node 0 */
1974         count = 0;
1975   }
1976   return REQ_OK;
1977 }
1978
1979
1980 int req_handle_abort(ChMessage *msg,SOCKET fd)
1981 {
1982   /*fprintf(stderr,"req_handle_abort called \n");*/
1983   if (msg->len==0) 
1984         fprintf(stderr,"Aborting!\n");
1985   else
1986         fprintf(stderr, "%s\n", msg->data);
1987   exit(1);
1988 }
1989
1990 int req_handle_scanf(ChMessage *msg,SOCKET fd)
1991 {
1992   char *fmt, *res, *p;
1993
1994   fmt = msg->data;
1995   fmt[msg->len-1]=0;
1996   res = input_scanf_chars(fmt);
1997   p = res; while (*p) { if (*p=='\n') *p=' '; p++; }
1998 #ifdef HSTART
1999   if(arg_hierarchical_start) 
2000           req_reply_child(fd, "scanf-data", res, strlen(res)+1);
2001   else
2002 #endif
2003   req_reply(fd, "scanf-data", res, strlen(res)+1);
2004   free(res);
2005   return REQ_OK;
2006 }
2007
2008 #ifdef __FAULT__        
2009 void restart_node(int crashed_node);
2010 void reconnect_crashed_client(int socket_index,int crashed_node);
2011 void announce_crash(int socket_index,int crashed_node);
2012
2013 static int _last_crash = 0;                     /* last crashed pe number */
2014 static int _crash_socket_index = 0;             /* last restart socket */
2015 #ifdef HSTART
2016 static int _crash_socket_charmrun_index = 0;            /* last restart socket */
2017 int crashed_pe_id;
2018 int restarted_pe_id;
2019 #endif
2020 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2021 static int numCrashes=0;  /*number of crashes*/
2022 static SOCKET last_crashed_fd=-1;
2023 #endif
2024
2025 /**
2026  * @brief Handles an ACK after a crash. Once it has received all the pending acks, it sends the nodetab
2027  * table to the crashed node.
2028  */
2029 int req_handle_crashack(ChMessage *msg,SOCKET fd)
2030 {
2031         static int count = 0;
2032         count ++;
2033 #ifdef HSTART
2034         if(arg_hierarchical_start)
2035                         {
2036                   if (count == nodetab_rank0_size-1) {
2037                         /* only after everybody else update its nodetab, can this
2038                            restarted process continue */
2039                         printf("Charmrun> continue node: %d\n", _last_crash);
2040                         req_handle_initnodetab1(NULL,req_clients[_crash_socket_charmrun_index]);
2041                         _last_crash = 0;
2042                         count = 0;
2043 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2044         last_crashed_fd=-1;
2045 #endif
2046             }
2047                 }
2048                 
2049     else
2050                         
2051 #endif
2052         if (count == req_nClients-1) {
2053                 // only after everybody else update its nodetab, can this restarted process continue 
2054                 printf("Charmrun> continue node: %d\n", _last_crash);
2055                 req_handle_initnodetab(NULL,req_clients[_crash_socket_index]);  
2056                 _last_crash = 0;
2057                 count = 0;
2058 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2059                         last_crashed_fd=-1;
2060 #endif
2061         }
2062 }
2063
2064 #ifdef HSTART
2065 /* send initnode to root*/
2066                 int set_crashed_socket_id(ChMessage *msg,SOCKET fd)
2067                 {
2068                         ChSingleNodeinfo *nodeInfo = (ChSingleNodeinfo *)msg->data;
2069                         int nt=nodetab_rank0_table[ChMessageInt(nodeInfo->nodeNo)-mynodes_start];
2070                         nodeInfo->nodeNo = ChMessageInt_new(nt);
2071                         /* Required for CCS */
2072                 /*Nodetable index for this node*/
2073                         int pe;
2074                         for (pe=0;pe<nodetab_cpus(nt);pe++)
2075                           {
2076                                 nodetab_table[nt+pe]->ctrlfd=fd;
2077                           }
2078                 }
2079
2080 /* Receives new dataport of restarted prcoess   and resends nodetable to everyone*/
2081                 int req_handle_crash(ChMessage *msg,SOCKET fd)
2082                 {
2083
2084                         ChMessageInt_t oldpe, newpe;
2085                         skt_recvN(fd, (const char *)&oldpe, sizeof(oldpe));
2086                         skt_recvN(fd, (const char *)&newpe, sizeof(newpe));
2087                         *nodetab_table[ChMessageInt(oldpe)] = *nodetab_table[ChMessageInt(newpe)]; 
2088
2089                         int status = req_handle_initnode(msg,fd);
2090                         int i;
2091                         for(i=0;i<req_nClients;i++){
2092                                 if(req_clients[i] == fd){
2093                                 break;
2094                                 }
2095                         }       
2096                         _crash_socket_charmrun_index = i;
2097
2098                         fprintf(stdout,"Root charmrun : Socket %d failed %d\n",fd, _crash_socket_charmrun_index);
2099                         fflush(stdout);
2100                         ChSingleNodeinfo *nodeInfo = (ChSingleNodeinfo *)msg->data;
2101                         int crashed_node = ChMessageInt(nodeInfo->nodeNo);
2102                         _last_crash = crashed_node;
2103                         switch (status) 
2104                         {
2105         case REQ_OK: break;
2106                 case REQ_FAILED: 
2107             return REQ_FAILED;
2108                          }
2109
2110                         /* Already processed, so send*/
2111                         int client;
2112                         for (client=0;client<req_nClients;client++)     {                       
2113                                 req_handle_initnodetab(NULL,req_clients[client]);
2114                         }
2115                         
2116                         /*Anounce crash to all child charmruns*/
2117                         announce_crash(nodetab_rank0_size+1,crashed_node );
2118
2119                 }
2120
2121 #endif
2122 #endif
2123
2124 #ifdef __FAULT__
2125 void error_in_req_serve_client(SOCKET fd){
2126         SOCKET * new_req_clients=(SOCKET *)malloc((req_nClients-1)*sizeof(SOCKET));
2127         int count=0,i;
2128         int crashed_node,crashed_pe,node_index,socket_index;
2129         fprintf(stdout,"Socket %d failed \n",fd);
2130
2131         
2132 #ifdef HSTART
2133         if(arg_hierarchical_start)
2134                         {
2135                         for(i=mynodes_start;i<mynodes_start+nodetab_rank0_size;i++){
2136                                 if(nodetab_ctrlfd(i) == fd){
2137                                         break;
2138                                 }
2139                         }
2140                         }
2141
2142                         else
2143 #endif
2144                         for(i=0;i<nodetab_max;i++){
2145                                 if(nodetab_ctrlfd(i) == fd){
2146                                         break;
2147                                 }
2148                         }
2149                 
2150         fflush(stdout);
2151 #if (!defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
2152         skt_close(fd);
2153 #endif
2154         crashed_pe = i;
2155         node_index = i-nodetab_rank(crashed_pe);
2156         for(i=0;i<nodetab_rank0_size;i++){
2157                 if(node_index == nodetab_rank0_table[i]){
2158                         break;
2159                 }
2160         }
2161         crashed_node = i;
2162         
2163         /** should also send a message to all the other processors telling them that this guy has crashed*/
2164         /*announce_crash(socket_index,crashed_node);*/
2165         restart_node(crashed_node);
2166
2167         fprintf(stdout,"charmrun says Processor %d failed on Node %d\n",crashed_pe,crashed_node);
2168         /** after the crashed processor has been recreated 
2169          it connects to charmrun. That data must now be filled 
2170          into the req_nClients array and the nodetab_table*/
2171
2172         for(i=0;i<req_nClients;i++){
2173                 if(req_clients[i] == fd){
2174                         break;
2175                 }
2176         }       
2177         socket_index = i;
2178         reconnect_crashed_client(socket_index,crashed_node);
2179 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2180         skt_close(fd);
2181 #endif
2182 }
2183 #endif
2184
2185 int req_handler_dispatch(ChMessage *msg,SOCKET replyFd)
2186 {
2187   char *cmd=msg->header.type;
2188   int recv_status;
2189   DEBUGF(("Got request '%s'\n",cmd,replyFd));
2190 #if CMK_CCS_AVAILABLE   /* CCS *doesn't* want data yet, for faster forwarding */
2191   if (strcmp(cmd,"reply_fw")==0)   return req_ccs_reply_fw(msg,replyFd);
2192 #endif
2193
2194   /* grab request data */
2195   recv_status = ChMessageData_recv(replyFd,msg);
2196 #ifdef __FAULT__
2197 #ifdef HSTART
2198         if(!arg_hierarchical_start)
2199 #endif
2200 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
2201  if(recv_status < 0){
2202         if(replyFd == last_crashed_fd){
2203             return REQ_OK;
2204         }
2205         DEBUGF(("recv_status %d on socket %d \n",recv_status,replyFd));
2206         error_in_req_serve_client(replyFd);
2207     }
2208 #else   
2209   if(recv_status < 0)  error_in_req_serve_client(replyFd);
2210 #endif
2211 #endif
2212
2213        if (strcmp(cmd,"ping")==0)       return REQ_OK;
2214   else if (strcmp(cmd,"print")==0)      return req_handle_print(msg,replyFd);
2215   else if (strcmp(cmd,"printerr")==0)   return req_handle_printerr(msg,replyFd);
2216   else if (strcmp(cmd,"printsyn")==0)  return req_handle_printsyn(msg,replyFd);
2217   else if (strcmp(cmd,"printerrsyn")==0) return req_handle_printerrsyn(msg,replyFd);
2218   else if (strcmp(cmd,"scanf")==0)      return req_handle_scanf(msg,replyFd);
2219   else if (strcmp(cmd,"barrier")==0)    return req_handle_barrier(msg,replyFd);
2220   else if (strcmp(cmd,"barrier0")==0)   return req_handle_barrier0(msg,replyFd);
2221   else if (strcmp(cmd,"ending")==0)     return req_handle_ending(msg,replyFd);
2222   else if (strcmp(cmd,"abort")==0)      return req_handle_abort(msg,replyFd);
2223 #ifdef __FAULT__        
2224   else if (strcmp(cmd,"crash_ack")==0)   return req_handle_crashack(msg,replyFd);
2225 #ifdef HSTART
2226   else if (strcmp(cmd,"initnode")==0)   return req_handle_crash(msg,replyFd);
2227 #endif
2228 #endif
2229   else {
2230 #ifndef __FAULT__       
2231         fprintf(stderr,"Charmrun> Bad control socket request '%s'\n",cmd); 
2232         abort();
2233         return REQ_OK;
2234 #endif                          
2235   }
2236   return REQ_OK;
2237 }
2238
2239 void req_serve_client(SOCKET fd)
2240 {
2241   int recv_status;
2242   int status;
2243   ChMessage msg;
2244   DEBUGF(("Getting message from client...\n"));
2245   recv_status = ChMessageHeader_recv(fd,&msg);
2246 #ifdef __FAULT__        
2247 #ifdef HSTART
2248   if(!arg_hierarchical_start && recv_status < 0) error_in_req_serve_client(fd);
2249 #else
2250   if(recv_status < 0) error_in_req_serve_client(fd);
2251 #endif
2252 #endif
2253         
2254   DEBUGF(("Message is '%s'\n",msg.header.type));
2255   status = req_handler_dispatch(&msg,fd);
2256   switch (status) 
2257   {
2258     case REQ_OK: break;
2259     case REQ_FAILED: 
2260         fprintf(stderr,"Charmrun> Error processing control socket request %s\n",msg.header.type); 
2261         abort();
2262         break;
2263   }
2264   ChMessage_free(&msg);
2265 }
2266
2267 #ifdef HSTART
2268 void req_forward_root(SOCKET fd)
2269 {
2270   int recv_status;
2271   int status;
2272   ChMessage msg;
2273   recv_status = ChMessage_recv(fd,&msg);
2274
2275   char *cmd=msg.header.type;
2276
2277 #ifdef __FAULT__
2278         if(recv_status < 0)
2279   {
2280                   error_in_req_serve_client(fd);
2281                   return;
2282   }
2283
2284         /*called from reconnect_crashed_client */
2285         if (strcmp(cmd,"initnode")==0)
2286   {
2287                 set_crashed_socket_id(&msg,fd);
2288         }
2289 #endif
2290
2291   if (strcmp(cmd,"ping")!=0)
2292   {
2293                   status = req_reply(parent_charmrun_fd, cmd, msg.data,ChMessageInt(msg.header.len));
2294
2295   if (strcmp(cmd,"scanf")==0 || strcmp(cmd,"printsyn")==0 || strcmp(cmd,"printerrsyn")==0)
2296                   skt_sendN(parent_charmrun_fd,(const char *)&fd, sizeof(fd)); 
2297   
2298 #ifdef __FAULT__
2299   if (strcmp(cmd,"initnode")==0)
2300   {
2301         ChMessageInt_t oldpe=ChMessageInt_new(crashed_pe_id);
2302         ChMessageInt_t newpe=ChMessageInt_new(restarted_pe_id);
2303         skt_sendN(parent_charmrun_fd,(const char *)&oldpe, sizeof(oldpe)); 
2304     skt_sendN(parent_charmrun_fd,(const char *)&newpe, sizeof(newpe)); 
2305   }
2306 #endif
2307   }
2308
2309
2310   switch (status) 
2311   {
2312     case REQ_OK: break;
2313     case REQ_FAILED:
2314         abort();
2315         break;
2316   }
2317   ChMessage_free(&msg);
2318 }
2319
2320 void req_forward_client()
2321 {
2322   int recv_status;
2323   int status;
2324   ChMessage msg;
2325   recv_status = ChMessage_recv(parent_charmrun_fd,&msg);
2326   if(recv_status < 0)
2327       {
2328           int i;
2329           for (i=0;i<req_nClients;i++)
2330               skt_close(req_clients[i]);
2331           exit(0);
2332       }
2333     
2334   char *cmd=msg.header.type;
2335
2336     if(strcmp(cmd, "barrier") ==0){
2337                         int i;
2338                 for (i=0;i<req_nClients;i++)
2339       if (REQ_OK != req_reply(req_clients[i],cmd,msg.data,ChMessageInt(msg.header.len)))
2340            {
2341                 abort();
2342       }
2343                 return;
2344         }
2345 #ifdef __FAULT__
2346         if(strcmp(cmd, "initnodetab") ==0){
2347                 if(_last_crash ==0 ) 
2348                         cur_restart_phase++;
2349                 int i;
2350                 for (i=0;i<req_nClients;i++)
2351                         if(_last_crash==0 || i !=_crash_socket_index)
2352                                 if (REQ_OK != req_reply(req_clients[i],cmd,msg.data,ChMessageInt(msg.header.len))){
2353                                         abort();
2354                                 }
2355                 return;
2356         }
2357
2358         if(strcmp(cmd, "crashnode") ==0){
2359
2360                 int i;
2361                 for (i=0;i<req_nClients;i++)
2362                         if(_last_crash==0 || i !=_crash_socket_index)
2363       if (REQ_OK != req_reply(req_clients[i],cmd,msg.data,ChMessageInt(msg.header.len)))
2364            {
2365                 abort();
2366       }
2367                 return;
2368         }
2369         if(strcmp(cmd, "initnttab") ==0){
2370                         _last_crash = 0;
2371             if (REQ_OK != req_reply(req_clients[_crash_socket_index],"initnodetab",msg.data,ChMessageInt(msg.header.len)))
2372            {
2373                 abort();
2374       }
2375                 return;
2376         }
2377
2378 #endif
2379
2380   SOCKET fd;
2381
2382   /* CCS forward request */
2383   if(strcmp(cmd,"req_fw") ==0)
2384                   {
2385                          CcsImplHeader * hdr =(CcsImplHeader *)msg.data;
2386                          int pe=ChMessageInt(hdr->pe);
2387                          fd = nodetab_table[pe]->ctrlfd;
2388                   }     
2389                   else if(strcmp(cmd, "barrier0") ==0)
2390                   {
2391                         fd = nodetab_table[0]->ctrlfd;
2392                   }
2393     else
2394                   skt_recvN(parent_charmrun_fd, (const char *)&fd,sizeof(SOCKET));
2395                   
2396                   status = req_reply(fd, cmd, msg.data,ChMessageInt(msg.header.len));
2397
2398                   switch (status) 
2399                   {
2400                         case REQ_OK: break;
2401                         case REQ_FAILED:
2402                                 abort();
2403                                 break;
2404                   }
2405                   ChMessage_free(&msg);
2406 }
2407
2408 #endif  
2409
2410 int ignore_socket_errors(int c,const char *m)
2411 {  /*Abandon on further socket errors during error shutdown*/
2412                   
2413 #ifndef __FAULT__       
2414                   exit(2);
2415 #endif  
2416                         return -1;
2417 }
2418
2419 /*A socket went bad somewhere!  Immediately disconnect,
2420 which kills everybody.
2421 */
2422 int socket_error_in_poll(int code,const char *msg)
2423 {
2424                 /*commenting it for fault tolerance*/
2425                 /*ifdef it*/
2426
2427         int i;
2428         skt_set_abort(ignore_socket_errors);
2429         fprintf(stderr,"Charmrun: error on request socket--\n"
2430                         "%s\n",msg);
2431 #ifndef __FAULT__                       
2432         for (i=0;i<req_nClients;i++)
2433                 skt_close(req_clients[i]);
2434         exit(1);
2435 #endif  
2436         ftTimer = GetClock();
2437         return -1;
2438 }
2439
2440 #if CMK_USE_POLL /*poll() version*/
2441 # define CMK_PIPE_DECL(maxn,delayMs) \
2442         static struct pollfd *fds = NULL; \
2443         int nFds_sto=0; int *nFds=&nFds_sto; \
2444         int pollDelayMs=delayMs; \
2445         if (fds == NULL) fds = (struct pollfd *)malloc((maxn) * sizeof(struct pollfd));
2446 # define CMK_PIPE_SUB fds,nFds
2447 # define CMK_PIPE_CALL() poll(fds, *nFds, pollDelayMs); *nFds=0
2448
2449 # define CMK_PIPE_PARAM struct pollfd *fds,int *nFds
2450 # define CMK_PIPE_ADDREAD(rd_fd) \
2451         do {fds[*nFds].fd=rd_fd; fds[*nFds].events=POLLIN; (*nFds)++;} while(0)
2452 # define CMK_PIPE_ADDWRITE(wr_fd) \
2453         do {fds[*nFds].fd=wr_fd; fds[*nFds].events=POLLOUT; (*nFds)++;} while(0)
2454 # define CMK_PIPE_CHECKREAD(rd_fd) fds[(*nFds)++].revents&POLLIN
2455 # define CMK_PIPE_CHECKWRITE(wr_fd) fds[(*nFds)++].revents&POLLOUT
2456
2457 #else /*select() version*/
2458
2459 # define CMK_PIPE_DECL(maxn, delayMs) \
2460         fd_set rfds_sto,wfds_sto;\
2461         int nFds=0;  \
2462         fd_set *rfds=&rfds_sto,*wfds=&wfds_sto; struct timeval tmo; \
2463         FD_ZERO(rfds); FD_ZERO(wfds); \
2464         tmo.tv_sec=delayMs/1000; tmo.tv_usec=1000*(delayMs%1000);
2465 # define CMK_PIPE_SUB rfds,wfds
2466 # define CMK_PIPE_CALL() select(FD_SETSIZE, rfds, 0, 0, &tmo)
2467
2468 # define CMK_PIPE_PARAM fd_set *rfds,fd_set *wfds
2469 # define CMK_PIPE_ADDREAD(rd_fd) { assert(nFds<FD_SETSIZE);FD_SET(rd_fd,rfds); nFds++; }
2470 # define CMK_PIPE_ADDWRITE(wr_fd) FD_SET(wr_fd,wfds)
2471 # define CMK_PIPE_CHECKREAD(rd_fd) FD_ISSET(rd_fd,rfds)
2472 # define CMK_PIPE_CHECKWRITE(wr_fd) FD_ISSET(wr_fd,wfds)
2473 #endif
2474
2475 /*
2476 Wait for incoming requests on all client sockets,
2477 and the CCS socket (if present).
2478 */
2479 void req_poll()
2480 {
2481   int status,i;
2482   int readcount;
2483
2484   CMK_PIPE_DECL(req_nClients+5, 1000);
2485   for (i=0;i<req_nClients;i++)
2486         CMK_PIPE_ADDREAD(req_clients[i]);
2487   if (CcsServer_fd()!=INVALID_SOCKET) CMK_PIPE_ADDREAD(CcsServer_fd());
2488   if (arg_charmdebug) {
2489     CMK_PIPE_ADDREAD(0);
2490     CMK_PIPE_ADDREAD(gdb_info_std[1]);
2491     CMK_PIPE_ADDREAD(gdb_info_std[2]);
2492   }
2493
2494   skt_set_abort(socket_error_in_poll);
2495
2496   DEBUGF(("Req_poll: Calling select...\n"));
2497   status=CMK_PIPE_CALL();
2498   DEBUGF(("Req_poll: Select returned %d...\n",status));
2499
2500   if (status==0) return;/*Nothing to do-- timeout*/
2501
2502   if (status<0){ 
2503                 if (errno == EINTR || errno == EAGAIN) return;
2504                 fflush(stdout);
2505                 fflush(stderr);
2506                 socket_error_in_poll(1359,"Node program terminated unexpectedly!\n");
2507         }
2508   for (i=0;i<req_nClients;i++)
2509         if (CMK_PIPE_CHECKREAD(req_clients[i]))
2510           {
2511             readcount=10;   /*number of successive reads we serve per socket*/
2512             /*This client is ready to read*/
2513             do { req_serve_client(req_clients[i]); readcount--;}
2514             while (1==skt_select1(req_clients[i],0) && readcount>0);
2515           }
2516
2517   if (CcsServer_fd()!=INVALID_SOCKET)
2518          if (CMK_PIPE_CHECKREAD(CcsServer_fd())) {
2519                   DEBUGF(("Activity on CCS server port...\n"));
2520                   req_ccs_connect();
2521          }
2522
2523   if (arg_charmdebug) {
2524     char buf[2048];
2525     if (CMK_PIPE_CHECKREAD(0)) {
2526       int indata = read(0, buf, 5);
2527       buf[indata] = 0;
2528       if (indata < 5) fprintf(stderr,"Error reading command (%s)\n",buf);
2529       if (strncmp(buf,"info:",5)==0) {
2530         /* Found info command, forward data to gdb info program */
2531         char c;
2532         int num=0;
2533         //printf("Command to be forwarded\n");
2534         while (read(0, &c, 1)!=-1) {
2535           buf[num++]=c;
2536           if (c=='\n' || num >= 2045) {
2537             write(gdb_info_std[0], buf, num);
2538             if (c=='\n') break;
2539           }
2540         }
2541       }
2542       //printf("Command from charmdebug: %d(%s)\n",indata,buf);
2543     }
2544     /* All streams from gdb are forwarded to the stderr stream through the FILE
2545        gdb_stream which has been duplicated from stderr */
2546     /* NOTE: gdb_info_std[2] must be flushed before gdb_info_std[1] because the
2547        latter contains the string "(gdb) " ending the synchronization. Also the
2548        std[1] should be read with the else statement. It will not work without. */
2549     if (CMK_PIPE_CHECKREAD(gdb_info_std[2])) {
2550       int indata = read(gdb_info_std[2], buf, 100);
2551       /*printf("read data from gdb info stderr %d\n",indata);*/
2552       if (indata > 0) {
2553         buf[indata] = 0;
2554         //printf("printing %s\n",buf);
2555         //fflush(stdout);
2556         //fprintf(gdb_stream,"%s",buf);
2557         fflush(gdb_stream);
2558       }
2559     } else if (CMK_PIPE_CHECKREAD(gdb_info_std[1])) {
2560       int indata = read(gdb_info_std[1], buf, 100);
2561       /*printf("read data from gdb info stdout %d\n",indata);*/
2562       if (indata > 0) {
2563         buf[indata] = 0;
2564         //printf("printing %s\n",buf);
2565         //fflush(stdout);
2566         fprintf(gdb_stream,"%s",buf);
2567         fflush(gdb_stream);
2568       }
2569     }
2570   }
2571 }
2572
2573 #ifdef HSTART
2574                 void req_poll_hierarchical()
2575                 {
2576                   int status,i;
2577                   fd_set  rfds;
2578                   struct timeval tmo;
2579                   int readcount;
2580
2581                   skt_set_abort(socket_error_in_poll);
2582
2583                   tmo.tv_sec = 1;
2584                   tmo.tv_usec = 0;
2585                   FD_ZERO(&rfds); /* clears set of file descriptor */
2586                   for (i=0;i<req_nClients;i++)
2587                         FD_SET(req_clients[i],&rfds); /* adds client sockets to rfds set*/
2588                   if (CcsServer_fd()!=INVALID_SOCKET) FD_SET(CcsServer_fd(),&rfds);
2589                   if (arg_charmdebug) {
2590                         FD_SET(0, &rfds);
2591                         FD_SET(gdb_info_std[1], &rfds);
2592                         FD_SET(gdb_info_std[2], &rfds);
2593                   }
2594
2595                   if(arg_child_charmrun) 
2596                         FD_SET(parent_charmrun_fd,&rfds); /* adds client sockets to rfds set*/
2597                   DEBUGF(("Req_poll: Calling select...\n"));
2598                   status=select(FD_SETSIZE, &rfds, 0, 0, &tmo); /* FD_SETSIZE is the maximum number of file descriptors that a fd_set object can hold information about, select returns number of polls gathered */ 
2599                   DEBUGF(("Req_poll: Select returned %d...\n",status));
2600
2601                   if (status==0) return;/*Nothing to do-- timeout*/
2602                   if (status<0){ 
2603                                 fflush(stdout);
2604                                 fflush(stderr);
2605                                 socket_error_in_poll(1359,"Node program terminated unexpectedly!\n");
2606                         }
2607                   for (i=0;i<req_nClients;i++)
2608                         if (FD_ISSET(req_clients[i],&rfds))
2609                           {
2610                                 readcount=10;   /*number of successive reads we serve per socket*/
2611                                 /*This client is ready to read*/
2612                                 do {
2613                                                 if(arg_child_charmrun)
2614                                                         req_forward_root(req_clients[i]);
2615                                                 else
2616                                                         req_serve_client(req_clients[i]); 
2617                                                 readcount--;
2618                                 }
2619                                 while (1==skt_select1(req_clients[i],0) && readcount>0);
2620                           }
2621
2622
2623                 if(arg_child_charmrun)
2624                   //Forward from root to clients
2625                         if (FD_ISSET(parent_charmrun_fd,&rfds))
2626                           {
2627                                 readcount=10;   /*number of successive reads we serve per socket*/
2628                                 do{ 
2629                                                 req_forward_client();
2630                                                 readcount--;
2631                                 }
2632                                 while (1==skt_select1(parent_charmrun_fd,0) && readcount>0);
2633                           }
2634
2635                   /*Wait to receive responses and Forward responses */
2636                   if (CcsServer_fd()!=INVALID_SOCKET)
2637                          if (FD_ISSET(CcsServer_fd(),&rfds)) {
2638                                   DEBUGF(("Activity on CCS server port...\n"));
2639                                   req_ccs_connect();
2640                          }
2641
2642                   if (arg_charmdebug) {
2643                         char buf[2048];
2644                         if (FD_ISSET(0, &rfds)) {
2645                           int indata = read(0, buf, 5);
2646                           buf[indata] = 0;
2647                           if (indata < 5) fprintf(stderr,"Error reading command (%s)\n",buf);
2648                           if (strncmp(buf,"info:",5)==0) {
2649                         /* Found info command, forward data to gdb info program */
2650                         char c;
2651                         int num=0;
2652                         //printf("Command to be forwarded\n");
2653                         while (read(0, &c, 1)!=-1) {
2654                           buf[num++]=c;
2655                           if (c=='\n' || num >= 2045) {
2656                                 write(gdb_info_std[0], buf, num);
2657                                 if (c=='\n') break;
2658                           }
2659                         }
2660                           }
2661                           //printf("Command from charmdebug: %d(%s)\n",indata,buf);
2662                         }
2663                         /* All streams from gdb are forwarded to the stderr stream through the FILE
2664                            gdb_stream which has been duplicated from stderr */
2665                         /* NOTE: gdb_info_std[2] must be flushed before gdb_info_std[1] because the
2666                            latter contains the string "(gdb) " ending the synchronization. Also the
2667                            std[1] should be read with the else statement. It will not work without. */
2668                         if (FD_ISSET(gdb_info_std[2], &rfds)) {
2669                           int indata = read(gdb_info_std[2], buf, 100);
2670                           /*printf("read data from gdb info stderr %d\n",indata);*/
2671                           if (indata > 0) {
2672                         buf[indata] = 0;
2673                                 //printf("printing %s\n",buf);
2674                                 //fflush(stdout);
2675                         //fprintf(gdb_stream,"%s",buf);
2676                         fflush(gdb_stream);
2677                           }
2678                         } else if (FD_ISSET(gdb_info_std[1], &rfds)) {
2679                           int indata = read(gdb_info_std[1], buf, 100);
2680                           /*printf("read data from gdb info stdout %d\n",indata);*/
2681                           if (indata > 0) {
2682                         buf[indata] = 0;
2683                                 //printf("printing %s\n",buf);
2684                                 //fflush(stdout);
2685                         fprintf(gdb_stream,"%s",buf);
2686                         fflush(gdb_stream);
2687                           }
2688                         }
2689                   }
2690                 }
2691 #endif 
2692         
2693 static unsigned int server_port;
2694 static char server_addr[1024];/* IP address or hostname of charmrun*/
2695 static SOCKET server_fd;
2696
2697 #ifdef HSTART
2698 static skt_ip_t parent_charmrun_IP;
2699 static int parent_charmrun_port;
2700 static int parent_charmrun_pid;
2701 static int dataport;
2702 static SOCKET dataskt;
2703 int charmrun_phase =0;
2704 #endif 
2705
2706 int client_connect_problem(int code,const char *msg)
2707 {/*Called when something goes wrong during a client connect*/
2708
2709         fprintf(stderr,"Charmrun> error %d attaching to node:\n"
2710                 "%s\n",code,msg);
2711         exit(1);
2712         return -1;
2713 }
2714
2715 /** return 1 if connection is openned succesfully with client**/
2716 int errorcheck_one_client_connect(int client){
2717 #ifdef HSTART
2718         /* Child charmruns are already connected - Do we need to conect again*/ 
2719         if(arg_hierarchical_start && !arg_child_charmrun && charmrun_phase ==1) 
2720             return 1;   
2721 #endif 
2722         unsigned int clientPort;/*These are actually ignored*/
2723         skt_ip_t clientIP;
2724         if (arg_verbose) printf("Charmrun> Waiting for %d-th client to connect.\n",client);
2725         if (0==skt_select1(server_fd,arg_timeout*1000))
2726                 client_connect_problem(client,"Timeout waiting for node-program to connect");
2727
2728                 
2729         req_clients[client]=skt_accept(server_fd,&clientIP,&clientPort);
2730
2731         if (req_clients[client]==SOCKET_ERROR) 
2732                 client_connect_problem(client,"Failure in node accept");
2733
2734         skt_tcp_no_nagle(req_clients[client]);
2735
2736         return 1;
2737 };
2738
2739
2740 #if CMK_C_INLINE
2741 inline static
2742 #endif
2743 void read_initnode_one_client(int client){
2744                 ChMessage msg;
2745                 if (!skt_select1(req_clients[client],arg_timeout*1000))
2746                    client_connect_problem(client,"Timeout on IP request");
2747                 ChMessage_recv(req_clients[client],&msg);
2748                 req_handle_initnode(&msg,req_clients[client]);
2749                 ChMessage_free(&msg);
2750 }
2751
2752
2753 #if CMK_IBVERBS_FAST_START
2754 void req_one_client_partinit(int client){
2755    ChMessage partStartMsg;
2756          int clientNode;
2757                 
2758          if(errorcheck_one_client_connect(client)){
2759            if (!skt_select1(req_clients[client],arg_timeout*1000))
2760                    client_connect_problem(client,"Timeout on partial init request");
2761                          
2762            ChMessage_recv(req_clients[client],&partStartMsg);
2763            clientNode =            ChMessageInt(*(ChMessageInt_t*)partStartMsg.data);
2764            assert(strncmp(partStartMsg.header.type,"partinit",8) == 0);
2765            ChMessage_free(&partStartMsg);
2766          } 
2767         
2768 };
2769 #endif
2770
2771
2772 #ifdef HSTART
2773 int nodeCount = 0;
2774 /* To keep a global node numbering */
2775 void add_singlenodeinfo_to_mynodeinfo(ChMessage * msg, SOCKET ctrlfd)
2776 {
2777         /*add to myNodesInfo */                         
2778         ChSingleNodeinfo *nodeInfo = (ChSingleNodeinfo *)msg->data;
2779         
2780     /* need to change nodeNo */
2781         myNodesInfo[nodeCount].nodeNo = ChMessageInt_new(nodetab_rank0_table[ChMessageInt(nodeInfo->nodeNo)-mynodes_start]);
2782         myNodesInfo[nodeCount++].info = nodeInfo->info;
2783
2784         /* Required for CCS */
2785         int nt=nodetab_rank0_table[ChMessageInt(nodeInfo->nodeNo)-mynodes_start];/*Nodetable index for this node*/
2786         int pe;
2787         for (pe=0;pe<nodetab_cpus(nt);pe++)
2788     {
2789             nodetab_table[nt+pe]->ctrlfd=ctrlfd;
2790         }
2791 }
2792 #endif
2793
2794 #ifndef HSTART
2795 /* Original Function, need to check if modifications required*/ 
2796 void req_set_client_connect(int start,int end) {
2797         fd_set sockset;
2798         ChMessage msg;
2799         int client,i;
2800         int done,maxdesc;
2801         int *finished;
2802         int curclient,curclientend,curclientstart;
2803         
2804         curclient=curclientend=curclientstart=start;
2805
2806         finished=malloc((end-start)*sizeof(int));
2807         for(i=0;i<(end-start);i++)
2808                 finished[i]=0;
2809
2810 #if CMK_USE_IBVERBS && !CMK_IBVERBS_FAST_START
2811         for (i=start;i<end;i++) {
2812                 errorcheck_one_client_connect(curclientend++);
2813         }        
2814         if (req_nClients > 1) {
2815                 /*  a barrier to make sure infiniband device gets initialized */
2816                 for (i=start;i<end;i++) 
2817                         ChMessage_recv(req_clients[i],&msg);
2818                 for (i=start;i<end;i++)
2819                         req_reply(req_clients[i], "barrier", "", 1);
2820         }
2821 #endif
2822
2823         done=0;
2824         while(!done) {
2825                 /* check server socket for messages */
2826 #if ! CMK_USE_IBVERBS || CMK_IBVERBS_FAST_START
2827                 while(curclientstart==curclientend||skt_select1(server_fd,1)!=0) {
2828                         errorcheck_one_client_connect(curclientend++);
2829                 }
2830 #endif
2831                 /* check appropriate clients for messages */
2832                 for(client=curclientstart;client<curclientend;client++)
2833                         if(req_clients[client]>0) {
2834                                 if(skt_select1(req_clients[client],1)!=0) {
2835                                         ChMessage_recv(req_clients[client],&msg);
2836                                         req_handle_initnode(&msg,req_clients[client]);
2837                                         finished[client-start]=1;
2838                                 }
2839                         }
2840
2841
2842                 /* test if done */
2843                 done=1;
2844                 for(i=curclientstart-start;i<(end-start);i++)
2845                         if(finished[i]==0) {
2846                                 curclientstart=start+i;
2847                                 done=0;
2848                                 break;
2849                         }
2850
2851         }
2852         ChMessage_free(&msg);
2853
2854         free(finished);
2855 }
2856 #else
2857 /*int charmrun_phase =0; meaningful for main charmun to decide what to receive*/
2858 void req_set_client_connect(int start,int end) {
2859                         fd_set sockset;
2860                         ChMessage msg;
2861                         int client,i;
2862                         int done,maxdesc;
2863                         int *finished;
2864                         int curclient,curclientend,curclientstart;
2865                         
2866                         curclient=curclientend=curclientstart=start;
2867
2868                         finished=malloc((end-start)*sizeof(int));
2869                         for(i=0;i<(end-start);i++)
2870                                 finished[i]=0;
2871
2872                         if(arg_child_charmrun && start==0 ) myNodesInfo = malloc(sizeof(ChSingleNodeinfo)*nodetab_rank0_size); 
2873
2874 #if CMK_USE_IBVERBS && !CMK_IBVERBS_FAST_START
2875         for (i=start;i<end;i++) {
2876                 errorcheck_one_client_connect(curclientend++);
2877         }        
2878         if (req_nClients > 1) {
2879                 /*  a barrier to make sure infiniband device gets initialized */
2880                 for (i=start;i<end;i++) 
2881                         ChMessage_recv(req_clients[i],&msg);
2882                 for (i=start;i<end;i++)
2883                         req_reply(req_clients[i], "barrier", "", 1);
2884         }
2885 #endif
2886
2887                         done=0;
2888                         while(!done) {
2889                                 /* check server socket for messages */
2890 #if ! CMK_USE_IBVERBS || CMK_IBVERBS_FAST_START
2891                 while(curclientstart==curclientend||skt_select1(server_fd,1)!=0) {
2892                         errorcheck_one_client_connect(curclientend++);
2893                 }
2894 #endif
2895                                 /* check appropriate clients for messages */
2896                                 for(client=curclientstart;client<curclientend;client++)
2897                                         if(req_clients[client]>0) {
2898                                                 if(skt_select1(req_clients[client],1)!=0) {
2899                                                         ChMessage_recv(req_clients[client],&msg);
2900                                                         if(!arg_hierarchical_start)
2901                                                                 req_handle_initnode(&msg,req_clients[client]);
2902                                                         else{
2903                                                                         if(!arg_child_charmrun)
2904                                                                                 {
2905                                                                                         if(charmrun_phase ==1) 
2906                                                                                                 receive_nodeset_from_child(&msg, req_clients[client]);
2907                                                                                         else
2908                                                                                                 set_sockets_list(&msg, req_clients[client]);    
2909                                                                                         //here we need to decide based upon the phase
2910                                                                                 }
2911                                                                         else /* hier-start with 2nd leval*/
2912                                                                                 add_singlenodeinfo_to_mynodeinfo(&msg,req_clients[client] );    
2913                                                         }
2914                                                         finished[client-start]=1;
2915                                                         }
2916                                                 }
2917                                         
2918                                 /* test if done */
2919                                 done=1;
2920                                 for(i=curclientstart-start;i<(end-start);i++)
2921                                         if(finished[i]==0) {
2922                                                 curclientstart=start+i;
2923                                                 done=0;
2924                                                 break;
2925                                         }
2926
2927                         }
2928                         ChMessage_free(&msg);
2929
2930                         free(finished);
2931 }
2932 #endif
2933                                                 
2934                                                 
2935 /* allow one client to connect */
2936 void req_one_client_connect(int client)
2937 {
2938         if(errorcheck_one_client_connect(client))
2939         { /*This client has just connected-- fetch his name and IP*/
2940                 read_initnode_one_client(client);
2941         }
2942 }
2943
2944 #if CMK_USE_IBVERBS
2945 /* Each node has sent the qpn data for all the qpns it has created
2946    This data needs to be sent to all the other nodes
2947          This needs to be done for all nodes
2948 **/
2949 void exchange_qpdata_clients(){
2950         int proc,i;
2951         for( i=0;i<nodetab_rank0_size;i++){
2952                 int nt=nodetab_rank0_table[i];/*Nodetable index for this node*/ 
2953                 nodetab_table[nt]->qpData = malloc(sizeof(ChInfiAddr)*nodetab_rank0_size);
2954         }
2955         for(proc =0;proc< nodetab_rank0_size;proc++){
2956                 int count=0;
2957                 for(i=0;i<nodetab_rank0_size;i++){
2958                         if(i == proc){
2959                         }else{
2960                                 int nt=nodetab_rank0_table[i];/*Nodetable index for this node*/ 
2961                                 nodetab_table[nt]->qpData[proc] =  nodeinfo_arr[proc].qpList[count];
2962         //                      printf("Charmrun> nt %d proc %d lid 0x%x qpn 0x%x psn 0x%x\n",nt,proc,ChMessageInt(nodetab_table[nt]->qpData[proc].lid),ChMessageInt(nodetab_table[nt]->qpData[proc].qpn),ChMessageInt(nodetab_table[nt]->qpData[proc].psn));
2963                                 count++;
2964                         }
2965                 }
2966                                 free(nodeinfo_arr[proc].qpList);
2967                         }
2968                 };
2969
2970                 void    send_clients_nodeinfo_qpdata(){
2971                         int node;
2972                         int msgSize = sizeof(ChMessageInt_t)+sizeof(ChNodeinfo)*nodetab_rank0_size+sizeof(ChInfiAddr)*nodetab_rank0_size;
2973                         for(node=0;node<nodetab_rank0_size;node++){
2974                                 int nt=nodetab_rank0_table[node];/*Nodetable index for this node*/
2975                 //              printf("Charmrun> Node %d proc %d sending initnodetab \n",node,nt);
2976                                 ChMessageHeader hdr;
2977                                 ChMessageInt_t nNodes=ChMessageInt_new(nodetab_rank0_size);
2978                                 ChMessageHeader_new("initnodetab",msgSize,&hdr);
2979                                 skt_sendN(nodetab_table[nt]->ctrlfd,(const char *)&hdr,sizeof(hdr));
2980                                 skt_sendN(nodetab_table[nt]->ctrlfd,(const char *)&nNodes,sizeof(nNodes));
2981                                 skt_sendN(nodetab_table[nt]->ctrlfd,(const char *)nodeinfo_arr,sizeof(ChNodeinfo)*nodetab_rank0_size);
2982                                 skt_sendN(nodetab_table[nt]->ctrlfd,(const char *)&nodetab_table[nt]->qpData[0],sizeof(ChInfiAddr)*nodetab_rank0_size);                         
2983                         }
2984                 }
2985 #endif
2986
2987                 struct timeval tim;
2988 #define  getthetime(x) gettimeofday(&tim,NULL); x = tim.tv_sec + (tim.tv_usec/1000000.0);
2989 #define getthetime1(x) gettimeofday(&tim,NULL); x = tim.tv_sec ;
2990                 /*Wait for all the clients to connect to our server port*/
2991                 void req_client_connect(void)
2992                 {
2993                         int client;
2994 #ifdef HSTART
2995                         if(!arg_hierarchical_start)
2996 #endif
2997                         nodeinfo_allocate();
2998                         req_nClients=nodetab_rank0_size;
2999                         req_clients=(SOCKET *)malloc(req_nClients*sizeof(SOCKET));
3000                         for(client=0;client<req_nClients;client++)
3001                                 req_clients[client]=-1;
3002                         
3003                         skt_set_abort(client_connect_problem);
3004                         
3005 #if CMK_IBVERBS_FAST_START
3006                         for (client=0;client<req_nClients;client++){
3007                                 req_one_client_partinit(client);
3008                         }
3009                         for (client=0;client<req_nClients;client++){
3010                                 read_initnode_one_client(client);
3011                         }
3012 #else
3013
3014                         req_set_client_connect(0,req_nClients);
3015
3016 #endif
3017                         
3018                                 if (portOk == 0) exit(1);
3019                         if (arg_verbose) printf("Charmrun> All clients connected.\n");
3020 #if CMK_USE_IBVERBS
3021                         exchange_qpdata_clients();
3022                         send_clients_nodeinfo_qpdata();
3023 #else
3024 #ifdef HSTART
3025                         if(arg_hierarchical_start) {
3026                                 /* first we need to send data to parent charmrun and then send the nodeinfo to the clients*/
3027                         send_myNodeInfo_to_parent();
3028                         /*then receive from root */
3029                         forward_nodetab_to_children();
3030                         }
3031
3032                         else 
3033 #endif
3034                         for (client=0;client<req_nClients;client++)     {                       
3035                                 req_handle_initnodetab(NULL,req_clients[client]);
3036                         }
3037                         
3038 #endif
3039                         if (arg_verbose) printf("Charmrun> IP tables sent.\n");
3040                 }
3041                 /*Wait for all the clients to connect to our server port, then collect and send nodetable to all */
3042 #ifdef HSTART
3043                 void req_charmrun_connect(void)
3044                 {
3045                 //      double t1, t2, t3, t4;
3046                         int client;
3047                         nodeinfo_allocate();
3048                         req_nClients=branchfactor;
3049                         req_clients=(SOCKET *)malloc(req_nClients*sizeof(SOCKET));
3050                         charmrun_fds=(SOCKET *)malloc(req_nClients*sizeof(SOCKET));
3051                         for(client=0;client<req_nClients;client++)
3052                                 req_clients[client]=-1;
3053                         
3054                         skt_set_abort(client_connect_problem);
3055                         
3056 #if CMK_IBVERBS_FAST_START
3057                         for (client=0;client<req_nClients;client++){
3058                                 req_one_client_partinit(client);
3059                         }
3060                         for (client=0;client<req_nClients;client++){
3061                                 read_initnode_one_client(client);
3062                         }
3063 #else
3064 //if(!arg_child_charmrun) getthetime(t1);
3065
3066                         req_set_client_connect(0,req_nClients);
3067 //if(!arg_child_charmrun)       getthetime(t2);         /* also need to process received nodesets JIT */
3068 #endif
3069                         
3070                                 if (portOk == 0) exit(1);
3071                         if (arg_verbose) printf("Charmrun> All clients connected.\n");
3072 #if CMK_USE_IBVERBS
3073                         exchange_qpdata_clients();
3074                         send_clients_nodeinfo_qpdata();
3075 #else
3076                         for (client=0;client<req_nClients;client++)     {
3077                                                         // add flag to check what leval charmrun it is and what phase
3078                                 req_handle_initnodedistribution(NULL, charmrun_fds[client], client);
3079                         }
3080 //getthetime(t3);
3081
3082                         /* Now receive the nodetab from child charmruns*/
3083                         charmrun_phase = 1;
3084                         
3085                         skt_set_abort(client_connect_problem);
3086
3087                         req_set_client_connect(0,req_nClients);
3088
3089                         /* Already processed, so send*/
3090                         for (client=0;client<req_nClients;client++)     {                       
3091                                 req_handle_initnodetab(NULL,req_clients[client]);
3092                         }
3093 //if(!arg_child_charmrun) getthetime(t4);
3094 #endif
3095                         if (arg_verbose) printf("Charmrun> IP tables sent.\n");
3096 //if(!arg_child_charmrun) printf("Time for charmruns connect= %f , sending nodes to fire= %f, node clients connected= %f n ", t2-t1, t3-t2, t4-t3);
3097                 }
3098
3099 #endif
3100
3101 #ifndef CMK_BPROC
3102
3103 void start_one_node_rsh(int rank0no);
3104 void finish_one_node(int rank0no);
3105 void finish_set_nodes(int start, int stop);
3106
3107
3108
3109 void req_client_start_and_connect(void)
3110 {
3111         int client, c;
3112         int batch = arg_batch_spawn;        /* fire several at a time */
3113         int clientgroup,clientstart;
3114         int counter;
3115
3116 #ifdef HSTART
3117         if(!arg_hierarchical_start)
3118 #endif
3119         nodeinfo_allocate();
3120         req_nClients=nodetab_rank0_size;
3121         req_clients=(SOCKET *)malloc(req_nClients*sizeof(SOCKET));
3122         
3123         skt_set_abort(client_connect_problem);
3124
3125         client=0;
3126         while(client<req_nClients) { /* initiate a batch */
3127                 clientstart=client;
3128
3129                 for(counter=0;counter<batch;counter++) { /* initiate batch number of nodes */
3130                         clientgroup=start_set_node_rsh(client);
3131                         client+=clientgroup;
3132                         if(client>=req_nClients) {
3133                                 client=req_nClients;
3134                                 break;
3135                         }
3136                 }
3137 #if CMK_USE_RSH
3138                   /* ssh x11 forwarding will make sure ssh exit */
3139                 if (!arg_ssh_display) 
3140 #endif
3141                 finish_set_nodes(clientstart,client);
3142
3143 #if CMK_IBVERBS_FAST_START
3144                 for (c=clientstart;c<client;c++) { 
3145                         req_one_client_partinit(c);
3146                 }
3147 #else
3148                 req_set_client_connect(clientstart,client);
3149 #endif                                          
3150         }
3151
3152
3153 #if CMK_IBVERBS_FAST_START
3154         for (client=0;client<req_nClients;client++){
3155                 read_initnode_one_client(client);
3156         }
3157 #endif
3158         if (portOk == 0) exit(1);
3159         if (arg_verbose) printf("Charmrun> All clients connected.\n");
3160
3161 #if CMK_USE_IBVERBS
3162         exchange_qpdata_clients();      
3163         send_clients_nodeinfo_qpdata();
3164 #else
3165 #ifdef HSTART
3166         if(arg_hierarchical_start) {
3167                                 /* first we need to send data to parent charmrun and then send the nodeinfo to the clients*/
3168                         send_myNodeInfo_to_parent();
3169                         /*then receive from root */
3170                         forward_nodetab_to_children();
3171                         }
3172
3173                         else
3174 #endif
3175                         for (client=0;client<req_nClients;client++)     {                       
3176                                 req_handle_initnodetab(NULL,req_clients[client]);
3177                         }
3178                         
3179
3180 #endif    
3181         if (arg_verbose) printf("Charmrun> IP tables sent.\n");
3182         free(rsh_pids); /* done with rsh_pids */
3183 }
3184
3185 #endif
3186
3187                 /*Start the server socket the clients will connect to.*/
3188                 void req_start_server(void)
3189                 {
3190                   skt_ip_t ip=skt_innode_my_ip();
3191                   if (arg_local)
3192                           /* local execution, use localhost always */
3193                         strcpy(server_addr, "127.0.0.1");
3194                   else if (arg_charmrunip != NULL)
3195                           /* user specify the IP at +useip */
3196                         strcpy(server_addr, arg_charmrunip);
3197                   else if ( (arg_charmrunip = getenv ("CHARMRUN_IP")) != NULL)
3198                           /* user specify the env  */
3199                         strcpy(server_addr, arg_charmrunip);
3200                   else if (skt_ip_match(ip,_skt_invalid_ip)) {
3201                           printf("Charmrun> Warning-- cannot find IP address for your hostname.  Using loopback.\n");
3202                           strcpy(server_addr, "127.0.0.1");
3203                   }
3204                   else if (arg_usehostname || skt_ip_match(ip,skt_lookup_ip("127.0.0.1")))
3205                           /*Use symbolic host name as charmrun address*/
3206                         gethostname(server_addr,sizeof(server_addr));
3207                   else 
3208                         skt_print_ip(server_addr,ip);
3209
3210                   server_port = 0;
3211                   server_fd=skt_server(&server_port);
3212
3213                   if (arg_verbose) {
3214                         printf("Charmrun> Charmrun = %s, port = %d\n", server_addr, server_port);
3215                   }
3216                   
3217 #if CMK_CCS_AVAILABLE
3218 #ifdef HSTART
3219                   if(!arg_hierarchical_start || (arg_hierarchical_start && !arg_child_charmrun))
3220 #endif
3221                   if(arg_server == 1) CcsServer_new(NULL,&arg_server_port,arg_server_auth);
3222 #endif
3223                 }
3224 #ifdef HSTART
3225 int unique_node_start;
3226                 /* Function copied from machine.c file */
3227                 void parse_netstart(void)
3228                 {
3229                   char *ns;
3230                   int nread;
3231                   int port;
3232                   ns = getenv("NETSTART");
3233                   if (ns!=0) 
3234                   {/*Read values set by Charmrun*/
3235                                 char parent_charmrun_name[1024];
3236                                 nread = sscanf(ns, "%d%s%d%d%d",
3237                                                  &unique_node_start,
3238                                                  parent_charmrun_name, &parent_charmrun_port,
3239                                                  &parent_charmrun_pid, &port);
3240                         parent_charmrun_IP=skt_lookup_ip(parent_charmrun_name);
3241                         mynodes_start = nodetab_unique_table[unique_node_start]; /*Works only when init_hierarchical called in child charmrun*/
3242
3243
3244                                 if (nread!=5) {
3245                                                 fprintf(stderr,"Error parsing NETSTART '%s'\n",ns);
3246                                                 exit(1);
3247                                 }
3248                   } 
3249 #if CMK_USE_IBVERBS | CMK_USE_IBUD
3250                         char *cmi_num_nodes = getenv("CmiNumNodes");
3251                         if(cmi_num_nodes != NULL){
3252                                 sscanf(cmi_num_nodes,"%d",&_Cmi_numnodes);
3253                         }
3254 #endif  
3255                 }
3256
3257                 int nodetab_rank0_size_total;
3258                 /* Receive nodes for which I am responsible*/
3259                 void my_nodetab_store(ChMessage *msg)
3260                 {
3261                         ChMessageInt_t * nodelistmsg = (ChMessageInt_t *)msg->data;     
3262                         nodetab_rank0_size = ChMessageInt(nodelistmsg[0]);
3263                         nodetab_rank0_size_total =  ChMessageInt(nodelistmsg[1]);
3264                         int k;
3265                         for(k =0; k<nodetab_rank0_size ; k++)
3266                         {
3267                                 nodetab_rank0_table[k] = ChMessageInt(nodelistmsg[k+2]);
3268                         }
3269                 }
3270
3271
3272 /* In hierarchical startup, this function is used by child charmrun to obtains the list of nodes for which it is responsible */
3273                 void nodelist_obtain(void)
3274                 {
3275                   ChMessage nodelistmsg; /* info about all nodes*/
3276                   /*Contact charmrun for machine info.*/
3277
3278 #if CMK_USE_IBVERBS
3279                         {
3280                 /*              int qpListSize = (_Cmi_numnodes-1)*sizeof(ChInfiAddr);
3281                                 me.info.qpList = malloc(qpListSize);
3282                                 copyInfiAddr(me.info.qpList);
3283                                 MACHSTATE1(3,"me.info.qpList created and copied size %d bytes",qpListSize);
3284                                 ctrl_sendone_nolock("initnode",(const char *)&me,sizeof(me),(const char *)me.info.qpList,qpListSize);
3285                                 free(me.info.qpList);
3286                 */      }
3287 #else
3288                         ChMessageHeader hdr;
3289                         ChMessageInt_t node_start=ChMessageInt_new(unique_node_start);
3290                         ChMessageHeader_new("initnodetab",sizeof(ChMessageInt_t),&hdr);
3291                         skt_sendN(parent_charmrun_fd,(const char *)&hdr,sizeof(hdr));
3292                         skt_sendN(parent_charmrun_fd,(const char *)&node_start,sizeof(node_start));
3293
3294                  #endif //CMK_USE_IBVERBS
3295
3296                   
3297                         /*We get the other node addresses from a message sent
3298                           back via the charmrun control port.*/
3299                         if (!skt_select1(parent_charmrun_fd,1200*1000)){
3300                         exit(0);
3301                         }
3302                         ChMessage_recv(parent_charmrun_fd,&nodelistmsg);
3303                   
3304                   my_nodetab_store(&nodelistmsg);
3305                   ChMessage_free(&nodelistmsg);
3306                 }
3307
3308
3309                 void init_mynodes(void)
3310                 {
3311                 parse_netstart();
3312                 if (!skt_ip_match(parent_charmrun_IP,_skt_invalid_ip)) {
3313                         dataskt=skt_server(&dataport);
3314                         parent_charmrun_fd = skt_connect(parent_charmrun_IP, parent_charmrun_port, 1800);
3315                           } else {
3316                         parent_charmrun_fd=-1;
3317                   }
3318
3319                   nodelist_obtain();
3320                 }
3321 #endif
3322
3323 /****************************************************************************
3324  *
3325  *  The Main Program
3326  *
3327  ****************************************************************************/
3328 void start_nodes_daemon(void);
3329 void start_nodes_rsh(void);
3330 void start_nodes_mpiexec();
3331 #ifdef HSTART
3332 void start_next_level_charmruns(void);
3333 #endif
3334 #if CMK_BPROC
3335 void nodetab_init_for_scyld(void);
3336 void start_nodes_scyld(void);
3337 #endif
3338 void start_nodes_local(char **envp);
3339 void kill_nodes(void);
3340 void open_gdb_info(void);
3341 void read_global_segments_size(void);
3342
3343 static void fast_idleFn(void) {sleep(0);}
3344 void finish_nodes(void);
3345
3346 int main(int argc, char **argv, char **envp)
3347 {
3348   srand(time(0)); 
3349   skt_init();
3350   skt_set_idle(fast_idleFn);
3351   /* CrnSrand((int) time(0)); */
3352   /* notify charm developers that charm is in use */
3353
3354 #ifdef HSTART
3355   if(!arg_child_charmrun)
3356 #endif
3357   ping_developers();    
3358   /* Compute the values of all constants */