void speedy_backend_be_wait_put(slotnum_t gslotnum, slotnum_t bslotnum) { gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum); FILE_SLOT(be_slot, bslotnum).fe_running = 0; speedy_slot_remove(bslotnum, &(gslot->be_head), &(gslot->be_tail)); speedy_slot_insert_sorted( bslotnum, &(gslot->be_head), &(gslot->be_tail), &do_sort ); }
slotnum_t speedy_backend_create_slot(slotnum_t gslotnum) { gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum); slotnum_t bslotnum; /* Create our backend slot */ bslotnum = SLOT_ALLOC("backend (speedy_backend_create_slot)"); FILE_SLOT(be_slot, bslotnum).fe_running = bslotnum; /* Put our slot at the end of group's be list */ speedy_slot_append(bslotnum, &(gslot->be_head), &(gslot->be_tail)); return bslotnum; }
void speedy_frontend_remove_running(const slotnum_t fslotnum) { fe_slot_t *fslot = &FILE_SLOT(fe_slot, fslotnum); if (fslot->backend) { be_slot_t *bslot = &FILE_SLOT(be_slot, fslot->backend); if (bslot->fe_running == fslotnum) bslot->fe_running = fslot->backend; } speedy_slot_remove(fslotnum, &(FILE_HEAD.fe_run_head), &(FILE_HEAD.fe_run_tail)); SLOT_FREE(fslotnum, "frontend (remove_running)"); }
void speedy_backend_dispose(slotnum_t gslotnum, slotnum_t bslotnum) { if (gslotnum && bslotnum) { gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum); if (FILE_SLOT(be_slot, bslotnum).fe_running) speedy_backend_died(bslotnum); speedy_slot_remove(bslotnum, &(gslot->be_head), &(gslot->be_tail)); speedy_ipc_cleanup(bslotnum); SLOT_FREE(bslotnum, "backend (speedy_backend_dispose)"); } }
/* Kill and remove all be's in the be_wait list */ void speedy_backend_remove_be_wait(slotnum_t gslotnum) { gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum); slotnum_t bslotnum, next; for (bslotnum = gslot->be_head; bslotnum && !FILE_SLOT(be_slot, bslotnum).fe_running; bslotnum = next) { next = speedy_slot_next(bslotnum); speedy_util_kill(FILE_SLOT(be_slot, bslotnum).pid, SIGTERM); } }
slotnum_t speedy_backend_be_wait_get(slotnum_t gslotnum) { gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum); slotnum_t head = gslot->be_head; /* Don't grab a backend while a backend is starting */ if (speedy_group_be_starting(gslotnum) || !head || FILE_SLOT(be_slot, head).fe_running) { return 0; } speedy_slot_move_tail(head, &(gslot->be_head), &(gslot->be_tail)); return head; }
void speedy_backend_exited(slotnum_t bslotnum, int exit_on_sig, int exit_val) { be_slot_t *bslot = &FILE_SLOT(be_slot, bslotnum); slotnum_t fslotnum; if ((fslotnum = bslot->fe_running)) { bslot->fe_running = bslotnum; if (fslotnum != bslotnum) { fe_slot_t *fslot = &FILE_SLOT(fe_slot, fslotnum); fslot->backend = 0; fslot->exit_on_sig = exit_on_sig; fslot->exit_val = exit_val; if (speedy_util_kill(fslot->pid, SIGUSR1) == -1) speedy_frontend_remove_running(fslotnum); } } }
void speedy_frontend_dispose(slotnum_t gslotnum, slotnum_t fslotnum) { if (fslotnum) { gr_slot_t *gslot = &FILE_SLOT(gr_slot, gslotnum); speedy_slot_remove(fslotnum, &(gslot->fe_head), &(gslot->fe_tail)); SLOT_FREE(fslotnum, "frontend (speedy_frontend_dispose)"); } }
static int count_bes(slotnum_t gslotnum, int max) { slotnum_t bslotnum; int count; for (bslotnum = FILE_SLOT(gr_slot, gslotnum).be_head, count = 0; bslotnum && count < max; bslotnum = speedy_slot_next(bslotnum)) { ++count; } return count; }
static int do_sort(slotnum_t bslotnum_a, slotnum_t bslotnum_b) { be_slot_t *a = &FILE_SLOT(be_slot, bslotnum_a); be_slot_t *b = &FILE_SLOT(be_slot, bslotnum_b); int diff; /* We want waiting be's to go before non-waiting. * If we return < 0, a will go before b. * If A is waiting and B is not, we return (B=0) - (A=1) == -1 * and A is first. * If B is waiting and A is not, we return (B=1) - (A=0) == 1 * and B is first. */ diff = ((b->fe_running ? 0 : 1) - (a->fe_running ? 0 : 1)); if (diff != 0) return diff; /* We want higher maturity#'s at the beginning. * If we return < 0, a will go before b * if A = 2 and B = 1, then we return -1 (B=1) - (A=2) == -1. * If A = 1 and B = 2, then we return 1 (B=2) - (A=1) == 1. */ return b->maturity - a->maturity; }
int speedy_frontend_collect_status (const slotnum_t fslotnum, int *exit_on_sig, int *exit_val) { fe_slot_t *fslot = &FILE_SLOT(fe_slot, fslotnum); if (fslot->backend && speedy_backend_dead(fslot->backend)) speedy_backend_died(fslot->backend); if (fslot->backend == 0) { *exit_on_sig = fslot->exit_on_sig; *exit_val = fslot->exit_val; speedy_frontend_remove_running(fslotnum); return 1; } return 0; }
int main(int argc, char **argv) { char filename[PATH_MAX]; int sz = 0; char *data = NULL; sprintf(filename, "/tmp/speedy.6.%x.F", geteuid()); FILE *fh = fopen(filename, "r"); if (fh) { struct stat st; if (stat(filename, &st) == 0) { sz = st.st_size; } if (sz) { data = malloc(sz); fread(data, 1, sz, fh); } } else { printf("Cannot read file (%s).\n", filename); } if (data) { speedy_file_t *speedy_file_maddr = (speedy_file_t*)data; file_head_t *h = &FILE_HEAD; slotnum_t slotnum, num1; slot_t *slot; int i; time_t ctime = h->create_time.tv_sec; printf("{\n"); printf(" header => {\n"); printf(" create_time => { sec => %d, usec => %d, text => '%s' },\n", h->create_time.tv_sec, h->create_time.tv_usec, ptime(&ctime)); printf(" lock_owner => %d,\n", h->lock_owner); printf(" group_head => %d,\n", h->group_head); printf(" group_tail => %d,\n", h->group_tail); printf(" slot_free => %d,\n", h->slot_free); printf(" slots_alloced => %d,\n", h->slots_alloced); printf(" fe_run_head => %d,\n", h->fe_run_head); printf(" fe_run_tail => %d,\n", h->fe_run_tail); printf(" file_removed => %d\n", h->file_removed); printf(" },\n"); printf(" free_slots => [ "); for (slotnum = h->slot_free; !BAD_SLOTNUM(slotnum); slotnum = speedy_slot_next(slotnum)) { printf("%d", slotnum); if (!BAD_SLOTNUM(speedy_slot_next(slotnum))) printf(", "); } printf(" ],\n"); printf(" fe_running => [ "); for (slotnum = h->fe_run_head; !BAD_SLOTNUM(slotnum); slotnum = speedy_slot_next(slotnum)) { printf("%d\n", slotnum); if (!BAD_SLOTNUM(speedy_slot_next(slotnum))) printf(", "); } printf(" ],\n"); printf(" group_list => {\n"); for (slotnum = h->group_head; !BAD_SLOTNUM(slotnum); slotnum = speedy_slot_next(slotnum)) { gr_slot_t *gr = &FILE_SLOT(gr_slot, slotnum); grnm_slot_t *name = &FILE_SLOT(grnm_slot, gr->name_slot); scr_slot_t *scr = &FILE_SLOT(scr_slot, gr->script_head); printf(" index => %d,\n", slotnum); printf(" be_starting => %d,\n", gr->be_starting); printf(" be_parent => { pid => %d },\n", gr->be_parent); printf(" script_head => %d,\n", gr->script_head); printf(" scripts => [\n"); for (num1 = gr->script_head; !BAD_SLOTNUM(num1); num1 = speedy_slot_next(num1)) { scr = &FILE_SLOT(scr_slot, num1); printf(" {\n"); printf(" index => %d,\n", num1); printf(" dev_num => %d,\n", scr->dev_num); printf(" ino_num => %d,\n", scr->ino_num); printf(" mtime => { sec => %d, text => '%s' }\n", scr->mtime, ptime(&scr->mtime)); printf(" }"); if (!BAD_SLOTNUM(speedy_slot_next(slotnum))) printf(", "); } printf(" ],\n"); printf(" name_slot => { index => %d, text => '%s' },\n", gr->name_slot, name->name); printf(" be_head => %d,\n", gr->be_head); printf(" be_tail => %d,\n", gr->be_tail); printf(" fe_head => %d,\n", gr->fe_head); printf(" fe_tail => %d,\n", gr->fe_tail); printf(" fe_wait_list => [\n"); for (num1 = gr->fe_head; !BAD_SLOTNUM(num1); num1 = speedy_slot_next(num1)) { fe_slot_t *fe = &FILE_SLOT(fe_slot, num1); printf(" {\n"); printf(" index => %d,\n", num1); printf(" pid => { pid => %d },\n", fe->pid); printf(" exit_val => %d,\n", fe->exit_val); printf(" backend => %d,\n", fe->backend); printf(" exit_on_sig => %d,\n", fe->exit_on_sig); printf(" sent_sig => %d,\n", fe->sent_sig); printf(" },\n"); } printf(" ],\n"); printf(" be_list => [\n"); for (num1 = gr->be_head; !BAD_SLOTNUM(num1); num1 = speedy_slot_next(num1)) { be_slot_t *be = &FILE_SLOT(be_slot, num1); printf(" {\n"); printf(" index => %d,\n", num1); printf(" pid => { pid => %d },\n", be->pid); printf(" fe_running => %d,\n", be->fe_running); printf(" maturity => %d\n", be->maturity); printf(" },\n"); } printf(" ]\n"); printf(" }\n"); } printf("}\n"); } return 0; }
/* Spawn the be_parent process */ static void be_parent_spawn(slotnum_t gslotnum) { int pid; const char * const *argv; /* Get args for exec'ing backend */ argv = speedy_opt_exec_argv(); /* Fork */ pid = fork(); if (pid > 0) { /* Parent */ int child_status; if (waitpid(pid, &child_status, 0) == -1) speedy_util_die("wait"); } else if (pid == 0) { /* Child */ /* Get rid of alarm handler and any alarms */ sig_handler_teardown(0); /* Unblock any signals due to file lock */ speedy_file_fork_child(); /* Fork again */ pid = fork(); if (pid == -1) { speedy_util_exit(1,1); } else if (pid) { /* Parent of Grandchild */ /* We don't hold the lock on the temp file, but our parent does, * and it's waiting for us to exit before proceeding, so it's * safe to write to the file here */ FILE_SLOT(gr_slot, gslotnum).be_parent = pid; FILE_SLOT(gr_slot, gslotnum).be_starting = pid; speedy_util_exit(0,1); } else { /* Grandchild */ /* We should be in our own session */ setsid(); /* Exec the backend */ speedy_util_execvp(argv[0], argv); /* Failed. Try the original argv[0] + "_backend" */ { const char *orig_file = speedy_opt_orig_argv()[0]; if (orig_file && *orig_file) { char *fname; speedy_new( fname, strlen(orig_file)+sizeof(BE_SUFFIX)+1, char ); sprintf(fname, "%s%s", orig_file, BE_SUFFIX); speedy_util_execvp(fname, argv); } } speedy_util_die(argv[0]); }