static batch_job_id_t batch_job_cluster_wait (struct batch_queue * q, struct batch_job_info * info_out, time_t stoptime) { struct batch_job_info *info; batch_job_id_t jobid; int t, c; while(1) { UINT64_T ujobid; itable_firstkey(q->job_table); while(itable_nextkey(q->job_table, &ujobid, (void **) &info)) { jobid = ujobid; char *statusfile = string_format("%s.status.%" PRIbjid, cluster_name, jobid); FILE *file = fopen(statusfile, "r"); if(file) { char line[BATCH_JOB_LINE_MAX]; while(fgets(line, sizeof(line), file)) { if(sscanf(line, "start %d", &t)) { info->started = t; } else if(sscanf(line, "stop %d %d", &c, &t) == 2) { debug(D_BATCH, "job %" PRIbjid " complete", jobid); if(!info->started) info->started = t; info->finished = t; info->exited_normally = 1; info->exit_code = c; } } fclose(file); if(info->finished != 0) { unlink(statusfile); info = itable_remove(q->job_table, jobid); *info_out = *info; free(info); free(statusfile); return jobid; } } else { debug(D_BATCH, "could not open status file \"%s\"", statusfile); } free(statusfile); } if(itable_size(q->job_table) <= 0) return 0; if(stoptime != 0 && time(0) >= stoptime) return -1; if(process_pending()) return -1; sleep(1); } return -1; }
struct pipes_res * pclose(struct pipes_close *pcmd, struct pipe *p, int task) { CPOSITION it; // check pipe type if(p->type == PIPES_FILEPIPE) { fclose(p->pf); return build_response_msg(PIPESERR_OK); } if(task == p->taskid) { p->task1_closed = 1; } else if(task == p->taskid2) { p->task2_closed = 1; } // if there was a pending read, send what's left on the buffer if(p->pending) { process_pending(p); } if((p->task1_closed && p->task2_closed) || task == p->creating_task) { it = get_head_position(&p->buffer->blocks); while(it != NULL) { struct pipe_buffer_block *b = (struct pipe_buffer_block*)get_next(&it); free_block(b); } lstclear(&p->buffer->blocks); avl_remove(&pipes, p->id); free(p); } return build_response_msg(PIPESERR_OK); }
void process_pipes_cmd(struct pipes_cmd *pcmd, int task) { struct pipes_res *res= NULL; struct pipe *p = NULL; // check for open if(pcmd->command == PIPES_OPENSHARED) { // create a new shared pipe struct pipe *p = (struct pipe*)malloc(sizeof(struct pipe)); p->id = get_new_pipeid(); p->type = PIPES_SHAREDPIPE; p->taskid = ((struct pipes_openshared*)pcmd)->task1; p->taskid2 = ((struct pipes_openshared*)pcmd)->task2; p->pf = NULL; p->creating_task = task; p->pending = 0; p->task1_closed = 0; p->task2_closed = 0; p->buffer = (struct pipe_buffer*)malloc(sizeof(struct pipe_buffer)); p->buffer->rcursor = p->buffer->wcursor = p->buffer->size = 0; init(&p->buffer->blocks); avl_insert(&pipes, p, p->id); res = build_response_msg(PIPESERR_OK); ((struct pipes_open_res*)res)->pipeid = p->id; } else if(pcmd->command == PIPES_OPENFILE) { // create a new file pipe struct pipe *p = (struct pipe*)malloc(sizeof(struct pipe)); char *filepath = get_string(((struct pipes_openfile*)pcmd)->path_smo); p->id = get_new_pipeid(); p->type = PIPES_FILEPIPE; p->taskid = ((struct pipes_openshared*)pcmd)->task1; p->taskid2 = -1; p->pf = fopen(filepath, (char*)((struct pipes_openfile*)pcmd)->open_mode); p->creating_task = task; p->buffer = NULL; p->pending = 0; if(p->pf != NULL) { avl_insert(&pipes, p, p->id); res = build_response_msg(PIPESERR_OK); ((struct pipes_open_res*)res)->pipeid = p->id; } else { res = build_response_msg(PIPESERR_FSERROR); free(p); } free(filepath); } else { p = (struct pipe*)avl_getvalue(pipes, ((struct pipes_close*)pcmd)->pipeid); if(p != NULL) { /* Check permissions */ switch(pcmd->command) { case PIPES_CLOSE: // a shared pipe must be closed on both ends or by the creating task if(p->type == PIPES_SHAREDPIPE) { if(task != p->taskid && task != p->taskid2 && task != p->creating_task) { res = build_response_msg(PIPESERR_ERR); } else if((task == p->taskid && p->task1_closed) || (task == p->taskid2 && p->task2_closed)) { res = build_response_msg(PIPESERR_PIPECLOSED); } } else if(p->type == PIPES_FILEPIPE && task != p->taskid) { res = build_response_msg(PIPESERR_ERR); } break; case PIPES_SEEK: case PIPES_TELL: break; case PIPES_WRITE: case PIPES_PUTS: case PIPES_PUTC: if(p->type == PIPES_SHAREDPIPE && task != p->taskid) { res = build_response_msg(PIPESERR_ERR); } break; case PIPES_READ: case PIPES_GETS: case PIPES_GETC: if(p->type == PIPES_SHAREDPIPE && task != p->taskid2) { res = build_response_msg(PIPESERR_ERR); } break; default: res = build_response_msg(PIPESERR_ERR); } if(res != NULL) { res->thr_id = pcmd->thr_id; res->command = pcmd->command; send_msg(task, pcmd->ret_port, res); return; } /* Process pipe command */ switch(pcmd->command) { case PIPES_CLOSE: res = pclose((struct pipes_close *)pcmd, p, task); if(res->ret == PIPESERR_OK) p = NULL; break; case PIPES_READ: res = pread((struct pipes_read *)pcmd, p); break; case PIPES_WRITE: res = pwrite((struct pipes_write *)pcmd, p); break; case PIPES_SEEK: res = pseek((struct pipes_seek *)pcmd, p, task); break; case PIPES_TELL: res = ptell((struct pipes_tell *)pcmd, p, task); break; case PIPES_PUTS: res = pputs((struct pipes_puts *)pcmd, p); break; case PIPES_PUTC: res = pputc((struct pipes_putc *)pcmd, p); break; case PIPES_GETS: res = pgets((struct pipes_gets *)pcmd, p); break; case PIPES_GETC: res = pgetc((struct pipes_getc *)pcmd, p); break; default: res = build_response_msg(PIPESERR_ERR); } } else { res = build_response_msg(PIPESERR_PIPECLOSED); } } if(p == NULL || (p != NULL && !(p->pending && (pcmd->command == PIPES_READ || (pcmd->command == PIPES_SEEK && task == p->taskid2) || pcmd->command == PIPES_GETS || pcmd->command == PIPES_GETC)))) { if(res == NULL) { res = build_response_msg(PIPESERR_ERR); } res->thr_id = pcmd->thr_id; res->command = pcmd->command; send_msg(task, pcmd->ret_port, res); if(res != NULL) free(res); } else { // check pending read if(p != NULL && p->pending && (pcmd->command == PIPES_WRITE || (pcmd->command == PIPES_SEEK && task == p->taskid2) || pcmd->command == PIPES_READ || pcmd->command == PIPES_PUTS || pcmd->command == PIPES_PUTC)) { // process the pending message process_pending(p); } send_msg(task, pcmd->ret_port, res); if(res != NULL) free(res); } }
static batch_job_id_t batch_job_condor_wait (struct batch_queue * q, struct batch_job_info * info_out, time_t stoptime) { static FILE *logfile = 0; if(!logfile) { logfile = fopen(q->logfile, "r"); if(!logfile) { debug(D_NOTICE, "couldn't open logfile %s: %s\n", q->logfile, strerror(errno)); return -1; } } while(1) { /* Note: clearerr is necessary to clear any cached end-of-file condition, otherwise some implementations of fgets (i.e. darwin) will read to end of file once and then never look for any more data. */ clearerr(logfile); char line[BATCH_JOB_LINE_MAX]; while(fgets(line, sizeof(line), logfile)) { int type, proc, subproc; batch_job_id_t jobid; time_t current; struct tm tm; struct batch_job_info *info; int logcode, exitcode; if(sscanf(line, "%d (%" SCNbjid ".%d.%d) %d/%d %d:%d:%d", &type, &jobid, &proc, &subproc, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 9) { tm.tm_year = 2008 - 1900; tm.tm_isdst = 0; current = mktime(&tm); info = itable_lookup(q->job_table, jobid); if(!info) { info = malloc(sizeof(*info)); memset(info, 0, sizeof(*info)); itable_insert(q->job_table, jobid, info); } debug(D_BATCH, "line: %s", line); if(type == 0) { info->submitted = current; } else if(type == 1) { info->started = current; debug(D_BATCH, "job %" PRIbjid " running now", jobid); } else if(type == 9) { itable_remove(q->job_table, jobid); info->finished = current; info->exited_normally = 0; info->exit_signal = SIGKILL; debug(D_BATCH, "job %" PRIbjid " was removed", jobid); memcpy(info_out, info, sizeof(*info)); free(info); return jobid; } else if(type == 5) { itable_remove(q->job_table, jobid); info->finished = current; fgets(line, sizeof(line), logfile); if(sscanf(line, " (%d) Normal termination (return value %d)", &logcode, &exitcode) == 2) { debug(D_BATCH, "job %" PRIbjid " completed normally with status %d.", jobid, exitcode); info->exited_normally = 1; info->exit_code = exitcode; } else if(sscanf(line, " (%d) Abnormal termination (signal %d)", &logcode, &exitcode) == 2) { debug(D_BATCH, "job %" PRIbjid " completed abnormally with signal %d.", jobid, exitcode); info->exited_normally = 0; info->exit_signal = exitcode; } else { debug(D_BATCH, "job %" PRIbjid " completed with unknown status.", jobid); info->exited_normally = 0; info->exit_signal = 0; } memcpy(info_out, info, sizeof(*info)); free(info); return jobid; } } } if(itable_size(q->job_table) <= 0) return 0; if(stoptime != 0 && time(0) >= stoptime) return -1; if(process_pending()) return -1; sleep(1); } return -1; }