PageRenderTime 59ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/src/sreport/job_reports.c

https://github.com/cfenoy/slurm
C | 1212 lines | 975 code | 166 blank | 71 comment | 198 complexity | 28996a7c7846c74639e62d45ce50a1cb MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * job_reports.c - functions for generating job reports
  3. * from accounting infrastructure.
  4. *****************************************************************************
  5. *
  6. * Copyright (C) 2008 Lawrence Livermore National Security.
  7. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  8. * Written by Danny Auble <da@llnl.gov>
  9. * CODE-OCEC-09-009. All rights reserved.
  10. *
  11. * This file is part of SLURM, a resource management program.
  12. * For details, see <http://www.schedmd.com/slurmdocs/>.
  13. * Please also read the included file: DISCLAIMER.
  14. *
  15. * SLURM is free software; you can redistribute it and/or modify it under
  16. * the terms of the GNU General Public License as published by the Free
  17. * Software Foundation; either version 2 of the License, or (at your option)
  18. * any later version.
  19. *
  20. * In addition, as a special exception, the copyright holders give permission
  21. * to link the code of portions of this program with the OpenSSL library under
  22. * certain conditions as described in each individual source file, and
  23. * distribute linked combinations including the two. You must obey the GNU
  24. * General Public License in all respects for all of the code used other than
  25. * OpenSSL. If you modify file(s) with this exception, you may extend this
  26. * exception to your version of the file(s), but you are not obligated to do
  27. * so. If you do not wish to do so, delete this exception statement from your
  28. * version. If you delete this exception statement from all source files in
  29. * the program, then also delete it here.
  30. *
  31. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  32. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  33. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  34. * details.
  35. *
  36. * You should have received a copy of the GNU General Public License along
  37. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  38. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  39. \*****************************************************************************/
  40. #include "src/common/uid.h"
  41. #include "job_reports.h"
  42. enum {
  43. PRINT_JOB_ACCOUNT,
  44. PRINT_JOB_CLUSTER,
  45. PRINT_JOB_COUNT,
  46. PRINT_JOB_CPUS,
  47. PRINT_JOB_DUR,
  48. PRINT_JOB_NODES,
  49. PRINT_JOB_SIZE,
  50. PRINT_JOB_USER,
  51. PRINT_JOB_WCKEY
  52. };
  53. static List print_fields_list = NULL; /* types are of print_field_t */
  54. static List grouping_print_fields_list = NULL; /* types are of print_field_t */
  55. static int print_job_count = 0;
  56. static bool flat_view = false;
  57. static bool individual_grouping = 0;
  58. /*
  59. * Comparator used for sorting clusters alphabetically
  60. *
  61. * returns: 1: cluster_a > cluster_b
  62. * 0: cluster_a == cluster_b
  63. * -1: cluster_a < cluster_b
  64. *
  65. */
  66. static int _sort_cluster_grouping_dec(
  67. slurmdb_report_cluster_grouping_t *cluster_a,
  68. slurmdb_report_cluster_grouping_t *cluster_b)
  69. {
  70. int diff = 0;
  71. if(!cluster_a->cluster || !cluster_b->cluster)
  72. return 0;
  73. diff = strcmp(cluster_a->cluster, cluster_b->cluster);
  74. if (diff > 0)
  75. return 1;
  76. else if (diff < 0)
  77. return -1;
  78. return 0;
  79. }
  80. /*
  81. * Comparator used for sorting clusters alphabetically
  82. *
  83. * returns: 1: acct_a > acct_b
  84. * 0: acct_a == acct_b
  85. * -1: acct_a < acct_b
  86. *
  87. */
  88. static int _sort_acct_grouping_dec(slurmdb_report_acct_grouping_t *acct_a,
  89. slurmdb_report_acct_grouping_t *acct_b)
  90. {
  91. int diff = 0;
  92. char tmp_acct_a[200];
  93. char tmp_acct_b[200];
  94. char *wckey_a = NULL, *wckey_b = NULL;
  95. if(!acct_a->acct || !acct_b->acct)
  96. return 0;
  97. snprintf(tmp_acct_a, sizeof(tmp_acct_a), "%s", acct_a->acct);
  98. snprintf(tmp_acct_b, sizeof(tmp_acct_b), "%s", acct_b->acct);
  99. if ((wckey_a = strstr(tmp_acct_a, ":")))
  100. *wckey_a++ = 0;
  101. if ((wckey_b = strstr(tmp_acct_b, ":")))
  102. *wckey_b++ = 0;
  103. diff = strcmp(tmp_acct_a, tmp_acct_b);
  104. if (diff > 0)
  105. return 1;
  106. else if (diff < 0)
  107. return -1;
  108. if(!wckey_a || !wckey_b)
  109. return 0;
  110. diff = strcmp(wckey_a, wckey_b);
  111. if (diff > 0)
  112. return 1;
  113. else if (diff < 0)
  114. return -1;
  115. return 0;
  116. }
  117. static char *_string_to_uid( char *name )
  118. {
  119. uid_t uid;
  120. if ( uid_from_string( name, &uid ) != 0 ) {
  121. fprintf(stderr, "Invalid user id: %s\n", name);
  122. exit(1);
  123. }
  124. xfree(name);
  125. return xstrdup_printf( "%d", (int) uid );
  126. }
  127. /* returns number of objects added to list */
  128. static int _addto_uid_char_list(List char_list, char *names)
  129. {
  130. int i=0, start=0;
  131. char *name = NULL, *tmp_char = NULL;
  132. ListIterator itr = NULL;
  133. char quote_c = '\0';
  134. int quote = 0;
  135. int count = 0;
  136. if(!char_list) {
  137. error("No list was given to fill in");
  138. return 0;
  139. }
  140. itr = list_iterator_create(char_list);
  141. if(names) {
  142. if (names[i] == '\"' || names[i] == '\'') {
  143. quote_c = names[i];
  144. quote = 1;
  145. i++;
  146. }
  147. start = i;
  148. while(names[i]) {
  149. //info("got %d - %d = %d", i, start, i-start);
  150. if(quote && names[i] == quote_c)
  151. break;
  152. else if (names[i] == '\"' || names[i] == '\'')
  153. names[i] = '`';
  154. else if(names[i] == ',') {
  155. if((i-start) > 0) {
  156. name = xmalloc((i-start+1));
  157. memcpy(name, names+start, (i-start));
  158. //info("got %s %d", name, i-start);
  159. name = _string_to_uid( name );
  160. while((tmp_char = list_next(itr))) {
  161. if(!strcasecmp(tmp_char, name))
  162. break;
  163. }
  164. if(!tmp_char) {
  165. list_append(char_list, name);
  166. count++;
  167. } else
  168. xfree(name);
  169. list_iterator_reset(itr);
  170. }
  171. i++;
  172. start = i;
  173. if(!names[i]) {
  174. info("There is a problem with "
  175. "your request. It appears you "
  176. "have spaces inside your list.");
  177. break;
  178. }
  179. }
  180. i++;
  181. }
  182. if((i-start) > 0) {
  183. name = xmalloc((i-start)+1);
  184. memcpy(name, names+start, (i-start));
  185. name = _string_to_uid( name );
  186. while((tmp_char = list_next(itr))) {
  187. if(!strcasecmp(tmp_char, name))
  188. break;
  189. }
  190. if(!tmp_char) {
  191. list_append(char_list, name);
  192. count++;
  193. } else
  194. xfree(name);
  195. }
  196. }
  197. list_iterator_destroy(itr);
  198. return count;
  199. }
  200. static int _set_cond(int *start, int argc, char *argv[],
  201. slurmdb_job_cond_t *job_cond,
  202. List format_list, List grouping_list)
  203. {
  204. int i;
  205. int set = 0;
  206. int end = 0;
  207. int local_cluster_flag = all_clusters_flag;
  208. time_t start_time, end_time;
  209. int command_len = 0;
  210. if(!job_cond->cluster_list)
  211. job_cond->cluster_list = list_create(slurm_destroy_char);
  212. for (i=(*start); i<argc; i++) {
  213. end = parse_option_end(argv[i]);
  214. if(!end)
  215. command_len=strlen(argv[i]);
  216. else
  217. command_len=end-1;
  218. if(!end && !strncasecmp(argv[i], "all_clusters",
  219. MAX(command_len, 1))) {
  220. local_cluster_flag = 1;
  221. continue;
  222. } else if(!end && !strncasecmp(argv[i], "PrintJobCount",
  223. MAX(command_len, 2))) {
  224. print_job_count = 1;
  225. continue;
  226. } else if (!end && !strncasecmp (argv[i], "FlatView",
  227. MAX(command_len, 2))) {
  228. flat_view = true;
  229. continue;
  230. } else if(!end
  231. || !strncasecmp (argv[i], "Clusters",
  232. MAX(command_len, 1))) {
  233. slurm_addto_char_list(job_cond->cluster_list,
  234. argv[i]+end);
  235. set = 1;
  236. } else if (!strncasecmp (argv[i], "Accounts",
  237. MAX(command_len, 2))
  238. || !strncasecmp(argv[i], "Acct",
  239. MAX(command_len, 4))) {
  240. if(!job_cond->acct_list)
  241. job_cond->acct_list =
  242. list_create(slurm_destroy_char);
  243. slurm_addto_char_list(job_cond->acct_list,
  244. argv[i]+end);
  245. set = 1;
  246. } else if (!strncasecmp (argv[i], "Associations",
  247. MAX(command_len, 2))) {
  248. if(!job_cond->associd_list)
  249. job_cond->associd_list =
  250. list_create(slurm_destroy_char);
  251. slurm_addto_char_list(job_cond->associd_list,
  252. argv[i]+end);
  253. set = 1;
  254. } else if (!strncasecmp (argv[i], "End", MAX(command_len, 1))) {
  255. job_cond->usage_end = parse_time(argv[i]+end, 1);
  256. set = 1;
  257. } else if (!strncasecmp (argv[i], "Format",
  258. MAX(command_len, 2))) {
  259. if(format_list)
  260. slurm_addto_char_list(format_list, argv[i]+end);
  261. } else if (!strncasecmp (argv[i], "Gid", MAX(command_len, 2))) {
  262. if(!job_cond->groupid_list)
  263. job_cond->groupid_list =
  264. list_create(slurm_destroy_char);
  265. slurm_addto_char_list(job_cond->groupid_list,
  266. argv[i]+end);
  267. set = 1;
  268. } else if (!strncasecmp (argv[i], "grouping",
  269. MAX(command_len, 2))) {
  270. if(!strncasecmp(argv[i]+end, "individual", 1)) {
  271. individual_grouping = 1;
  272. } else if(grouping_list)
  273. slurm_addto_char_list(grouping_list,
  274. argv[i]+end);
  275. } else if (!strncasecmp (argv[i], "Jobs",
  276. MAX(command_len, 1))) {
  277. char *end_char = NULL, *start_char = argv[i]+end;
  278. slurmdb_selected_step_t *selected_step = NULL;
  279. char *dot = NULL;
  280. if(!job_cond->step_list)
  281. job_cond->step_list =
  282. list_create(slurm_destroy_char);
  283. while ((end_char = strstr(start_char, ","))
  284. && start_char) {
  285. *end_char = 0;
  286. while (isspace(*start_char))
  287. start_char++; /* discard whitespace */
  288. if(!(int)*start_char)
  289. continue;
  290. selected_step = xmalloc(
  291. sizeof(slurmdb_selected_step_t));
  292. list_append(job_cond->step_list, selected_step);
  293. dot = strstr(start_char, ".");
  294. if (dot == NULL) {
  295. debug2("No jobstep requested");
  296. selected_step->stepid = NO_VAL;
  297. } else {
  298. *dot++ = 0;
  299. selected_step->stepid = atoi(dot);
  300. }
  301. selected_step->jobid = atoi(start_char);
  302. start_char = end_char + 1;
  303. }
  304. set = 1;
  305. } else if(!strncasecmp (argv[i], "Nodes",
  306. MAX(command_len, 1))) {
  307. if(job_cond->used_nodes) {
  308. error("You already specified nodes '%s' "
  309. " combine your request into 1 nodes=.",
  310. job_cond->used_nodes);
  311. exit_code = 1;
  312. break;
  313. }
  314. job_cond->used_nodes = xstrdup(argv[i]+end);
  315. set = 1;
  316. } else if (!strncasecmp (argv[i], "Partitions",
  317. MAX(command_len, 2))) {
  318. if(!job_cond->partition_list)
  319. job_cond->partition_list =
  320. list_create(slurm_destroy_char);
  321. slurm_addto_char_list(job_cond->partition_list,
  322. argv[i]+end);
  323. set = 1;
  324. } else if (!strncasecmp (argv[i], "Start",
  325. MAX(command_len, 1))) {
  326. job_cond->usage_start = parse_time(argv[i]+end, 1);
  327. set = 1;
  328. } else if (!strncasecmp (argv[i], "Users",
  329. MAX(command_len, 1))) {
  330. if(!job_cond->userid_list)
  331. job_cond->userid_list =
  332. list_create(slurm_destroy_char);
  333. _addto_uid_char_list(job_cond->userid_list,
  334. argv[i]+end);
  335. set = 1;
  336. } else if (!strncasecmp (argv[i], "Wckeys",
  337. MAX(command_len, 2))) {
  338. if(!job_cond->wckey_list)
  339. job_cond->wckey_list =
  340. list_create(slurm_destroy_char);
  341. slurm_addto_char_list(job_cond->wckey_list,
  342. argv[i]+end);
  343. set = 1;
  344. } else {
  345. exit_code=1;
  346. fprintf(stderr, " Unknown condition: %s\n"
  347. "Use keyword set to modify value\n", argv[i]);
  348. }
  349. }
  350. (*start) = i;
  351. if(!local_cluster_flag && !list_count(job_cond->cluster_list)) {
  352. char *temp = slurm_get_cluster_name();
  353. if(temp)
  354. list_append(job_cond->cluster_list, temp);
  355. }
  356. /* This needs to be done on some systems to make sure
  357. cluster_cond isn't messed. This has happened on some 64
  358. bit machines and this is here to be on the safe side.
  359. */
  360. start_time = job_cond->usage_start;
  361. end_time = job_cond->usage_end;
  362. slurmdb_report_set_start_end_time(&start_time, &end_time);
  363. job_cond->usage_start = start_time;
  364. job_cond->usage_end = end_time;
  365. return set;
  366. }
  367. static int _setup_print_fields_list(List format_list)
  368. {
  369. ListIterator itr = NULL;
  370. print_field_t *field = NULL;
  371. char *object = NULL;
  372. if(!format_list || !list_count(format_list)) {
  373. exit_code=1;
  374. fprintf(stderr,
  375. " We need a format list to set up the print.\n");
  376. return SLURM_ERROR;
  377. }
  378. if(!print_fields_list)
  379. print_fields_list = list_create(destroy_print_field);
  380. itr = list_iterator_create(format_list);
  381. while((object = list_next(itr))) {
  382. char *tmp_char = NULL;
  383. int command_len = 0;
  384. int newlen = 0;
  385. if((tmp_char = strstr(object, "\%"))) {
  386. newlen = atoi(tmp_char+1);
  387. tmp_char[0] = '\0';
  388. }
  389. command_len = strlen(object);
  390. field = xmalloc(sizeof(print_field_t));
  391. if(!strncasecmp("Account", object, MAX(command_len, 1))
  392. || !strncasecmp("Acct", object, MAX(command_len, 4))) {
  393. field->type = PRINT_JOB_ACCOUNT;
  394. field->name = xstrdup("Account");
  395. field->len = 9;
  396. field->print_routine = print_fields_str;
  397. } else if(!strncasecmp("Cluster", object,
  398. MAX(command_len, 2))) {
  399. field->type = PRINT_JOB_CLUSTER;
  400. field->name = xstrdup("Cluster");
  401. field->len = 9;
  402. field->print_routine = print_fields_str;
  403. } else if(!strncasecmp("CpuCount", object,
  404. MAX(command_len, 2))) {
  405. field->type = PRINT_JOB_CPUS;
  406. field->name = xstrdup("CPU Count");
  407. field->len = 9;
  408. field->print_routine = print_fields_uint;
  409. } else if(!strncasecmp("Duration", object,
  410. MAX(command_len, 1))) {
  411. field->type = PRINT_JOB_DUR;
  412. field->name = xstrdup("Duration");
  413. field->len = 12;
  414. field->print_routine = print_fields_time;
  415. } else if(!strncasecmp("JobCount", object,
  416. MAX(command_len, 2))) {
  417. field->type = PRINT_JOB_COUNT;
  418. field->name = xstrdup("Job Count");
  419. field->len = 9;
  420. field->print_routine = print_fields_uint;
  421. } else if(!strncasecmp("NodeCount", object,
  422. MAX(command_len, 2))) {
  423. field->type = PRINT_JOB_NODES;
  424. field->name = xstrdup("Node Count");
  425. field->len = 9;
  426. field->print_routine = print_fields_uint;
  427. } else if(!strncasecmp("User", object,
  428. MAX(command_len, 1))) {
  429. field->type = PRINT_JOB_USER;
  430. field->name = xstrdup("User");
  431. field->len = 9;
  432. field->print_routine = print_fields_str;
  433. } else if(!strncasecmp("Wckey", object,
  434. MAX(command_len, 1))) {
  435. field->type = PRINT_JOB_WCKEY;
  436. field->name = xstrdup("Wckey");
  437. field->len = 9;
  438. field->print_routine = print_fields_str;
  439. } else {
  440. exit_code=1;
  441. fprintf(stderr, " Unknown field '%s'\n", object);
  442. xfree(field);
  443. continue;
  444. }
  445. if(newlen)
  446. field->len = newlen;
  447. list_append(print_fields_list, field);
  448. }
  449. list_iterator_destroy(itr);
  450. return SLURM_SUCCESS;
  451. }
  452. static int _setup_grouping_print_fields_list(List grouping_list)
  453. {
  454. ListIterator itr = NULL;
  455. print_field_t *field = NULL;
  456. char *object = NULL;
  457. char *last_object = NULL;
  458. uint32_t last_size = 0;
  459. uint32_t size = 0;
  460. char *tmp_char = NULL;
  461. if(!grouping_list || !list_count(grouping_list)) {
  462. exit_code=1;
  463. fprintf(stderr, " We need a grouping list to "
  464. "set up the print.\n");
  465. return SLURM_ERROR;
  466. }
  467. if(!grouping_print_fields_list)
  468. grouping_print_fields_list = list_create(destroy_print_field);
  469. itr = list_iterator_create(grouping_list);
  470. while((object = list_next(itr))) {
  471. field = xmalloc(sizeof(print_field_t));
  472. size = atoi(object);
  473. if(print_job_count)
  474. field->type = PRINT_JOB_COUNT;
  475. else
  476. field->type = PRINT_JOB_SIZE;
  477. if(individual_grouping)
  478. field->name = xstrdup_printf("%u cpus", size);
  479. else
  480. field->name = xstrdup_printf("%u-%u cpus",
  481. last_size, size-1);
  482. if(time_format == SLURMDB_REPORT_TIME_SECS_PER
  483. || time_format == SLURMDB_REPORT_TIME_MINS_PER
  484. || time_format == SLURMDB_REPORT_TIME_HOURS_PER)
  485. field->len = 20;
  486. else
  487. field->len = 13;
  488. if(print_job_count)
  489. field->print_routine = print_fields_uint;
  490. else
  491. field->print_routine = slurmdb_report_print_time;
  492. last_size = size;
  493. last_object = object;
  494. if((tmp_char = strstr(object, "\%"))) {
  495. int newlen = atoi(tmp_char+1);
  496. if(newlen)
  497. field->len = newlen;
  498. }
  499. list_append(grouping_print_fields_list, field);
  500. }
  501. list_iterator_destroy(itr);
  502. if(last_size && !individual_grouping) {
  503. field = xmalloc(sizeof(print_field_t));
  504. if(print_job_count)
  505. field->type = PRINT_JOB_COUNT;
  506. else
  507. field->type = PRINT_JOB_SIZE;
  508. field->name = xstrdup_printf(">= %u cpus", last_size);
  509. if(time_format == SLURMDB_REPORT_TIME_SECS_PER
  510. || time_format == SLURMDB_REPORT_TIME_MINS_PER
  511. || time_format == SLURMDB_REPORT_TIME_HOURS_PER)
  512. field->len = 20;
  513. else
  514. field->len = 13;
  515. if(print_job_count)
  516. field->print_routine = print_fields_uint;
  517. else
  518. field->print_routine = slurmdb_report_print_time;
  519. if((tmp_char = strstr(last_object, "\%"))) {
  520. int newlen = atoi(tmp_char+1);
  521. if(newlen)
  522. field->len = newlen;
  523. }
  524. list_append(grouping_print_fields_list, field);
  525. }
  526. return SLURM_SUCCESS;
  527. }
  528. extern int job_sizes_grouped_by_top_acct(int argc, char *argv[])
  529. {
  530. int rc = SLURM_SUCCESS;
  531. slurmdb_job_cond_t *job_cond = xmalloc(sizeof(slurmdb_job_cond_t));
  532. int i=0;
  533. uint64_t count1, count2;
  534. ListIterator itr = NULL;
  535. ListIterator itr2 = NULL;
  536. ListIterator cluster_itr = NULL;
  537. ListIterator local_itr = NULL;
  538. ListIterator acct_itr = NULL;
  539. slurmdb_report_cluster_grouping_t *cluster_group = NULL;
  540. slurmdb_report_acct_grouping_t *acct_group = NULL;
  541. slurmdb_report_job_grouping_t *job_group = NULL;
  542. print_field_t *field = NULL;
  543. print_field_t total_field;
  544. slurmdb_report_time_format_t temp_format;
  545. List slurmdb_report_cluster_grouping_list = NULL;
  546. List assoc_list = NULL;
  547. List format_list = list_create(slurm_destroy_char);
  548. List grouping_list = list_create(slurm_destroy_char);
  549. List header_list = NULL;
  550. // slurmdb_report_time_format_t temp_time_format = time_format;
  551. print_fields_list = list_create(destroy_print_field);
  552. _set_cond(&i, argc, argv, job_cond, format_list, grouping_list);
  553. if(!list_count(format_list))
  554. slurm_addto_char_list(format_list, "Cl,a");
  555. if(!individual_grouping && !list_count(grouping_list))
  556. slurm_addto_char_list(grouping_list, "50,250,500,1000");
  557. _setup_print_fields_list(format_list);
  558. list_destroy(format_list);
  559. if(!(slurmdb_report_cluster_grouping_list =
  560. slurmdb_report_job_sizes_grouped_by_top_account(db_conn,
  561. job_cond, grouping_list, flat_view))) {
  562. exit_code = 1;
  563. goto end_it;
  564. }
  565. _setup_grouping_print_fields_list(grouping_list);
  566. if(print_fields_have_header) {
  567. char start_char[20];
  568. char end_char[20];
  569. time_t my_start = job_cond->usage_start;
  570. time_t my_end = job_cond->usage_end-1;
  571. slurm_make_time_str(&my_start, start_char, sizeof(start_char));
  572. slurm_make_time_str(&my_end, end_char, sizeof(end_char));
  573. printf("----------------------------------------"
  574. "----------------------------------------\n");
  575. printf("Job Sizes %s - %s (%d secs)\n",
  576. start_char, end_char,
  577. (int)(job_cond->usage_end - job_cond->usage_start));
  578. if(print_job_count)
  579. printf("Units are in number of jobs ran\n");
  580. else
  581. printf("Time reported in %s\n", time_format_string);
  582. printf("----------------------------------------"
  583. "----------------------------------------\n");
  584. }
  585. header_list = list_create(NULL);
  586. list_append_list(header_list, print_fields_list);
  587. list_append_list(header_list, grouping_print_fields_list);
  588. memset(&total_field, 0, sizeof(print_field_t));
  589. total_field.type = PRINT_JOB_SIZE;
  590. total_field.name = xstrdup("% of cluster");
  591. total_field.len = 12;
  592. total_field.print_routine = slurmdb_report_print_time;
  593. list_append(header_list, &total_field);
  594. print_fields_header(header_list);
  595. list_destroy(header_list);
  596. // time_format = SLURMDB_REPORT_TIME_PERCENT;
  597. itr = list_iterator_create(print_fields_list);
  598. itr2 = list_iterator_create(grouping_print_fields_list);
  599. list_sort(slurmdb_report_cluster_grouping_list,
  600. (ListCmpF)_sort_cluster_grouping_dec);
  601. cluster_itr =
  602. list_iterator_create(slurmdb_report_cluster_grouping_list);
  603. while((cluster_group = list_next(cluster_itr))) {
  604. list_sort(cluster_group->acct_list,
  605. (ListCmpF)_sort_acct_grouping_dec);
  606. acct_itr = list_iterator_create(cluster_group->acct_list);
  607. while((acct_group = list_next(acct_itr))) {
  608. while((field = list_next(itr))) {
  609. switch(field->type) {
  610. case PRINT_JOB_CLUSTER:
  611. field->print_routine(
  612. field,
  613. cluster_group->cluster, 0);
  614. break;
  615. case PRINT_JOB_ACCOUNT:
  616. field->print_routine(field,
  617. acct_group->acct,
  618. 0);
  619. break;
  620. default:
  621. field->print_routine(field,
  622. NULL,
  623. 0);
  624. break;
  625. }
  626. }
  627. list_iterator_reset(itr);
  628. local_itr = list_iterator_create(acct_group->groups);
  629. while((job_group = list_next(local_itr))) {
  630. field = list_next(itr2);
  631. switch(field->type) {
  632. case PRINT_JOB_SIZE:
  633. field->print_routine(
  634. field,
  635. job_group->cpu_secs,
  636. acct_group->cpu_secs,
  637. 0);
  638. break;
  639. case PRINT_JOB_COUNT:
  640. field->print_routine(
  641. field,
  642. job_group->count,
  643. 0);
  644. break;
  645. default:
  646. field->print_routine(field,
  647. NULL,
  648. 0);
  649. break;
  650. }
  651. }
  652. list_iterator_reset(itr2);
  653. list_iterator_destroy(local_itr);
  654. temp_format = time_format;
  655. time_format = SLURMDB_REPORT_TIME_PERCENT;
  656. if (!print_job_count) {
  657. count1 = acct_group->cpu_secs;
  658. count2 = cluster_group->cpu_secs;
  659. } else {
  660. count1 = acct_group->count;
  661. count2 = cluster_group->count;
  662. }
  663. total_field.print_routine(&total_field,
  664. count1, count2, 1);
  665. time_format = temp_format;
  666. printf("\n");
  667. }
  668. list_iterator_destroy(acct_itr);
  669. }
  670. list_iterator_destroy(itr);
  671. // time_format = temp_time_format;
  672. end_it:
  673. xfree(total_field.name);
  674. if(print_job_count)
  675. print_job_count = 0;
  676. if(individual_grouping)
  677. individual_grouping = 0;
  678. slurmdb_destroy_job_cond(job_cond);
  679. if(grouping_list) {
  680. list_destroy(grouping_list);
  681. grouping_list = NULL;
  682. }
  683. if(assoc_list) {
  684. list_destroy(assoc_list);
  685. assoc_list = NULL;
  686. }
  687. if(slurmdb_report_cluster_grouping_list) {
  688. list_destroy(slurmdb_report_cluster_grouping_list);
  689. slurmdb_report_cluster_grouping_list = NULL;
  690. }
  691. if(print_fields_list) {
  692. list_destroy(print_fields_list);
  693. print_fields_list = NULL;
  694. }
  695. if(grouping_print_fields_list) {
  696. list_destroy(grouping_print_fields_list);
  697. grouping_print_fields_list = NULL;
  698. }
  699. return rc;
  700. }
  701. extern int job_sizes_grouped_by_wckey(int argc, char *argv[])
  702. {
  703. int rc = SLURM_SUCCESS;
  704. slurmdb_job_cond_t *job_cond = xmalloc(sizeof(slurmdb_job_cond_t));
  705. int i=0;
  706. uint64_t count1, count2;
  707. ListIterator itr = NULL;
  708. ListIterator itr2 = NULL;
  709. ListIterator cluster_itr = NULL;
  710. ListIterator local_itr = NULL;
  711. ListIterator acct_itr = NULL;
  712. slurmdb_report_cluster_grouping_t *cluster_group = NULL;
  713. slurmdb_report_acct_grouping_t *acct_group = NULL;
  714. slurmdb_report_job_grouping_t *job_group = NULL;
  715. print_field_t *field = NULL;
  716. print_field_t total_field;
  717. slurmdb_report_time_format_t temp_format;
  718. List slurmdb_report_cluster_grouping_list = NULL;
  719. List wckey_list = NULL;
  720. List format_list = list_create(slurm_destroy_char);
  721. List grouping_list = list_create(slurm_destroy_char);
  722. List header_list = NULL;
  723. // slurmdb_report_time_format_t temp_time_format = time_format;
  724. print_fields_list = list_create(destroy_print_field);
  725. _set_cond(&i, argc, argv, job_cond, format_list, grouping_list);
  726. if(!list_count(format_list))
  727. slurm_addto_char_list(format_list, "Cl,wc");
  728. if(!individual_grouping && !list_count(grouping_list))
  729. slurm_addto_char_list(grouping_list, "50,250,500,1000");
  730. _setup_print_fields_list(format_list);
  731. list_destroy(format_list);
  732. if(!(slurmdb_report_cluster_grouping_list =
  733. slurmdb_report_job_sizes_grouped_by_wckey(db_conn,
  734. job_cond, grouping_list))) {
  735. exit_code = 1;
  736. goto end_it;
  737. }
  738. _setup_grouping_print_fields_list(grouping_list);
  739. if(print_fields_have_header) {
  740. char start_char[20];
  741. char end_char[20];
  742. time_t my_start = job_cond->usage_start;
  743. time_t my_end = job_cond->usage_end-1;
  744. slurm_make_time_str(&my_start, start_char, sizeof(start_char));
  745. slurm_make_time_str(&my_end, end_char, sizeof(end_char));
  746. printf("----------------------------------------"
  747. "----------------------------------------\n");
  748. printf("Job Sizes by Wckey %s - %s (%d secs)\n",
  749. start_char, end_char,
  750. (int)(job_cond->usage_end - job_cond->usage_start));
  751. if(print_job_count)
  752. printf("Units are in number of jobs ran\n");
  753. else
  754. printf("Time reported in %s\n", time_format_string);
  755. printf("----------------------------------------"
  756. "----------------------------------------\n");
  757. }
  758. header_list = list_create(NULL);
  759. list_append_list(header_list, print_fields_list);
  760. list_append_list(header_list, grouping_print_fields_list);
  761. memset(&total_field, 0, sizeof(print_field_t));
  762. total_field.type = PRINT_JOB_SIZE;
  763. total_field.name = xstrdup("% of cluster");
  764. total_field.len = 12;
  765. total_field.print_routine = slurmdb_report_print_time;
  766. list_append(header_list, &total_field);
  767. print_fields_header(header_list);
  768. list_destroy(header_list);
  769. // time_format = SLURMDB_REPORT_TIME_PERCENT;
  770. itr = list_iterator_create(print_fields_list);
  771. itr2 = list_iterator_create(grouping_print_fields_list);
  772. list_sort(slurmdb_report_cluster_grouping_list,
  773. (ListCmpF)_sort_cluster_grouping_dec);
  774. cluster_itr = list_iterator_create(
  775. slurmdb_report_cluster_grouping_list);
  776. while((cluster_group = list_next(cluster_itr))) {
  777. list_sort(cluster_group->acct_list,
  778. (ListCmpF)_sort_acct_grouping_dec);
  779. acct_itr = list_iterator_create(cluster_group->acct_list);
  780. while((acct_group = list_next(acct_itr))) {
  781. while((field = list_next(itr))) {
  782. switch(field->type) {
  783. case PRINT_JOB_CLUSTER:
  784. field->print_routine(
  785. field,
  786. cluster_group->cluster, 0);
  787. break;
  788. case PRINT_JOB_WCKEY:
  789. field->print_routine(field,
  790. acct_group->acct,
  791. 0);
  792. break;
  793. default:
  794. field->print_routine(field,
  795. NULL,
  796. 0);
  797. break;
  798. }
  799. }
  800. list_iterator_reset(itr);
  801. local_itr = list_iterator_create(acct_group->groups);
  802. while((job_group = list_next(local_itr))) {
  803. field = list_next(itr2);
  804. switch(field->type) {
  805. case PRINT_JOB_SIZE:
  806. field->print_routine(
  807. field,
  808. job_group->cpu_secs,
  809. acct_group->cpu_secs,
  810. 0);
  811. break;
  812. case PRINT_JOB_COUNT:
  813. field->print_routine(
  814. field,
  815. job_group->count,
  816. 0);
  817. break;
  818. default:
  819. field->print_routine(field,
  820. NULL,
  821. 0);
  822. break;
  823. }
  824. }
  825. list_iterator_reset(itr2);
  826. list_iterator_destroy(local_itr);
  827. temp_format = time_format;
  828. time_format = SLURMDB_REPORT_TIME_PERCENT;
  829. if (!print_job_count) {
  830. count1 = acct_group->cpu_secs;
  831. count2 = cluster_group->cpu_secs;
  832. } else {
  833. count1 = acct_group->count;
  834. count2 = cluster_group->count;
  835. }
  836. total_field.print_routine(&total_field,
  837. count1, count2, 1);
  838. time_format = temp_format;
  839. printf("\n");
  840. }
  841. list_iterator_destroy(acct_itr);
  842. }
  843. list_iterator_destroy(itr);
  844. // time_format = temp_time_format;
  845. end_it:
  846. xfree(total_field.name);
  847. if(print_job_count)
  848. print_job_count = 0;
  849. if(individual_grouping)
  850. individual_grouping = 0;
  851. slurmdb_destroy_job_cond(job_cond);
  852. if(grouping_list) {
  853. list_destroy(grouping_list);
  854. grouping_list = NULL;
  855. }
  856. if(wckey_list) {
  857. list_destroy(wckey_list);
  858. wckey_list = NULL;
  859. }
  860. if(slurmdb_report_cluster_grouping_list) {
  861. list_destroy(slurmdb_report_cluster_grouping_list);
  862. slurmdb_report_cluster_grouping_list = NULL;
  863. }
  864. if(print_fields_list) {
  865. list_destroy(print_fields_list);
  866. print_fields_list = NULL;
  867. }
  868. if(grouping_print_fields_list) {
  869. list_destroy(grouping_print_fields_list);
  870. grouping_print_fields_list = NULL;
  871. }
  872. return rc;
  873. }
  874. extern int job_sizes_grouped_by_top_acct_and_wckey(int argc, char *argv[])
  875. {
  876. int rc = SLURM_SUCCESS;
  877. slurmdb_job_cond_t *job_cond = xmalloc(sizeof(slurmdb_job_cond_t));
  878. int i=0;
  879. uint64_t count1, count2;
  880. ListIterator itr = NULL;
  881. ListIterator itr2 = NULL;
  882. ListIterator cluster_itr = NULL;
  883. ListIterator local_itr = NULL;
  884. ListIterator acct_itr = NULL;
  885. slurmdb_report_cluster_grouping_t *cluster_group = NULL;
  886. slurmdb_report_acct_grouping_t *acct_group = NULL;
  887. slurmdb_report_job_grouping_t *job_group = NULL;
  888. print_field_t *field = NULL;
  889. print_field_t total_field;
  890. slurmdb_report_time_format_t temp_format;
  891. List slurmdb_report_cluster_grouping_list = NULL;
  892. List assoc_list = NULL;
  893. List format_list = list_create(slurm_destroy_char);
  894. List grouping_list = list_create(slurm_destroy_char);
  895. List header_list = NULL;
  896. // slurmdb_report_time_format_t temp_time_format = time_format;
  897. print_fields_list = list_create(destroy_print_field);
  898. _set_cond(&i, argc, argv, job_cond, format_list, grouping_list);
  899. if(!list_count(format_list))
  900. slurm_addto_char_list(format_list, "Cl,a%-20");
  901. if(!individual_grouping && !list_count(grouping_list))
  902. slurm_addto_char_list(grouping_list, "50,250,500,1000");
  903. _setup_print_fields_list(format_list);
  904. list_destroy(format_list);
  905. if(!(slurmdb_report_cluster_grouping_list =
  906. slurmdb_report_job_sizes_grouped_by_top_account_then_wckey(
  907. db_conn, job_cond, grouping_list, flat_view))) {
  908. exit_code = 1;
  909. goto end_it;
  910. }
  911. _setup_grouping_print_fields_list(grouping_list);
  912. if(print_fields_have_header) {
  913. char start_char[20];
  914. char end_char[20];
  915. time_t my_start = job_cond->usage_start;
  916. time_t my_end = job_cond->usage_end-1;
  917. slurm_make_time_str(&my_start, start_char, sizeof(start_char));
  918. slurm_make_time_str(&my_end, end_char, sizeof(end_char));
  919. printf("----------------------------------------"
  920. "----------------------------------------\n");
  921. printf("Job Sizes %s - %s (%d secs)\n",
  922. start_char, end_char,
  923. (int)(job_cond->usage_end - job_cond->usage_start));
  924. if(print_job_count)
  925. printf("Units are in number of jobs ran\n");
  926. else
  927. printf("Time reported in %s\n", time_format_string);
  928. printf("----------------------------------------"
  929. "----------------------------------------\n");
  930. }
  931. header_list = list_create(NULL);
  932. list_append_list(header_list, print_fields_list);
  933. list_append_list(header_list, grouping_print_fields_list);
  934. memset(&total_field, 0, sizeof(print_field_t));
  935. total_field.type = PRINT_JOB_SIZE;
  936. total_field.name = xstrdup("% of cluster");
  937. total_field.len = 12;
  938. total_field.print_routine = slurmdb_report_print_time;
  939. list_append(header_list, &total_field);
  940. print_fields_header(header_list);
  941. list_destroy(header_list);
  942. // time_format = SLURMDB_REPORT_TIME_PERCENT;
  943. itr = list_iterator_create(print_fields_list);
  944. itr2 = list_iterator_create(grouping_print_fields_list);
  945. list_sort(slurmdb_report_cluster_grouping_list,
  946. (ListCmpF)_sort_cluster_grouping_dec);
  947. cluster_itr =
  948. list_iterator_create(slurmdb_report_cluster_grouping_list);
  949. while((cluster_group = list_next(cluster_itr))) {
  950. list_sort(cluster_group->acct_list,
  951. (ListCmpF)_sort_acct_grouping_dec);
  952. acct_itr = list_iterator_create(cluster_group->acct_list);
  953. while((acct_group = list_next(acct_itr))) {
  954. while((field = list_next(itr))) {
  955. switch(field->type) {
  956. case PRINT_JOB_CLUSTER:
  957. field->print_routine(
  958. field,
  959. cluster_group->cluster, 0);
  960. break;
  961. case PRINT_JOB_ACCOUNT:
  962. field->print_routine(field,
  963. acct_group->acct,
  964. 0);
  965. break;
  966. default:
  967. field->print_routine(field,
  968. NULL,
  969. 0);
  970. break;
  971. }
  972. }
  973. list_iterator_reset(itr);
  974. local_itr = list_iterator_create(acct_group->groups);
  975. while((job_group = list_next(local_itr))) {
  976. field = list_next(itr2);
  977. switch(field->type) {
  978. case PRINT_JOB_SIZE:
  979. field->print_routine(
  980. field,
  981. job_group->cpu_secs,
  982. acct_group->cpu_secs,
  983. 0);
  984. break;
  985. case PRINT_JOB_COUNT:
  986. field->print_routine(
  987. field,
  988. job_group->count,
  989. 0);
  990. break;
  991. default:
  992. field->print_routine(field,
  993. NULL,
  994. 0);
  995. break;
  996. }
  997. }
  998. list_iterator_reset(itr2);
  999. list_iterator_destroy(local_itr);
  1000. temp_format = time_format;
  1001. time_format = SLURMDB_REPORT_TIME_PERCENT;
  1002. if (!print_job_count) {
  1003. count1 = acct_group->cpu_secs;
  1004. count2 = cluster_group->cpu_secs;
  1005. } else {
  1006. count1 = acct_group->count;
  1007. count2 = cluster_group->count;
  1008. }
  1009. total_field.print_routine(&total_field,
  1010. count1, count2, 1);
  1011. time_format = temp_format;
  1012. printf("\n");
  1013. }
  1014. list_iterator_destroy(acct_itr);
  1015. }
  1016. list_iterator_destroy(itr);
  1017. // time_format = temp_time_format;
  1018. end_it:
  1019. xfree(total_field.name);
  1020. if(print_job_count)
  1021. print_job_count = 0;
  1022. if(individual_grouping)
  1023. individual_grouping = 0;
  1024. slurmdb_destroy_job_cond(job_cond);
  1025. if(grouping_list) {
  1026. list_destroy(grouping_list);
  1027. grouping_list = NULL;
  1028. }
  1029. if(assoc_list) {
  1030. list_destroy(assoc_list);
  1031. assoc_list = NULL;
  1032. }
  1033. if(slurmdb_report_cluster_grouping_list) {
  1034. list_destroy(slurmdb_report_cluster_grouping_list);
  1035. slurmdb_report_cluster_grouping_list = NULL;
  1036. }
  1037. if(print_fields_list) {
  1038. list_destroy(print_fields_list);
  1039. print_fields_list = NULL;
  1040. }
  1041. if(grouping_print_fields_list) {
  1042. list_destroy(grouping_print_fields_list);
  1043. grouping_print_fields_list = NULL;
  1044. }
  1045. return rc;
  1046. }