Exemple #1
0
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");
  }
Exemple #2
0
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");


}