Changeset 4450 for trunk/Ohana/src/opihi/pantasks
- Timestamp:
- Jul 4, 2005, 5:35:47 PM (21 years ago)
- Location:
- trunk/Ohana/src/opihi/pantasks
- Files:
-
- 7 added
- 9 edited
-
CheckJobs.c (added)
-
CheckSystem.c (added)
-
CheckTasks.c (added)
-
ControllerOps.c (added)
-
IOBufferOps.c (added)
-
JobOps.c (modified) (9 diffs)
-
LocalJob.c (modified) (1 diff)
-
Makefile (modified) (2 diffs)
-
TaskOps.c (modified) (3 diffs)
-
controller.c (added)
-
init.c (modified) (2 diffs)
-
memstr.c (added)
-
run.c (modified) (2 diffs)
-
scheduler.c (modified) (1 diff)
-
task_command.c (modified) (1 diff)
-
task_host.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Ohana/src/opihi/pantasks/JobOps.c
r3140 r4450 1 # include "opihi.h"2 1 # include "scheduler.h" 3 2 … … 9 8 10 9 static Job *jobs; 11 static int Njobs;12 static int NJOBS;10 static int Njobs; 11 static int NJOBS; 13 12 14 13 static char *JobName = dot; … … 65 64 66 65 for (i = 0; i < Njobs; i++) { 67 fprintf (stderr, "%d: %-15s %5d %20s (%x)\n", Njobs, jobs[i].task .name, jobs[i].JobID, jobs[i].task.argv[0], jobs[i].task.argv);66 fprintf (stderr, "%d: %-15s %5d %20s (%x)\n", Njobs, jobs[i].task[0].name, jobs[i].JobID, jobs[i].argv[0], jobs[i].argv); 68 67 } 69 68 return; … … 75 74 int i; 76 75 77 /* try for an exact match first*/76 /* return job with matching JobID */ 78 77 for (i = 0; i < Njobs; i++) { 79 78 if (jobs[i].JobID == JobID) { … … 90 89 91 90 jobs[Njobs].JobID = NextJobID (); 92 jobs[Njobs].PID = 0; 93 jobs[Njobs].task = task[0]; 94 95 /* we need our own copy of task[0].argv */ 96 ALLOCATE (jobs[Njobs].task.argv, char *, MAX (jobs[Njobs].task.argc, 1)); 97 for (i = 0; i < jobs[Njobs].task.argc; i++) { 98 jobs[Njobs].task.argv[i] = strcreate (task[0].argv[i]); 99 } 100 jobs[Njobs].task.host = strcreate (task[0].host); 91 jobs[Njobs].pid = 0; 92 jobs[Njobs].mode = JOB_LOCAL; 93 if (task[0].host != NULL) { 94 jobs[Njobs].mode = JOB_CONTROLLER; 95 } 96 97 /* we need our own copy of task[0].argv 98 * argc is the number of valid args, like the usual command line. 99 * we allocate one extra element, with value 0 to be passed to execvp 100 */ 101 jobs[Njobs].argc = task[0].argc; 102 ALLOCATE (jobs[Njobs].argv, char *, MAX (task[0].argc + 1, 1)); 103 for (i = 0; i < task[0].argc; i++) { 104 jobs[Njobs].argv[i] = strcreate (task[0].argv[i]); 105 } 106 jobs[Njobs].argv[i] = 0; 107 108 /* other data from the task is needed by the job 109 we carry a pointer back to the task. this means we 110 cannot modify the task once a job is created, or the changes will 111 be applied to the existing jobs */ 112 113 jobs[Njobs].task = task; 114 115 /* if we decide we need to be able to dynamically set task qualities 116 (like host, timeouts, etc), the we will need to have matched 117 entries to these quantites in the job structure */ 101 118 102 119 Njobs ++; … … 108 125 } 109 126 127 void FreeJob (Job *job) { 128 129 int i; 130 131 if (job == NULL) return; 132 133 if ((job[0].JobID >= 0) || (job[0].JobID < MAX_N_JOBS)) { 134 JobIDList[job[0].JobID] = FALSE; 135 } 136 137 for (i = 0; i < job[0].argc; i++) { 138 free (job[0].argv[i]); 139 } 140 free (job[0].argv); 141 return; 142 } 143 110 144 void SetCurrentJob (char *name) { 111 145 JobName = name; … … 114 148 char *GetCurrentJob () { 115 149 return (JobName); 116 }117 118 void FreeJob (Job *job) {119 120 int i;121 122 if (job == NULL) return;123 124 if ((job[0].JobID >= 0) || (job[0].JobID < MAX_N_JOBS)) {125 JobIDList[job[0].JobID] = FALSE;126 }127 128 for (i = 0; i < job[0].task.argc; i++) {129 free (job[0].task.argv[i]);130 }131 free (job[0].task.argv);132 free (job[0].task.host);133 return;134 150 } 135 151 … … 161 177 } 162 178 163 /* this needs to:164 1) distinguish local from controller jobs165 2) fork the local jobs in the background166 3) send the controller jobs to the controller */167 168 179 int SubmitJob (Job *job) { 169 180 170 int i, Nchar; 171 char *string; 172 173 Nchar = 0; 174 for (i = 0; i < job[0].task.argc; i++) { 175 Nchar += strlen (job[0].task.argv[i]) + 1; 176 } 177 ALLOCATE (string, char, Nchar); 178 bzero (string, Nchar); 179 180 strcat (string, job[0].task.argv[0]); 181 for (i = 1; i < job[0].task.argc; i++) { 182 strcat (string, " "); 183 strcat (string, job[0].task.argv[i]); 184 } 185 186 fprintf (stderr, "executing job %d ...%s...\n", job[0].JobID, string); 187 free (string); 181 if (job[0].mode == JOB_LOCAL) { 182 SubmitLocalJob (job); 183 } else { 184 SubmitControllerJob (job); 185 } 188 186 189 187 /* reset clock for start and poll-test */ … … 196 194 int CheckJob (Job *job) { 197 195 198 float f; 199 f = drand48 (); 200 201 if ((0.00 < f) && (f < 0.25)) { 202 job[0].state = JOB_BUSY; 203 job[0].exit_status = -1; 204 return (JOB_BUSY); 205 } 206 if ((0.25 < f) && (f < 0.50)) { 207 job[0].state = JOB_BUSY; 208 job[0].exit_status = -1; 209 return (JOB_CRASH); 210 } 211 if ((0.50 < f) && (f < 0.75)) { 212 job[0].state = JOB_BUSY; 213 job[0].exit_status = 0; 214 return (JOB_EXIT); 215 } 216 if ((0.75 < f) && (f < 1.00)) { 217 job[0].state = JOB_BUSY; 218 job[0].exit_status = 1; 219 return (JOB_EXIT); 220 } 221 } 196 /* add checks for timeouts */ 197 198 if (job[0].mode == JOB_LOCAL) { 199 CheckLocalJob (job); 200 } else { 201 CheckControllerJob (job); 202 } 203 return (job[0].state); 204 } -
trunk/Ohana/src/opihi/pantasks/LocalJob.c
r3392 r4450 1 # include "scheduler.h" 1 2 2 /* local jobs are forked in the background */ 3 /* this could be written a just a one-way pipe */ 4 int SubmitLocalJob (Job *job) { 3 5 4 SubmitLocalJob (Job *job) { 6 int status, pid; 7 int stdout_fd[2], stderr_fd[2]; 5 8 6 /* 7 construct the command line 8 fork the command, get back the PID 9 increment local job counter 10 */ 9 bzero (stdout_fd, 2*sizeof(int)); 10 bzero (stderr_fd, 2*sizeof(int)); 11 11 12 if (pipe (stdout_fd) < 0) goto pipe_error; 13 if (pipe (stderr_fd) < 0) goto pipe_error; 14 15 pid = fork (); 16 if (!pid) { /* must be child process */ 17 fprintf (stderr, "starting controller connection\n"); 18 19 /* close the other ends of the pipes */ 20 close (stdout_fd[0]); 21 close (stderr_fd[0]); 22 23 /* tie our ends of the pipes to stdin, stdout, stderr */ 24 dup2 (stdout_fd[1], STDOUT_FILENO); 25 dup2 (stderr_fd[1], STDERR_FILENO); 26 27 /* set all three unblocking */ 28 setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ); 29 setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ); 30 31 status = execvp (job[0].argv[0], job[0].argv); 32 exit (1); 33 } 34 35 /* close the other ends of the pipes */ 36 close (stdout_fd[1]); stdout_fd[1] = 0; 37 close (stderr_fd[1]); stderr_fd[1] = 0; 38 39 /* make the pipes non-blocking */ 40 fcntl (stdout_fd[0], F_SETFL, O_NONBLOCK); 41 fcntl (stderr_fd[0], F_SETFL, O_NONBLOCK); 42 43 job[0].stdout_fd = stdout_fd[0]; 44 job[0].stderr_fd = stderr_fd[0]; 45 job[0].pid = pid; 46 47 return (TRUE); 48 49 pipe_error: 50 perror ("pipe error:"); 51 if (stdout_fd[0] != 0) close (stdout_fd[0]); 52 if (stdout_fd[1] != 0) close (stdout_fd[1]); 53 if (stderr_fd[0] != 0) close (stderr_fd[0]); 54 if (stderr_fd[1] != 0) close (stderr_fd[1]); 55 return (FALSE); 12 56 } 13 57 14 CheckLocalJob (Job *job) { 58 /* update current state, drain stdout/stderr buffers */ 59 int CheckLocalJob (Job *job) { 15 60 16 /* 17 61 int Nread; 62 63 // XXX do something useful with exit status? 64 CheckLocalJobStatus (job); 65 66 /* read stdout buffer */ 67 Nread = ReadtoIOBuffer (&job[0].stdout, job[0].stdout_fd); 68 switch (Nread) { 69 case -2: /* error in read (programming error? system level error?) */ 70 fprintf (stderr, "serious IO error\n"); 71 exit (2); 72 case -1: /* no data in pipe */ 73 break; 74 case 0: /* pipe is closed */ 75 /** change child state? **/ 76 break; 77 default: /* data in pipe */ 78 break; 79 } 80 81 /* read stderr buffer */ 82 Nread = ReadtoIOBuffer (&job[0].stderr, job[0].stderr_fd); 83 switch (Nread) { 84 case -2: /* error in read (programming error? system level error?) */ 85 fprintf (stderr, "serious IO error\n"); 86 exit (2); 87 case -1: /* no data in pipe */ 88 break; 89 case 0: /* pipe is closed */ 90 /** change child state? **/ 91 break; 92 default: /* data in pipe */ 93 break; 94 } 95 return (TRUE); 96 } 97 98 int CheckLocalJobStatus (Job *job) { 99 100 int result, waitstatus; 101 102 /* check local job status */ 103 result = waitpid (job[0].pid, &waitstatus, WNOHANG); 104 switch (result) { 105 case -1: /* error with waitpid */ 106 switch (errno) { 107 case ECHILD: 108 fprintf (stderr, "unknown PID, not a child proc\n"); 109 fprintf (stderr, "did process already exit? programming error?\n"); 110 job[0].state = JOB_NONE; 111 job[0].exit_status = 0; 112 return (FALSE); 113 case EINVAL: 114 fprintf (stderr, "error EINVAL (waitpid): programming error\n"); 115 exit (1); 116 case EINTR: 117 fprintf (stderr, "error EINTR (waitpid): programming error\n"); 118 exit (1); 119 default: 120 fprintf (stderr, "unknown error for waitpid (%d): programming error\n", errno); 121 exit (1); 122 } 123 break; 124 125 case 0: /* process not exited */ 126 job[0].state = JOB_BUSY; 127 job[0].exit_status = 0; 128 return (TRUE); 129 130 default: 131 if (result != job[0].pid) { 132 fprintf (stderr, "waitpid error: mis-matched PID (%d vs %d). programming error\n", result, job[0].pid); 133 exit (1); 134 } 135 136 if (WIFEXITED(waitstatus)) { 137 job[0].state = JOB_EXIT; 138 job[0].exit_status = WEXITSTATUS(waitstatus); 139 } 140 if (WIFSIGNALED(waitstatus)) { 141 job[0].state = JOB_CRASH; 142 job[0].exit_status = WTERMSIG(waitstatus); 143 } 144 if (WIFSTOPPED(waitstatus)) { 145 fprintf (stderr, "waitpid returns 'stopped': programming error\n"); 146 exit (1); 147 } 148 } 149 return; 150 } -
trunk/Ohana/src/opihi/pantasks/Makefile
r3525 r4450 25 25 # sched user commands and support functions ######################## 26 26 27 sched = \ 27 funcs = \ 28 $(SDIR)/CheckJobs.$(ARCH).o \ 29 $(SDIR)/CheckSystem.$(ARCH).o \ 30 $(SDIR)/CheckTasks.$(ARCH).o \ 31 $(SDIR)/ControllerOps.$(ARCH).o \ 32 $(SDIR)/LocalJob.$(ARCH).o \ 33 $(SDIR)/JobOps.$(ARCH).o \ 34 $(SDIR)/TaskOps.$(ARCH).o \ 35 $(SDIR)/IOBufferOps.$(ARCH).o \ 36 $(SDIR)/memstr.$(ARCH).o \ 37 $(SDIR)/init.$(ARCH).o 38 39 cmds = \ 40 $(SDIR)/controller.$(ARCH).o \ 28 41 $(SDIR)/run.$(ARCH).o \ 42 $(SDIR)/scheduler.$(ARCH).o \ 29 43 $(SDIR)/task.$(ARCH).o \ 30 44 $(SDIR)/task_command.$(ARCH).o \ 31 45 $(SDIR)/task_host.$(ARCH).o \ 32 46 $(SDIR)/task_macros.$(ARCH).o \ 33 $(SDIR)/task_periods.$(ARCH).o \ 34 $(SDIR)/JobOps.$(ARCH).o \ 35 $(SDIR)/TaskOps.$(ARCH).o \ 36 $(SDIR)/init.$(ARCH).o \ 37 $(SDIR)/scheduler.$(ARCH).o 47 $(SDIR)/task_periods.$(ARCH).o 38 48 39 49 libs = \ … … 49 59 @echo done 50 60 51 $(BIN)/scheduler.$(ARCH) : $( sched) $(libs)61 $(BIN)/scheduler.$(ARCH) : $(funcs) $(cmds) $(libs) 52 62 53 63 install: $(DESTBIN)/scheduler -
trunk/Ohana/src/opihi/pantasks/TaskOps.c
r3140 r4450 108 108 109 109 tasks[Ntasks].host = NULL; 110 tasks[Ntasks].host_required = FALSE; 110 111 111 112 tasks[Ntasks].argc = 0; … … 124 125 tasks[Ntasks].poll_period = 1.0; 125 126 tasks[Ntasks].timeout_period = 1.0; 127 128 /* init task timer (is reset by 'run') */ 129 gettimeofday (&tasks[Ntasks].last, (void *) NULL); 126 130 127 131 Ntasks ++; … … 155 159 gettimeofday (timer, (void *) NULL); 156 160 } 161 162 /* start the clock for all tasks */ 163 void InitTaskTimers () { 164 165 Task *task; 166 167 while ((task = NextTask ()) != NULL) { 168 gettimeofday (&task[0].last, (void *) NULL); 169 } 170 } -
trunk/Ohana/src/opihi/pantasks/init.c
r3140 r4450 2 2 # include "scheduler.h" 3 3 4 int controller PROTO((int, char **)); 4 5 int task PROTO((int, char **)); 5 6 int task_host PROTO((int, char **)); … … 8 9 int task_periods PROTO((int, char **)); 9 10 int run PROTO((int, char **)); 11 int stop PROTO((int, char **)); 10 12 11 13 static Command cmds[] = { 12 {"task", task, "define a schedulable task"}, 13 {"host", task_host, "define host machine for a task"}, 14 {"task.exit", task_macros, "define exit macros for a task"}, 15 {"task.exec", task_macros, "define pre-exec macro for a task"}, 16 {"command", task_command, "define executed command for a task"}, 17 {"periods", task_periods, "define time scales for a task"}, 18 {"run", run, "run the scheduler"}, 14 {"controller", controller, "controller commands"}, 15 {"task", task, "define a schedulable task"}, 16 {"host", task_host, "define host machine for a task"}, 17 {"task.exit", task_macros, "define exit macros for a task"}, 18 {"task.exec", task_macros, "define pre-exec macro for a task"}, 19 {"command", task_command, "define executed command for a task"}, 20 {"periods", task_periods, "define time scales for a task"}, 21 {"run", run, "run the scheduler"}, 22 {"stop", stop, "stop the scheduler"}, 19 23 }; 20 24 -
trunk/Ohana/src/opihi/pantasks/run.c
r3140 r4450 1 # include "basic.h"2 1 # include "scheduler.h" 3 2 4 3 int run (int argc, char **argv) { 5 6 Job *job;7 Task *task;8 Macro *macro;9 int i, found, status;10 int Ntest;11 4 12 5 if (argc != 1) { … … 15 8 } 16 9 17 /* start the clock for all tasks */ 18 while ((task = NextTask ()) != NULL) { 19 gettimeofday (&task[0].last, (void *) NULL); 10 InitTaskTimers (); 11 rl_event_hook = CheckSystem; 12 rl_set_keyboard_input_timeout (1000000); 13 14 return (TRUE); 15 } 16 17 int stop (int argc, char **argv) { 18 19 if (argc != 1) { 20 fprintf (stderr, "USAGE: stop\n"); 21 return (FALSE); 20 22 } 21 23 22 Ntest = 0; 24 rl_event_hook = NULL; 25 rl_set_keyboard_input_timeout (1000000); 23 26 24 /* loop forever, checking for completed jobs and ready tasks */25 while (1) {26 if (Ntest > 5) {27 ListJobs ();28 Ntest = 0;29 }30 usleep (10000);31 Ntest ++;32 33 /** test all tasks: ready to test? ready to run? **/34 while ((task = NextTask ()) != NULL) {35 36 /* ready to test? : check exec period */37 if (GetTaskTimer(task[0].last) < task[0].exec_period) continue;38 39 SetCurrentTask (task[0].name);40 fprintf (stderr, "trying task %s\n", task[0].name);41 42 /* ready to run? : run task.exec macro */43 if (task[0].exec != NULL) {44 status = exec_loop (task[0].exec);45 if (!status) continue;46 }47 48 /* is task valid? check state of task.(argc, argv) */49 /*** ADD CODE HERE ***/50 51 /* construct job from task */52 job = CreateJob (task);53 54 /* execute job - XXX add status test */55 SubmitJob (job);56 57 /* reset timer on task (don't do this if Create/Submit fails)*/58 gettimeofday (&task[0].last, (void *) NULL);59 }60 61 /** test all jobs: ready to test? finished? **/62 while ((job = NextJob ()) != NULL) {63 64 /* check for timeout */65 if (GetTaskTimer(job[0].start) >= job[0].task.timeout_period) {66 fprintf (stderr, "timeout on %s\n", job[0].task.name);67 /* run task.timeout macro, if it exists */68 if (job[0].task.timeout != NULL) {69 exec_loop (job[0].task.timeout);70 }71 DeleteJob (job);72 continue;73 }74 75 /* check poll period (ready to run again?) */76 if (GetTaskTimer(job[0].last) < job[0].task.poll_period) continue;77 78 /* check current status */79 status = CheckJob (job);80 switch (status) {81 case JOB_BUSY:82 fprintf (stderr, "job %s (%d) busy\n", job[0].task.name, job[0].JobID);83 break;84 85 case JOB_CRASH:86 fprintf (stderr, "job %s (%d) crash\n", job[0].task.name, job[0].JobID);87 /* run task.crash macro, if it exists */88 if (job[0].task.crash != NULL) {89 exec_loop (job[0].task.crash);90 }91 DeleteJob (job);92 continue;93 break;94 95 case JOB_EXIT:96 fprintf (stderr, "job %s (%d) exit\n", job[0].task.name, job[0].JobID);97 /* run corresponding task.exit macro, if it exists */98 macro = job[0].task.def;99 for (i = 0; i < job[0].task.Nexit; i++) {100 if (job[0].exit_status == atoi(job[0].task.exit[i][0].name)) {101 macro = job[0].task.exit[i];102 break;103 }104 }105 if (macro != NULL) exec_loop (macro);106 DeleteJob (job);107 continue;108 break;109 110 default:111 fprintf (stderr, "unknown exit status\n");112 /** do something more useful here ?? **/113 break;114 }115 116 /* reset polling clock */117 SetTaskTimer (&job[0].last);118 }119 }120 27 return (TRUE); 121 28 } -
trunk/Ohana/src/opihi/pantasks/scheduler.c
r2598 r4450 49 49 rl_readline_name = opihi_name; 50 50 rl_attempted_completion_function = command_completer; 51 rl_event_hook = NULL; 52 rl_set_keyboard_input_timeout (1000000); 51 53 52 54 set_str_variable ("HISTORY", opihi_history); -
trunk/Ohana/src/opihi/pantasks/task_command.c
r2598 r4450 41 41 return (TRUE); 42 42 } 43 44 45 /**46 careful with this: the command is supposed to be realized47 for the Job, not the Task (at execution)48 the code is right, but who calls it when needs to be clarified.49 **/50 -
trunk/Ohana/src/opihi/pantasks/task_host.c
r2598 r4450 4 4 int task_host (int argc, char **argv) { 5 5 6 int N, RequiredHost; 6 7 Task *task; 7 8 char *taskname; 8 9 10 RequiredHost = FALSE; 11 if (N = get_argument (argc, argv, "-required")) { 12 remove_argument (N, &argc, argv); 13 RequiredHost = TRUE; 14 } 15 9 16 if (argc != 2) { 10 fprintf (stderr, "USAGE: host <name>\n"); 11 fprintf (stderr, " (define host machine for this task (or 'none'))\n"); 17 fprintf (stderr, "USAGE: host <name> [-required]\n"); 18 fprintf (stderr, " define host machine for this task\n"); 19 fprintf (stderr, " -required flags indicates controller must use this host\n"); 20 fprintf (stderr, " value of 'local' for host indicates process not using controller\n"); 21 fprintf (stderr, " value of 'none' for host indicates controller may assign at will\n"); 12 22 return (FALSE); 13 23 } … … 23 33 return (FALSE); 24 34 } 35 task[0].host_required = RequiredHost; 25 36 26 37 if (task[0].host != NULL) free (task[0].host); 27 38 task[0].host = NULL; 28 39 29 if (!strcasecmp (argv[1], " NONE")) return (TRUE);40 if (!strcasecmp (argv[1], "LOCAL")) return (TRUE); 30 41 31 42 task[0].host = strcreate (argv[1]);
Note:
See TracChangeset
for help on using the changeset viewer.
