/* * * decay_fairshare_tree - decay the usage information kept in the fair * share tree * * root - the root of the fairshare tree * * returns nothing * */ void decay_fairshare_tree(group_info *root) { if (root == NULL) return; decay_fairshare_tree(root -> sibling); decay_fairshare_tree(root -> child); root -> usage /= 2; if (root -> usage == 0) root -> usage = 1; }
int init_scheduling_cycle(server_info *sinfo) { group_info *user; /* the user for the running jobs of the last cycle */ queue_info *qinfo; /* user to cycle through the queues to sort the jobs */ char decayed = 0; /* boolean: have we decayed usage? */ time_t t; /* used in decaying fair share */ int i, j; if (cstat.fair_share) { if (last_running != NULL) { /* add the usage which was accumulated between the last cycle and this * one and calculate a new value */ for (i = 0; i < last_running_size ; i++) { job_info** jobs; user = last_running[i].ginfo; #if HIGH_PRECISION_FAIRSHARE jobs = sinfo -> jobs; /* check all jobs (exiting, completed, running) */ #else jobs = sinfo -> running_jobs; /* check only running */ #endif for (j = 0; jobs[j] != NULL; j++) { if (jobs[j] -> is_completed || jobs[j] -> is_exiting || jobs[j] -> is_running) if (!strcmp(last_running[i].name, jobs[j] -> name)) break; } if (jobs[j] != NULL) { user -> usage += calculate_usage_value(jobs[j] -> resused) - calculate_usage_value(last_running[i].resused); } } /* assign usage into temp usage since temp usage is used for usage * calculations. Temp usage starts at usage and can be modified later. */ for (i = 0; i < last_running_size; i++) last_running[i].ginfo -> temp_usage = last_running[i].ginfo -> usage; } /* The half life for the fair share tree might have passed since the last * scheduling cycle. For that matter, several half lives could have * passed. If this is the case, perform as many decays as necessary */ t = cstat.current_time; while (t - last_decay > conf.half_life) { sched_log(PBSEVENT_DEBUG2, PBS_EVENTCLASS_SERVER, "", "Decaying Fairshare Tree"); decay_fairshare_tree(conf.group_root); t -= conf.half_life; decayed = 1; } if (decayed) { /* set the time to the acuall the half-life should have occured */ last_decay = cstat.current_time - (cstat.current_time - last_decay) % conf.half_life; } if (cstat.current_time - last_sync > conf.sync_time) { write_usage(); last_sync = cstat.current_time; sched_log(PBSEVENT_DEBUG2, PBS_EVENTCLASS_SERVER, "", "Usage Sync"); } } if (cstat.help_starving_jobs) cstat.starving_job = update_starvation(sinfo -> jobs); /* sort queues by priority if requested */ if (cstat.sort_queues) qsort(sinfo -> queues, sinfo -> num_queues, sizeof(queue_info *), cmp_queue_prio_dsc); if (cstat.sort_by[0].sort != NO_SORT) { if (cstat.by_queue || cstat.round_robin) { for (i = 0; i < sinfo -> num_queues; i++) { qinfo = sinfo -> queues[i]; qsort(qinfo -> jobs, qinfo -> sc.total, sizeof(job_info *), cmp_sort); } } else qsort(sinfo -> jobs, sinfo -> sc.total, sizeof(job_info *), cmp_sort); } next_job(sinfo, INITIALIZE); return 1; /* SUCCESS */ }
/** * @brief * The entry point of pbsfs * * @return int * @retval 0 : success * @retval 1 : something is wrong! */ int main(int argc, char *argv[]) { char path_buf[256] = {0}; char sched_name[PBS_MAXSCHEDNAME + 1] = "default"; group_info *ginfo; group_info *ginfo2; int c; int flags = FS_PRINT; int flag1 = 0; double val; char *endp; char *testp; /* the real deal or output version and exit? */ PRINT_VERSION_AND_EXIT(argc, argv); set_msgdaemonname("pbsfs"); #ifdef WIN32 if (winsock_init()) { return 1; } #endif if (pbs_loadconf(0) <= 0) exit(1); while ((c = getopt(argc, argv, "sgptdceI:-:")) != -1) switch (c) { case 'g': flags = FS_GET; break; case 's': flags = FS_SET | FS_WRITE_FILE; break; case 'p': flags = FS_PRINT; break; case 't': flags = FS_PRINT_TREE; break; case 'd': flags = FS_DECAY | FS_WRITE_FILE; break; case 'c': flags = FS_COMP; break; case 'e': flags = FS_TRIM_TREE | FS_WRITE_FILE; break; case 'I': snprintf(sched_name, sizeof(sched_name), "%s", optarg); break; case '-': flag1 = 1; break; } if (flag1 == 1) { fprintf(stderr, "Usage: pbsfs --version\n"); exit(1); } if ((flags & (FS_PRINT | FS_PRINT_TREE)) && (argc - optind) != 0) { fprintf(stderr, "Usage: pbsfs -[ptdgcs] [-I sched_name]\n"); exit(1); } else if ((flags & FS_GET) && (argc - optind) != 1) { fprintf(stderr, "Usage: pbsfs [-I sched_name] -g <fairshare_entity>\n"); exit(1); } else if ((flags & FS_SET) && (argc - optind) != 2) { fprintf(stderr, "Usage: pbsfs [-I sched_name] -s <fairshare_entity> <usage>\n"); exit(1); } else if ((flags & FS_COMP) && (argc - optind) != 2) { fprintf(stderr, "Usage: pbsfs [-I sched_name] -c <entity1> <entity2>\n"); exit(1); } if (strcmp(sched_name, "default") != 0) { int pbs_sd; struct batch_status *bs; struct batch_status *cur_bs; pbs_sd = pbs_connect(NULL); if (pbs_sd < 0) { fprintf(stderr, "Can't connect to the server\n"); exit(1); } bs = pbs_statsched(pbs_sd, NULL, NULL); for (cur_bs = bs; cur_bs != NULL; cur_bs = cur_bs->next) { if (strcmp(cur_bs->name, sched_name) == 0) { struct attrl *cur_attrl; for (cur_attrl = cur_bs->attribs; cur_attrl != NULL; cur_attrl = cur_attrl->next) { if (strcmp(cur_attrl->name, ATTR_sched_priv) == 0) { strncpy(path_buf, cur_attrl->value, sizeof(path_buf)); path_buf[sizeof(path_buf) - 1] = '\0'; break; } } if (cur_attrl == NULL) { fprintf(stderr, "Scheduler %s does not have its sched_priv set\n", sched_name); exit(1); } break; } } if (cur_bs == NULL) { fprintf(stderr, "Scheduler %s does not exist\n", sched_name); exit(1); } pbs_disconnect(pbs_sd); } else snprintf(path_buf, sizeof(path_buf), "%s/sched_priv/", pbs_conf.pbs_home_path); if (chdir(path_buf) == -1) { perror("Unable to access fairshare data"); exit(1); } init_config(); parse_config(CONFIG_FILE); if ((conf.fairshare = preload_tree()) == NULL) { fprintf(stderr, "Error in preloading fairshare information\n"); return 1; } if (parse_group(RESGROUP_FILE, conf.fairshare->root) == 0) return 1; if (flags & FS_TRIM_TREE) read_usage(USAGE_FILE, FS_TRIM, conf.fairshare); else read_usage(USAGE_FILE, 0, conf.fairshare); calc_fair_share_perc(conf.fairshare->root->child, UNSPECIFIED); calc_usage_factor(conf.fairshare); if (flags & FS_PRINT_TREE) print_fairshare(conf.fairshare->root, 0); else if (flags & FS_PRINT ) { printf("Fairshare usage units are in: %s\n", conf.fairshare_res); print_fairshare(conf.fairshare->root, -1); } else if (flags & FS_DECAY) decay_fairshare_tree(conf.fairshare->root); else if (flags & (FS_GET | FS_SET | FS_COMP)) { ginfo = find_group_info(argv[optind], conf.fairshare->root); if (ginfo == NULL) { fprintf(stderr, "Fairshare Entity %s does not exist.\n", argv[optind]); return 1; } if (flags & FS_COMP) { ginfo2 = find_group_info(argv[optind + 1], conf.fairshare->root); if (ginfo2 == NULL) { fprintf(stderr, "Fairshare Entity %s does not exist.\n", argv[optind + 1]); return 1; } switch (compare_path(ginfo->gpath, ginfo2->gpath)) { case -1: printf("%s\n", ginfo->name); break; case 0: printf("%s == %s\n", ginfo->name, ginfo2->name); break; case 1: printf("%s\n", ginfo2->name); } } else if (flags & FS_GET) print_fairshare_entity(ginfo); else { testp = argv[optind + 1]; val = strtod(testp, &endp); if (*endp == '\0') ginfo->usage = val; } } if (flags & FS_WRITE_FILE) { FILE *fp; /* make backup of database file */ remove(USAGE_FILE ".bak"); if (rename(USAGE_FILE, USAGE_FILE ".bak") < 0) perror("Could not backup usage database."); write_usage(USAGE_FILE, conf.fairshare); if ((fp = fopen(USAGE_TOUCH, "w")) != NULL) fclose(fp); } return 0; }