[1853] | 1 | #include <mpi.h> |
---|
| 2 | #include <stdio.h> |
---|
| 3 | #include <stdlib.h> |
---|
| 4 | #include <string.h> |
---|
| 5 | #include <getopt.h> |
---|
| 6 | #include <signal.h> |
---|
| 7 | |
---|
| 8 | |
---|
| 9 | #ifdef __HAVE_LIBCCC_USER__ |
---|
| 10 | #include "ccc_user.h" |
---|
| 11 | #else |
---|
| 12 | static int ccc_tremain(double *tremain) |
---|
| 13 | { |
---|
| 14 | tremain[0] = 0. ; |
---|
| 15 | return EXIT_FAILURE; |
---|
| 16 | } |
---|
| 17 | #endif |
---|
| 18 | |
---|
| 19 | #define GLOST_MAXLEN 4096 |
---|
| 20 | #define GLOST_MASTER 0 |
---|
| 21 | #define TAG_AVAIL 1 |
---|
| 22 | #define TAG_TSK 2 |
---|
| 23 | |
---|
| 24 | static int glost_no_new_task=0; |
---|
| 25 | |
---|
| 26 | void read_options(int argc, char *argv[],double *user_tremain); |
---|
| 27 | void read_and_exec(char *filename, double user_tremain); |
---|
| 28 | void read_and_send(int slaves, char *filename, double user_tremain); |
---|
| 29 | void recv_and_exec(int rank); |
---|
| 30 | void set_sigaction(); |
---|
| 31 | |
---|
| 32 | static void set_glost_no_new_task(int signum) |
---|
| 33 | { |
---|
| 34 | fprintf(stderr,"#signal %i received: no new task will be submitted\n",signum); |
---|
| 35 | glost_no_new_task=1; |
---|
| 36 | } |
---|
| 37 | |
---|
| 38 | static void read_next_command(FILE *fl,char *tsk, double user_tremain) |
---|
| 39 | { |
---|
| 40 | int r; |
---|
| 41 | double tremain; |
---|
| 42 | |
---|
| 43 | tsk[0]='\0'; |
---|
| 44 | |
---|
| 45 | r = ccc_tremain(&tremain); |
---|
| 46 | |
---|
| 47 | fprintf(stderr,"#time remaining = %g\n", tremain); |
---|
| 48 | fprintf(stderr,"#user_tremain = %g\n", user_tremain); |
---|
| 49 | // fprintf(stderr,"#r=%d\n", r); |
---|
| 50 | |
---|
| 51 | r = (!r && tremain < user_tremain); |
---|
| 52 | if (r) |
---|
| 53 | fprintf(stderr,"#time remaining = %g < %g : do not launch new tasks.\n", |
---|
| 54 | tremain,user_tremain); |
---|
| 55 | |
---|
| 56 | if (glost_no_new_task) r = 1; |
---|
| 57 | if (r) return; |
---|
| 58 | |
---|
| 59 | /* if(!fgets(tsk,GLOST_MAXLEN,fl)) tsk[0]='\0'; */ |
---|
| 60 | /* if(tsk[strlen(tsk)-1]=='\n') tsk[strlen(tsk)-1]='\0'; */ |
---|
| 61 | |
---|
| 62 | do { |
---|
| 63 | if(!fgets(tsk,GLOST_MAXLEN,fl)){ |
---|
| 64 | tsk[0] = '\0'; |
---|
| 65 | break; |
---|
| 66 | } |
---|
| 67 | r = strlen(tsk); |
---|
| 68 | } while (r < 2); |
---|
| 69 | |
---|
| 70 | if(tsk[r-1]=='\n') tsk[r-1]='\0'; |
---|
| 71 | |
---|
| 72 | } |
---|
| 73 | |
---|
| 74 | static void exec_command(char *tsk, int rank) |
---|
| 75 | { |
---|
| 76 | double t; |
---|
| 77 | int r; |
---|
| 78 | |
---|
| 79 | t = MPI_Wtime(); |
---|
| 80 | r = system(tsk); |
---|
| 81 | t = MPI_Wtime() - t; |
---|
| 82 | if ( WIFEXITED(r) ) |
---|
| 83 | { |
---|
| 84 | r = WEXITSTATUS(r); |
---|
| 85 | fprintf(stderr,"#executed by process\t%d in %gs\twith status\t%d : %s\n", |
---|
| 86 | rank,t,r,tsk); |
---|
| 87 | } |
---|
| 88 | else { |
---|
| 89 | if( WIFSIGNALED(r) ){ |
---|
| 90 | r = WTERMSIG(r); |
---|
| 91 | fprintf(stderr,"#executed by process\t%d in %gs\tkilled by signal %d: %s\n", |
---|
| 92 | rank,t,r,tsk); |
---|
| 93 | } |
---|
| 94 | } |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | |
---|
| 98 | int main(int argc,char **argv) |
---|
| 99 | { |
---|
| 100 | FILE *fl; |
---|
| 101 | int rank,size; |
---|
| 102 | double user_tremain; |
---|
| 103 | |
---|
| 104 | MPI_Init(&argc,&argv); |
---|
| 105 | MPI_Comm_rank(MPI_COMM_WORLD,&rank); |
---|
| 106 | MPI_Comm_size(MPI_COMM_WORLD,&size); |
---|
| 107 | |
---|
| 108 | set_sigaction(); |
---|
| 109 | if (rank == GLOST_MASTER){ |
---|
| 110 | printf("master is %d , nb slaves: %d\n", GLOST_MASTER,size-1); |
---|
| 111 | read_options(argc,argv,&user_tremain); |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | if (size == 1) |
---|
| 115 | read_and_exec(argv[optind],user_tremain); |
---|
| 116 | else if(size != 1 && rank == GLOST_MASTER) |
---|
| 117 | read_and_send(size-1,argv[optind],user_tremain); |
---|
| 118 | else |
---|
| 119 | recv_and_exec(rank); |
---|
| 120 | |
---|
| 121 | MPI_Finalize(); |
---|
| 122 | } |
---|
| 123 | |
---|
| 124 | void read_options(int argc, char *argv[],double *user_tremain ) |
---|
| 125 | { |
---|
| 126 | int r; |
---|
| 127 | int longoptind; |
---|
| 128 | char opt[256]; |
---|
| 129 | |
---|
| 130 | user_tremain[0] = -1.; |
---|
| 131 | static struct option longopts[]= |
---|
| 132 | { |
---|
| 133 | {"time_remaining",required_argument,NULL,'R'}, |
---|
| 134 | {0,0,0,0} |
---|
| 135 | }; |
---|
| 136 | |
---|
| 137 | while (r = getopt_long(argc, argv,"R:",longopts,&longoptind)) |
---|
| 138 | { |
---|
| 139 | if (r == -1) break; |
---|
| 140 | if (r == 0){ /* long option */ |
---|
| 141 | fprintf(stderr,"r %c\n",longopts[longoptind].val); |
---|
| 142 | r = longopts[longoptind].val ; |
---|
| 143 | } |
---|
| 144 | |
---|
| 145 | switch(r) |
---|
| 146 | { |
---|
| 147 | case 'R': |
---|
| 148 | *user_tremain = strtod(optarg,NULL); |
---|
| 149 | #ifndef __HAVE_LIBCCC_USER__ |
---|
| 150 | fprintf(stderr,"WARNING option -R %g ignored: not compiled with libccc_user\n",*user_tremain); |
---|
| 151 | #endif |
---|
| 152 | break; |
---|
| 153 | |
---|
| 154 | case '?': |
---|
| 155 | fprintf(stderr,"WARNING option %c ignored: unknown option\n",optopt); |
---|
| 156 | break; |
---|
| 157 | |
---|
| 158 | default: |
---|
| 159 | abort(); |
---|
| 160 | break; |
---|
| 161 | } |
---|
| 162 | } |
---|
| 163 | } |
---|
| 164 | |
---|
| 165 | void read_and_exec(char *filename, double user_tremain ) |
---|
| 166 | { |
---|
| 167 | FILE *fl; |
---|
| 168 | char tsk[GLOST_MAXLEN]; |
---|
| 169 | double t; |
---|
| 170 | |
---|
| 171 | fl = fopen(filename,"r"); |
---|
| 172 | do { |
---|
| 173 | read_next_command(fl,tsk,user_tremain); |
---|
| 174 | if(!strlen(tsk)) |
---|
| 175 | break; |
---|
| 176 | exec_command(tsk,GLOST_MASTER); |
---|
| 177 | } while (strlen(tsk)); |
---|
| 178 | fclose(fl); |
---|
| 179 | } |
---|
| 180 | |
---|
| 181 | void read_and_send(int slaves,char *filename, double user_tremain ) |
---|
| 182 | { |
---|
| 183 | int i, num, r; |
---|
| 184 | MPI_Status status; |
---|
| 185 | FILE *fl; |
---|
| 186 | char tsk[GLOST_MAXLEN]; |
---|
| 187 | |
---|
| 188 | fl = fopen(filename,"r"); |
---|
| 189 | i=0; |
---|
| 190 | do { |
---|
| 191 | read_next_command(fl,tsk,user_tremain); |
---|
| 192 | |
---|
| 193 | MPI_Recv(&num,1,MPI_INT,MPI_ANY_SOURCE, |
---|
| 194 | TAG_AVAIL,MPI_COMM_WORLD,&status); |
---|
| 195 | MPI_Send(tsk,GLOST_MAXLEN,MPI_CHAR,num, |
---|
| 196 | TAG_TSK,MPI_COMM_WORLD); |
---|
| 197 | if (!strlen(tsk)) /* terminate command sent */ |
---|
| 198 | i++; |
---|
| 199 | } while (i < slaves); |
---|
| 200 | fclose(fl); |
---|
| 201 | } |
---|
| 202 | |
---|
| 203 | void recv_and_exec(int rank) |
---|
| 204 | { |
---|
| 205 | char tsk[GLOST_MAXLEN]; |
---|
| 206 | MPI_Status status; |
---|
| 207 | |
---|
| 208 | do { |
---|
| 209 | MPI_Send(&rank,1,MPI_INT,GLOST_MASTER, |
---|
| 210 | TAG_AVAIL,MPI_COMM_WORLD); |
---|
| 211 | MPI_Recv(tsk,GLOST_MAXLEN,MPI_CHAR,GLOST_MASTER, |
---|
| 212 | TAG_TSK,MPI_COMM_WORLD,&status); |
---|
| 213 | if(!strlen(tsk)) /* terminate command */ |
---|
| 214 | break; |
---|
| 215 | exec_command(tsk,rank); |
---|
| 216 | } while (strlen(tsk)); |
---|
| 217 | } |
---|
| 218 | |
---|
| 219 | |
---|
| 220 | /* signal handling */ |
---|
| 221 | void set_sigaction() |
---|
| 222 | { |
---|
| 223 | struct sigaction new_action; |
---|
| 224 | |
---|
| 225 | new_action.sa_handler = set_glost_no_new_task ; |
---|
| 226 | sigemptyset(&new_action.sa_mask); |
---|
| 227 | new_action.sa_flags = SA_RESETHAND; |
---|
| 228 | |
---|
| 229 | if (sigaction(SIGUSR1,&new_action,NULL) < 0) |
---|
| 230 | fprintf(stderr,"#WARNING sigaction failed: no SIGQUIT support\n"); |
---|
| 231 | } |
---|
| 232 | |
---|
| 233 | |
---|
| 234 | |
---|