static struct share_acct * get_sacct(const char *acct_name, const char *user_list) { char name[128]; uint32_t shares; int cc; int n; struct share_acct *sacct; char *p; char *p0; p0 = p = strdup(user_list); /* If we don't find account name * in the user list make sure we * return NULL and not random memory. */ sacct = NULL; cc = sscanf(p, "%s%u%n", name, &shares, &n); if (cc == EOF) { _free_(p); return NULL; } /* default can have users all * or explicitly named users */ if (strcmp(name, "default") == 0) { sacct = make_sacct(acct_name, shares); goto pryc; } /* Match the user in the user_list */ while (1) { cc = sscanf(p, "%s%u%n", name, &shares, &n); if (cc == EOF) break; if (strcmp(name, acct_name) != 0) { p = p + n; continue; } sacct = make_sacct(name, shares); break; } pryc: _free_(p0); return sacct; }
/* parse_user_shares() * * parse user_shares[[g, 1] [e,1]] */ static link_t * parse_user_shares(const char *user_shares) { link_t *l; char *p; char *u; int cc; int n; struct share_acct *sacct; uint32_t sum_shares; linkiter_t iter; u = strdup(user_shares); assert(u); p = strchr(u, '['); *p++ = 0; tokenize(p); l = make_link(); sum_shares = 0; while (1 ) { char name[128]; uint32_t shares; cc = sscanf(p, "%s%u%n", name, &shares, &n); if (cc == EOF) break; if (cc != 2) goto bail; p = p + n; sacct = make_sacct(name, shares); assert(sacct); sum_shares = sum_shares + sacct->shares; enqueue_link(l, sacct); } traverse_init(l, &iter); while ((sacct = traverse_link(&iter))) { sacct->dshares = (double)sacct->shares/(double)sum_shares; } _free_(u); return l; bail: _free_(u); traverse_init(l, &iter); while ((sacct = traverse_link(&iter))) free_sacct(sacct); fin_link(l); return NULL; }
/* sshare_make_tree() * In this function we match the user_shares as configured * in the queue file with the groups configured in lsb.users. * The fairshare configuration in the queues can be such * that they don't match for example: * * FAIRSHARE = USER_SHARES[[crock ,2] [zebra, 1]] * FAIRSHARE = USER_SHARES[[all, 1]] * * in these cases the shares are specified for users * directly and no groups are involved. */ struct tree_ *sshare_make_tree(const char *user_shares, uint32_t num_grp, struct group_acct *grp) { struct tree_ *t; link_t *l; link_t *stack; linkiter_t iter; struct share_acct *sacct; struct tree_node_ *n; struct tree_node_ *root; n = NULL; stack = make_link(); t = tree_init(""); /* root summarizes all the tree counters */ t->root->data = make_sacct("/", 1); root = NULL; /* First parse the user shares and make * the first level of the tree */ l = parse_user_shares(user_shares); z: if (root) l = parse_group_member(n->name, num_grp, grp); else root = t->root; if (l == NULL) { free_sacct(t->root->data); fin_link(stack); tree_free(t, free_sacct); return NULL; } traverse_init(l, &iter); while ((sacct = traverse_link(&iter))) { n = calloc(1, sizeof(struct tree_node_)); /* dup() the name as later we free both * the tree node and the share account */ n->name = strdup(sacct->name); n = tree_insert_node(root, n); enqueue_link(stack, n); n->data = sacct; } /* Sort by shares so the tree * is always sorted by share * priority */ sort_siblings(root, node_cmp); fin_link(l); n = pop_link(stack); if (n) { root = n; goto z; } fin_link(stack); n = t->root; while ((n = tree_next_node(n))) { char buf[BUFSIZ]; /* Create the hash table of nodes and their * immediate parent. */ sacct = n->data; if (n->child == NULL) { /* all and default are synonyms as they * both indicate a user that is not explicitly * defined. */ if (strcasecmp(sacct->name, "all") == 0 || strcasecmp(sacct->name, "default") == 0) { sacct->options |= SACCT_USER_ALL; } sacct->options |= SACCT_USER; sprintf(buf, "%s/%s", n->parent->name, n->name); hash_install(t->node_tab, buf, n, NULL); } else { sacct->options |= SACCT_GROUP; } sprintf(buf, "%s", n->name); hash_install(t->node_tab, buf, n, NULL); print_node(n, t); } traverse_init(t->leafs, &iter); while ((n = traverse_link(&iter))) print_node(n, t); /* Fairshare tree is built and sorted * by decreasing shares, the scheduler * algorithm will fill it up with * slots from now on. */ tree_walk2(t, print_node); sort_tree_by_shares(t); return t; }