END_TEST START_TEST(find_depend_test) { pbs_attribute pattr; struct depend *pdep; initialize_depend_attr(&pattr); pdep = make_depend(1, &pattr); pdep = make_depend(2, &pattr); pdep = make_depend(3, &pattr); pdep = find_depend(1, &pattr); fail_unless(pdep != NULL, "couldn't find 1"); fail_unless(pdep->dp_type == 1, "bad type returned"); pdep = find_depend(2, &pattr); fail_unless(pdep != NULL, "couldn't find 2"); fail_unless(pdep->dp_type == 2, "bad type returned"); pdep = find_depend(3, &pattr); fail_unless(pdep != NULL, "couldn't find 3"); fail_unless(pdep->dp_type == 3, "bad type returned"); pdep = find_depend(0, &pattr); fail_unless(pdep == NULL, "found non-existent thing"); }
void req_register(struct batch_request *preq) { int made; attribute *pattr; struct depend *pdep; struct depend_job *pdj; job *pjob; char *ps; struct work_task *ptask; int rc = 0; int revtype; int type; int savetype = SAVEJOB_FULL; /* make sure request is from a server */ if (!preq->rq_fromsvr) { #ifdef NAS /* localmod 109 */ sprintf(log_buffer, "Dependency request not from server"); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, preq->rq_ind.rq_register.rq_parent, log_buffer); #endif /* localmod 109 */ req_reject(PBSE_IVALREQ, 0, preq); return; } /* find the "parent" job specified in the request */ if ((pjob = find_job(preq->rq_ind.rq_register.rq_parent)) == NULL) { /* * job not found... if server is initializing, it may not * yet recovered, that is not an error. */ if (server.sv_attr[(int)SRV_ATR_State].at_val.at_long != SV_STATE_INIT) { log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, preq->rq_ind.rq_register.rq_parent, msg_unkjobid); req_reject(PBSE_UNKJOBID, 0, preq); } else { reply_ack(preq); } return; } pattr = &pjob->ji_wattr[(int)JOB_ATR_depend]; type = preq->rq_ind.rq_register.rq_dependtype; pjob->ji_modified = 1; /* more of the server:port fix kludge */ ps = strchr(preq->rq_ind.rq_register.rq_child, (int)'@'); if (ps != NULL) { (void)strcpy(preq->rq_ind.rq_register.rq_svr, ps+1); *ps = '\0'; } else { (void)strcpy(preq->rq_ind.rq_register.rq_svr, preq->rq_host); } if (pjob->ji_qs.ji_state == JOB_STATE_MOVED) { snprintf(log_buffer, sizeof(log_buffer), "Parent %s%s", msg_movejob, pjob->ji_qs.ji_destin); log_event(PBSEVENT_DEBUG|PBSEVENT_SYSTEM|PBSEVENT_ERROR, PBS_EVENTCLASS_REQUEST, LOG_INFO, preq->rq_ind.rq_register.rq_child, log_buffer); req_reject(PBSE_JOB_MOVED, 0, preq); return; } switch (preq->rq_ind.rq_register.rq_op) { /* * Register a dependency */ case JOB_DEPEND_OP_REGISTER: switch (type) { case JOB_DEPEND_TYPE_AFTERSTART: if (pjob->ji_qs.ji_substate >= JOB_SUBSTATE_RUNNING) { /* job already running, setup task to send */ /* release back to child and continue with */ /* registration process */ ptask = set_task(WORK_Immed, 0, post_run_depend, (void *)pjob); if (ptask) append_link(&pjob->ji_svrtask, &ptask->wt_linkobj, ptask); } /* fall through to complete registration */ case JOB_DEPEND_TYPE_AFTERANY: case JOB_DEPEND_TYPE_AFTEROK: case JOB_DEPEND_TYPE_AFTERNOTOK: rc = register_dep(pattr, preq, type, &made); break; case JOB_DEPEND_TYPE_BEFORESTART: case JOB_DEPEND_TYPE_BEFOREANY: case JOB_DEPEND_TYPE_BEFOREOK: case JOB_DEPEND_TYPE_BEFORENOTOK: /* * Check job owner for permission, use the real * job owner, not the sending server's name. */ (void)strcpy(preq->rq_user, preq->rq_ind.rq_register.rq_owner); if (svr_chk_owner(preq, pjob)) { rc = PBSE_PERM; /* not same user */ } else { /* ok owner, see if job has "on" */ pdep = find_depend(JOB_DEPEND_TYPE_ON, pattr); if (pdep == 0) { /* on "on", see if child already registered */ revtype = type ^ (JOB_DEPEND_TYPE_BEFORESTART - JOB_DEPEND_TYPE_AFTERSTART); pdep = find_depend(revtype, pattr); if (pdep == 0) { /* no "on" and no prior - return error */ rc = PBSE_BADDEPEND; } else { pdj = find_dependjob(pdep, preq->rq_ind.rq_register.rq_child); if (pdj) { /* has prior register, update it */ (void)strcpy(pdj->dc_svr, preq->rq_ind.rq_register.rq_svr); } } } else if ((rc=register_dep(pattr, preq, type, &made)) == 0) { if (made) { /* first time registered */ if (--pdep->dp_numexp <= 0) del_depend(pdep); } } } break; default: #ifdef NAS /* localmod 109 */ sprintf(log_buffer, "Unknown dep. op: %d", preq->rq_ind.rq_register.rq_op); log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, preq->rq_ind.rq_register.rq_parent, log_buffer); #endif /* localmod 109 */ rc = PBSE_IVALREQ; break; } break; /* * Release a dependency so job might run */ case JOB_DEPEND_OP_RELEASE: switch (type) { case JOB_DEPEND_TYPE_BEFORESTART: case JOB_DEPEND_TYPE_BEFOREANY: case JOB_DEPEND_TYPE_BEFOREOK: case JOB_DEPEND_TYPE_BEFORENOTOK: /* predecessor sent release-reduce "on", */ /* see if this job can now run */ type ^= (JOB_DEPEND_TYPE_BEFORESTART - JOB_DEPEND_TYPE_AFTERSTART); if ((pdep = find_depend(type, pattr)) != NULL) { pdj = find_dependjob(pdep, preq->rq_ind.rq_register.rq_child); if (pdj) { del_depend_job(pdj); pattr->at_flags |= ATR_VFLAG_MODIFY | ATR_VFLAG_MODCACHE; savetype = SAVEJOB_FULLFORCE; (void)sprintf(log_buffer, msg_registerrel, preq->rq_ind.rq_register.rq_child); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); if (GET_NEXT(pdep->dp_jobs) == 0) { /* no more dependencies of this type */ del_depend(pdep); set_depend_hold(pjob, pattr); } break; } #ifdef NAS /* localmod 109 */ sprintf(log_buffer, "Dep.rls. job not found: %d/%s", type, preq->rq_ind.rq_register.rq_child); } else { sprintf(log_buffer, "Dep.rls. type not found: %d", type); #endif /* localmod 109 */ } #ifdef NAS /* localmod 109 */ log_event(PBSEVENT_DEBUG, PBS_EVENTCLASS_JOB, LOG_INFO, preq->rq_ind.rq_register.rq_parent, log_buffer); #endif /* localmod 109 */ rc = PBSE_IVALREQ; break; } break; case JOB_DEPEND_OP_READY: rc = PBSE_NOSYNCMSTR; break; case JOB_DEPEND_OP_DELETE: (void)sprintf(log_buffer, msg_registerdel, preq->rq_ind.rq_register.rq_child); log_event(PBSEVENT_JOB, PBS_EVENTCLASS_JOB, LOG_INFO, pjob->ji_qs.ji_jobid, log_buffer); job_abt(pjob, log_buffer); break; case JOB_DEPEND_OP_UNREG: unregister_dep(pattr, preq); set_depend_hold(pjob, pattr); break; default: sprintf(log_buffer, msg_illregister, preq->rq_ind.rq_register.rq_parent); log_event(PBSEVENT_DEBUG|PBSEVENT_SYSTEM|PBSEVENT_ERROR, PBS_EVENTCLASS_REQUEST, LOG_INFO, preq->rq_host, log_buffer); rc = PBSE_IVALREQ; break;; } if (rc) { pjob->ji_modified = 0; req_reject(rc, 0, preq); } else { /* If this is an array job, forcibly save it to ensure * dependencies are recorded. */ if (pjob->ji_qs.ji_svrflags & JOB_SVFLG_ArrayJob) savetype = SAVEJOB_FULLFORCE; if (pjob->ji_modified) (void)job_save(pjob, savetype); reply_ack(preq); } return; }
void calculate_values() { cell_list ***depend = NULL; cell_list *first = NULL; cell_list *sorted = NULL, *sorted_last = NULL; cell_list *p = NULL; int i,j; //rtlDebugOutString("calc"); abort_calc = 0; depend = (cell_list***)allocmem(col_count * sizeof(void*)); for (i = 0; i < col_count; i++) { depend[i] = (cell_list**)allocmem(row_count * sizeof(void*)); for (j = 0; j < row_count; j++) { if (values[i][j]) freemem(values[i][j]); values[i][j] = NULL; if (cells[i][j] && cells[i][j][0] == '=') { depend[i][j] = find_depend(cells[i][j] + 1); // после = if (abort_calc) { values[i][j] = (char*)allocmem(2); values[i][j][0] = '#'; values[i][j][1] = '\0'; abort_calc = 0; continue; } cell_list *cur; cur = (cell_list*)allocmem(sizeof(cell_list)); cur->x = i; cur->y = j; cur->next = first; // вставили тек. ячейку в начало списка ячеек с формулами first = cur; } } } //rtlDebugOutString("depend end"); // топологическая сортировка if (!first) goto free_memory; if (abort_calc) goto free_memory; while (first) { // найти наименьший элемент. если его нет - ошибка, т.к. циклическая зависимость cell_list *prev = NULL,*min = first; bool is_min; while (min) { cell_list *p = first; is_min = 1; while (p && is_min) { if (is_in_list(p,depend[min->x][min->y])) is_min = 0; p = p->next; } if (is_min) break; prev = min; min = min->next; } if (!is_min) { abort_calc = 1; goto free_memory; // все плохо. ужасно. я плакаю, но пишу goto } // надо убрать минимум во второй список if (prev == NULL) { first = first->next; } else { prev->next = min->next; } /* min->next = sorted; sorted = min; */ if (sorted == NULL) { sorted = min; sorted_last = min; } else { sorted_last->next = min; sorted_last = min; min->next = NULL; } } // вычисление значений //rtlDebugOutString("sort end"); p = sorted; while (p) { double d; abort_calc = 0; set_exp(cells[p->x][p->y]+1); // все что после "=" find_var = &calc_callback; if (get_exp(&d)) { char *new_val = ftoa(d); if (values[p->x][p->y] && strcmp(values[p->x][p->y],new_val) == 0) { freemem(new_val); } else { if (values[p->x][p->y]) freemem(values[p->x][p->y]); values[p->x][p->y] = new_val; sel_moved = 0; } //sprintf(debuf,"calc %U %U formula %S result %f",p->x,p->y,cells[p->x][p->y]+1,d); //rtlDebugOutString(debuf); } else { values[p->x][p->y] = (char*)allocmem(2); values[p->x][p->y][0] = '#'; values[p->x][p->y][1] = '\0'; //sprintf(debuf,"calc %U %U formula %S result #",p->x,p->y,cells[p->x][p->y]+1); //rtlDebugOutString(debuf); } p = p->next; } if (abort_calc) goto free_memory; //rtlDebugOutString("calc end"); // освобождение памяти free_memory: p = sorted; while (p) { cell_list *tmp = p->next; cell_list *pp = depend[p->x][p->y]; while (pp) { cell_list *tmp = pp->next; freemem(pp); pp = tmp; } freemem(p); p = tmp; } for (i = 0; i < col_count; i++) freemem(depend[i]); freemem(depend); //rtlDebugOutString("freemem end"); }