Example #1
0
/**
 * @brief
 *		cmp_events - sort jobs/resvs into a timeline of the next event
 *		to happen: running jobs ending, advanced reservations starting
 *		or ending
 *
 * @param[in]	v1	-	resource_resv 1
 * @param[in]	v2	-	resource_resv 2
 *
 * @return	int
 * @retval	-1	: if v1 < v2
 * @retval	0 	: if v1 == v2
 * @retval	1  	: if v1 > v2
 */
int
cmp_events(const void *v1, const void *v2)
{
	resource_resv *r1, *r2;
	time_t t1, t2;
	int run1, run2;			/* are r1 and r2 in runnable states? */
	int end_event1 = 0, end_event2 = 0;	/* are r1 and r2 end events? */

	r1 = *((resource_resv **) v1);
	r2 = *((resource_resv **) v2);

	if (r1->start != UNSPECIFIED && r2->start ==UNSPECIFIED)
		return -1;

	if (r1->start == UNSPECIFIED && r2->start ==UNSPECIFIED)
		return 0;

	if (r1->start == UNSPECIFIED && r2->start !=UNSPECIFIED)
		return 1;

	run1 = in_runnable_state(r1);
	run2 = in_runnable_state(r2);


	if (r1->start >= r1->server->server_time && run1)
		t1 = r1->start;
	else {
		end_event1 = 1;
		t1 = r1->end;
	}

	if (r2->start >= r2->server->server_time && run2)
		t2 = r2->start;
	else {
		end_event2 = 1;
		t2 = r2->end;
	}

	if (t1 < t2)
		return -1;
	else if (t1 == t2) {
		/* if event times are equal, this means that events which consume
		 * resources and release resources happen at the same time.  We need to
		 * make sure events which release resources come first, so the events
		 * which consume them, can indeed do that.
		 */
		if (end_event1)
			return -1;
		else if (end_event2)
			return 1;
		else
			return 0;
	}
	else
		return 1;
}
Example #2
0
/**
 * @brief
 *		create_events - creates an timed_event list from running jobs
 *			    and confirmed reservations
 *
 * @param[in] sinfo - server universe to act upon
 *
 * @return	timed_event list
 *
 */
timed_event *
create_events(server_info *sinfo)
{
	timed_event	*events = NULL;
	timed_event	*te = NULL;
	resource_resv	**all = NULL;
	int		errflag = 0;
	int		i = 0;
	time_t 		end = 0;

	/* all_resresv is sorted such that the timed events are in the front of
	 * the array.  Once the first non-timed event is reached, we're done
	 */
	all = sinfo->all_resresv;

	/* sort the all resersv list so all the timed events are in the front */
	qsort(all, count_array((void **)all), sizeof(resource_resv *), cmp_events);

	for (i = 0; all[i] != NULL && is_timed(all[i]); i++) {
		if (all[i]->is_resv && all[i]->resv &&
			all[i]->resv->resv_state == RESV_BEING_ALTERED)
			continue;
		/* only add a run event for a job or reservation if they're
		 * in a runnable state (i.e. don't add it if they're running)
		 */
		if (in_runnable_state(all[i])) {
			te = create_event(TIMED_RUN_EVENT, all[i]->start, all[i], NULL, NULL);
			if (te == NULL) {
				errflag++;
				break;
			}
			events = add_timed_event(events, te);
		}

		if (sinfo->use_hard_duration)
			end = all[i]->start + all[i]->hard_duration;
		else
			end = all[i]->end;
		te = create_event(TIMED_END_EVENT, end, all[i], NULL, NULL);
		if (te == NULL) {
			errflag++;
			break;
		}
		events = add_timed_event(events, te);
	}

	/* A malloc error was encountered, free all allocated memory and return */
	if (errflag > 0) {
		free_timed_event_list(events);
		return 0;
	}

	return events;
}
Example #3
0
/**
 * @brief
 * 		entrypoint into job sort used by qsort
 *
 *		1. Sort all preemption priority jobs in the front
 *		2. Sort all preempted jobs in ascending order of their preemption time
 *		3. Sort all starving jobs after the high priority jobs
 *		4. Sort jobs according to their fairshare usage.
 *		5. sort by unique rank to stabilize the sort
 *
 * @param[in]	v1	-	resource_resv 1
 * @param[in]	v2	-	resource_resv 2
 *
 * @return	-1,0,1 : based on sorting function.
 */
