Example #1
0
/* Calculate fairshare for each child then sort children by fairshare value
 * (level_fs). Once they are sorted, operate on each child in sorted order.
 * This portion of the tree is now sorted and users are given a fairshare value
 * based on the order they are operated on. The basic equation is
 * (rank / g_user_assoc_count), though ties are allowed. The rank is decremented
 * for each user that is encountered.
 */
static void _calc_tree_fs(slurmdb_assoc_rec_t** siblings,
			  uint16_t assoc_level, uint32_t *rank, uint32_t *i,
			  bool account_tied)
{
	slurmdb_assoc_rec_t *assoc = NULL;
	long double prev_level_fs = (long double) NO_VAL;
	bool tied = false;
	size_t ndx;

	/* Calculate level_fs for each child */
	for (ndx = 0; (assoc = siblings[ndx]); ndx++)
		_calc_assoc_fs(assoc);

	/* Sort children by level_fs */
	qsort(siblings, ndx, sizeof(slurmdb_assoc_rec_t *),
	      _cmp_level_fs);

	/* Iterate through children in sorted order. If it's a user, calculate
	 * fs_factor, otherwise recurse. */
	for (ndx = 0; (assoc = siblings[ndx]); ndx++) {
		if (account_tied) {
			tied = true;
			account_tied = false;
		} else {
			tied = prev_level_fs == assoc->usage->level_fs;
		}

		if (priority_debug)
			_ft_debug(assoc, assoc_level, tied);
		if (assoc->user) {
			if (!tied)
				*rank = *i;

			/* Set the final fairshare factor for this user */
			assoc->usage->fs_factor =
				*rank / (double) g_user_assoc_count;
			(*i)--;
		} else {
			slurmdb_assoc_rec_t** children;
			size_t merge_count =
				_count_tied_accounts(siblings, ndx);

			/* Merging does not affect child level_fs calculations
			 * since the necessary information is stored on each
			 * assoc's usage struct */
			children = _merge_accounts(siblings, ndx,
						   ndx + merge_count,
						   assoc_level);

			_calc_tree_fs(children, assoc_level + 1, rank, i, tied);

			/* Skip over any merged accounts */
			ndx += merge_count;

			xfree(children);
		}
		prev_level_fs = assoc->usage->level_fs;
	}

}
Example #2
0
/* Calculate fairshare for each child then sort children by fairshare value
 * (level_fs). Once they are sorted, operate on each child in sorted order.
 * This portion of the tree is now sorted and users are given a fairshare value
 * based on the order they are operated on. The basic equation is
 * (rank / g_user_assoc_count), though ties are allowed. The rank is
 * decremented for each user that is encountered except when ties occur.
 *
 * Tie Handling Rules:
 * 	1) Sibling users with the same level_fs receive the same rank
 *	2) Sibling accounts with the same level_fs have their children lists
 *	   merged before sorting
 *	3) A user with the same level_fs as a sibling account will receive
 *	   the same rank as the account's highest ranked user
 *
 * IN siblings - array of siblings
 * IN assoc_level - depth in the tree (root is 0)
 * IN/OUT rank - current user ranking, starting at g_user_assoc_count
 * IN/OUT rnt - rank, no ties (what rank would be if no tie exists)
 * IN account_tied - is this account tied with the previous user
 */
static void _calc_tree_fs(slurmdb_assoc_rec_t** siblings,
			  uint16_t assoc_level, uint32_t *rank,
			  uint32_t *rnt, bool account_tied)
{
	slurmdb_assoc_rec_t *assoc = NULL;
	long double prev_level_fs = (long double) NO_VAL;
	bool tied = false;
	size_t i;

	/* Calculate level_fs for each child */
	for (i = 0; (assoc = siblings[i]); i++)
		_calc_assoc_fs(assoc);

	/* Sort children by level_fs */
	qsort(siblings, i, sizeof(slurmdb_assoc_rec_t *), _cmp_level_fs);

	/* Iterate through children in sorted order. If it's a user, calculate
	 * fs_factor, otherwise recurse. */
	for (i = 0; (assoc = siblings[i]); i++) {
		/* tied is used while iterating across siblings.
		 * account_tied preserves ties while recursing */
		if (i == 0 && account_tied) {
			/* The parent was tied so this level starts out tied */
			tied = true;
		} else {
			tied = prev_level_fs == assoc->usage->level_fs;
		}

		if (priority_debug)
			_ft_debug(assoc, assoc_level, tied);

		/* If user, set their final fairshare factor and
		 * handle ranking.
		 * If account, merge any tied accounts then recurse with the
		 * merged children array. */
		if (assoc->user) {
			if (!tied)
				*rank = *rnt;

			assoc->usage->fs_factor =
				*rank / (double) g_user_assoc_count;

			(*rnt)--;
		} else {
			slurmdb_assoc_rec_t** children;
			size_t merge_count = _count_tied_accounts(siblings, i);

			/* Merging does not affect child level_fs calculations
			 * since the necessary information is stored on each
			 * assoc's usage struct */
			children = _merge_accounts(siblings, i,
						   i + merge_count,
						   assoc_level);

			_calc_tree_fs(children, assoc_level+1,
				      rank, rnt, tied);

			/* Skip over any merged accounts */
			i += merge_count;

			xfree(children);
		}
		prev_level_fs = assoc->usage->level_fs;
	}

}