int
cmp_sort(const void *v1, const void *v2)
{
	int cmp;
	resource_resv *r1;
	resource_resv *r2;

	r1 = *((resource_resv **) v1);
	r2 = *((resource_resv **) v2);

	if (r1 != NULL && r2 == NULL)
		return -1;

	if (r1 == NULL && r2 == NULL)
		return 0;

	if (r1 == NULL && r2 != NULL)
		return 1;

	if (in_runnable_state(r1) && !in_runnable_state(r2))
		return -1;
	else if (in_runnable_state(r2) && !in_runnable_state(r1))
		return 1;
	/* both jobs are runnable */
	else {
		/* sort based on preemption */
		cmp = cmp_preemption(r1, r2);
		if (cmp != 0)
			return cmp;

		cmp = cmp_job_preemption_time_asc(&r1, &r2);
		if (cmp != 0)
			return cmp;
#ifndef NAS /* localmod 041 */
		if (r1->is_job && r1->server->policy->help_starving_jobs) {
			cmp = cmp_starving_jobs(&r1, &r2);
			if (cmp != 0)
				return cmp;
		}
#endif /* localmod 041 */
		/* sort on the basis of job sort formula */
		cmp = cmp_job_sort_formula(&r1, &r2);
		if (cmp != 0)
			return cmp;
#ifndef NAS /* localmod 041 */
		if (r1->server->policy->fair_share) {
			cmp = cmp_fairshare(&r1, &r2);
			if (cmp != 0)
				return cmp;
		}
#endif /* localmod 041 */

		/* normal resource based sort */
		cmp = multi_sort(r1, r2);
		if (cmp != 0)
			return cmp;

		/* stabilize the sort */
		else {
			if (r1->qrank < r2->qrank)
				return -1;
			else if (r1->qrank > r2->qrank)
				return 1;
			if (r1->rank < r2->rank)
				return -1;
			else if (r1->rank > r2->rank)
				return 1;
			else {
				return 0;
			}
		}
	}
}
Example #4
0
/**
 * @brief
 *		update_resresv_on_end - update a resource_resv structure when
 *				      it ends
 *
 * @param[out]	resresv	-	the resresv to update
 * @param[in]	job_state	-	the new state if resresv is a job
 *
 * @return	nothing
 *
 */
void
update_resresv_on_end(resource_resv *resresv, char *job_state)
{
	queue_info *resv_queue;
	resource_resv *next_occr = NULL;
	time_t next_occr_time;
	char logbuf[MAX_LOG_SIZE];
	int ret;
	int i;

	if (resresv == NULL)
		return;

	/* now that it isn't running, it might be runnable again */
	resresv->can_not_run = 0;

	/* unless of course it's a job and its queue is in an ineligible state */
	if (resresv->is_job && resresv->job != NULL &&
		!resresv->job->queue->is_ok_to_run)
		resresv->can_not_run = 1;

	/* no longer running... clear start and end times */
	resresv->start = UNSPECIFIED;
	resresv->end = UNSPECIFIED;

	if (resresv->is_job && resresv->job != NULL) {
		set_job_state(job_state, resresv->job);
		if (resresv->job->is_suspended) {
#ifndef NAS /* localmod 005 */
			int i;
#endif /* localmod 005 */
			nspec **ns = resresv->nspec_arr;
			resresv->job->is_susp_sched = 1;
			for (i = 0; ns[i] != NULL; i++)
				ns[i]->ninfo->num_susp_jobs++;
		}

		resresv->job->is_provisioning = 0;

		/* free resources allocated to job since it's now been requeued */
		if (resresv->job->is_queued && !resresv->job->is_checkpointed) {
			free(resresv->ninfo_arr);
			resresv->ninfo_arr = NULL;
			free_nspecs(resresv->nspec_arr);
			resresv->nspec_arr = NULL;
			free_resource_req_list(resresv->job->resused);
			resresv->job->resused = NULL;
			if (resresv->nodepart_name != NULL) {
				free(resresv->nodepart_name);
				resresv->nodepart_name = NULL;
			}
			free_selspec(resresv->execselect);
			resresv->execselect = NULL;
		}
	}
	else if (resresv->is_resv && resresv->resv !=NULL) {
		resresv->resv->resv_state = RESV_DELETED;

		resv_queue = find_queue_info(resresv->server->queues,
			resresv->resv->queuename);
		if (resv_queue != NULL) {
			resv_queue->is_started = 0;
			ret = is_ok_to_run_queue(resresv->server->policy, resv_queue);
			if (ret == SUCCESS)
				resv_queue->is_ok_to_run = 1;
			else
				resv_queue->is_ok_to_run = 0;

			if (resresv->resv->is_standing) {
				/* This occurrence is over, move resv pointers of all jobs that are
				 * left to next occurrence if one exists
				 */
				if (resresv->resv->resv_idx < resresv->resv->count) {
					next_occr_time = get_occurrence(resresv->resv->rrule,
						resresv->resv->req_start, resresv->resv->timezone, 2);
					if (next_occr_time >= 0) {
						next_occr = find_resource_resv_by_time(resresv->server->resvs,
							resresv->name, next_occr_time);
						if (next_occr != NULL) {
							if (resv_queue->jobs != NULL) {
								for (i = 0; resv_queue->jobs[i] != NULL; i++) {
									if (in_runnable_state(resv_queue->jobs[i]))
										resv_queue->jobs[i]->job->resv = next_occr;
								}
							}
						}
						else {
							snprintf(logbuf, MAX_LOG_SIZE,
								"Can't find occurrence of standing reservation at time %ld",
								next_occr_time);
							schdlog(PBSEVENT_DEBUG, PBS_EVENTCLASS_SERVER, LOG_DEBUG,
								resresv->name, logbuf);
						}
					}
				}
			}
		}
	}
}