PageRenderTime 69ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/src/sview/job_info.c

https://github.com/cfenoy/slurm
C | 4370 lines | 3809 code | 406 blank | 155 comment | 672 complexity | 7c6477fd62adad1796e0a4c59e75ae66 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /*****************************************************************************\
  2. * job_info.c - Functions related to job display mode of sview.
  3. *****************************************************************************
  4. * Copyright (C) 2004-2007 The Regents of the University of California.
  5. * Copyright (C) 2008-2011 Lawrence Livermore National Security.
  6. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  7. * Written by Danny Auble <da@llnl.gov>
  8. *
  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. * SLURM is distributed in the hope that it will be useful, but WITHOUT ANY
  21. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  22. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  23. * details.
  24. *
  25. * You should have received a copy of the GNU General Public License along
  26. * with SLURM; if not, write to the Free Software Foundation, Inc.,
  27. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  28. \*****************************************************************************/
  29. #include <fcntl.h>
  30. #include <grp.h>
  31. #include <sys/stat.h>
  32. #include <sys/types.h>
  33. #include "src/common/uid.h"
  34. #include "src/common/node_select.h"
  35. #include "src/sview/sview.h"
  36. #include "src/common/parse_time.h"
  37. #include "src/common/proc_args.h"
  38. #include "src/common/slurm_strcasestr.h"
  39. #define _DEBUG 0
  40. #define MAX_CANCEL_RETRY 10
  41. #define SIZE(a) (sizeof(a)/sizeof(a[0]))
  42. /* We do not read the node table here, but allocated space for up to
  43. * MAX_NODE_SPACE nodes and generate fatal error if we go higher. Increase
  44. * this value if needed */
  45. #ifndef SVIEW_MAX_NODE_SPACE
  46. #define SVIEW_MAX_NODE_SPACE (24 * 1024)
  47. #endif
  48. /* Collection of data for printing reports. Like data is combined here */
  49. typedef struct {
  50. int color_inx;
  51. GtkTreeIter iter_ptr;
  52. bool iter_set;
  53. job_info_t *job_ptr;
  54. int node_cnt;
  55. char *nodes;
  56. int pos;
  57. bool small_block;
  58. List step_list;
  59. } sview_job_info_t;
  60. static List foreach_list = NULL;
  61. static char *stacked_job_list = NULL;
  62. typedef struct {
  63. int job_id;
  64. int state;
  65. int step_id;
  66. } jobs_foreach_t;
  67. typedef struct {
  68. int edit_type;
  69. GtkWidget *entry;
  70. job_desc_msg_t *job_msg;
  71. char *type;
  72. } jobs_foreach_common_t;
  73. enum {
  74. EDIT_SIGNAL = 1,
  75. EDIT_SIGNAL_USER,
  76. EDIT_CANCEL,
  77. EDIT_CANCEL_USER,
  78. EDIT_REQUEUE,
  79. EDIT_SUSPEND,
  80. EDIT_EDIT
  81. };
  82. /* These need to be in alpha order (except POS and CNT) */
  83. enum {
  84. SORTID_POS = POS_LOC,
  85. SORTID_ACCOUNT,
  86. SORTID_ACTION,
  87. SORTID_ALLOC,
  88. SORTID_ALLOC_NODE,
  89. SORTID_ALPS_RESV_ID,
  90. SORTID_BATCH,
  91. SORTID_BATCH_HOST,
  92. SORTID_BLOCK,
  93. SORTID_COLOR,
  94. SORTID_COLOR_INX,
  95. SORTID_COMMAND,
  96. SORTID_COMMENT,
  97. SORTID_CONNECTION,
  98. SORTID_CONTIGUOUS,
  99. /* SORTID_CORES_MAX, */
  100. /* SORTID_CORES_MIN, */
  101. SORTID_CPUS,
  102. SORTID_CPU_MAX,
  103. SORTID_CPU_MIN,
  104. SORTID_CPUS_PER_TASK,
  105. SORTID_DEPENDENCY,
  106. SORTID_DERIVED_EC,
  107. SORTID_EXIT_CODE,
  108. SORTID_FEATURES,
  109. SORTID_GEOMETRY,
  110. SORTID_GRES,
  111. SORTID_GROUP_ID,
  112. SORTID_IMAGE_BLRTS,
  113. #ifdef HAVE_BGL
  114. SORTID_IMAGE_LINUX,
  115. SORTID_IMAGE_MLOADER,
  116. SORTID_IMAGE_RAMDISK,
  117. #else
  118. SORTID_IMAGE_LINUX,
  119. SORTID_IMAGE_RAMDISK,
  120. SORTID_IMAGE_MLOADER,
  121. #endif
  122. SORTID_JOBID,
  123. SORTID_LICENSES,
  124. SORTID_CPU_REQ,
  125. SORTID_MEM_MIN,
  126. SORTID_TMP_DISK,
  127. #ifdef HAVE_BG
  128. SORTID_NODELIST,
  129. SORTID_NODELIST_EXC,
  130. SORTID_NODELIST_REQ,
  131. #endif
  132. SORTID_NAME,
  133. SORTID_NETWORK,
  134. SORTID_NICE,
  135. #ifndef HAVE_BG
  136. SORTID_NODELIST,
  137. SORTID_NODELIST_EXC,
  138. SORTID_NODELIST_REQ,
  139. #endif
  140. SORTID_NODE_INX,
  141. SORTID_NODES,
  142. SORTID_NODES_MAX,
  143. SORTID_NODES_MIN,
  144. /* SORTID_NTASKS_PER_CORE, */
  145. /* SORTID_NTASKS_PER_NODE, */
  146. /* SORTID_NTASKS_PER_SOCKET, */
  147. SORTID_PARTITION,
  148. SORTID_PREEMPT_TIME,
  149. SORTID_PRIORITY,
  150. SORTID_QOS,
  151. SORTID_REASON,
  152. SORTID_REQUEUE,
  153. SORTID_RESV_NAME,
  154. SORTID_RESTARTS,
  155. SORTID_ROTATE,
  156. SORTID_SHARED,
  157. /* SORTID_SOCKETS_MAX, */
  158. /* SORTID_SOCKETS_MIN, */
  159. SORTID_STATE,
  160. SORTID_STATE_NUM,
  161. SORTID_SWITCHES,
  162. SORTID_TASKS,
  163. /* SORTID_THREADS_MAX, */
  164. /* SORTID_THREADS_MIN, */
  165. SORTID_TIME_ELIGIBLE,
  166. SORTID_TIME_END,
  167. SORTID_TIMELIMIT,
  168. SORTID_TIME_RESIZE,
  169. SORTID_TIME_RUNNING,
  170. SORTID_TIME_START,
  171. SORTID_TIME_SUBMIT,
  172. SORTID_TIME_SUSPEND,
  173. SORTID_SMALL_BLOCK,
  174. SORTID_UPDATED,
  175. SORTID_USER_ID,
  176. SORTID_WCKEY,
  177. SORTID_WORKDIR,
  178. SORTID_CNT
  179. };
  180. /* extra field here is for choosing the type of edit you that will
  181. * take place. If you choose EDIT_MODEL (means only display a set of
  182. * known options) create it in function create_model_*.
  183. */
  184. static char *_initial_page_opts = ("JobID,Partition,BG_Block,"
  185. "ALPS_Resv_ID,UserID,Name,"
  186. "State,Time_Running,Node_Count,NodeList");
  187. static display_data_t display_data_job[] = {
  188. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE, refresh_job,
  189. create_model_job, admin_edit_job},
  190. {G_TYPE_INT, SORTID_JOBID, "JobID", FALSE, EDIT_NONE, refresh_job,
  191. create_model_job, admin_edit_job},
  192. {G_TYPE_STRING, SORTID_COLOR, NULL, TRUE, EDIT_COLOR,
  193. refresh_job, create_model_job, admin_edit_job},
  194. {G_TYPE_STRING, SORTID_ACTION, "Action", FALSE,
  195. EDIT_MODEL, refresh_job, create_model_job, admin_edit_job},
  196. {G_TYPE_INT, SORTID_ALLOC, NULL, FALSE, EDIT_NONE, refresh_job,
  197. create_model_job, admin_edit_job},
  198. {G_TYPE_STRING, SORTID_PARTITION, "Partition", FALSE,
  199. EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  200. #ifdef HAVE_BG
  201. {G_TYPE_STRING, SORTID_BLOCK, "BG Block", FALSE, EDIT_NONE, refresh_job,
  202. create_model_job, admin_edit_job},
  203. {G_TYPE_STRING, SORTID_GEOMETRY, "Geometry",
  204. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  205. {G_TYPE_STRING, SORTID_ROTATE, "Rotate",
  206. FALSE, EDIT_MODEL, refresh_job, create_model_job, admin_edit_job},
  207. {G_TYPE_STRING, SORTID_CONNECTION, "Connection",
  208. FALSE, EDIT_MODEL, refresh_job, create_model_job, admin_edit_job},
  209. #ifdef HAVE_BGL
  210. {G_TYPE_STRING, SORTID_IMAGE_BLRTS, "Image Blrts",
  211. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  212. {G_TYPE_STRING, SORTID_IMAGE_LINUX, "Image Linux",
  213. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  214. {G_TYPE_STRING, SORTID_IMAGE_RAMDISK, "Image Ramdisk",
  215. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  216. #else
  217. {G_TYPE_STRING, SORTID_IMAGE_BLRTS, NULL,
  218. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  219. {G_TYPE_STRING, SORTID_IMAGE_LINUX, "Image Cnload",
  220. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  221. {G_TYPE_STRING, SORTID_IMAGE_RAMDISK, "Image Ioload",
  222. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  223. #endif
  224. {G_TYPE_STRING, SORTID_IMAGE_MLOADER, "Image Mloader",
  225. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  226. #else
  227. {G_TYPE_STRING, SORTID_BLOCK, NULL, TRUE, EDIT_NONE, refresh_job,
  228. create_model_job, admin_edit_job},
  229. {G_TYPE_STRING, SORTID_GEOMETRY, NULL,
  230. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  231. {G_TYPE_STRING, SORTID_ROTATE, NULL,
  232. FALSE, EDIT_MODEL, refresh_job, create_model_job, admin_edit_job},
  233. {G_TYPE_STRING, SORTID_CONNECTION, NULL,
  234. FALSE, EDIT_MODEL, refresh_job, create_model_job, admin_edit_job},
  235. {G_TYPE_STRING, SORTID_IMAGE_BLRTS, NULL,
  236. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  237. {G_TYPE_STRING, SORTID_IMAGE_LINUX, NULL,
  238. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  239. {G_TYPE_STRING, SORTID_IMAGE_RAMDISK, NULL,
  240. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  241. {G_TYPE_STRING, SORTID_IMAGE_MLOADER, NULL,
  242. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  243. #endif
  244. #ifdef HAVE_CRAY
  245. {G_TYPE_STRING, SORTID_ALPS_RESV_ID, "ALPS Resv ID", FALSE, EDIT_NONE,
  246. refresh_job, create_model_job, admin_edit_job},
  247. #else
  248. {G_TYPE_STRING, SORTID_ALPS_RESV_ID, NULL, TRUE, EDIT_NONE,
  249. refresh_job, create_model_job, admin_edit_job},
  250. #endif
  251. {G_TYPE_STRING, SORTID_USER_ID, "UserID", FALSE, EDIT_NONE,
  252. refresh_job, create_model_job, admin_edit_job},
  253. {G_TYPE_STRING, SORTID_GROUP_ID, "GroupID", FALSE, EDIT_NONE,
  254. refresh_job, create_model_job, admin_edit_job},
  255. {G_TYPE_STRING, SORTID_WCKEY, "WCKey", FALSE, EDIT_TEXTBOX, refresh_job,
  256. create_model_job, admin_edit_job},
  257. {G_TYPE_STRING, SORTID_NAME, "Name", FALSE, EDIT_TEXTBOX, refresh_job,
  258. create_model_job, admin_edit_job},
  259. {G_TYPE_STRING, SORTID_STATE, "State", FALSE, EDIT_NONE, refresh_job,
  260. create_model_job, admin_edit_job},
  261. {G_TYPE_INT, SORTID_STATE_NUM, NULL, FALSE, EDIT_NONE, refresh_job,
  262. create_model_job, admin_edit_job},
  263. {G_TYPE_STRING, SORTID_PREEMPT_TIME, "Preempt Time", FALSE,
  264. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  265. {G_TYPE_STRING, SORTID_TIME_RESIZE, "Time Resize", FALSE,
  266. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  267. {G_TYPE_STRING, SORTID_TIME_RUNNING, "Time Running", FALSE,
  268. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  269. {G_TYPE_STRING, SORTID_TIME_SUBMIT, "Time Submit", FALSE,
  270. EDIT_NONE, refresh_job,
  271. create_model_job, admin_edit_job},
  272. {G_TYPE_STRING, SORTID_TIME_ELIGIBLE, "Time Eligible", FALSE,
  273. EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  274. {G_TYPE_STRING, SORTID_TIME_START, "Time Start", FALSE,
  275. EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  276. {G_TYPE_STRING, SORTID_TIME_END, "Time End", FALSE,
  277. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  278. {G_TYPE_STRING, SORTID_TIME_SUSPEND, "Time Suspended", FALSE,
  279. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  280. {G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", FALSE,
  281. EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  282. {G_TYPE_STRING, SORTID_NODES, "Node Count", FALSE, EDIT_TEXTBOX,
  283. refresh_job, create_model_job, admin_edit_job},
  284. {G_TYPE_STRING, SORTID_CPUS, "CPU Count",
  285. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  286. #ifdef HAVE_BG
  287. {G_TYPE_STRING, SORTID_NODELIST, "MidplaneList", FALSE, EDIT_NONE,
  288. refresh_job, create_model_job, admin_edit_job},
  289. {G_TYPE_STRING, SORTID_NODELIST_EXC, "MidplaneList Excluded",
  290. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  291. {G_TYPE_STRING, SORTID_NODELIST_REQ, "MidplaneList Requested",
  292. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  293. #else
  294. {G_TYPE_STRING, SORTID_NODELIST, "NodeList", FALSE,
  295. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  296. {G_TYPE_STRING, SORTID_NODELIST_EXC, "NodeList Excluded",
  297. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  298. {G_TYPE_STRING, SORTID_NODELIST_REQ, "NodeList Requested",
  299. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  300. #endif
  301. {G_TYPE_STRING, SORTID_CONTIGUOUS, "Contiguous", FALSE, EDIT_MODEL,
  302. refresh_job, create_model_job, admin_edit_job},
  303. {G_TYPE_STRING, SORTID_REQUEUE, "Requeue", FALSE, EDIT_MODEL,
  304. refresh_job, create_model_job, admin_edit_job},
  305. {G_TYPE_INT, SORTID_RESTARTS, "Restart Count", FALSE, EDIT_NONE,
  306. refresh_job, create_model_job, admin_edit_job},
  307. /* Priority is a string so we can edit using a text box */
  308. {G_TYPE_STRING, SORTID_PRIORITY, "Priority", FALSE,
  309. EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  310. {G_TYPE_STRING, SORTID_DERIVED_EC, "Derived Exit Code", FALSE,
  311. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  312. {G_TYPE_STRING, SORTID_EXIT_CODE, "Exit Code", FALSE,
  313. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  314. {G_TYPE_STRING, SORTID_BATCH, "Batch Flag", FALSE,
  315. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  316. {G_TYPE_STRING, SORTID_BATCH_HOST, "Batch Host", FALSE,
  317. EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  318. {G_TYPE_STRING, SORTID_CPU_MIN, "CPUs Min",
  319. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  320. {G_TYPE_STRING, SORTID_CPU_MAX, "CPUs Max",
  321. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  322. {G_TYPE_STRING, SORTID_TASKS, "Task Count",
  323. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  324. {G_TYPE_STRING, SORTID_SHARED, "Shared", FALSE,
  325. EDIT_MODEL, refresh_job, create_model_job, admin_edit_job},
  326. {G_TYPE_STRING, SORTID_CPUS_PER_TASK, "CPUs per Task",
  327. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  328. {G_TYPE_STRING, SORTID_RESV_NAME, "Reservation Name",
  329. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  330. {G_TYPE_STRING, SORTID_NODES_MIN, "Nodes Min",
  331. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  332. {G_TYPE_STRING, SORTID_NODES_MAX, "Nodes Max",
  333. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  334. {G_TYPE_STRING, SORTID_CPU_REQ, "Min CPUs Per Node",
  335. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  336. {G_TYPE_STRING, SORTID_MEM_MIN, "Min Memory",
  337. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  338. {G_TYPE_STRING, SORTID_TMP_DISK, "Min Tmp Disk Per Node",
  339. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  340. /* Nice is a string so we can edit using a text box */
  341. {G_TYPE_STRING, SORTID_NICE, "Nice", FALSE,
  342. EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  343. {G_TYPE_STRING, SORTID_ACCOUNT, "Account", FALSE,
  344. EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  345. {G_TYPE_STRING, SORTID_QOS, "QOS", FALSE,
  346. EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  347. {G_TYPE_STRING, SORTID_REASON, "Reason Waiting",
  348. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  349. {G_TYPE_STRING, SORTID_SWITCHES, "Switches",
  350. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  351. {G_TYPE_STRING, SORTID_FEATURES, "Features",
  352. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  353. {G_TYPE_STRING, SORTID_GRES, "Gres",
  354. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  355. {G_TYPE_STRING, SORTID_LICENSES, "Licenses",
  356. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  357. {G_TYPE_STRING, SORTID_DEPENDENCY, "Dependency",
  358. FALSE, EDIT_TEXTBOX, refresh_job, create_model_job, admin_edit_job},
  359. {G_TYPE_STRING, SORTID_ALLOC_NODE, "Alloc Node : Sid",
  360. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  361. #ifdef HAVE_AIX
  362. {G_TYPE_STRING, SORTID_NETWORK, "Network",
  363. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  364. #else
  365. {G_TYPE_STRING, SORTID_NETWORK, NULL,
  366. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  367. #endif
  368. {G_TYPE_STRING, SORTID_COMMAND, "Command",
  369. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  370. {G_TYPE_STRING, SORTID_COMMENT, "Comment",
  371. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  372. {G_TYPE_STRING, SORTID_WORKDIR, "Work Dir",
  373. FALSE, EDIT_NONE, refresh_job, create_model_job, admin_edit_job},
  374. {G_TYPE_INT, SORTID_COLOR_INX, NULL, FALSE, EDIT_NONE,
  375. refresh_job, create_model_job, admin_edit_job},
  376. {G_TYPE_POINTER, SORTID_NODE_INX, NULL, FALSE, EDIT_NONE,
  377. refresh_job, create_model_job, admin_edit_job},
  378. {G_TYPE_INT, SORTID_SMALL_BLOCK, NULL, FALSE, EDIT_NONE, refresh_job,
  379. create_model_job, admin_edit_job},
  380. {G_TYPE_INT, SORTID_UPDATED, NULL, FALSE, EDIT_NONE, refresh_job,
  381. create_model_job, admin_edit_job},
  382. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  383. };
  384. static display_data_t create_data_job[] = {
  385. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE,
  386. refresh_job, create_model_job, admin_edit_job},
  387. {G_TYPE_STRING, SORTID_COMMAND, "Script File", FALSE, EDIT_TEXTBOX,
  388. refresh_job, create_model_job, admin_edit_job},
  389. {G_TYPE_STRING, SORTID_TIMELIMIT, "Time Limit", FALSE, EDIT_TEXTBOX,
  390. refresh_job, create_model_job, admin_edit_job},
  391. {G_TYPE_STRING, SORTID_NODES_MIN, "Nodes Min", FALSE, EDIT_TEXTBOX,
  392. refresh_job, create_model_job, admin_edit_job},
  393. {G_TYPE_STRING, SORTID_TASKS, "Task Count", FALSE, EDIT_TEXTBOX,
  394. refresh_job, create_model_job, admin_edit_job},
  395. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  396. };
  397. static display_data_t options_data_job[] = {
  398. {G_TYPE_INT, SORTID_POS, NULL, FALSE, EDIT_NONE},
  399. {G_TYPE_STRING, INFO_PAGE, "Full Info", TRUE, JOB_PAGE},
  400. {G_TYPE_STRING, JOB_PAGE, "Signal", TRUE, ADMIN_PAGE},
  401. {G_TYPE_STRING, JOB_PAGE, "Requeue", TRUE, ADMIN_PAGE},
  402. {G_TYPE_STRING, JOB_PAGE, "Cancel", TRUE, ADMIN_PAGE},
  403. {G_TYPE_STRING, JOB_PAGE, "Suspend/Resume", TRUE, ADMIN_PAGE},
  404. {G_TYPE_STRING, JOB_PAGE, "Edit Job", TRUE, ADMIN_PAGE},
  405. {G_TYPE_STRING, PART_PAGE, "Partition", TRUE, JOB_PAGE},
  406. #ifdef HAVE_BG
  407. {G_TYPE_STRING, BLOCK_PAGE, "Block", TRUE, JOB_PAGE},
  408. {G_TYPE_STRING, NODE_PAGE, "Midplanes", TRUE, JOB_PAGE},
  409. #else
  410. {G_TYPE_STRING, BLOCK_PAGE, NULL, TRUE, JOB_PAGE},
  411. {G_TYPE_STRING, NODE_PAGE, "Nodes", TRUE, JOB_PAGE},
  412. #endif
  413. {G_TYPE_STRING, RESV_PAGE, "Reservation", TRUE, JOB_PAGE},
  414. {G_TYPE_NONE, -1, NULL, FALSE, EDIT_NONE}
  415. };
  416. struct signv {
  417. char *name;
  418. uint16_t val;
  419. } sig_name_num[ ] = {
  420. { "HUP", SIGHUP },
  421. { "INT", SIGINT },
  422. { "QUIT", SIGQUIT },
  423. { "ABRT", SIGABRT },
  424. { "KILL", SIGKILL },
  425. { "ALRM", SIGALRM },
  426. { "TERM", SIGTERM },
  427. { "USR1", SIGUSR1 },
  428. { "USR2", SIGUSR2 },
  429. { "CONT", SIGCONT },
  430. { "STOP", SIGSTOP },
  431. { "TSTP", SIGTSTP },
  432. { "TTIN", SIGTTIN },
  433. { "TTOU", SIGTTOU },
  434. { "SIGHUP", SIGHUP },
  435. { "SIGINT", SIGINT },
  436. { "SIGQUIT", SIGQUIT },
  437. { "SIGABRT", SIGABRT },
  438. { "SIGKILL", SIGKILL },
  439. { "SIGALRM", SIGALRM },
  440. { "SIGTERM", SIGTERM },
  441. { "SIGUSR1", SIGUSR1 },
  442. { "SIGUSR2", SIGUSR2 },
  443. { "SIGCONT", SIGCONT },
  444. { "SIGSTOP", SIGSTOP },
  445. { "SIGTSTP", SIGTSTP },
  446. { "SIGTTIN", SIGTTIN },
  447. { "SIGTTOU", SIGTTOU }
  448. };
  449. static display_data_t *local_display_data = NULL;
  450. static char *got_edit_signal = NULL;
  451. static void _update_info_step(sview_job_info_t *sview_job_info_ptr,
  452. GtkTreeModel *model,
  453. GtkTreeIter *step_iter,
  454. GtkTreeIter *iter);
  455. static char *_read_file(const char *f_name)
  456. {
  457. int fd, f_size, offset = 0;
  458. ssize_t rd_size;
  459. struct stat f_stat;
  460. char *buf;
  461. fd = open(f_name, 0);
  462. if (fd < 0)
  463. return NULL;
  464. if (fstat(fd, &f_stat)) {
  465. close(fd);
  466. return NULL;
  467. }
  468. f_size = f_stat.st_size;
  469. buf = xmalloc(f_size);
  470. while (offset < f_size) {
  471. rd_size = read(fd, buf+offset, f_size-offset);
  472. if (rd_size < 0) {
  473. if ((errno == EAGAIN) || (errno == EINTR))
  474. continue;
  475. xfree(buf);
  476. break;
  477. }
  478. offset += rd_size;
  479. }
  480. close(fd);
  481. return buf;
  482. }
  483. static void _job_info_list_del(void *object)
  484. {
  485. sview_job_info_t *sview_job_info = (sview_job_info_t *)object;
  486. if (sview_job_info) {
  487. xfree(sview_job_info->nodes);
  488. if (sview_job_info->step_list)
  489. list_destroy(sview_job_info->step_list);
  490. xfree(sview_job_info);
  491. }
  492. }
  493. static void _destroy_jobs_foreach(void *object)
  494. {
  495. jobs_foreach_t *jobs_foreach = (jobs_foreach_t *)object;
  496. xfree(jobs_foreach);
  497. }
  498. /* translate name name to number */
  499. static uint16_t _xlate_signal_name(const char *signal_name)
  500. {
  501. uint16_t sig_num = (uint16_t)NO_VAL;
  502. char *end_ptr, *sig_names = NULL;
  503. int i;
  504. sig_num = (uint16_t) strtol(signal_name, &end_ptr, 10);
  505. if ((*end_ptr == '\0') && (sig_num != 0))
  506. return sig_num;
  507. for (i=0; i<SIZE(sig_name_num); i++) {
  508. if (strcasecmp(sig_name_num[i].name, signal_name) == 0) {
  509. xfree(sig_names);
  510. return sig_name_num[i].val;
  511. }
  512. if (i == 0)
  513. sig_names = xstrdup(sig_name_num[i].name);
  514. else {
  515. xstrcat(sig_names, ",");
  516. xstrcat(sig_names, sig_name_num[i].name);
  517. }
  518. }
  519. xfree(sig_names);
  520. return (uint16_t)NO_VAL;
  521. }
  522. static int _cancel_job_id (uint32_t job_id, uint16_t signal)
  523. {
  524. int error_code = SLURM_SUCCESS, i;
  525. char *temp = NULL;
  526. if (signal == (uint16_t)-1)
  527. signal = SIGKILL;
  528. for (i = 0; i < MAX_CANCEL_RETRY; i++) {
  529. /* NOTE: RPC always sent to slurmctld rather than directly
  530. * to slurmd daemons */
  531. error_code = slurm_kill_job(job_id, signal, false);
  532. if (error_code == 0
  533. || (errno != ESLURM_TRANSITION_STATE_NO_UPDATE
  534. && errno != ESLURM_JOB_PENDING))
  535. break;
  536. temp = g_strdup_printf("Sending signal %u to job %u",
  537. signal, job_id);
  538. display_edit_note(temp);
  539. g_free(temp);
  540. sleep ( 5 + i );
  541. }
  542. if (error_code) {
  543. error_code = slurm_get_errno();
  544. if ((error_code != ESLURM_ALREADY_DONE) &&
  545. (error_code != ESLURM_INVALID_JOB_ID)) {
  546. temp = g_strdup_printf(
  547. "Kill job error on job id %u: %s",
  548. job_id, slurm_strerror(slurm_get_errno()));
  549. display_edit_note(temp);
  550. g_free(temp);
  551. } else {
  552. display_edit_note(slurm_strerror(slurm_get_errno()));
  553. }
  554. }
  555. return error_code;
  556. }
  557. static int _cancel_step_id(uint32_t job_id, uint32_t step_id,
  558. uint16_t signal)
  559. {
  560. int error_code = SLURM_SUCCESS, i;
  561. char *temp = NULL;
  562. if (signal == (uint16_t)-1)
  563. signal = SIGKILL;
  564. for (i = 0; i < MAX_CANCEL_RETRY; i++) {
  565. /* NOTE: RPC always sent to slurmctld rather than directly
  566. * to slurmd daemons */
  567. if (signal == SIGKILL) {
  568. error_code = slurm_terminate_job_step(job_id, step_id);
  569. } else {
  570. error_code = slurm_kill_job_step(job_id, step_id,
  571. signal);
  572. }
  573. if (error_code == 0
  574. || (errno != ESLURM_TRANSITION_STATE_NO_UPDATE
  575. && errno != ESLURM_JOB_PENDING))
  576. break;
  577. temp = g_strdup_printf("Sending signal %u to job step %u.%u",
  578. signal, job_id, step_id);
  579. display_edit_note(temp);
  580. g_free(temp);
  581. sleep ( 5 + i );
  582. }
  583. if (error_code) {
  584. error_code = slurm_get_errno();
  585. if (error_code != ESLURM_ALREADY_DONE) {
  586. temp = g_strdup_printf(
  587. "Kill job error on job step id %u.%u: %s",
  588. job_id, step_id,
  589. slurm_strerror(slurm_get_errno()));
  590. display_edit_note(temp);
  591. g_free(temp);
  592. } else {
  593. display_edit_note(slurm_strerror(slurm_get_errno()));
  594. }
  595. }
  596. return error_code;
  597. }
  598. static void _set_active_combo_job(GtkComboBox *combo,
  599. GtkTreeModel *model, GtkTreeIter *iter,
  600. int type)
  601. {
  602. char *temp_char = NULL;
  603. int action = 0;
  604. if (model)
  605. gtk_tree_model_get(model, iter, type, &temp_char, -1);
  606. if (!temp_char)
  607. goto end_it;
  608. switch(type) {
  609. case SORTID_ACTION:
  610. if (!strcasecmp(temp_char, "None"))
  611. action = 0;
  612. else if (!strcasecmp(temp_char, "Cancel"))
  613. action = 1;
  614. else if (!strcasecmp(temp_char, "Suspend"))
  615. action = 2;
  616. else if (!strcasecmp(temp_char, "Resume"))
  617. action = 3;
  618. else if (!strcasecmp(temp_char, "Checkpoint"))
  619. action = 4;
  620. else if (!strcasecmp(temp_char, "Requeue"))
  621. action = 5;
  622. else
  623. action = 0;
  624. break;
  625. case SORTID_SHARED:
  626. case SORTID_CONTIGUOUS:
  627. case SORTID_REQUEUE:
  628. case SORTID_ROTATE:
  629. if (!strcasecmp(temp_char, "yes"))
  630. action = 0;
  631. else if (!strcasecmp(temp_char, "no"))
  632. action = 1;
  633. else
  634. action = 0;
  635. break;
  636. case SORTID_CONNECTION:
  637. if (!strcasecmp(temp_char, "Torus"))
  638. action = 0;
  639. else if (!strcasecmp(temp_char, "Mesh"))
  640. action = 1;
  641. else if (!strcasecmp(temp_char, "NAV"))
  642. action = 2;
  643. else if (!strcasecmp(temp_char, "HTC_S"))
  644. action = 3;
  645. else if (!strcasecmp(temp_char, "HTC_D"))
  646. action = 4;
  647. else if (!strcasecmp(temp_char, "HTC_V"))
  648. action = 5;
  649. else if (!strcasecmp(temp_char, "HTC_L"))
  650. action = 6;
  651. else
  652. action = 0;
  653. break;
  654. default:
  655. break;
  656. }
  657. g_free(temp_char);
  658. end_it:
  659. gtk_combo_box_set_active(combo, action);
  660. }
  661. /* don't free this char */
  662. static const char *_set_job_msg(job_desc_msg_t *job_msg, const char *new_text,
  663. int column)
  664. {
  665. char *type = "";
  666. int temp_int = 0;
  667. char *p;
  668. uint16_t rotate;
  669. uint16_t conn_type[cluster_dims];
  670. char* token, *delimiter = ",x", *next_ptr;
  671. char *sep_char;
  672. int j;
  673. uint16_t geo[cluster_dims];
  674. char* geometry_tmp = xstrdup(new_text);
  675. char* original_ptr = geometry_tmp;
  676. /* need to clear global_edit_error here (just in case) */
  677. global_edit_error = 0;
  678. if (!job_msg)
  679. return NULL;
  680. switch(column) {
  681. case SORTID_ACTION:
  682. xfree(got_edit_signal);
  683. if (!strcasecmp(new_text, "None"))
  684. got_edit_signal = NULL;
  685. else
  686. got_edit_signal = xstrdup(new_text);
  687. break;
  688. case SORTID_TIMELIMIT:
  689. if (!strcasecmp(new_text, "infinite"))
  690. temp_int = INFINITE;
  691. else
  692. temp_int = time_str2mins((char *)new_text);
  693. type = "timelimit";
  694. if (temp_int <= 0 && temp_int != INFINITE)
  695. goto return_error;
  696. job_msg->time_limit = (uint32_t)temp_int;
  697. break;
  698. case SORTID_PRIORITY:
  699. if (!strcasecmp(new_text, "infinite"))
  700. temp_int = INFINITE;
  701. else
  702. temp_int = strtol(new_text, (char **)NULL, 10);
  703. type = "priority";
  704. if ((temp_int < 0) && (temp_int != INFINITE))
  705. goto return_error;
  706. job_msg->priority = (uint32_t)temp_int;
  707. break;
  708. case SORTID_NICE:
  709. temp_int = strtol(new_text, (char **)NULL, 10);
  710. type = "nice";
  711. if (abs(temp_int) > NICE_OFFSET) {
  712. //error("Invalid nice value, must be between "
  713. // "-%d and %d", NICE_OFFSET, NICE_OFFSET);
  714. goto return_error;
  715. }
  716. job_msg->nice = NICE_OFFSET + temp_int;
  717. break;
  718. case SORTID_CPU_REQ:
  719. temp_int = strtol(new_text, &p, 10);
  720. if (*p == 'k' || *p == 'K')
  721. temp_int *= 1024;
  722. else if (*p == 'm' || *p == 'M')
  723. temp_int *= 1048576;
  724. type = "min cpus per node";
  725. if (temp_int <= 0)
  726. goto return_error;
  727. job_msg->pn_min_cpus = (uint32_t)temp_int;
  728. break;
  729. case SORTID_TASKS:
  730. temp_int = strtol(new_text, (char **)NULL, 10);
  731. type = "requested tasks";
  732. if (temp_int <= 0)
  733. goto return_error;
  734. job_msg->num_tasks = (uint32_t)temp_int;
  735. break;
  736. case SORTID_CPUS_PER_TASK:
  737. temp_int = strtol(new_text, (char **)NULL, 10);
  738. type = "cpus per task";
  739. if (temp_int <= 0)
  740. goto return_error;
  741. job_msg->cpus_per_task = (uint32_t)temp_int;
  742. break;
  743. case SORTID_RESV_NAME:
  744. job_msg->reservation = xstrdup(new_text);
  745. type = "reservation name";
  746. break;
  747. case SORTID_NODES_MIN:
  748. temp_int = strtol(new_text, &p, 10);
  749. if (*p == 'k' || *p == 'K')
  750. temp_int *= 1024;
  751. else if (*p == 'm' || *p == 'M')
  752. temp_int *= 1048576;
  753. type = "min nodes";
  754. if (temp_int <= 0)
  755. goto return_error;
  756. job_msg->min_nodes = (uint32_t)temp_int;
  757. break;
  758. case SORTID_NODES:
  759. temp_int = strtol(new_text, &p, 10);
  760. if (*p == 'k' || *p == 'K')
  761. temp_int *= 1024;
  762. else if (*p == 'm' || *p == 'M')
  763. temp_int *= 1048576;
  764. type = "node count";
  765. if (temp_int <= 0)
  766. goto return_error;
  767. job_msg->min_nodes = job_msg->max_nodes = (uint32_t)temp_int;
  768. break;
  769. case SORTID_NODES_MAX:
  770. temp_int = strtol(new_text, &p, 10);
  771. if (*p == 'k' || *p == 'K')
  772. temp_int *= 1024;
  773. else if (*p == 'm' || *p == 'M')
  774. temp_int *= 1048576;
  775. type = "max nodes";
  776. if (temp_int <= 0)
  777. goto return_error;
  778. if (cluster_flags & CLUSTER_FLAG_BG)
  779. /* this needs to be set up for correct functionality */
  780. if (job_msg->min_nodes == NO_VAL)
  781. job_msg->min_nodes = (uint32_t)temp_int;
  782. job_msg->max_nodes = (uint32_t)temp_int;
  783. break;
  784. case SORTID_MEM_MIN:
  785. temp_int = strtol(new_text, &p, 10);
  786. if (*p == 'g' || *p == 'G')
  787. temp_int *= 1024;
  788. else if (*p == 't' || *p == 'T')
  789. temp_int *= 1048576;
  790. p = slurm_strcasestr((char *)new_text, "cpu");
  791. if (p)
  792. type = "min memory per cpu";
  793. else
  794. type = "min memory per node";
  795. if (temp_int <= 0)
  796. goto return_error;
  797. job_msg->pn_min_memory = (uint32_t)temp_int;
  798. if (p)
  799. job_msg->pn_min_memory |= MEM_PER_CPU;
  800. break;
  801. case SORTID_TMP_DISK:
  802. temp_int = strtol(new_text, &p, 10);
  803. if (*p == 'g' || *p == 'G')
  804. temp_int *= 1024;
  805. else if (*p == 't' || *p == 'T')
  806. temp_int *= 1048576;
  807. type = "min tmp disk per node";
  808. if (temp_int <= 0)
  809. goto return_error;
  810. job_msg->pn_min_tmp_disk = (uint32_t)temp_int;
  811. break;
  812. case SORTID_PARTITION:
  813. job_msg->partition = xstrdup(new_text);
  814. type = "partition";
  815. break;
  816. case SORTID_NAME:
  817. job_msg->name = xstrdup(new_text);
  818. type = "name";
  819. break;
  820. case SORTID_WCKEY:
  821. job_msg->wckey = xstrdup(new_text);
  822. type = "wckey";
  823. break;
  824. case SORTID_SHARED:
  825. if (!strcasecmp(new_text, "yes"))
  826. job_msg->shared = 1;
  827. else
  828. job_msg->shared = 0;
  829. type = "shared";
  830. break;
  831. case SORTID_CONTIGUOUS:
  832. if (!strcasecmp(new_text, "yes"))
  833. job_msg->contiguous = 1;
  834. else
  835. job_msg->contiguous = 0;
  836. type = "contiguous";
  837. break;
  838. case SORTID_REQUEUE:
  839. if (!strcasecmp(new_text, "yes"))
  840. job_msg->requeue = 1;
  841. else
  842. job_msg->requeue = 0;
  843. type = "requeue";
  844. break;
  845. case SORTID_NODELIST_REQ:
  846. job_msg->req_nodes = xstrdup(new_text);
  847. type = "requested nodelist";
  848. break;
  849. case SORTID_NODELIST_EXC:
  850. job_msg->exc_nodes = xstrdup(new_text);
  851. type = "excluded nodelist";
  852. break;
  853. case SORTID_FEATURES:
  854. job_msg->features = xstrdup(new_text);
  855. type = "features";
  856. break;
  857. case SORTID_GRES:
  858. job_msg->gres = xstrdup(new_text);
  859. type = "gres";
  860. break;
  861. case SORTID_LICENSES:
  862. job_msg->licenses = xstrdup(new_text);
  863. type = "licenses";
  864. break;
  865. case SORTID_ACCOUNT:
  866. job_msg->account = xstrdup(new_text);
  867. type = "account";
  868. break;
  869. case SORTID_QOS:
  870. job_msg->qos = xstrdup(new_text);
  871. type = "qos";
  872. break;
  873. case SORTID_COMMAND:
  874. type = "script_file";
  875. xfree(job_msg->script);
  876. job_msg->script = _read_file(new_text);
  877. if (job_msg->script == NULL)
  878. goto return_error;
  879. if (job_msg->argc) {
  880. for (j = 0; j < job_msg->argc; j++)
  881. xfree(job_msg->argv[j]);
  882. }
  883. xfree(job_msg->argv);
  884. xfree(job_msg->name);
  885. job_msg->argc = 1;
  886. job_msg->argv = xmalloc(sizeof(char *) * job_msg->argc);
  887. if (new_text[0] == '/') {
  888. job_msg->argv[0] = xstrdup(new_text);
  889. token = strrchr(new_text, (int) '/');
  890. if (token)
  891. job_msg->name = xstrdup(token + 1);
  892. } else {
  893. job_msg->argv[0] = xmalloc(1024);
  894. if (!getcwd(job_msg->argv[0], 1024))
  895. goto return_error;
  896. xstrcat(job_msg->argv[0], "/");
  897. xstrcat(job_msg->argv[0], new_text);
  898. job_msg->name = xstrdup(new_text);
  899. }
  900. break;
  901. case SORTID_DEPENDENCY:
  902. job_msg->dependency = xstrdup(new_text);
  903. type = "dependency";
  904. break;
  905. case SORTID_GEOMETRY:
  906. type = "geometry";
  907. token = strtok_r(geometry_tmp, delimiter, &next_ptr);
  908. for (j=0; j<cluster_dims; j++)
  909. geo[j] = (uint16_t) NO_VAL;
  910. for (j=0; j<cluster_dims; j++) {
  911. if (!token) {
  912. //error("insufficient dimensions in "
  913. // "Geometry");
  914. goto return_error;
  915. }
  916. geo[j] = (uint16_t) atoi(token);
  917. if (geo[j] <= 0) {
  918. //error("invalid --geometry argument");
  919. goto return_error;
  920. break;
  921. }
  922. geometry_tmp = next_ptr;
  923. token = strtok_r(geometry_tmp, delimiter,
  924. &next_ptr);
  925. }
  926. if (token) {
  927. //error("too many dimensions in Geometry");
  928. goto return_error;
  929. }
  930. if (!job_msg->select_jobinfo)
  931. job_msg->select_jobinfo
  932. = select_g_select_jobinfo_alloc();
  933. select_g_select_jobinfo_set(job_msg->select_jobinfo,
  934. SELECT_JOBDATA_GEOMETRY,
  935. (void *) &geo);
  936. break;
  937. case SORTID_ROTATE:
  938. type = "rotate";
  939. if (!strcasecmp(new_text, "yes")) {
  940. rotate = 1;
  941. } else {
  942. rotate = 0;
  943. }
  944. if (!job_msg->select_jobinfo)
  945. job_msg->select_jobinfo
  946. = select_g_select_jobinfo_alloc();
  947. select_g_select_jobinfo_set(job_msg->select_jobinfo,
  948. SELECT_JOBDATA_ROTATE,
  949. (void *) &rotate);
  950. break;
  951. case SORTID_CONNECTION:
  952. verify_conn_type(new_text, conn_type);
  953. type = "connection";
  954. if (!job_msg->select_jobinfo)
  955. job_msg->select_jobinfo
  956. = select_g_select_jobinfo_alloc();
  957. select_g_select_jobinfo_set(job_msg->select_jobinfo,
  958. SELECT_JOBDATA_CONN_TYPE,
  959. (void *) &conn_type);
  960. break;
  961. case SORTID_IMAGE_BLRTS:
  962. type = "BlrtsImage";
  963. if (!job_msg->select_jobinfo)
  964. job_msg->select_jobinfo
  965. = select_g_select_jobinfo_alloc();
  966. select_g_select_jobinfo_set(job_msg->select_jobinfo,
  967. SELECT_JOBDATA_BLRTS_IMAGE,
  968. (void *) new_text);
  969. break;
  970. case SORTID_IMAGE_LINUX:
  971. if (cluster_flags & CLUSTER_FLAG_BGL)
  972. type = "LinuxImage";
  973. else
  974. type = "CnloadImage";
  975. if (!job_msg->select_jobinfo)
  976. job_msg->select_jobinfo
  977. = select_g_select_jobinfo_alloc();
  978. select_g_select_jobinfo_set(job_msg->select_jobinfo,
  979. SELECT_JOBDATA_LINUX_IMAGE,
  980. (void *) new_text);
  981. break;
  982. case SORTID_IMAGE_MLOADER:
  983. type = "MloaderImage";
  984. if (!job_msg->select_jobinfo)
  985. job_msg->select_jobinfo
  986. = select_g_select_jobinfo_alloc();
  987. select_g_select_jobinfo_set(job_msg->select_jobinfo,
  988. SELECT_JOBDATA_MLOADER_IMAGE,
  989. (void *) new_text);
  990. break;
  991. case SORTID_IMAGE_RAMDISK:
  992. if (cluster_flags & CLUSTER_FLAG_BGL)
  993. type = "RamdiskImage";
  994. else
  995. type = "IoloadImage";
  996. if (!job_msg->select_jobinfo)
  997. job_msg->select_jobinfo
  998. = select_g_select_jobinfo_alloc();
  999. select_g_select_jobinfo_set(job_msg->select_jobinfo,
  1000. SELECT_JOBDATA_RAMDISK_IMAGE,
  1001. (void *) new_text);
  1002. break;
  1003. case SORTID_TIME_ELIGIBLE:
  1004. case SORTID_TIME_START:
  1005. type = "start time";
  1006. job_msg->begin_time = parse_time((char *)new_text, 0);
  1007. if (!job_msg->begin_time)
  1008. goto return_error;
  1009. if (job_msg->begin_time < time(NULL))
  1010. job_msg->begin_time = time(NULL);
  1011. break;
  1012. case SORTID_SWITCHES:
  1013. type = "switches";
  1014. job_msg->req_switch =
  1015. (uint32_t) strtol(new_text, &sep_char, 10);
  1016. if (sep_char && sep_char[0] == '@') {
  1017. job_msg->wait4switch = time_str2mins(sep_char+1) * 60;
  1018. }
  1019. break;
  1020. default:
  1021. type = "unknown";
  1022. break;
  1023. }
  1024. if (strcmp(type, "unknown"))
  1025. global_send_update_msg = 1;
  1026. xfree(original_ptr);
  1027. return type;
  1028. return_error:
  1029. xfree(original_ptr);
  1030. global_edit_error = 1;
  1031. return type;
  1032. }
  1033. static void _admin_edit_combo_box_job(GtkComboBox *combo,
  1034. job_desc_msg_t *job_msg)
  1035. {
  1036. GtkTreeModel *model = NULL;
  1037. GtkTreeIter iter;
  1038. int column = 0;
  1039. char *name = NULL;
  1040. if (!job_msg)
  1041. return;
  1042. if (!gtk_combo_box_get_active_iter(combo, &iter)) {
  1043. g_print("nothing selected\n");
  1044. return;
  1045. }
  1046. model = gtk_combo_box_get_model(combo);
  1047. if (!model) {
  1048. g_print("nothing selected\n");
  1049. return;
  1050. }
  1051. gtk_tree_model_get(model, &iter, 0, &name, -1);
  1052. gtk_tree_model_get(model, &iter, 1, &column, -1);
  1053. _set_job_msg(job_msg, name, column);
  1054. g_free(name);
  1055. }
  1056. static gboolean _admin_focus_out_job(GtkEntry *entry,
  1057. GdkEventFocus *event,
  1058. job_desc_msg_t *job_msg)
  1059. {
  1060. if (global_entry_changed) {
  1061. const char *col_name = NULL;
  1062. int type = gtk_entry_get_max_length(entry);
  1063. const char *name = gtk_entry_get_text(entry);
  1064. type -= DEFAULT_ENTRY_LENGTH;
  1065. col_name = _set_job_msg(job_msg, name, type);
  1066. if (global_edit_error) {
  1067. if (global_edit_error_msg)
  1068. g_free(global_edit_error_msg);
  1069. global_edit_error_msg = g_strdup_printf(
  1070. "Job %d %s can't be set to %s",
  1071. job_msg->job_id,
  1072. col_name,
  1073. name);
  1074. }
  1075. global_entry_changed = 0;
  1076. }
  1077. return false;
  1078. }
  1079. static GtkWidget *_admin_full_edit_job(job_desc_msg_t *job_msg,
  1080. GtkTreeModel *model, GtkTreeIter *iter)
  1081. {
  1082. GtkScrolledWindow *window = create_scrolled_window();
  1083. GtkBin *bin = NULL;
  1084. GtkViewport *view = NULL;
  1085. GtkTable *table = NULL;
  1086. int i = 0, row = 0;
  1087. display_data_t *display_data = display_data_job;
  1088. gtk_scrolled_window_set_policy(window,
  1089. GTK_POLICY_NEVER,
  1090. GTK_POLICY_AUTOMATIC);
  1091. bin = GTK_BIN(&window->container);
  1092. view = GTK_VIEWPORT(bin->child);
  1093. bin = GTK_BIN(&view->bin);
  1094. table = GTK_TABLE(bin->child);
  1095. gtk_table_resize(table, SORTID_CNT, 2);
  1096. gtk_table_set_homogeneous(table, FALSE);
  1097. for(i = 0; i < SORTID_CNT; i++) {
  1098. while (display_data++) {
  1099. if (display_data->id == -1)
  1100. break;
  1101. if (!display_data->name)
  1102. continue;
  1103. if (display_data->id != i)
  1104. continue;
  1105. display_admin_edit(
  1106. table, job_msg, &row, model, iter,
  1107. display_data,
  1108. G_CALLBACK(_admin_edit_combo_box_job),
  1109. G_CALLBACK(_admin_focus_out_job),
  1110. _set_active_combo_job);
  1111. break;
  1112. }
  1113. display_data = display_data_job;
  1114. }
  1115. gtk_table_resize(table, row, 2);
  1116. return GTK_WIDGET(window);
  1117. }
  1118. static int _nodes_in_list(char *node_list)
  1119. {
  1120. hostset_t host_set = hostset_create(node_list);
  1121. int count = hostset_count(host_set);
  1122. hostset_destroy(host_set);
  1123. return count;
  1124. }
  1125. static int _get_node_cnt(job_info_t * job)
  1126. {
  1127. int node_cnt = 0;
  1128. /* For PENDING jobs, return the maximum of the requested nodelist,
  1129. * requested maximum number of nodes, or requested CPUs rounded
  1130. * to nearest node.
  1131. *
  1132. * For COMPLETING jobs, the job->nodes nodelist has already been
  1133. * altered to list only the nodes still in the comp state, and
  1134. * thus we count only those nodes toward the total nodes still
  1135. * allocated to this job.
  1136. */
  1137. if (IS_JOB_PENDING(job)) {
  1138. node_cnt = _nodes_in_list(job->req_nodes);
  1139. node_cnt = MAX(node_cnt, job->num_nodes);
  1140. } else
  1141. node_cnt = _nodes_in_list(job->nodes);
  1142. return node_cnt;
  1143. }
  1144. /* this needs to be freed by xfree() */
  1145. static void _convert_char_to_job_and_step(const char *data,
  1146. int *jobid, int *stepid)
  1147. {
  1148. int i = 0;
  1149. if (!data)
  1150. return;
  1151. *jobid = atoi(data);
  1152. *stepid = NO_VAL;
  1153. while (data[i]) {
  1154. if (data[i] == '.') {
  1155. i++;
  1156. if (data[i])
  1157. *stepid = atoi(&data[i]);
  1158. break;
  1159. }
  1160. i++;
  1161. }
  1162. return;
  1163. }
  1164. static void _layout_job_record(GtkTreeView *treeview,
  1165. sview_job_info_t *sview_job_info_ptr,
  1166. int update)
  1167. {
  1168. char *nodes = NULL, *reason = NULL, *uname = NULL;
  1169. char tmp_char[50];
  1170. char time_buf[32];
  1171. char running_char[50];
  1172. time_t now_time = time(NULL);
  1173. int suspend_secs = 0;
  1174. job_info_t *job_ptr = sview_job_info_ptr->job_ptr;
  1175. struct group *group_info = NULL;
  1176. uint16_t term_sig = 0;
  1177. uint32_t min_mem = 0;
  1178. GtkTreeIter iter;
  1179. GtkTreeStore *treestore =
  1180. GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
  1181. if (!treestore)
  1182. return;
  1183. if (!job_ptr->nodes || !strcasecmp(job_ptr->nodes,"waiting...")) {
  1184. sprintf(running_char,"00:00:00");
  1185. nodes = "waiting...";
  1186. } else {
  1187. if (IS_JOB_SUSPENDED(job_ptr))
  1188. now_time = job_ptr->pre_sus_time;
  1189. else {
  1190. if (!IS_JOB_RUNNING(job_ptr) &&
  1191. (job_ptr->end_time != 0))
  1192. now_time = job_ptr->end_time;
  1193. if (job_ptr->suspend_time) {
  1194. now_time = (time_t)
  1195. (difftime(now_time,
  1196. job_ptr->suspend_time)
  1197. + job_ptr->pre_sus_time);
  1198. } else
  1199. now_time = (time_t)difftime(
  1200. now_time, job_ptr->start_time);
  1201. }
  1202. suspend_secs = (time(NULL) - job_ptr->start_time) - now_time;
  1203. secs2time_str(now_time, running_char, sizeof(running_char));
  1204. nodes = sview_job_info_ptr->nodes;
  1205. }
  1206. add_display_treestore_line(update, treestore, &iter,
  1207. find_col_name(display_data_job,
  1208. SORTID_ACCOUNT),
  1209. job_ptr->account);
  1210. snprintf(tmp_char, sizeof(tmp_char), "%s:%u",
  1211. job_ptr->alloc_node, job_ptr->alloc_sid);
  1212. add_display_treestore_line(update, treestore, &iter,
  1213. find_col_name(display_data_job,
  1214. SORTID_ALLOC_NODE),
  1215. tmp_char);
  1216. if (cluster_flags & CLUSTER_FLAG_CRAYXT)
  1217. add_display_treestore_line(update, treestore, &iter,
  1218. find_col_name(display_data_job,
  1219. SORTID_ALPS_RESV_ID),
  1220. select_g_select_jobinfo_sprint(
  1221. job_ptr->select_jobinfo,
  1222. tmp_char,
  1223. sizeof(tmp_char),
  1224. SELECT_PRINT_DATA));
  1225. if (job_ptr->batch_flag)
  1226. sprintf(tmp_char, "yes");
  1227. else
  1228. sprintf(tmp_char, "no");
  1229. add_display_treestore_line(update, treestore, &iter,
  1230. find_col_name(display_data_job,
  1231. SORTID_BATCH),
  1232. tmp_char);
  1233. add_display_treestore_line(update, treestore, &iter,
  1234. find_col_name(display_data_job,
  1235. SORTID_BATCH_HOST),
  1236. job_ptr->batch_host);
  1237. if (cluster_flags & CLUSTER_FLAG_BG) {
  1238. add_display_treestore_line(update, treestore, &iter,
  1239. find_col_name(display_data_job,
  1240. SORTID_NODELIST),
  1241. nodes);
  1242. add_display_treestore_line(update, treestore, &iter,
  1243. find_col_name(display_data_job,
  1244. SORTID_NODELIST_EXC),
  1245. job_ptr->exc_nodes);
  1246. add_display_treestore_line(update, treestore, &iter,
  1247. find_col_name(display_data_job,
  1248. SORTID_NODELIST_REQ),
  1249. job_ptr->req_nodes);
  1250. add_display_treestore_line(update, treestore, &iter,
  1251. find_col_name(display_data_job,
  1252. SORTID_BLOCK),
  1253. select_g_select_jobinfo_sprint(
  1254. job_ptr->select_jobinfo,
  1255. tmp_char,
  1256. sizeof(tmp_char),
  1257. SELECT_PRINT_BG_ID));
  1258. }
  1259. add_display_treestore_line(update, treestore, &iter,
  1260. find_col_name(display_data_job,
  1261. SORTID_COMMAND),
  1262. job_ptr->command);
  1263. add_display_treestore_line(update, treestore, &iter,
  1264. find_col_name(display_data_job,
  1265. SORTID_COMMENT),
  1266. job_ptr->comment);
  1267. if (cluster_flags & CLUSTER_FLAG_BG)
  1268. add_display_treestore_line(update, treestore, &iter,
  1269. find_col_name(display_data_job,
  1270. SORTID_CONNECTION),
  1271. select_g_select_jobinfo_sprint(
  1272. job_ptr->select_jobinfo,
  1273. tmp_char,
  1274. sizeof(tmp_char),
  1275. SELECT_PRINT_CONNECTION));
  1276. if (job_ptr->contiguous)
  1277. sprintf(tmp_char, "yes");
  1278. else
  1279. sprintf(tmp_char, "no");
  1280. add_display_treestore_line(update, treestore, &iter,
  1281. find_col_name(display_data_job,
  1282. SORTID_CONTIGUOUS),
  1283. tmp_char);
  1284. if (cluster_flags & CLUSTER_FLAG_BG)
  1285. convert_num_unit((float)job_ptr->num_cpus,
  1286. tmp_char, sizeof(tmp_char),
  1287. UNIT_NONE);
  1288. else
  1289. snprintf(tmp_char, sizeof(tmp_char), "%u", job_ptr->num_cpus);
  1290. add_display_treestore_line(update, treestore, &iter,
  1291. find_col_name(display_data_job,
  1292. SORTID_CPUS),
  1293. tmp_char);
  1294. if (cluster_flags & CLUSTER_FLAG_BG)
  1295. convert_num_unit((float)job_ptr->max_cpus,
  1296. tmp_char, sizeof(tmp_char),
  1297. UNIT_NONE);
  1298. else
  1299. snprintf(tmp_char, sizeof(tmp_char), "%u", job_ptr->max_cpus);
  1300. add_display_treestore_line(update, treestore, &iter,
  1301. find_col_name(display_data_job,
  1302. SORTID_CPU_MAX),
  1303. tmp_char);
  1304. if (cluster_flags & CLUSTER_FLAG_BG)
  1305. convert_num_unit((float)job_ptr->num_cpus,
  1306. tmp_char, sizeof(tmp_char),
  1307. UNIT_NONE);
  1308. else
  1309. snprintf(tmp_char, sizeof(tmp_char), "%u", job_ptr->num_cpus);
  1310. add_display_treestore_line(update, treestore, &iter,
  1311. find_col_name(display_data_job,
  1312. SORTID_CPU_MIN),
  1313. tmp_char);
  1314. if (job_ptr->cpus_per_task > 0)
  1315. sprintf(tmp_char, "%u", job_ptr->cpus_per_task);
  1316. else
  1317. sprintf(tmp_char, " ");
  1318. add_display_treestore_line(update, treestore, &iter,
  1319. find_col_name(display_data_job,
  1320. SORTID_CPUS_PER_TASK),
  1321. tmp_char);
  1322. add_display_treestore_line(update, treestore, &iter,
  1323. find_col_name(display_data_job,
  1324. SORTID_DEPENDENCY),
  1325. job_ptr->dependency);
  1326. if (WIFSIGNALED(job_ptr->derived_ec))
  1327. term_sig = WTERMSIG(job_ptr->derived_ec);
  1328. snprintf(tmp_char, sizeof(tmp_char), "%u:%u",
  1329. WEXITSTATUS(job_ptr->derived_ec), term_sig);
  1330. add_display_treestore_line(update, treestore, &iter,
  1331. find_col_name(display_data_job,
  1332. SORTID_DERIVED_EC),
  1333. tmp_char);
  1334. if (WIFSIGNALED(job_ptr->exit_code))
  1335. term_sig = WTERMSIG(job_ptr->exit_code);
  1336. else
  1337. term_sig = 0;
  1338. snprintf(tmp_char, sizeof(tmp_char), "%u:%u",
  1339. WEXITSTATUS(job_ptr->exit_code), term_sig);
  1340. add_display_treestore_line(update, treestore, &iter,
  1341. find_col_name(display_data_job,
  1342. SORTID_EXIT_CODE),
  1343. tmp_char);
  1344. add_display_treestore_line(update, treestore, &iter,
  1345. find_col_name(display_data_job,
  1346. SORTID_FEATURES),
  1347. job_ptr->features);
  1348. add_display_treestore_line(update, treestore, &iter,
  1349. find_col_name(display_data_job,
  1350. SORTID_GRES),
  1351. job_ptr->gres);
  1352. if (cluster_flags & CLUSTER_FLAG_BG)
  1353. add_display_treestore_line(update, treestore, &iter,
  1354. find_col_name(display_data_job,
  1355. SORTID_GEOMETRY),
  1356. select_g_select_jobinfo_sprint(
  1357. job_ptr->select_jobinfo,
  1358. tmp_char,
  1359. sizeof(tmp_char),
  1360. SELECT_PRINT_GEOMETRY));
  1361. group_info = getgrgid((gid_t)job_ptr->group_id);
  1362. if (group_info && group_info->gr_name[0])
  1363. snprintf(tmp_char, sizeof(tmp_char), "%s", group_info->gr_name);
  1364. else
  1365. snprintf(tmp_char, sizeof(tmp_char), "%u", job_ptr->group_id);
  1366. add_display_treestore_line(update, treestore, &iter,
  1367. find_col_name(display_data_job,
  1368. SORTID_GROUP_ID),
  1369. tmp_char);
  1370. if (cluster_flags & CLUSTER_FLAG_BG) {
  1371. if (cluster_flags & CLUSTER_FLAG_BGL)
  1372. add_display_treestore_line(
  1373. update, treestore, &iter,
  1374. find_col_name(display_data_job,
  1375. SORTID_IMAGE_BLRTS),
  1376. select_g_select_jobinfo_sprint(
  1377. job_ptr->select_jobinfo,
  1378. tmp_char,
  1379. sizeof(tmp_char),
  1380. SELECT_PRINT_BLRTS_IMAGE));
  1381. add_display_treestore_line(update, treestore, &iter,
  1382. find_col_name(display_data_job,
  1383. SORTID_IMAGE_LINUX),
  1384. select_g_select_jobinfo_sprint(
  1385. job_ptr->select_jobinfo,
  1386. tmp_char,
  1387. sizeof(tmp_char),
  1388. SELECT_PRINT_LINUX_IMAGE));
  1389. add_display_treestore_line(update, treestore, &iter,
  1390. find_col_name(display_data_job,
  1391. SORTID_IMAGE_MLOADER),
  1392. select_g_select_jobinfo_sprint(
  1393. job_ptr->select_jobinfo,
  1394. tmp_char,
  1395. sizeof(tmp_char),
  1396. SELECT_PRINT_MLOADER_IMAGE));
  1397. add_display_treestore_line(update, treestore, &iter,
  1398. find_col_name(display_data_job,
  1399. SORTID_IMAGE_RAMDISK),
  1400. select_g_select_jobinfo_sprint(
  1401. job_ptr->select_jobinfo,
  1402. tmp_char,
  1403. sizeof(tmp_char),
  1404. SELECT_PRINT_RAMDISK_IMAGE));
  1405. }
  1406. snprintf(tmp_char, sizeof(tmp_char), "%u", job_ptr->job_id);
  1407. add_display_treestore_line(update, treestore, &iter,
  1408. find_col_name(display_data_job,
  1409. SORTID_JOBID),
  1410. tmp_char);
  1411. add_display_treestore_line(update, treestore, &iter,
  1412. find_col_name(display_data_job,
  1413. SORTID_LICENSES),
  1414. job_ptr->licenses);
  1415. convert_num_unit((float)job_ptr->pn_min_cpus,
  1416. tmp_char, sizeof(tmp_char), UNIT_NONE);
  1417. add_display_treestore_line(update, treestore, &iter,
  1418. find_col_name(display_data_job,
  1419. SORTID_CPU_REQ),
  1420. tmp_char);
  1421. min_mem = job_ptr->pn_min_memory;
  1422. if (min_mem & MEM_PER_CPU)
  1423. min_mem &= (~MEM_PER_CPU);
  1424. if (min_mem > 0) {
  1425. int len;
  1426. convert_num_unit((float)min_mem,
  1427. tmp_char, sizeof(tmp_char), UNIT_MEGA);
  1428. len = strlen(tmp_char);
  1429. if (job_ptr->pn_min_memory & MEM_PER_CPU)
  1430. sprintf(tmp_char+len, " Per CPU");
  1431. else
  1432. sprintf(tmp_char+len, " Per Node");
  1433. } else
  1434. sprintf(tmp_char, " ");
  1435. add_display_treestore_line(update, treestore, &iter,
  1436. find_col_name(display_data_job,
  1437. SORTID_MEM_MIN),
  1438. tmp_char);
  1439. if (job_ptr->pn_min_tmp_disk > 0)
  1440. convert_num_unit((float)job_ptr->pn_min_tmp_disk,
  1441. tmp_char, sizeof(tmp_char), UNIT_MEGA);
  1442. else
  1443. sprintf(tmp_char, " ");
  1444. add_display_treestore_line(update, treestore, &iter,
  1445. find_col_name(display_data_job,
  1446. SORTID_TMP_DISK),
  1447. tmp_char);
  1448. add_display_treestore_line(update, treestore, &iter,
  1449. find_col_name(display_data_job,
  1450. SORTID_NAME),
  1451. job_ptr->name);
  1452. if (cluster_flags & CLUSTER_FLAG_AIX)
  1453. add_display_treestore_line(update, treestore, &iter,
  1454. find_col_name(display_data_job,
  1455. SORTID_NETWORK),
  1456. job_ptr->network);
  1457. if (job_ptr->nice > 0)
  1458. sprintf(tmp_char, "%u", job_ptr->nice - NICE_OFFSET);
  1459. else
  1460. sprintf(tmp_char, " ");
  1461. add_display_treestore_line(update, treestore, &iter,
  1462. find_col_name(display_data_job,
  1463. SORTID_NICE),
  1464. tmp_char);
  1465. if (!(cluster_flags & CLUSTER_FLAG_BG)) {
  1466. add_display_treestore_line(update, treestore, &iter,
  1467. find_col_name(display_data_job,
  1468. SORTID_NODELIST),
  1469. nodes);
  1470. add_display_treestore_line(update, treestore, &iter,
  1471. find_col_name(display_data_job,
  1472. SORTID_NODELIST_EXC),
  1473. job_ptr->exc_nodes);
  1474. add_display_treestore_line(update, treestore, &iter,
  1475. find_col_name(display_data_job,
  1476. SORTID_NODELIST_REQ),
  1477. job_ptr->req_nodes);
  1478. }
  1479. if (cluster_flags & CLUSTER_FLAG_BG)
  1480. convert_num_unit((float)sview_job_info_ptr->node_cnt,
  1481. tmp_char, sizeof(tmp_char), UNIT_NONE);
  1482. else
  1483. snprintf(tmp_char, sizeof(tmp_char), "%u",
  1484. sview_job_info_ptr->node_cnt);
  1485. add_display_treestore_line(update, treestore, &iter,
  1486. find_col_name(display_data_job,
  1487. SORTID_NODES),
  1488. tmp_char);
  1489. if (cluster_flags & CLUSTER_FLAG_BG)
  1490. convert_num_unit((float)sview_job_info_ptr->node_cnt,
  1491. tmp_char, sizeof(tmp_char), UNIT_NONE);
  1492. else
  1493. snprintf(tmp_char, sizeof(tmp_char), "%u",
  1494. job_ptr->max_nodes);
  1495. add_display_treestore_line(update, treestore, &iter,
  1496. find_col_name(display_data_job,
  1497. SORTID_NODES_MAX),
  1498. tmp_char);
  1499. if (cluster_flags & CLUSTER_FLAG_BG)
  1500. convert_num_unit((float)sview_job_info_ptr->node_cnt,
  1501. tmp_char, sizeof(tmp_char), UNIT_NONE);
  1502. else
  1503. snprintf(tmp_char, sizeof(tmp_char), "%u",
  1504. job_ptr->num_nodes);
  1505. add_display_treestore_line(update, treestore, &iter,
  1506. find_col_name(display_data_job,
  1507. SORTID_NODES_MIN),
  1508. tmp_char);
  1509. add_display_treestore_line(update, treestore, &iter,
  1510. find_col_name(display_data_job,
  1511. SORTID_PARTITION),
  1512. job_ptr->partition);
  1513. sprintf(tmp_char, "%u", job_ptr->priority);
  1514. add_display_treestore_line(update, treestore, &iter,
  1515. find_col_name(display_data_job,
  1516. SORTID_PRIORITY),
  1517. tmp_char);
  1518. add_display_treestore_line(update, treestore, &iter,
  1519. find_col_name(display_data_job,
  1520. SORTID_QOS),
  1521. job_ptr->qos);
  1522. if (job_ptr->state_desc)
  1523. reason = job_ptr->state_desc;
  1524. else
  1525. reason = job_reason_string(job_ptr->state_reason);
  1526. add_display_treestore_line(update, treestore, &iter,
  1527. find_col_name(display_data_job,
  1528. SORTID_REASON), reason);
  1529. if (job_ptr->requeue)
  1530. sprintf(tmp_char, "yes");
  1531. else
  1532. sprintf(tmp_char, "no");
  1533. add_display_treestore_line(update, treestore, &iter,
  1534. find_col_name(display_data_job,
  1535. SORTID_REQUEUE),
  1536. tmp_char);
  1537. add_display_treestore_line(update, treestore, &iter,
  1538. find_col_name(display_data_job,
  1539. SORTID_RESV_NAME),
  1540. job_ptr->resv_name);
  1541. snprintf(tmp_char, sizeof(tmp_char), "%u", job_ptr->restart_cnt);
  1542. add_display_treestore_line(update, treestore, &iter,
  1543. find_col_name(display_data_job,
  1544. SORTID_RESTARTS),
  1545. tmp_char);
  1546. if (cluster_flags & CLUSTER_FLAG_BG)
  1547. add_display_treestore_line(update, treestore, &iter,
  1548. find_col_name(display_data_job,
  1549. SORTID_ROTATE),
  1550. select_g_select_jobinfo_sprint(
  1551. job_ptr->select_jobinfo,
  1552. tmp_char,
  1553. sizeof(tmp_char),
  1554. SELECT_PRINT_ROTATE));
  1555. if (job_ptr->shared)
  1556. sprintf(tmp_char, "yes");
  1557. else
  1558. sprintf(tmp_char, "no");
  1559. add_display_treestore_line(update, treestore, &iter,
  1560. find_col_name(display_data_job,
  1561. SORTID_SHARED),
  1562. tmp_char);
  1563. add_display_treestore_line(update, treestore, &iter,
  1564. find_col_name(display_data_job,
  1565. SORTID_STATE),
  1566. job_state_string(job_ptr->job_state));
  1567. slurm_make_time_str((time_t *)&job_ptr->eligible_time, tmp_char,
  1568. sizeof(tmp_char));
  1569. add_display_treestore_line(update, treestore, &iter,
  1570. find_col_name(display_data_job,
  1571. SORTID_TIME_ELIGIBLE),
  1572. tmp_char);
  1573. if ((job_ptr->time_limit == INFINITE) &&
  1574. (job_ptr->end_time > time(NULL)))
  1575. sprintf(tmp_char, "Unknown");
  1576. else
  1577. slurm_make_time_str((time_t *)&job_ptr->end_time, tmp_char,
  1578. sizeof(tmp_char));
  1579. add_display_treestore_line(update, treestore, &iter,
  1580. find_col_name(display_data_job,
  1581. SORTID_TIME_END),
  1582. tmp_char);
  1583. if (job_ptr->time_limit == NO_VAL)
  1584. sprintf(tmp_char, "Partition Limit");
  1585. else if (job_ptr->time_limit == INFINITE)
  1586. sprintf(tmp_char, "Infinite");
  1587. else
  1588. secs2time_str((job_ptr->time_limit * 60),
  1589. tmp_char, sizeof(tmp_char));
  1590. add_display_treestore_line(update, treestore, &iter,
  1591. find_col_name(display_data_job,
  1592. SORTID_TIMELIMIT),
  1593. tmp_char);
  1594. if (job_ptr->preempt_time) {
  1595. slurm_make_time_str((time_t *)&job_ptr->preempt_time, tmp_char,
  1596. sizeof(tmp_char));
  1597. } else
  1598. sprintf(tmp_char, "N/A");
  1599. add_display_treestore_line(update, treestore, &iter,
  1600. find_col_name(display_data_job,
  1601. SORTID_PREEMPT_TIME),
  1602. tmp_char);
  1603. if (job_ptr->resize_time) {
  1604. slurm_make_time_str((time_t *)&job_ptr->resize_time, tmp_char,
  1605. sizeof(tmp_char));
  1606. } else
  1607. sprintf(tmp_char, "N/A");
  1608. add_display_treestore_line(update, treestore, &iter,
  1609. find_col_name(display_data_job,
  1610. SORTID_TIME_RESIZE),
  1611. tmp_char);
  1612. add_display_treestore_line(update, treestore, &iter,
  1613. find_col_name(display_data_job,
  1614. SORTID_TIME_RUNNING),
  1615. running_char);
  1616. slurm_make_time_str((time_t *)&job_ptr->start_time, tmp_char,
  1617. sizeof(tmp_char));
  1618. add_display_treestore_line(update, treestore, &iter,
  1619. find_col_name(display_data_job,
  1620. SORTID_TIME_START),
  1621. tmp_char);
  1622. slurm_make_time_str((time_t *)&job_ptr->submit_time, tmp_char,
  1623. sizeof(tmp_char));
  1624. add_display_treestore_line(update, treestore, &iter,
  1625. find_col_name(display_data_job,
  1626. SORTID_TIME_SUBMIT),
  1627. tmp_char);
  1628. secs2time_str(suspend_secs, tmp_char, sizeof(tmp_char));
  1629. add_display_treestore_line(update, treestore, &iter,
  1630. find_col_name(display_data_job,
  1631. SORTID_TIME_SUSPEND),
  1632. tmp_char);
  1633. secs2time_str((time_t) job_ptr->wait4switch, time_buf,
  1634. sizeof(time_buf));
  1635. snprintf(tmp_char, sizeof(tmp_char), "%u@%s\n",
  1636. job_ptr->req_switch, time_buf);
  1637. add_display_treestore_line(update, treestore, &iter,
  1638. find_col_name(display_data_job,
  1639. SORTID_SWITCHES),
  1640. tmp_char);
  1641. uname = uid_to_string((uid_t)job_ptr->user_id);
  1642. add_display_treestore_line(update, treestore, &iter,
  1643. find_col_name(display_data_job,
  1644. SORTID_USER_ID), uname);
  1645. xfree(uname);
  1646. add_display_treestore_line(update, treestore, &iter,
  1647. find_col_name(display_data_job,
  1648. SORTID_WCKEY),
  1649. job_ptr->wckey);
  1650. add_display_treestore_line(update, treestore, &iter,
  1651. find_col_name(display_data_job,
  1652. SORTID_WORKDIR),
  1653. job_ptr->work_dir);
  1654. }
  1655. static void _update_job_record(sview_job_info_t *sview_job_info_ptr,
  1656. GtkTreeStore *treestore)
  1657. {
  1658. char tmp_time_run[40], tmp_time_resize[40], tmp_time_submit[40];
  1659. char tmp_time_elig[40], tmp_time_start[40], tmp_time_end[40];
  1660. char tmp_time_sus[40], tmp_time_limit[40], tmp_alloc_node[40];
  1661. char tmp_exit[40], tmp_group_id[40], tmp_derived_ec[40];
  1662. char tmp_cpu_cnt[40], tmp_node_cnt[40], tmp_disk[40];
  1663. char tmp_cpus_max[40], tmp_mem_min[40], tmp_cpu_req[40];
  1664. char tmp_nodes_min[40], tmp_nodes_max[40], tmp_cpus_per_task[40];
  1665. char tmp_prio[40], tmp_nice[40], tmp_preempt_time[40];
  1666. char tmp_rqswitch[40];
  1667. char *tmp_batch, *tmp_cont, *tmp_shared, *tmp_requeue, *tmp_uname;
  1668. char *tmp_reason, *tmp_nodes;
  1669. char time_buf[32];
  1670. time_t now_time = time(NULL);
  1671. int suspend_secs = 0;
  1672. GtkTreeIter step_iter;
  1673. job_info_t *job_ptr = sview_job_info_ptr->job_ptr;
  1674. struct group *group_info = NULL;
  1675. uint16_t term_sig = 0;
  1676. uint32_t min_mem = 0;
  1677. snprintf(tmp_alloc_node, sizeof(tmp_alloc_node), "%s:%u",
  1678. job_ptr->alloc_node, job_ptr->alloc_sid);
  1679. if (job_ptr->batch_flag)
  1680. tmp_batch = "yes";
  1681. else
  1682. tmp_batch = "no";
  1683. if (job_ptr->contiguous)
  1684. tmp_cont = "yes";
  1685. else
  1686. tmp_cont = "no";
  1687. if (job_ptr->cpus_per_task > 0)
  1688. sprintf(tmp_cpus_per_task, "%u", job_ptr->cpus_per_task);
  1689. else
  1690. tmp_cpus_per_task[0] = '\0';
  1691. if (cluster_flags & CLUSTER_FLAG_BG) {
  1692. convert_num_unit((float)job_ptr->num_cpus,
  1693. tmp_cpu_cnt, sizeof(tmp_cpu_cnt),
  1694. UNIT_NONE);
  1695. } else {
  1696. snprintf(tmp_cpu_cnt, sizeof(tmp_cpu_cnt), "%u",
  1697. job_ptr->num_cpus);
  1698. }
  1699. convert_num_unit((float)job_ptr->pn_min_cpus,
  1700. tmp_cpu_req, sizeof(tmp_cpu_req), UNIT_NONE);
  1701. if (cluster_flags & CLUSTER_FLAG_BG) {
  1702. convert_num_unit((float)job_ptr->max_cpus,
  1703. tmp_cpus_max, sizeof(tmp_cpus_max),
  1704. UNIT_NONE);
  1705. } else {
  1706. snprintf(tmp_cpus_max, sizeof(tmp_cpus_max), "%u",
  1707. job_ptr->max_cpus);
  1708. }
  1709. convert_num_unit((float)job_ptr->pn_min_tmp_disk,
  1710. tmp_disk, sizeof(tmp_disk), UNIT_MEGA);
  1711. if (WIFSIGNALED(job_ptr->derived_ec))
  1712. term_sig = WTERMSIG(job_ptr->derived_ec);
  1713. snprintf(tmp_derived_ec, sizeof(tmp_derived_ec), "%u:%u",
  1714. WEXITSTATUS(job_ptr->derived_ec), term_sig);
  1715. if (WIFSIGNALED(job_ptr->exit_code))
  1716. term_sig = WTERMSIG(job_ptr->exit_code);
  1717. else
  1718. term_sig = 0;
  1719. snprintf(tmp_exit, sizeof(tmp_exit), "%u:%u",
  1720. WEXITSTATUS(job_ptr->exit_code), term_sig);
  1721. group_info = getgrgid((gid_t) job_ptr->group_id);
  1722. if ( group_info && group_info->gr_name[ 0 ] ) {
  1723. snprintf(tmp_group_id, sizeof(tmp_group_id), "%s",
  1724. group_info->gr_name);
  1725. } else {
  1726. snprintf(tmp_group_id, sizeof(tmp_group_id), "%u",
  1727. job_ptr->group_id);
  1728. }
  1729. min_mem = job_ptr->pn_min_memory;
  1730. if (min_mem & MEM_PER_CPU)
  1731. min_mem &= (~MEM_PER_CPU);
  1732. if (min_mem > 0) {
  1733. int len;
  1734. convert_num_unit((float)min_mem,
  1735. tmp_mem_min, sizeof(tmp_mem_min), UNIT_MEGA);
  1736. len = strlen(tmp_mem_min);
  1737. if (job_ptr->pn_min_memory & MEM_PER_CPU)
  1738. sprintf(tmp_mem_min+len, " Per CPU");
  1739. else
  1740. sprintf(tmp_mem_min+len, " Per Node");
  1741. } else
  1742. sprintf(tmp_mem_min, " ");
  1743. if (cluster_flags & CLUSTER_FLAG_BG)
  1744. convert_num_unit((float)sview_job_info_ptr->node_cnt,
  1745. tmp_node_cnt, sizeof(tmp_node_cnt), UNIT_NONE);
  1746. else
  1747. sprintf(tmp_node_cnt, "%u", sview_job_info_ptr->node_cnt);
  1748. sprintf(tmp_nodes_min, "%u", sview_job_info_ptr->node_cnt);
  1749. if (job_ptr->state_desc)
  1750. tmp_reason = job_ptr->state_desc;
  1751. else
  1752. tmp_reason = job_reason_string(job_ptr->state_reason);
  1753. if (job_ptr->requeue)
  1754. tmp_requeue = "yes";
  1755. else
  1756. tmp_requeue = "no";
  1757. if (job_ptr->shared)
  1758. tmp_shared = "yes";
  1759. else
  1760. tmp_shared = "no";
  1761. sprintf(tmp_nice, "%u", job_ptr->nice - NICE_OFFSET);
  1762. if (!job_ptr->nodes || !strcasecmp(job_ptr->nodes,"waiting...")) {
  1763. sprintf(tmp_time_run,"00:00:00");
  1764. tmp_nodes = "waiting...";
  1765. } else {
  1766. if (IS_JOB_SUSPENDED(job_ptr))
  1767. now_time = job_ptr->pre_sus_time;
  1768. else {
  1769. if (!IS_JOB_RUNNING(job_ptr) &&
  1770. (job_ptr->end_time != 0))
  1771. now_time = job_ptr->end_time;
  1772. if (job_ptr->suspend_time) {
  1773. now_time = (time_t)
  1774. (difftime(now_time,
  1775. job_ptr->suspend_time)
  1776. + job_ptr->pre_sus_time);
  1777. } else
  1778. now_time = (time_t)difftime(
  1779. now_time, job_ptr->start_time);
  1780. }
  1781. suspend_secs = (time(NULL) - job_ptr->start_time) - now_time;
  1782. secs2time_str(now_time, tmp_time_run, sizeof(tmp_time_run));
  1783. tmp_nodes = sview_job_info_ptr->nodes;
  1784. }
  1785. if (job_ptr->max_nodes > 0)
  1786. sprintf(tmp_nodes_max, "%u", sview_job_info_ptr->node_cnt);
  1787. else
  1788. tmp_nodes_max[0] = '\0';
  1789. sprintf(tmp_prio, "%u", job_ptr->priority);
  1790. slurm_make_time_str((time_t *)&job_ptr->eligible_time, tmp_time_elig,
  1791. sizeof(tmp_time_elig));
  1792. if ((job_ptr->time_limit == INFINITE) &&
  1793. (job_ptr->end_time > time(NULL)))
  1794. sprintf(tmp_time_end, "Unknown");
  1795. else
  1796. slurm_make_time_str((time_t *)&job_ptr->end_time, tmp_time_end,
  1797. sizeof(tmp_time_end));
  1798. if (job_ptr->time_limit == NO_VAL)
  1799. sprintf(tmp_time_limit, "Partition Limit");
  1800. else if (job_ptr->time_limit == INFINITE)
  1801. sprintf(tmp_time_limit, "Infinite");
  1802. else
  1803. secs2time_str((job_ptr->time_limit * 60),
  1804. tmp_time_limit, sizeof(tmp_time_limit));
  1805. if (job_ptr->preempt_time) {
  1806. slurm_make_time_str((time_t *)&job_ptr->preempt_time,
  1807. tmp_preempt_time, sizeof(tmp_time_resize));
  1808. } else
  1809. sprintf(tmp_preempt_time, "N/A");
  1810. if (job_ptr->resize_time) {
  1811. slurm_make_time_str((time_t *)&job_ptr->resize_time,
  1812. tmp_time_resize, sizeof(tmp_time_resize));
  1813. } else
  1814. sprintf(tmp_time_resize, "N/A");
  1815. slurm_make_time_str((time_t *)&job_ptr->start_time, tmp_time_start,
  1816. sizeof(tmp_time_start));
  1817. slurm_make_time_str((time_t *)&job_ptr->submit_time, tmp_time_submit,
  1818. sizeof(tmp_time_submit));
  1819. secs2time_str(suspend_secs, tmp_time_sus, sizeof(tmp_time_sus));
  1820. if (job_ptr->req_switch != NO_VAL) {
  1821. if (job_ptr->wait4switch != NO_VAL) {
  1822. secs2time_str((time_t) job_ptr->wait4switch, time_buf,
  1823. sizeof(time_buf));
  1824. sprintf(tmp_rqswitch, "%u@%s",
  1825. job_ptr->req_switch, time_buf);
  1826. } else {
  1827. sprintf(tmp_rqswitch, "%u", job_ptr->req_switch);
  1828. }
  1829. } else {
  1830. sprintf(tmp_rqswitch, "N/A");
  1831. }
  1832. tmp_uname = uid_to_string((uid_t)job_ptr->user_id);
  1833. gtk_tree_store_set(treestore, &sview_job_info_ptr->iter_ptr,
  1834. SORTID_ACCOUNT, job_ptr->account,
  1835. SORTID_ALLOC, 1,
  1836. SORTID_ALLOC_NODE, tmp_alloc_node,
  1837. SORTID_BATCH, tmp_batch,
  1838. SORTID_BATCH_HOST, job_ptr->batch_host,
  1839. SORTID_COLOR,
  1840. sview_colors[sview_job_info_ptr->color_inx],
  1841. SORTID_COLOR_INX, sview_job_info_ptr->color_inx,
  1842. SORTID_COMMAND, job_ptr->command,
  1843. SORTID_COMMENT, job_ptr->comment,
  1844. SORTID_CONTIGUOUS, tmp_cont,
  1845. SORTID_CPUS, tmp_cpu_cnt,
  1846. SORTID_CPU_MAX, tmp_cpus_max,
  1847. SORTID_CPU_MIN, tmp_cpu_cnt,
  1848. SORTID_CPUS_PER_TASK,tmp_cpus_per_task,
  1849. SORTID_CPU_REQ, tmp_cpu_req,
  1850. SORTID_DEPENDENCY, job_ptr->dependency,
  1851. SORTID_DERIVED_EC, tmp_derived_ec,
  1852. SORTID_EXIT_CODE, tmp_exit,
  1853. SORTID_FEATURES, job_ptr->features,
  1854. SORTID_GRES, job_ptr->gres,
  1855. SORTID_GROUP_ID, tmp_group_id,
  1856. SORTID_JOBID, job_ptr->job_id,
  1857. SORTID_LICENSES, job_ptr->licenses,
  1858. SORTID_MEM_MIN, tmp_mem_min,
  1859. SORTID_NAME, job_ptr->name,
  1860. SORTID_NICE, tmp_nice,
  1861. SORTID_NODE_INX, job_ptr->node_inx,
  1862. SORTID_NODELIST, tmp_nodes,
  1863. SORTID_NODELIST_EXC, job_ptr->exc_nodes,
  1864. SORTID_NODELIST_REQ, job_ptr->req_nodes,
  1865. SORTID_NODES, tmp_node_cnt,
  1866. SORTID_NODES_MAX, tmp_nodes_max,
  1867. SORTID_NODES_MIN, tmp_nodes_min,
  1868. SORTID_PARTITION, job_ptr->partition,
  1869. SORTID_PREEMPT_TIME, tmp_preempt_time,
  1870. SORTID_PRIORITY, tmp_prio,
  1871. SORTID_QOS, job_ptr->qos,
  1872. SORTID_REASON, tmp_reason,
  1873. SORTID_REQUEUE, tmp_requeue,
  1874. SORTID_RESTARTS, job_ptr->restart_cnt,
  1875. SORTID_RESV_NAME, job_ptr->resv_name,
  1876. SORTID_SHARED, tmp_shared,
  1877. SORTID_STATE,
  1878. job_state_string(job_ptr->job_state),
  1879. SORTID_STATE_NUM, job_ptr->job_state,
  1880. SORTID_SWITCHES, tmp_rqswitch,
  1881. SORTID_TIME_ELIGIBLE,tmp_time_elig,
  1882. SORTID_TIME_END, tmp_time_end,
  1883. SORTID_TIME_RESIZE, tmp_time_resize,
  1884. SORTID_TIME_RUNNING, tmp_time_run,
  1885. SORTID_TIME_START, tmp_time_start,
  1886. SORTID_TIME_SUBMIT, tmp_time_submit,
  1887. SORTID_TIME_SUSPEND, tmp_time_sus,
  1888. SORTID_TIMELIMIT, tmp_time_limit,
  1889. SORTID_TMP_DISK, tmp_disk,
  1890. SORTID_UPDATED, 1,
  1891. SORTID_USER_ID, tmp_uname,
  1892. SORTID_WCKEY, job_ptr->wckey,
  1893. SORTID_WORKDIR, job_ptr->work_dir,
  1894. -1);
  1895. xfree(tmp_uname);
  1896. if (cluster_flags & CLUSTER_FLAG_AIX) {
  1897. gtk_tree_store_set(treestore, &sview_job_info_ptr->iter_ptr,
  1898. SORTID_NETWORK, job_ptr->network, -1);
  1899. }
  1900. if (cluster_flags & CLUSTER_FLAG_BG) {
  1901. char tmp_block[40], tmp_conn[40], tmp_geo[40], tmp_rotate[40];
  1902. char tmp_linux[40], tmp_ramdisk[40], tmp_mloader[40];
  1903. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1904. tmp_block, sizeof(tmp_block),
  1905. SELECT_PRINT_BG_ID);
  1906. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1907. tmp_conn, sizeof(tmp_conn),
  1908. SELECT_PRINT_CONNECTION);
  1909. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1910. tmp_geo, sizeof(tmp_geo),
  1911. SELECT_PRINT_GEOMETRY);
  1912. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1913. tmp_linux, sizeof(tmp_linux),
  1914. SELECT_PRINT_LINUX_IMAGE);
  1915. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1916. tmp_mloader, sizeof(tmp_mloader),
  1917. SELECT_PRINT_MLOADER_IMAGE);
  1918. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1919. tmp_ramdisk, sizeof(tmp_ramdisk),
  1920. SELECT_PRINT_RAMDISK_IMAGE);
  1921. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1922. tmp_rotate, sizeof(tmp_rotate),
  1923. SELECT_PRINT_ROTATE);
  1924. gtk_tree_store_set(treestore, &sview_job_info_ptr->iter_ptr,
  1925. SORTID_BLOCK, tmp_block,
  1926. SORTID_CONNECTION, tmp_conn,
  1927. SORTID_GEOMETRY, tmp_geo,
  1928. SORTID_IMAGE_LINUX, tmp_linux,
  1929. SORTID_IMAGE_MLOADER, tmp_mloader,
  1930. SORTID_IMAGE_RAMDISK, tmp_ramdisk,
  1931. SORTID_ROTATE, tmp_rotate,
  1932. SORTID_SMALL_BLOCK,
  1933. sview_job_info_ptr->small_block,
  1934. -1);
  1935. }
  1936. if (cluster_flags & CLUSTER_FLAG_BGL) {
  1937. char tmp_blrts[40];
  1938. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1939. tmp_blrts, sizeof(tmp_blrts),
  1940. SELECT_PRINT_BLRTS_IMAGE);
  1941. gtk_tree_store_set(treestore, &sview_job_info_ptr->iter_ptr,
  1942. SORTID_IMAGE_BLRTS, tmp_blrts,
  1943. -1);
  1944. }
  1945. if (cluster_flags & CLUSTER_FLAG_CRAYXT) {
  1946. char tmp_resv_id[40];
  1947. select_g_select_jobinfo_sprint(job_ptr->select_jobinfo,
  1948. tmp_resv_id, sizeof(tmp_resv_id),
  1949. SELECT_PRINT_DATA);
  1950. gtk_tree_store_set(treestore, &sview_job_info_ptr->iter_ptr,
  1951. SORTID_ALPS_RESV_ID, tmp_resv_id,
  1952. -1);
  1953. }
  1954. if (gtk_tree_model_iter_children(GTK_TREE_MODEL(treestore),
  1955. &step_iter,
  1956. &sview_job_info_ptr->iter_ptr))
  1957. _update_info_step(sview_job_info_ptr,
  1958. GTK_TREE_MODEL(treestore), &step_iter,
  1959. &sview_job_info_ptr->iter_ptr);
  1960. else
  1961. _update_info_step(sview_job_info_ptr,
  1962. GTK_TREE_MODEL(treestore), NULL,
  1963. &sview_job_info_ptr->iter_ptr);
  1964. return;
  1965. }
  1966. static void _get_step_nodelist(job_step_info_t *step_ptr, char *buf,
  1967. int buf_size)
  1968. {
  1969. char *ionodes = NULL;
  1970. if (cluster_flags & CLUSTER_FLAG_BG) {
  1971. select_g_select_jobinfo_get(step_ptr->select_jobinfo,
  1972. SELECT_JOBDATA_IONODES,
  1973. &ionodes);
  1974. if (step_ptr->nodes && ionodes) {
  1975. snprintf(buf, buf_size, "%s[%s]", step_ptr->nodes,
  1976. ionodes);
  1977. } else {
  1978. snprintf(buf, buf_size, "%s", step_ptr->nodes);
  1979. }
  1980. xfree(ionodes);
  1981. } else {
  1982. snprintf(buf, buf_size, "%s", step_ptr->nodes);
  1983. }
  1984. }
  1985. static void _layout_step_record(GtkTreeView *treeview,
  1986. job_step_info_t *step_ptr,
  1987. int update)
  1988. {
  1989. char *uname;
  1990. char tmp_char[50], tmp_nodes[50], tmp_time[50];
  1991. time_t now_time = time(NULL);
  1992. GtkTreeIter iter;
  1993. enum job_states state;
  1994. GtkTreeStore *treestore =
  1995. GTK_TREE_STORE(gtk_tree_view_get_model(treeview));
  1996. if (!treestore)
  1997. return;
  1998. convert_num_unit((float)step_ptr->num_cpus, tmp_char, sizeof(tmp_char),
  1999. UNIT_NONE);
  2000. add_display_treestore_line(update, treestore, &iter,
  2001. find_col_name(display_data_job,
  2002. SORTID_CPUS),
  2003. tmp_char);
  2004. uname = uid_to_string((uid_t)step_ptr->user_id);
  2005. add_display_treestore_line(update, treestore, &iter,
  2006. find_col_name(display_data_job,
  2007. SORTID_USER_ID), uname);
  2008. xfree(uname);
  2009. snprintf(tmp_char, sizeof(tmp_char), "%u.%u",
  2010. step_ptr->job_id,
  2011. step_ptr->step_id);
  2012. add_display_treestore_line(update, treestore, &iter,
  2013. find_col_name(display_data_job,
  2014. SORTID_JOBID),
  2015. tmp_char);
  2016. add_display_treestore_line(update, treestore, &iter,
  2017. find_col_name(display_data_job,
  2018. SORTID_GRES),
  2019. step_ptr->gres);
  2020. add_display_treestore_line(update, treestore, &iter,
  2021. find_col_name(display_data_job,
  2022. SORTID_NAME),
  2023. step_ptr->name);
  2024. if (!step_ptr->nodes
  2025. || !strcasecmp(step_ptr->nodes, "waiting...")) {
  2026. sprintf(tmp_time,"00:00:00");
  2027. snprintf(tmp_nodes, sizeof(tmp_nodes), "waiting...");
  2028. state = JOB_PENDING;
  2029. } else {
  2030. now_time -= step_ptr->start_time;
  2031. secs2time_str(now_time, tmp_time, sizeof(tmp_time));
  2032. _get_step_nodelist(step_ptr, tmp_nodes, sizeof(tmp_nodes));
  2033. if (cluster_flags & CLUSTER_FLAG_BGQ)
  2034. convert_num_unit(
  2035. (float)step_ptr->num_tasks,
  2036. tmp_char, sizeof(tmp_char), UNIT_NONE);
  2037. else if (cluster_flags & CLUSTER_FLAG_BG)
  2038. convert_num_unit(
  2039. (float)step_ptr->num_tasks / cpus_per_node,
  2040. tmp_char, sizeof(tmp_char), UNIT_NONE);
  2041. else {
  2042. convert_num_unit((float)_nodes_in_list(tmp_nodes),
  2043. tmp_char, sizeof(tmp_char), UNIT_NONE);
  2044. }
  2045. add_display_treestore_line(update, treestore, &iter,
  2046. find_col_name(display_data_job,
  2047. SORTID_NODES),
  2048. tmp_char);
  2049. state = JOB_RUNNING;
  2050. }
  2051. add_display_treestore_line(update, treestore, &iter,
  2052. find_col_name(display_data_job,
  2053. SORTID_NODELIST),
  2054. tmp_nodes);
  2055. add_display_treestore_line(update, treestore, &iter,
  2056. find_col_name(display_data_job,
  2057. SORTID_PARTITION),
  2058. step_ptr->partition);
  2059. add_display_treestore_line(update, treestore, &iter,
  2060. find_col_name(display_data_job,
  2061. SORTID_STATE),
  2062. job_state_string(state));
  2063. if (step_ptr->time_limit == NO_VAL)
  2064. sprintf(tmp_char, "Partition Limit");
  2065. else if (step_ptr->time_limit == INFINITE)
  2066. sprintf(tmp_char, "Infinite");
  2067. else
  2068. secs2time_str((step_ptr->time_limit * 60),
  2069. tmp_char, sizeof(tmp_char));
  2070. add_display_treestore_line(update, treestore, &iter,
  2071. find_col_name(display_data_job,
  2072. SORTID_TIMELIMIT),
  2073. tmp_char);
  2074. add_display_treestore_line(update, treestore, &iter,
  2075. find_col_name(display_data_job,
  2076. SORTID_TIME_RUNNING),
  2077. tmp_time);
  2078. convert_num_unit((float)step_ptr->num_tasks, tmp_char, sizeof(tmp_char),
  2079. UNIT_NONE);
  2080. add_display_treestore_line(update, treestore, &iter,
  2081. find_col_name(display_data_job,
  2082. SORTID_TASKS),
  2083. tmp_char);
  2084. }
  2085. static void _update_step_record(job_step_info_t *step_ptr,
  2086. GtkTreeStore *treestore,
  2087. GtkTreeIter *iter)
  2088. {
  2089. char *tmp_uname;
  2090. char tmp_nodes[50];
  2091. char tmp_cpu_min[40], tmp_time_run[40], tmp_time_limit[40];
  2092. char tmp_node_cnt[40], tmp_time_start[40], tmp_task_cnt[40];
  2093. time_t now_time = time(NULL);
  2094. enum job_states state;
  2095. int color_inx = step_ptr->step_id % sview_colors_cnt;
  2096. convert_num_unit((float)step_ptr->num_cpus, tmp_cpu_min,
  2097. sizeof(tmp_cpu_min), UNIT_NONE);
  2098. if (!step_ptr->nodes ||
  2099. !strcasecmp(step_ptr->nodes,"waiting...")) {
  2100. sprintf(tmp_time_run, "00:00:00");
  2101. snprintf(tmp_nodes, sizeof(tmp_nodes), "waiting...");
  2102. tmp_node_cnt[0] = '\0';
  2103. state = JOB_PENDING;
  2104. } else {
  2105. now_time -= step_ptr->start_time;
  2106. secs2time_str(now_time, tmp_time_run, sizeof(tmp_time_run));
  2107. _get_step_nodelist(step_ptr, tmp_nodes, sizeof(tmp_nodes));
  2108. if (cluster_flags & CLUSTER_FLAG_BGQ) {
  2109. uint32_t nodes = 0;
  2110. select_g_select_jobinfo_get(step_ptr->select_jobinfo,
  2111. SELECT_JOBDATA_NODE_CNT,
  2112. &nodes);
  2113. convert_num_unit((float)nodes, tmp_node_cnt,
  2114. sizeof(tmp_node_cnt), UNIT_NONE);
  2115. } else if (cluster_flags & CLUSTER_FLAG_BG) {
  2116. convert_num_unit(
  2117. (float)step_ptr->num_tasks / cpus_per_node,
  2118. tmp_node_cnt, sizeof(tmp_node_cnt), UNIT_NONE);
  2119. } else {
  2120. convert_num_unit((float)_nodes_in_list(tmp_nodes),
  2121. tmp_node_cnt, sizeof(tmp_node_cnt),
  2122. UNIT_NONE);
  2123. }
  2124. state = JOB_RUNNING;
  2125. }
  2126. convert_num_unit((float)step_ptr->num_tasks, tmp_task_cnt,
  2127. sizeof(tmp_task_cnt), UNIT_NONE);
  2128. if ((step_ptr->time_limit == NO_VAL) ||
  2129. (step_ptr->time_limit == INFINITE)) {
  2130. sprintf(tmp_time_limit, "Job Limit");
  2131. } else {
  2132. secs2time_str((step_ptr->time_limit * 60),
  2133. tmp_time_limit, sizeof(tmp_time_limit));
  2134. }
  2135. slurm_make_time_str((time_t *)&step_ptr->start_time, tmp_time_start,
  2136. sizeof(tmp_time_start));
  2137. tmp_uname = uid_to_string((uid_t)step_ptr->user_id);
  2138. gtk_tree_store_set(treestore, iter,
  2139. SORTID_ALLOC, 0,
  2140. SORTID_COLOR, sview_colors[color_inx],
  2141. SORTID_COLOR_INX, color_inx,
  2142. SORTID_CPUS, tmp_cpu_min,
  2143. SORTID_GRES, step_ptr->gres,
  2144. SORTID_JOBID, step_ptr->step_id,
  2145. SORTID_NAME, step_ptr->name,
  2146. SORTID_NODE_INX, step_ptr->node_inx,
  2147. SORTID_NODELIST, tmp_nodes,
  2148. SORTID_NODES, tmp_node_cnt,
  2149. SORTID_PARTITION, step_ptr->partition,
  2150. SORTID_STATE, job_state_string(state),
  2151. SORTID_TASKS, tmp_task_cnt,
  2152. SORTID_TIME_RUNNING, tmp_time_run,
  2153. SORTID_TIME_START, tmp_time_start,
  2154. SORTID_TIMELIMIT, tmp_time_limit,
  2155. SORTID_UPDATED, 1,
  2156. SORTID_USER_ID, tmp_uname,
  2157. -1);
  2158. xfree(tmp_uname);
  2159. return;
  2160. }
  2161. static void _append_job_record(sview_job_info_t *sview_job_info_ptr,
  2162. GtkTreeStore *treestore)
  2163. {
  2164. gtk_tree_store_append(treestore, &sview_job_info_ptr->iter_ptr, NULL);
  2165. gtk_tree_store_set(treestore, &sview_job_info_ptr->iter_ptr, SORTID_POS,
  2166. sview_job_info_ptr->pos, -1);
  2167. _update_job_record(sview_job_info_ptr, treestore);
  2168. }
  2169. static void _append_step_record(job_step_info_t *step_ptr,
  2170. GtkTreeStore *treestore, GtkTreeIter *iter,
  2171. int jobid)
  2172. {
  2173. GtkTreeIter step_iter;
  2174. gtk_tree_store_append(treestore, &step_iter, iter);
  2175. gtk_tree_store_set(treestore, &step_iter, SORTID_POS, jobid, -1);
  2176. _update_step_record(step_ptr, treestore, &step_iter);
  2177. }
  2178. static void _update_info_step(sview_job_info_t *sview_job_info_ptr,
  2179. GtkTreeModel *model,
  2180. GtkTreeIter *step_iter,
  2181. GtkTreeIter *iter)
  2182. {
  2183. int stepid = 0;
  2184. int i;
  2185. GtkTreeIter first_step_iter;
  2186. int set = 0;
  2187. ListIterator itr = NULL;
  2188. job_step_info_t *step_ptr = NULL;
  2189. memset(&first_step_iter, 0, sizeof(GtkTreeIter));
  2190. /* make sure all the steps are still here */
  2191. if (step_iter) {
  2192. first_step_iter = *step_iter;
  2193. while (1) {
  2194. gtk_tree_store_set(GTK_TREE_STORE(model), step_iter,
  2195. SORTID_UPDATED, 0, -1);
  2196. if (!gtk_tree_model_iter_next(model, step_iter)) {
  2197. break;
  2198. }
  2199. }
  2200. memcpy(step_iter, &first_step_iter, sizeof(GtkTreeIter));
  2201. set = 1;
  2202. }
  2203. itr = list_iterator_create(sview_job_info_ptr->step_list);
  2204. while ((step_ptr = list_next(itr))) {
  2205. /* get the iter, or find out the list is empty goto add */
  2206. if (!step_iter) {
  2207. goto adding;
  2208. } else {
  2209. memcpy(step_iter, &first_step_iter,
  2210. sizeof(GtkTreeIter));
  2211. }
  2212. while (1) {
  2213. /* search for the jobid and check to see if
  2214. it is in the list */
  2215. gtk_tree_model_get(model, step_iter, SORTID_JOBID,
  2216. &stepid, -1);
  2217. if (stepid == (int)step_ptr->step_id) {
  2218. /* update with new info */
  2219. _update_step_record(step_ptr,
  2220. GTK_TREE_STORE(model),
  2221. step_iter);
  2222. goto found;
  2223. }
  2224. if (!gtk_tree_model_iter_next(model, step_iter)) {
  2225. step_iter = NULL;
  2226. break;
  2227. }
  2228. }
  2229. adding:
  2230. _append_step_record(step_ptr, GTK_TREE_STORE(model),
  2231. iter, sview_job_info_ptr->job_ptr->job_id);
  2232. found:
  2233. ;
  2234. }
  2235. list_iterator_destroy(itr);
  2236. if (set) {
  2237. step_iter = &first_step_iter;
  2238. /* clear all steps that aren't active */
  2239. while (1) {
  2240. gtk_tree_model_get(model, step_iter,
  2241. SORTID_UPDATED, &i, -1);
  2242. if (!i) {
  2243. if (!gtk_tree_store_remove(
  2244. GTK_TREE_STORE(model),
  2245. step_iter))
  2246. break;
  2247. else
  2248. continue;
  2249. }
  2250. if (!gtk_tree_model_iter_next(model, step_iter)) {
  2251. break;
  2252. }
  2253. }
  2254. }
  2255. return;
  2256. }
  2257. static void _update_info_job(List info_list,
  2258. GtkTreeView *tree_view)
  2259. {
  2260. GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  2261. static GtkTreeModel *last_model = NULL;
  2262. int jobid = 0;
  2263. job_info_t *job_ptr = NULL;
  2264. ListIterator itr = NULL;
  2265. sview_job_info_t *sview_job_info = NULL;
  2266. set_for_update(model, SORTID_UPDATED);
  2267. itr = list_iterator_create(info_list);
  2268. while ((sview_job_info = (sview_job_info_t*) list_next(itr))) {
  2269. job_ptr = sview_job_info->job_ptr;
  2270. /* This means the tree_store changed (added new column
  2271. or something). */
  2272. if (last_model != model)
  2273. sview_job_info->iter_set = false;
  2274. if (sview_job_info->iter_set) {
  2275. gtk_tree_model_get(model, &sview_job_info->iter_ptr,
  2276. SORTID_JOBID, &jobid, -1);
  2277. if (jobid != job_ptr->job_id) /* Bad pointer */
  2278. sview_job_info->iter_set = false;
  2279. }
  2280. if (sview_job_info->iter_set)
  2281. _update_job_record(sview_job_info,
  2282. GTK_TREE_STORE(model));
  2283. else {
  2284. GtkTreePath *path = gtk_tree_path_new_first();
  2285. /* get the iter, or find out the list is empty
  2286. * goto add */
  2287. if (gtk_tree_model_get_iter(
  2288. model, &sview_job_info->iter_ptr, path)) {
  2289. do {
  2290. /* search for the jobid and
  2291. check to see if it is in
  2292. the list */
  2293. gtk_tree_model_get(
  2294. model,
  2295. &sview_job_info->iter_ptr,
  2296. SORTID_JOBID,
  2297. &jobid, -1);
  2298. if (jobid == job_ptr->job_id) {
  2299. /* update with new info */
  2300. _update_job_record(
  2301. sview_job_info,
  2302. GTK_TREE_STORE(model));
  2303. sview_job_info->iter_set = 1;
  2304. break;
  2305. }
  2306. } while (gtk_tree_model_iter_next(
  2307. model,
  2308. &sview_job_info->iter_ptr));
  2309. }
  2310. if (!sview_job_info->iter_set) {
  2311. _append_job_record(sview_job_info,
  2312. GTK_TREE_STORE(model));
  2313. sview_job_info->iter_set = true;
  2314. }
  2315. gtk_tree_path_free(path);
  2316. }
  2317. }
  2318. list_iterator_destroy(itr);
  2319. /* remove all old jobs */
  2320. remove_old(model, SORTID_UPDATED);
  2321. last_model = model;
  2322. return;
  2323. }
  2324. static int _sview_job_sort_aval_dec(sview_job_info_t* rec_a,
  2325. sview_job_info_t* rec_b)
  2326. {
  2327. int size_a = rec_a->node_cnt;
  2328. int size_b = rec_b->node_cnt;
  2329. if (size_a < size_b)
  2330. return -1;
  2331. else if (size_a > size_b)
  2332. return 1;
  2333. if (rec_a->nodes && rec_b->nodes) {
  2334. size_a = strcmp(rec_a->nodes, rec_b->nodes);
  2335. if (size_a < 0)
  2336. return -1;
  2337. else if (size_a > 0)
  2338. return 1;
  2339. }
  2340. return 0;
  2341. }
  2342. static List _create_job_info_list(job_info_msg_t *job_info_ptr,
  2343. job_step_info_response_msg_t *step_info_ptr,
  2344. int want_odd_states)
  2345. {
  2346. static List info_list = NULL;
  2347. static List odd_info_list = NULL;
  2348. static job_info_msg_t *last_job_info_ptr = NULL;
  2349. static job_step_info_response_msg_t *last_step_info_ptr = NULL;
  2350. int i = 0, j = 0;
  2351. sview_job_info_t *sview_job_info_ptr = NULL;
  2352. job_info_t *job_ptr = NULL;
  2353. job_step_info_t *step_ptr = NULL;
  2354. char *ionodes = NULL;
  2355. char tmp_char[50];
  2356. if (info_list && (job_info_ptr == last_job_info_ptr)
  2357. && (step_info_ptr == last_step_info_ptr))
  2358. goto update_color;
  2359. last_job_info_ptr = job_info_ptr;
  2360. last_step_info_ptr = step_info_ptr;
  2361. if (info_list) {
  2362. list_flush(info_list);
  2363. list_flush(odd_info_list);
  2364. } else {
  2365. info_list = list_create(NULL);
  2366. odd_info_list = list_create(_job_info_list_del);
  2367. }
  2368. if (!info_list || !odd_info_list) {
  2369. g_print("malloc error\n");
  2370. return NULL;
  2371. }
  2372. for(i=0; i<job_info_ptr->record_count; i++) {
  2373. job_ptr = &(job_info_ptr->job_array[i]);
  2374. sview_job_info_ptr = xmalloc(sizeof(sview_job_info_t));
  2375. sview_job_info_ptr->job_ptr = job_ptr;
  2376. sview_job_info_ptr->step_list = list_create(NULL);
  2377. sview_job_info_ptr->pos = i;
  2378. sview_job_info_ptr->node_cnt = 0;
  2379. sview_job_info_ptr->color_inx =
  2380. job_ptr->job_id % sview_colors_cnt;
  2381. if (cluster_flags & CLUSTER_FLAG_BG) {
  2382. select_g_select_jobinfo_get(job_ptr->select_jobinfo,
  2383. SELECT_JOBDATA_IONODES,
  2384. &ionodes);
  2385. select_g_select_jobinfo_get(
  2386. job_ptr->select_jobinfo,
  2387. SELECT_JOBDATA_NODE_CNT,
  2388. &sview_job_info_ptr->node_cnt);
  2389. if (job_ptr->nodes && ionodes) {
  2390. sview_job_info_ptr->small_block = 1;
  2391. snprintf(tmp_char, sizeof(tmp_char), "%s[%s]",
  2392. job_ptr->nodes, ionodes);
  2393. /* keep a different string here so we don't
  2394. just keep tacking on ionodes to a
  2395. node list */
  2396. sview_job_info_ptr->nodes = xstrdup(tmp_char);
  2397. } else
  2398. sview_job_info_ptr->nodes =
  2399. xstrdup(job_ptr->nodes);
  2400. xfree(ionodes);
  2401. } else
  2402. sview_job_info_ptr->nodes = xstrdup(job_ptr->nodes);
  2403. if (!sview_job_info_ptr->node_cnt)
  2404. sview_job_info_ptr->node_cnt = _get_node_cnt(job_ptr);
  2405. for(j = 0; j < step_info_ptr->job_step_count; j++) {
  2406. step_ptr = &(step_info_ptr->job_steps[j]);
  2407. if (step_ptr->job_id == job_ptr->job_id) {
  2408. list_append(sview_job_info_ptr->step_list,
  2409. step_ptr);
  2410. }
  2411. }
  2412. list_append(odd_info_list, sview_job_info_ptr);
  2413. if (!IS_JOB_PENDING(job_ptr) &&
  2414. !IS_JOB_RUNNING(job_ptr) &&
  2415. !IS_JOB_SUSPENDED(job_ptr) &&
  2416. !IS_JOB_COMPLETING(job_ptr)) {
  2417. continue;
  2418. }
  2419. list_append(info_list, sview_job_info_ptr);
  2420. }
  2421. list_sort(info_list, (ListCmpF)_sview_job_sort_aval_dec);
  2422. list_sort(odd_info_list, (ListCmpF)_sview_job_sort_aval_dec);
  2423. update_color:
  2424. if (want_odd_states)
  2425. return odd_info_list;
  2426. else
  2427. return info_list;
  2428. }
  2429. void _display_info_job(List info_list, popup_info_t *popup_win)
  2430. {
  2431. job_step_info_t *step_ptr;
  2432. specific_info_t *spec_info = popup_win->spec_info;
  2433. ListIterator itr = NULL;
  2434. sview_job_info_t *sview_job_info = NULL;
  2435. int found = 0;
  2436. GtkTreeView *treeview = NULL;
  2437. int update = 0;
  2438. int j, k;
  2439. if (spec_info->search_info->int_data == NO_VAL) {
  2440. /* info = xstrdup("No pointer given!"); */
  2441. goto finished;
  2442. }
  2443. need_refresh:
  2444. if (!spec_info->display_widget) {
  2445. treeview = create_treeview_2cols_attach_to_table(
  2446. popup_win->table);
  2447. spec_info->display_widget =
  2448. gtk_widget_ref(GTK_WIDGET(treeview));
  2449. } else {
  2450. treeview = GTK_TREE_VIEW(spec_info->display_widget);
  2451. update = 1;
  2452. }
  2453. itr = list_iterator_create(info_list);
  2454. while ((sview_job_info = (sview_job_info_t*) list_next(itr))) {
  2455. if (sview_job_info->job_ptr->job_id ==
  2456. spec_info->search_info->int_data)
  2457. break;
  2458. }
  2459. list_iterator_destroy(itr);
  2460. if (!sview_job_info) {
  2461. /* not found */
  2462. } else if (spec_info->search_info->int_data2 == NO_VAL) {
  2463. int top_node_inx = 0;
  2464. int array_size = SVIEW_MAX_NODE_SPACE;
  2465. int *color_inx = xmalloc(sizeof(int) * array_size);
  2466. bool *color_set_flag = xmalloc(sizeof(bool) * array_size);
  2467. j = 0;
  2468. while (sview_job_info->job_ptr->node_inx[j] >= 0) {
  2469. top_node_inx = MAX(top_node_inx,
  2470. sview_job_info->job_ptr->
  2471. node_inx[j+1]);
  2472. if (top_node_inx > SVIEW_MAX_NODE_SPACE)
  2473. fatal("Expand SVIEW_MAX_NODE_SPACE in sview");
  2474. for (k = sview_job_info->job_ptr->node_inx[j];
  2475. k <= sview_job_info->job_ptr->node_inx[j+1];
  2476. k++) {
  2477. color_set_flag[k] = true;
  2478. color_inx[k] = sview_job_info->
  2479. color_inx;
  2480. }
  2481. j += 2;
  2482. }
  2483. change_grid_color_array(popup_win->grid_button_list,
  2484. top_node_inx+1, color_inx,
  2485. color_set_flag, true, 0);
  2486. xfree(color_inx);
  2487. xfree(color_set_flag);
  2488. _layout_job_record(treeview, sview_job_info, update);
  2489. found = 1;
  2490. } else {
  2491. int top_node_inx = 0;
  2492. int array_size = SVIEW_MAX_NODE_SPACE;
  2493. int *color_inx = xmalloc(sizeof(int) * array_size);
  2494. bool *color_set_flag = xmalloc(sizeof(bool) * array_size);
  2495. itr = list_iterator_create(sview_job_info->step_list);
  2496. while ((step_ptr = list_next(itr))) {
  2497. if (step_ptr->step_id ==
  2498. spec_info->search_info->int_data2) {
  2499. j = 0;
  2500. while (step_ptr->node_inx[j] >= 0) {
  2501. top_node_inx = MAX(top_node_inx,
  2502. step_ptr->
  2503. node_inx[j+1]);
  2504. if (top_node_inx > SVIEW_MAX_NODE_SPACE)
  2505. fatal("Expand "
  2506. "SVIEW_MAX_NODE_SPACE "
  2507. "in sview");
  2508. for (k = step_ptr->node_inx[j];
  2509. k <= step_ptr->node_inx[j+1];
  2510. k++) {
  2511. color_set_flag[k] = true;
  2512. color_inx[k] = step_ptr->step_id
  2513. % sview_colors_cnt;
  2514. }
  2515. j += 2;
  2516. }
  2517. change_grid_color_array(
  2518. popup_win->grid_button_list,
  2519. top_node_inx+1, color_inx,
  2520. color_set_flag, false, 0);
  2521. xfree(color_inx);
  2522. xfree(color_set_flag);
  2523. _layout_step_record(treeview,
  2524. step_ptr, update);
  2525. found = 1;
  2526. break;
  2527. }
  2528. }
  2529. list_iterator_destroy(itr);
  2530. }
  2531. post_setup_popup_grid_list(popup_win);
  2532. if (!found) {
  2533. if (!popup_win->not_found) {
  2534. char *temp = "JOB ALREADY FINISHED OR NOT FOUND\n";
  2535. GtkTreeIter iter;
  2536. GtkTreeModel *model = NULL;
  2537. /* only time this will be run so no update */
  2538. model = gtk_tree_view_get_model(treeview);
  2539. add_display_treestore_line(0,
  2540. GTK_TREE_STORE(model),
  2541. &iter,
  2542. temp, "");
  2543. if (spec_info->search_info->int_data2 != NO_VAL)
  2544. add_display_treestore_line(
  2545. 1,
  2546. GTK_TREE_STORE(model),
  2547. &iter,
  2548. find_col_name(display_data_job,
  2549. SORTID_STATE),
  2550. job_state_string(JOB_COMPLETE));
  2551. }
  2552. popup_win->not_found = true;
  2553. } else {
  2554. if (popup_win->not_found) {
  2555. popup_win->not_found = false;
  2556. gtk_widget_destroy(spec_info->display_widget);
  2557. goto need_refresh;
  2558. }
  2559. }
  2560. gtk_widget_show_all(spec_info->display_widget);
  2561. finished:
  2562. return;
  2563. }
  2564. extern GtkWidget *create_job_entry(job_desc_msg_t *job_msg,
  2565. GtkTreeModel *model, GtkTreeIter *iter)
  2566. {
  2567. GtkScrolledWindow *window = create_scrolled_window();
  2568. GtkBin *bin = NULL;
  2569. GtkViewport *view = NULL;
  2570. GtkTable *table = NULL;
  2571. int row = 0;
  2572. display_data_t *display_data = create_data_job;
  2573. gtk_scrolled_window_set_policy(window,
  2574. GTK_POLICY_NEVER,
  2575. GTK_POLICY_AUTOMATIC);
  2576. bin = GTK_BIN(&window->container);
  2577. view = GTK_VIEWPORT(bin->child);
  2578. bin = GTK_BIN(&view->bin);
  2579. table = GTK_TABLE(bin->child);
  2580. gtk_table_resize(table, SORTID_CNT, 2);
  2581. gtk_table_set_homogeneous(table, FALSE);
  2582. /* NOTE: We build this in the order defined in the data structure
  2583. * rather than in SORTID order for more flexibility. */
  2584. while (display_data++) {
  2585. if (display_data->id == -1)
  2586. break;
  2587. if (!display_data->name)
  2588. continue;
  2589. display_admin_edit(table, job_msg, &row, model, iter,
  2590. display_data,
  2591. G_CALLBACK(_admin_edit_combo_box_job),
  2592. G_CALLBACK(_admin_focus_out_job),
  2593. _set_active_combo_job);
  2594. }
  2595. gtk_table_resize(table, row, 2);
  2596. return GTK_WIDGET(window);
  2597. }
  2598. extern void refresh_job(GtkAction *action, gpointer user_data)
  2599. {
  2600. popup_info_t *popup_win = (popup_info_t *)user_data;
  2601. xassert(popup_win);
  2602. xassert(popup_win->spec_info);
  2603. xassert(popup_win->spec_info->title);
  2604. popup_win->force_refresh = 1;
  2605. specific_info_job(popup_win);
  2606. }
  2607. extern int get_new_info_job(job_info_msg_t **info_ptr,
  2608. int force)
  2609. {
  2610. job_info_msg_t *new_job_ptr = NULL;
  2611. uint16_t show_flags = 0;
  2612. int error_code = SLURM_NO_CHANGE_IN_DATA;
  2613. time_t now = time(NULL);
  2614. static time_t last;
  2615. static bool changed = 0;
  2616. static uint16_t last_flags = 0;
  2617. if (g_job_info_ptr && !force
  2618. && ((now - last) < working_sview_config.refresh_delay)) {
  2619. if (*info_ptr != g_job_info_ptr)
  2620. error_code = SLURM_SUCCESS;
  2621. *info_ptr = g_job_info_ptr;
  2622. if (changed)
  2623. error_code = SLURM_SUCCESS;
  2624. goto end_it;
  2625. }
  2626. last = now;
  2627. if (working_sview_config.show_hidden)
  2628. show_flags |= SHOW_ALL;
  2629. if (g_job_info_ptr) {
  2630. if (show_flags != last_flags)
  2631. g_job_info_ptr->last_update = 0;
  2632. error_code = slurm_load_jobs(g_job_info_ptr->last_update,
  2633. &new_job_ptr, show_flags);
  2634. if (error_code == SLURM_SUCCESS) {
  2635. slurm_free_job_info_msg(g_job_info_ptr);
  2636. changed = 1;
  2637. } else if (slurm_get_errno() == SLURM_NO_CHANGE_IN_DATA) {
  2638. error_code = SLURM_NO_CHANGE_IN_DATA;
  2639. new_job_ptr = g_job_info_ptr;
  2640. changed = 0;
  2641. }
  2642. } else {
  2643. new_job_ptr = NULL;
  2644. error_code = slurm_load_jobs((time_t) NULL, &new_job_ptr,
  2645. show_flags);
  2646. changed = 1;
  2647. }
  2648. last_flags = show_flags;
  2649. g_job_info_ptr = new_job_ptr;
  2650. if (g_job_info_ptr && (*info_ptr != g_job_info_ptr))
  2651. error_code = SLURM_SUCCESS;
  2652. *info_ptr = g_job_info_ptr;
  2653. end_it:
  2654. return error_code;
  2655. }
  2656. extern int get_new_info_job_step(job_step_info_response_msg_t **info_ptr,
  2657. int force)
  2658. {
  2659. job_step_info_response_msg_t *new_step_ptr = NULL;
  2660. uint16_t show_flags = 0;
  2661. int error_code = SLURM_NO_CHANGE_IN_DATA;
  2662. time_t now = time(NULL);
  2663. static time_t last;
  2664. static bool changed = 0;
  2665. if (g_step_info_ptr && !force
  2666. && ((now - last) < working_sview_config.refresh_delay)) {
  2667. if (*info_ptr != g_step_info_ptr)
  2668. error_code = SLURM_SUCCESS;
  2669. *info_ptr = g_step_info_ptr;
  2670. if (changed)
  2671. error_code = SLURM_SUCCESS;
  2672. goto end_it;
  2673. }
  2674. last = now;
  2675. /* This needs to always be like this even if you are only
  2676. looking for non-hidden jobs or you will get an error below.
  2677. */
  2678. show_flags |= SHOW_ALL;
  2679. if (g_step_info_ptr) {
  2680. error_code = slurm_get_job_steps(g_step_info_ptr->last_update,
  2681. NO_VAL, NO_VAL, &new_step_ptr,
  2682. show_flags);
  2683. if (error_code == SLURM_SUCCESS) {
  2684. slurm_free_job_step_info_response_msg(g_step_info_ptr);
  2685. changed = 1;
  2686. } else if (slurm_get_errno () == SLURM_NO_CHANGE_IN_DATA) {
  2687. error_code = SLURM_NO_CHANGE_IN_DATA;
  2688. new_step_ptr = g_step_info_ptr;
  2689. changed = 0;
  2690. }
  2691. } else {
  2692. new_step_ptr = NULL;
  2693. error_code = slurm_get_job_steps((time_t) NULL, NO_VAL, NO_VAL,
  2694. &new_step_ptr, show_flags);
  2695. changed = 1;
  2696. }
  2697. g_step_info_ptr = new_step_ptr;
  2698. if (g_step_info_ptr && (*info_ptr != g_step_info_ptr))
  2699. error_code = SLURM_SUCCESS;
  2700. *info_ptr = g_step_info_ptr;
  2701. end_it:
  2702. return error_code;
  2703. }
  2704. extern GtkListStore *create_model_job(int type)
  2705. {
  2706. GtkListStore *model = NULL;
  2707. GtkTreeIter iter;
  2708. switch(type) {
  2709. case SORTID_ACTION:
  2710. model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
  2711. gtk_list_store_append(model, &iter);
  2712. gtk_list_store_set(model, &iter,
  2713. 1, SORTID_ACTION,
  2714. 0, "None",
  2715. -1);
  2716. gtk_list_store_append(model, &iter);
  2717. gtk_list_store_set(model, &iter,
  2718. 1, SORTID_ACTION,
  2719. 0, "Cancel",
  2720. -1);
  2721. gtk_list_store_append(model, &iter);
  2722. gtk_list_store_set(model, &iter,
  2723. 1, SORTID_ACTION,
  2724. 0, "Suspend/Resume",
  2725. -1);
  2726. gtk_list_store_append(model, &iter);
  2727. gtk_list_store_set(model, &iter,
  2728. 1, SORTID_ACTION,
  2729. 0, "Checkpoint",
  2730. -1);
  2731. gtk_list_store_append(model, &iter);
  2732. gtk_list_store_set(model, &iter,
  2733. 1, SORTID_ACTION,
  2734. 0, "Requeue",
  2735. -1);
  2736. break;
  2737. case SORTID_SHARED:
  2738. case SORTID_CONTIGUOUS:
  2739. case SORTID_REQUEUE:
  2740. case SORTID_ROTATE:
  2741. model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
  2742. gtk_list_store_append(model, &iter);
  2743. gtk_list_store_set(model, &iter,
  2744. 0, "yes",
  2745. 1, type,
  2746. -1);
  2747. gtk_list_store_append(model, &iter);
  2748. gtk_list_store_set(model, &iter,
  2749. 0, "no",
  2750. 1, type,
  2751. -1);
  2752. break;
  2753. case SORTID_CONNECTION:
  2754. model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
  2755. gtk_list_store_append(model, &iter);
  2756. gtk_list_store_set(model, &iter,
  2757. 0, "Torus",
  2758. 1, SORTID_CONNECTION,
  2759. -1);
  2760. gtk_list_store_append(model, &iter);
  2761. gtk_list_store_set(model, &iter,
  2762. 0, "Mesh",
  2763. 1, SORTID_CONNECTION,
  2764. -1);
  2765. gtk_list_store_append(model, &iter);
  2766. gtk_list_store_set(model, &iter,
  2767. 0, "NAV",
  2768. 1, SORTID_CONNECTION,
  2769. -1);
  2770. if (!(cluster_flags & CLUSTER_FLAG_BGL)) {
  2771. gtk_list_store_append(model, &iter);
  2772. gtk_list_store_set(model, &iter,
  2773. 0, "HTC SMP",
  2774. 1, SORTID_CONNECTION,
  2775. -1);
  2776. gtk_list_store_append(model, &iter);
  2777. gtk_list_store_set(model, &iter,
  2778. 0, "HTC Dual",
  2779. 1, SORTID_CONNECTION,
  2780. -1);
  2781. gtk_list_store_append(model, &iter);
  2782. gtk_list_store_set(model, &iter,
  2783. 0, "HTC Virtual",
  2784. 1, SORTID_CONNECTION,
  2785. -1);
  2786. gtk_list_store_append(model, &iter);
  2787. gtk_list_store_set(model, &iter,
  2788. 0, "HTC Linux",
  2789. 1, SORTID_CONNECTION,
  2790. -1);
  2791. }
  2792. break;
  2793. default:
  2794. break;
  2795. }
  2796. return model;
  2797. }
  2798. extern void admin_edit_job(GtkCellRendererText *cell,
  2799. const char *path_string,
  2800. const char *new_text,
  2801. gpointer data)
  2802. {
  2803. GtkTreeStore *treestore = GTK_TREE_STORE(data);
  2804. GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
  2805. GtkTreeIter iter;
  2806. job_desc_msg_t *job_msg = xmalloc(sizeof(job_desc_msg_t));
  2807. char *temp = NULL;
  2808. char *old_text = NULL;
  2809. const char *type = NULL;
  2810. int stepid = NO_VAL;
  2811. int column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cell),
  2812. "column"));
  2813. if (!new_text || !strcmp(new_text, ""))
  2814. goto no_input;
  2815. gtk_tree_model_get_iter(GTK_TREE_MODEL(treestore), &iter, path);
  2816. slurm_init_job_desc_msg(job_msg);
  2817. gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter,
  2818. SORTID_JOBID, &job_msg->job_id,
  2819. column, &old_text,
  2820. -1);
  2821. gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter,
  2822. SORTID_ALLOC, &stepid, -1);
  2823. if (stepid)
  2824. stepid = NO_VAL;
  2825. else {
  2826. stepid = job_msg->job_id;
  2827. gtk_tree_model_get(GTK_TREE_MODEL(treestore), &iter,
  2828. SORTID_POS, &job_msg->job_id, -1);
  2829. }
  2830. type = _set_job_msg(job_msg, new_text, column);
  2831. if (global_edit_error)
  2832. goto print_error;
  2833. if (got_edit_signal) {
  2834. temp = got_edit_signal;
  2835. got_edit_signal = NULL;
  2836. admin_job(GTK_TREE_MODEL(treestore), &iter, temp, NULL);
  2837. xfree(temp);
  2838. goto no_input;
  2839. }
  2840. if (old_text && !strcmp(old_text, new_text)) {
  2841. temp = g_strdup_printf("No change in value.");
  2842. } else if (slurm_update_job(job_msg)
  2843. == SLURM_SUCCESS) {
  2844. gtk_tree_store_set(treestore, &iter, column, new_text, -1);
  2845. temp = g_strdup_printf("Job %d %s changed to %s",
  2846. job_msg->job_id,
  2847. type,
  2848. new_text);
  2849. } else if (errno == ESLURM_DISABLED) {
  2850. temp = g_strdup_printf(
  2851. "Can only edit %s on pending jobs.", type);
  2852. } else {
  2853. print_error:
  2854. temp = g_strdup_printf("Job %d %s can't be "
  2855. "set to %s",
  2856. job_msg->job_id,
  2857. type,
  2858. new_text);
  2859. }
  2860. display_edit_note(temp);
  2861. g_free(temp);
  2862. no_input:
  2863. slurm_free_job_desc_msg(job_msg);
  2864. gtk_tree_path_free (path);
  2865. g_free(old_text);
  2866. g_static_mutex_unlock(&sview_mutex);
  2867. }
  2868. extern void get_info_job(GtkTable *table, display_data_t *display_data)
  2869. {
  2870. int job_error_code = SLURM_SUCCESS;
  2871. int step_error_code = SLURM_SUCCESS;
  2872. static int view = -1;
  2873. static job_info_msg_t *job_info_ptr = NULL;
  2874. static job_step_info_response_msg_t *step_info_ptr = NULL;
  2875. char error_char[100];
  2876. GtkWidget *label = NULL;
  2877. GtkTreeView *tree_view = NULL;
  2878. static GtkWidget *display_widget = NULL;
  2879. List info_list = NULL;
  2880. int j, k;
  2881. sview_job_info_t *sview_job_info_ptr = NULL;
  2882. job_info_t *job_ptr = NULL;
  2883. ListIterator itr = NULL;
  2884. GtkTreePath *path = NULL;
  2885. static bool set_opts = FALSE;
  2886. if (!set_opts)
  2887. set_page_opts(JOB_PAGE, display_data_job,
  2888. SORTID_CNT, _initial_page_opts);
  2889. set_opts = TRUE;
  2890. /* reset */
  2891. if (!table && !display_data) {
  2892. if (display_widget)
  2893. gtk_widget_destroy(display_widget);
  2894. display_widget = NULL;
  2895. job_info_ptr = NULL;
  2896. step_info_ptr = NULL;
  2897. return;
  2898. }
  2899. if (display_data)
  2900. local_display_data = display_data;
  2901. if (!table) {
  2902. display_data_job->set_menu = local_display_data->set_menu;
  2903. return;
  2904. }
  2905. if (display_widget && toggled) {
  2906. gtk_widget_destroy(display_widget);
  2907. display_widget = NULL;
  2908. goto display_it;
  2909. }
  2910. if ((job_error_code = get_new_info_job(&job_info_ptr, force_refresh))
  2911. == SLURM_NO_CHANGE_IN_DATA){
  2912. } else if (job_error_code != SLURM_SUCCESS) {
  2913. if (view == ERROR_VIEW)
  2914. goto end_it;
  2915. if (display_widget)
  2916. gtk_widget_destroy(display_widget);
  2917. view = ERROR_VIEW;
  2918. sprintf(error_char, "slurm_load_job: %s",
  2919. slurm_strerror(slurm_get_errno()));
  2920. label = gtk_label_new(error_char);
  2921. gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
  2922. gtk_widget_show(label);
  2923. display_widget = gtk_widget_ref(GTK_WIDGET(label));
  2924. goto end_it;
  2925. }
  2926. if ((step_error_code = get_new_info_job_step(&step_info_ptr,
  2927. force_refresh))
  2928. == SLURM_NO_CHANGE_IN_DATA){
  2929. if ((!display_widget || view == ERROR_VIEW)
  2930. || (job_error_code != SLURM_NO_CHANGE_IN_DATA))
  2931. goto display_it;
  2932. } else if (step_error_code != SLURM_SUCCESS) {
  2933. if (view == ERROR_VIEW)
  2934. goto end_it;
  2935. if (display_widget)
  2936. gtk_widget_destroy(display_widget);
  2937. view = ERROR_VIEW;
  2938. sprintf(error_char, "slurm_load_job_step: %s",
  2939. slurm_strerror(slurm_get_errno()));
  2940. label = gtk_label_new(error_char);
  2941. gtk_table_attach_defaults(table, label, 0, 1, 0, 1);
  2942. gtk_widget_show(label);
  2943. display_widget = gtk_widget_ref(GTK_WIDGET(label));
  2944. goto end_it;
  2945. }
  2946. display_it:
  2947. info_list = _create_job_info_list(job_info_ptr, step_info_ptr, 0);
  2948. if (!info_list)
  2949. goto reset_curs;
  2950. /* set up the grid */
  2951. if (display_widget && GTK_IS_TREE_VIEW(display_widget)
  2952. && gtk_tree_selection_count_selected_rows(
  2953. gtk_tree_view_get_selection(
  2954. GTK_TREE_VIEW(display_widget)))) {
  2955. GtkTreeViewColumn *focus_column = NULL;
  2956. /* highlight the correct nodes from the last selection */
  2957. gtk_tree_view_get_cursor(GTK_TREE_VIEW(display_widget),
  2958. &path, &focus_column);
  2959. }
  2960. if (!path) {
  2961. int top_node_inx = 0;
  2962. int array_size = SVIEW_MAX_NODE_SPACE;
  2963. int *color_inx = xmalloc(sizeof(int) * array_size);
  2964. bool *color_set_flag = xmalloc(sizeof(bool) * array_size);
  2965. itr = list_iterator_create(info_list);
  2966. while ((sview_job_info_ptr = list_next(itr))) {
  2967. uint16_t base_state;
  2968. job_ptr = sview_job_info_ptr->job_ptr;
  2969. base_state = job_ptr->job_state & JOB_STATE_BASE;
  2970. if (base_state != JOB_RUNNING)
  2971. continue;
  2972. j = 0;
  2973. while (job_ptr->node_inx[j] >= 0) {
  2974. top_node_inx = MAX(top_node_inx,
  2975. job_ptr->node_inx[j+1]);
  2976. if (top_node_inx > SVIEW_MAX_NODE_SPACE) {
  2977. fatal("Increase SVIEW_MAX_NODE_SPACE "
  2978. "in sview");
  2979. }
  2980. for (k = job_ptr->node_inx[j];
  2981. k <= job_ptr->node_inx[j+1]; k++) {
  2982. color_set_flag[k] = true;
  2983. color_inx[k] = sview_job_info_ptr->
  2984. color_inx;
  2985. }
  2986. j += 2;
  2987. }
  2988. }
  2989. list_iterator_destroy(itr);
  2990. change_grid_color_array(grid_button_list, top_node_inx+1,
  2991. color_inx, color_set_flag, true, 0);
  2992. xfree(color_inx);
  2993. xfree(color_set_flag);
  2994. change_grid_color(grid_button_list, -1, -1,
  2995. MAKE_WHITE, true, 0);
  2996. } else {
  2997. highlight_grid(GTK_TREE_VIEW(display_widget),
  2998. SORTID_NODE_INX, SORTID_COLOR_INX,
  2999. grid_button_list);
  3000. }
  3001. if (view == ERROR_VIEW && display_widget) {
  3002. gtk_widget_destroy(display_widget);
  3003. display_widget = NULL;
  3004. }
  3005. if (!display_widget) {
  3006. tree_view = create_treeview(local_display_data,
  3007. &grid_button_list);
  3008. /*set multiple capability here*/
  3009. gtk_tree_selection_set_mode(
  3010. gtk_tree_view_get_selection(tree_view),
  3011. GTK_SELECTION_MULTIPLE);
  3012. display_widget = gtk_widget_ref(GTK_WIDGET(tree_view));
  3013. gtk_table_attach_defaults(GTK_TABLE(table),
  3014. GTK_WIDGET(tree_view),
  3015. 0, 1, 0, 1);
  3016. /* since this function sets the model of the tree_view
  3017. to the treestore we don't really care about
  3018. the return value */
  3019. create_treestore(tree_view, display_data_job,
  3020. SORTID_CNT, SORTID_TIME_SUBMIT, SORTID_COLOR);
  3021. }
  3022. view = INFO_VIEW;
  3023. /* If the system has a large number of jobs then not all lines
  3024. * will be displayed. You can try different values for the third
  3025. * argument of gtk_widget_set_size_request() in an attempt to
  3026. * maximumize the data displayed in your environment. These are my
  3027. * results: Y=1000 good for 43 lines, Y=-1 good for 1151 lines,
  3028. * Y=64000 good for 2781 lines, Y=99000 good for 1453 lines */
  3029. /* gtk_widget_set_size_request(display_widget, -1, -1); */
  3030. _update_info_job(info_list, GTK_TREE_VIEW(display_widget));
  3031. end_it:
  3032. toggled = FALSE;
  3033. force_refresh = FALSE;
  3034. reset_curs:
  3035. if (main_window && main_window->window)
  3036. gdk_window_set_cursor(main_window->window, NULL);
  3037. return;
  3038. }
  3039. extern void specific_info_job(popup_info_t *popup_win)
  3040. {
  3041. int job_error_code = SLURM_SUCCESS;
  3042. int step_error_code = SLURM_SUCCESS;
  3043. static job_info_msg_t *job_info_ptr = NULL;
  3044. static job_step_info_response_msg_t *step_info_ptr = NULL;
  3045. specific_info_t *spec_info = popup_win->spec_info;
  3046. sview_search_info_t *search_info = spec_info->search_info;
  3047. char error_char[100];
  3048. GtkWidget *label = NULL;
  3049. GtkTreeView *tree_view = NULL;
  3050. List info_list = NULL;
  3051. List send_info_list = NULL;
  3052. int i=-1, j, k;
  3053. sview_job_info_t *sview_job_info_ptr = NULL;
  3054. job_info_t *job_ptr = NULL;
  3055. ListIterator itr = NULL;
  3056. char name[30], *uname = NULL;
  3057. hostset_t hostset = NULL;
  3058. int name_diff;
  3059. int top_node_inx, array_size, *color_inx;
  3060. bool *color_set_flag;
  3061. if (!spec_info->display_widget)
  3062. setup_popup_info(popup_win, display_data_job, SORTID_CNT);
  3063. if (spec_info->display_widget && popup_win->toggled) {
  3064. gtk_widget_destroy(spec_info->display_widget);
  3065. spec_info->display_widget = NULL;
  3066. goto display_it;
  3067. }
  3068. if ((job_error_code =
  3069. get_new_info_job(&job_info_ptr, popup_win->force_refresh))
  3070. == SLURM_NO_CHANGE_IN_DATA) {
  3071. } else if (job_error_code != SLURM_SUCCESS) {
  3072. if (spec_info->view == ERROR_VIEW)
  3073. goto end_it;
  3074. spec_info->view = ERROR_VIEW;
  3075. if (spec_info->display_widget)
  3076. gtk_widget_destroy(spec_info->display_widget);
  3077. sprintf(error_char, "slurm_load_job: %s",
  3078. slurm_strerror(slurm_get_errno()));
  3079. label = gtk_label_new(error_char);
  3080. gtk_table_attach_defaults(GTK_TABLE(popup_win->table),
  3081. label,
  3082. 0, 1, 0, 1);
  3083. gtk_widget_show(label);
  3084. spec_info->display_widget = gtk_widget_ref(GTK_WIDGET(label));
  3085. goto end_it;
  3086. }
  3087. if ((step_error_code =
  3088. get_new_info_job_step(&step_info_ptr, popup_win->force_refresh))
  3089. == SLURM_NO_CHANGE_IN_DATA) {
  3090. if ((!spec_info->display_widget
  3091. || spec_info->view == ERROR_VIEW)
  3092. || (job_error_code != SLURM_NO_CHANGE_IN_DATA))
  3093. goto display_it;
  3094. } else if (step_error_code != SLURM_SUCCESS) {
  3095. if (spec_info->view == ERROR_VIEW)
  3096. goto end_it;
  3097. if (spec_info->display_widget)
  3098. gtk_widget_destroy(spec_info->display_widget);
  3099. spec_info->view = ERROR_VIEW;
  3100. sprintf(error_char, "slurm_load_job_step: %s",
  3101. slurm_strerror(slurm_get_errno()));
  3102. label = gtk_label_new(error_char);
  3103. gtk_table_attach_defaults(popup_win->table, label,
  3104. 0, 1, 0, 1);
  3105. gtk_widget_show(label);
  3106. spec_info->display_widget = gtk_widget_ref(GTK_WIDGET(label));
  3107. goto end_it;
  3108. }
  3109. display_it:
  3110. info_list = _create_job_info_list(job_info_ptr, step_info_ptr, 1);
  3111. if (!info_list)
  3112. return;
  3113. if (spec_info->view == ERROR_VIEW && spec_info->display_widget) {
  3114. gtk_widget_destroy(spec_info->display_widget);
  3115. spec_info->display_widget = NULL;
  3116. }
  3117. if (spec_info->type != INFO_PAGE && !spec_info->display_widget) {
  3118. tree_view = create_treeview(local_display_data,
  3119. &popup_win->grid_button_list);
  3120. /*set multiple capability here*/
  3121. gtk_tree_selection_set_mode(
  3122. gtk_tree_view_get_selection(tree_view),
  3123. GTK_SELECTION_MULTIPLE);
  3124. spec_info->display_widget =
  3125. gtk_widget_ref(GTK_WIDGET(tree_view));
  3126. gtk_table_attach_defaults(popup_win->table,
  3127. GTK_WIDGET(tree_view),
  3128. 0, 1, 0, 1);
  3129. /* since this function sets the model of the tree_view
  3130. to the treestore we don't really care about
  3131. the return value */
  3132. create_treestore(tree_view, popup_win->display_data,
  3133. SORTID_CNT, SORTID_TIME_SUBMIT, SORTID_COLOR);
  3134. }
  3135. setup_popup_grid_list(popup_win);
  3136. spec_info->view = INFO_VIEW;
  3137. if (spec_info->type == INFO_PAGE) {
  3138. _display_info_job(info_list, popup_win);
  3139. goto end_it;
  3140. }
  3141. /* just linking to another list, don't free the inside, just
  3142. the list */
  3143. send_info_list = list_create(NULL);
  3144. itr = list_iterator_create(info_list);
  3145. i = -1;
  3146. while ((sview_job_info_ptr = list_next(itr))) {
  3147. i++;
  3148. job_ptr = sview_job_info_ptr->job_ptr;
  3149. switch(spec_info->type) {
  3150. case JOB_PAGE:
  3151. switch(search_info->search_type) {
  3152. case SEARCH_JOB_ID:
  3153. if (search_info->int_data
  3154. == NO_VAL) {
  3155. if (!search_info->gchar_data)
  3156. continue;
  3157. _convert_char_to_job_and_step(
  3158. search_info->gchar_data,
  3159. &search_info->int_data,
  3160. &search_info->int_data2);
  3161. }
  3162. if (job_ptr->job_id != search_info->int_data) {
  3163. continue;
  3164. }
  3165. /* if we ever want to display just the step
  3166. this is where we would do it */
  3167. /* if (spec_info->search_info->int_data2 */
  3168. /* == NO_VAL) */
  3169. /* break; */
  3170. /* step_itr = list_iterator_create( */
  3171. /* sview_job_info->step_list); */
  3172. /* while ((step_ptr = list_next(itr))) { */
  3173. /* if (step_ptr->step_id */
  3174. /* == spec_info->search_info->int_data2) { */
  3175. /* break; */
  3176. /* } */
  3177. /* } */
  3178. break;
  3179. case SEARCH_JOB_USER:
  3180. if (!search_info->gchar_data)
  3181. continue;
  3182. uname = uid_to_string(job_ptr->user_id);
  3183. name_diff = strcmp(uname,
  3184. search_info->gchar_data);
  3185. xfree(uname);
  3186. if (name_diff)
  3187. continue;
  3188. break;
  3189. case SEARCH_JOB_STATE:
  3190. if (search_info->int_data == NO_VAL)
  3191. continue;
  3192. if (job_ptr->job_state != search_info->int_data)
  3193. continue;
  3194. break;
  3195. default:
  3196. break;
  3197. }
  3198. break;
  3199. case PART_PAGE:
  3200. if (strcmp(search_info->gchar_data,
  3201. job_ptr->partition))
  3202. continue;
  3203. break;
  3204. case RESV_PAGE:
  3205. if (!job_ptr->resv_name
  3206. || strcmp(search_info->gchar_data,
  3207. job_ptr->resv_name))
  3208. continue;
  3209. break;
  3210. case BLOCK_PAGE:
  3211. select_g_select_jobinfo_sprint(
  3212. job_ptr->select_jobinfo,
  3213. name,
  3214. sizeof(name),
  3215. SELECT_PRINT_BG_ID);
  3216. if (strcmp(search_info->gchar_data, name))
  3217. continue;
  3218. break;
  3219. case NODE_PAGE:
  3220. if (!job_ptr->nodes)
  3221. continue;
  3222. if (!(hostset = hostset_create(
  3223. search_info->gchar_data)))
  3224. continue;
  3225. if (!hostset_intersects(hostset, job_ptr->nodes)) {
  3226. hostset_destroy(hostset);
  3227. continue;
  3228. }
  3229. hostset_destroy(hostset);
  3230. break;
  3231. default:
  3232. continue;
  3233. }
  3234. list_push(send_info_list, sview_job_info_ptr);
  3235. top_node_inx = 0;
  3236. array_size = SVIEW_MAX_NODE_SPACE;
  3237. color_inx = xmalloc(sizeof(int) * array_size);
  3238. color_set_flag = xmalloc(sizeof(bool) * array_size);
  3239. j = 0;
  3240. while (job_ptr->node_inx[j] >= 0) {
  3241. top_node_inx = MAX(top_node_inx,
  3242. job_ptr->node_inx[j+1]);
  3243. if (top_node_inx > SVIEW_MAX_NODE_SPACE)
  3244. fatal("Increase SVIEW_MAX_NODE_SPACE in sview");
  3245. for (k = job_ptr->node_inx[j];
  3246. k <= job_ptr->node_inx[j+1]; k++) {
  3247. color_set_flag[k] = true;
  3248. color_inx[k] = sview_job_info_ptr->color_inx;
  3249. }
  3250. j += 2;
  3251. }
  3252. change_grid_color_array(popup_win->grid_button_list,
  3253. top_node_inx+1, color_inx,
  3254. color_set_flag, true, 0);
  3255. xfree(color_inx);
  3256. xfree(color_set_flag);
  3257. }
  3258. list_iterator_destroy(itr);
  3259. post_setup_popup_grid_list(popup_win);
  3260. _update_info_job(send_info_list,
  3261. GTK_TREE_VIEW(spec_info->display_widget));
  3262. list_destroy(send_info_list);
  3263. end_it:
  3264. popup_win->toggled = 0;
  3265. popup_win->force_refresh = 0;
  3266. return;
  3267. }
  3268. extern void set_menus_job(void *arg, void *arg2, GtkTreePath *path, int type)
  3269. {
  3270. GtkTreeView *tree_view = (GtkTreeView *)arg;
  3271. popup_info_t *popup_win = (popup_info_t *)arg;
  3272. GtkMenu *menu = (GtkMenu *)arg2;
  3273. List button_list = (List)arg2;
  3274. switch(type) {
  3275. case TAB_CLICKED:
  3276. make_fields_menu(NULL, menu, display_data_job, SORTID_CNT);
  3277. break;
  3278. case ROW_CLICKED:
  3279. make_options_menu(tree_view, path, menu, options_data_job);
  3280. break;
  3281. case ROW_LEFT_CLICKED:
  3282. highlight_grid(tree_view, SORTID_NODE_INX,
  3283. SORTID_COLOR_INX, button_list);
  3284. break;
  3285. case FULL_CLICKED:
  3286. {
  3287. GtkTreeModel *model = gtk_tree_view_get_model(tree_view);
  3288. GtkTreeIter iter;
  3289. if (!gtk_tree_model_get_iter(model, &iter, path)) {
  3290. g_error("job error getting iter from model\n");
  3291. break;
  3292. }
  3293. popup_all_job(model, &iter, INFO_PAGE);
  3294. break;
  3295. }
  3296. case POPUP_CLICKED:
  3297. make_fields_menu(popup_win, menu,
  3298. popup_win->display_data, SORTID_CNT);
  3299. break;
  3300. default:
  3301. g_error("UNKNOWN type %d given to set_fields\n", type);
  3302. }
  3303. }
  3304. extern void popup_all_job(GtkTreeModel *model, GtkTreeIter *iter, int id)
  3305. {
  3306. char *name = NULL;
  3307. char title[100];
  3308. ListIterator itr = NULL;
  3309. popup_info_t *popup_win = NULL;
  3310. int jobid = NO_VAL;
  3311. int stepid = NO_VAL;
  3312. GError *error = NULL;
  3313. int i=0;
  3314. char *type;
  3315. if (cluster_flags & CLUSTER_FLAG_BG)
  3316. type = "Midplane";
  3317. else
  3318. type = "Node";
  3319. gtk_tree_model_get(model, iter, SORTID_JOBID, &jobid, -1);
  3320. gtk_tree_model_get(model, iter, SORTID_ALLOC, &stepid, -1);
  3321. if (stepid)
  3322. stepid = NO_VAL;
  3323. else {
  3324. stepid = jobid;
  3325. gtk_tree_model_get(model, iter, SORTID_POS, &jobid, -1);
  3326. }
  3327. switch(id) {
  3328. case PART_PAGE:
  3329. if (stepid == NO_VAL)
  3330. snprintf(title, 100, "Partition with job %d", jobid);
  3331. else
  3332. snprintf(title, 100, "Partition with job step %d.%d",
  3333. jobid, stepid);
  3334. break;
  3335. case RESV_PAGE:
  3336. if (stepid == NO_VAL)
  3337. snprintf(title, 100, "Reservation with job %d", jobid);
  3338. else
  3339. snprintf(title, 100, "Reservation with job step %d.%d",
  3340. jobid, stepid);
  3341. break;
  3342. case NODE_PAGE:
  3343. if (stepid == NO_VAL)
  3344. snprintf(title, 100,
  3345. "%s(s) running job %d", type, jobid);
  3346. else
  3347. snprintf(title, 100, "%s(s) running job step %d.%d",
  3348. type, jobid, stepid);
  3349. break;
  3350. case BLOCK_PAGE:
  3351. if (stepid == NO_VAL)
  3352. snprintf(title, 100, "Block with job %d", jobid);
  3353. else
  3354. snprintf(title, 100, "Block with job step %d.%d",
  3355. jobid, stepid);
  3356. break;
  3357. case INFO_PAGE:
  3358. if (stepid == NO_VAL)
  3359. snprintf(title, 100, "Full info for job %d", jobid);
  3360. else
  3361. snprintf(title, 100, "Full info for job step %d.%d",
  3362. jobid, stepid);
  3363. break;
  3364. default:
  3365. g_print("jobs got id %d\n", id);
  3366. }
  3367. itr = list_iterator_create(popup_list);
  3368. while ((popup_win = list_next(itr))) {
  3369. if (popup_win->spec_info)
  3370. if (!strcmp(popup_win->spec_info->title, title)) {
  3371. break;
  3372. }
  3373. }
  3374. list_iterator_destroy(itr);
  3375. if (!popup_win) {
  3376. if (id == INFO_PAGE)
  3377. popup_win = create_popup_info(id, JOB_PAGE, title);
  3378. else
  3379. popup_win = create_popup_info(JOB_PAGE, id, title);
  3380. } else {
  3381. gtk_window_present(GTK_WINDOW(popup_win->popup));
  3382. return;
  3383. }
  3384. /* Pass the model and the structs from the iter so we can always get
  3385. the current node_inx.
  3386. */
  3387. popup_win->model = model;
  3388. popup_win->iter = *iter;
  3389. popup_win->node_inx_id = SORTID_NODE_INX;
  3390. switch(id) {
  3391. case NODE_PAGE:
  3392. gtk_tree_model_get(model, iter, SORTID_NODELIST, &name, -1);
  3393. if (cluster_flags & CLUSTER_FLAG_BG) {
  3394. gtk_tree_model_get(model, iter,
  3395. SORTID_SMALL_BLOCK, &i, -1);
  3396. if (i) {
  3397. i=0;
  3398. /* strip off the ionodes part */
  3399. while (name[i]) {
  3400. if (name[i] == '[') {
  3401. name[i] = '\0';
  3402. break;
  3403. }
  3404. i++;
  3405. }
  3406. }
  3407. }
  3408. popup_win->spec_info->search_info->gchar_data = name;
  3409. break;
  3410. case PART_PAGE:
  3411. gtk_tree_model_get(model, iter, SORTID_PARTITION, &name, -1);
  3412. popup_win->spec_info->search_info->gchar_data = name;
  3413. break;
  3414. case RESV_PAGE:
  3415. gtk_tree_model_get(model, iter, SORTID_RESV_NAME, &name, -1);
  3416. popup_win->spec_info->search_info->gchar_data = name;
  3417. break;
  3418. case BLOCK_PAGE:
  3419. if (cluster_flags & CLUSTER_FLAG_BG) {
  3420. gtk_tree_model_get(model, iter,
  3421. SORTID_BLOCK, &name, -1);
  3422. popup_win->spec_info->search_info->gchar_data = name;
  3423. }
  3424. break;
  3425. case SUBMIT_PAGE:
  3426. break;
  3427. case INFO_PAGE:
  3428. popup_win->spec_info->search_info->int_data = jobid;
  3429. popup_win->spec_info->search_info->int_data2 = stepid;
  3430. break;
  3431. default:
  3432. g_print("jobs got %d\n", id);
  3433. }
  3434. if (!sview_thread_new((gpointer)popup_thr, popup_win, FALSE, &error)) {
  3435. g_printerr ("Failed to create part popup thread: %s\n",
  3436. error->message);
  3437. return;
  3438. }
  3439. }
  3440. static void process_foreach_list (jobs_foreach_common_t *jobs_foreach_common)
  3441. {
  3442. int jobid;
  3443. int state;
  3444. int stepid;
  3445. uint16_t signal = SIGKILL;
  3446. int response = 0;
  3447. char *tmp_char_ptr = "";
  3448. jobs_foreach_t *job_foreach = NULL;
  3449. ListIterator itr = NULL;
  3450. if (jobs_foreach_common->edit_type == EDIT_SIGNAL) {
  3451. const gchar *entry_txt = gtk_entry_get_text(
  3452. GTK_ENTRY(jobs_foreach_common->entry));
  3453. signal = _xlate_signal_name(entry_txt);
  3454. if (signal == (uint16_t)NO_VAL) {
  3455. tmp_char_ptr = g_strdup_printf(
  3456. "%s is not a valid signal.",
  3457. entry_txt);
  3458. display_edit_note(tmp_char_ptr);
  3459. g_free(tmp_char_ptr);
  3460. goto end_it;
  3461. }
  3462. }
  3463. itr = list_iterator_create(foreach_list);
  3464. while ((job_foreach = list_next(itr))) {
  3465. /*stop processing remaining jobs on any error*/
  3466. if (global_error_code)
  3467. break;
  3468. jobid = job_foreach->job_id;
  3469. stepid = job_foreach->step_id;
  3470. state = job_foreach->state;
  3471. switch(jobs_foreach_common->edit_type) {
  3472. case EDIT_SIGNAL:
  3473. /* fall through to the cancel now the signal
  3474. * is set (Default is SIGKILL from above for
  3475. * just a regular cancel).
  3476. */
  3477. case EDIT_CANCEL:
  3478. if (stepid == NO_VAL)
  3479. global_error_code =
  3480. _cancel_job_id(jobid, signal);
  3481. else
  3482. global_error_code =
  3483. _cancel_step_id(jobid,
  3484. stepid, signal);
  3485. break;
  3486. case EDIT_REQUEUE:
  3487. response = slurm_requeue(jobid);
  3488. if (response) {
  3489. /* stop rest of jobs */
  3490. global_error_code = response;
  3491. tmp_char_ptr = g_strdup_printf(
  3492. "Error happened trying "
  3493. "to requeue job %u: %s",
  3494. jobid, slurm_strerror(response));
  3495. display_edit_note(tmp_char_ptr);
  3496. g_free(tmp_char_ptr);
  3497. }
  3498. break;
  3499. case EDIT_SUSPEND:
  3500. //note: derive state from job_foreach..
  3501. if (state == JOB_SUSPENDED)
  3502. response = slurm_resume(jobid);
  3503. else
  3504. response = slurm_suspend(jobid);
  3505. if (!response) {
  3506. /* stop rest of jobs */
  3507. global_error_code = response;
  3508. tmp_char_ptr = g_strdup_printf(
  3509. "Error happened trying to "
  3510. "SUSPEND/RESUME job %u.",
  3511. jobid);
  3512. display_edit_note(tmp_char_ptr);
  3513. g_free(tmp_char_ptr);
  3514. }
  3515. break;
  3516. default:
  3517. break;
  3518. }/*end switch*/
  3519. } /*spin thru selected jobs*/
  3520. if (global_edit_error || global_error_code)
  3521. goto end_it;
  3522. switch(jobs_foreach_common->edit_type) {
  3523. case EDIT_SIGNAL:
  3524. tmp_char_ptr = g_strdup_printf(
  3525. "Signal successfully sent to job(s)%s",
  3526. stacked_job_list);
  3527. display_edit_note(tmp_char_ptr);
  3528. g_free(tmp_char_ptr);
  3529. break;
  3530. case EDIT_CANCEL:
  3531. tmp_char_ptr = g_strdup_printf(
  3532. "Cancel successful for job(s)%s",
  3533. stacked_job_list);
  3534. display_edit_note(tmp_char_ptr);
  3535. g_free(tmp_char_ptr);
  3536. break;
  3537. case EDIT_REQUEUE:
  3538. tmp_char_ptr = g_strdup_printf(
  3539. "Requeue successful for job(s)%s",
  3540. stacked_job_list);
  3541. display_edit_note(tmp_char_ptr);
  3542. g_free(tmp_char_ptr);
  3543. break;
  3544. case EDIT_SUSPEND:
  3545. tmp_char_ptr = g_strdup_printf(
  3546. "SUSPEND/RESUME action successful for job(s)%s",
  3547. stacked_job_list);
  3548. display_edit_note(tmp_char_ptr);
  3549. g_free(tmp_char_ptr);
  3550. break;
  3551. default:
  3552. break;
  3553. }/*end switch*/
  3554. end_it:
  3555. xfree(stacked_job_list);
  3556. } /*process_foreach_list ^^^*/
  3557. static void selected_foreach_build_list(GtkTreeModel *model,
  3558. GtkTreePath *path,
  3559. GtkTreeIter *iter,
  3560. gpointer userdata)
  3561. {
  3562. uint32_t jobid = NO_VAL;
  3563. uint32_t stepid = NO_VAL;
  3564. int state;
  3565. jobs_foreach_t *fe_ptr = NULL;
  3566. gtk_tree_model_get(model, iter, SORTID_JOBID, &jobid, -1);
  3567. gtk_tree_model_get(model, iter, SORTID_ALLOC, &stepid, -1);
  3568. if (stepid)
  3569. stepid = NO_VAL;
  3570. else {
  3571. stepid = jobid;
  3572. gtk_tree_model_get(model, iter, SORTID_POS, &jobid, -1);
  3573. }
  3574. gtk_tree_model_get(model, iter, SORTID_STATE_NUM, &state, -1);
  3575. /* alc mem for individual job processor target */
  3576. fe_ptr = xmalloc(sizeof(jobs_foreach_t));
  3577. fe_ptr->job_id = jobid;
  3578. fe_ptr->step_id = stepid;
  3579. fe_ptr->state = state;
  3580. list_append(foreach_list, fe_ptr); /* stuff target away*/
  3581. if (stacked_job_list)
  3582. xstrcat(stacked_job_list, ", ");
  3583. else
  3584. xstrcat(stacked_job_list, ": ");
  3585. if (stepid == NO_VAL)
  3586. xstrfmtcat(stacked_job_list, "%u", jobid);
  3587. else
  3588. xstrfmtcat(stacked_job_list, "%u.%u", jobid, stepid);
  3589. }
  3590. static void _edit_each_job (GtkTreeModel *model, GtkTreeIter *iter,
  3591. jobs_foreach_common_t *jobs_foreach_common)
  3592. {
  3593. int response;
  3594. GtkWidget *popup;
  3595. GtkWidget *label = NULL;
  3596. GtkWidget *entry = NULL;
  3597. char tmp_char[255];
  3598. char *tmp_char_ptr = "";
  3599. jobs_foreach_t *job_foreach = NULL;
  3600. job_desc_msg_t *job_msg;
  3601. ListIterator itr = NULL;
  3602. itr = list_iterator_create(foreach_list);
  3603. while ((job_foreach = list_next(itr))) {
  3604. /*stop processing remaining jobs on any error*/
  3605. if (global_error_code || got_edit_signal)
  3606. break;
  3607. popup = gtk_dialog_new_with_buttons(
  3608. "Edit Job",
  3609. GTK_WINDOW(main_window),
  3610. GTK_DIALOG_MODAL |
  3611. GTK_DIALOG_DESTROY_WITH_PARENT,
  3612. NULL);
  3613. gtk_window_set_transient_for(GTK_WINDOW(popup), NULL);
  3614. label = gtk_dialog_add_button(GTK_DIALOG(popup),
  3615. GTK_STOCK_OK, GTK_RESPONSE_OK);
  3616. gtk_window_set_default(GTK_WINDOW(popup), label);
  3617. gtk_dialog_add_button(GTK_DIALOG(popup), GTK_STOCK_CANCEL,
  3618. GTK_RESPONSE_CANCEL);
  3619. gtk_dialog_add_button(GTK_DIALOG(popup), "Cancel all",
  3620. GTK_RESPONSE_DELETE_EVENT);
  3621. gtk_window_set_default_size(GTK_WINDOW(popup), 200, 400);
  3622. snprintf(tmp_char, sizeof(tmp_char),
  3623. "Editing job %u think before you type",
  3624. job_foreach->job_id);
  3625. label = gtk_label_new(tmp_char);
  3626. job_msg = xmalloc(sizeof(job_desc_msg_t));
  3627. slurm_init_job_desc_msg(job_msg);
  3628. job_msg->job_id = job_foreach->job_id;
  3629. entry = _admin_full_edit_job(job_msg, model, iter);
  3630. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
  3631. label, FALSE, FALSE, 0);
  3632. if (entry)
  3633. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
  3634. entry, TRUE, TRUE, 0);
  3635. gtk_widget_show_all(popup);
  3636. response = gtk_dialog_run(GTK_DIALOG(popup));
  3637. gtk_widget_destroy(popup);
  3638. if (got_edit_signal ||
  3639. (response == GTK_RESPONSE_DELETE_EVENT)) {
  3640. slurm_free_job_desc_msg(job_msg);
  3641. break;
  3642. }
  3643. if (global_edit_error) {
  3644. tmp_char_ptr = global_edit_error_msg;
  3645. } else if (!global_send_update_msg ||
  3646. (response == GTK_RESPONSE_CANCEL)) {
  3647. tmp_char_ptr = g_strdup_printf("No change detected.");
  3648. } else if (slurm_update_job(job_msg)
  3649. == SLURM_SUCCESS) {
  3650. tmp_char_ptr = g_strdup_printf(
  3651. "Job %u updated successfully",
  3652. job_foreach->job_id);
  3653. } else if (errno == ESLURM_DISABLED) {
  3654. tmp_char_ptr = g_strdup_printf(
  3655. "Can't edit that part of non-pending job %u.",
  3656. job_foreach->job_id);
  3657. } else {
  3658. tmp_char_ptr = g_strdup_printf(
  3659. "Problem updating job %u.",
  3660. job_foreach->job_id);
  3661. }
  3662. display_edit_note(tmp_char_ptr);
  3663. g_free(tmp_char_ptr);
  3664. slurm_free_job_desc_msg(job_msg);
  3665. } /*spin thru selected jobs*/
  3666. xfree(stacked_job_list);
  3667. } /*process_foreach_list ^^^*/
  3668. static void _edit_jobs(GtkTreeModel *model, GtkTreeIter *iter,
  3669. char *type, GtkTreeView *treeview)
  3670. {
  3671. jobs_foreach_common_t job_foreach_common;
  3672. global_error_code = SLURM_SUCCESS;
  3673. /* setup params that applies to ALL selections */
  3674. memset(&job_foreach_common, 0, sizeof(jobs_foreach_common_t));
  3675. job_foreach_common.type = type;
  3676. job_foreach_common.edit_type = EDIT_EDIT;
  3677. /* create a list to stack the selected jobs */
  3678. foreach_list = list_create(_destroy_jobs_foreach);
  3679. /* build array of job(s) to process */
  3680. if (treeview) {
  3681. gtk_tree_selection_selected_foreach(
  3682. gtk_tree_view_get_selection(treeview),
  3683. selected_foreach_build_list, NULL);
  3684. } else
  3685. selected_foreach_build_list(model, NULL, iter, NULL);
  3686. /* determine what to do with them/it */
  3687. _edit_each_job(model, iter, &job_foreach_common); /*go do them*/
  3688. list_destroy(foreach_list);
  3689. return;
  3690. }
  3691. extern void admin_job(GtkTreeModel *model, GtkTreeIter *iter,
  3692. char *type, GtkTreeView *treeview)
  3693. {
  3694. int jobid = NO_VAL;
  3695. int stepid = NO_VAL;
  3696. int response = 0;
  3697. char tmp_char[255];
  3698. int edit_type = 0;
  3699. job_desc_msg_t *job_msg;
  3700. GtkWidget *label = NULL;
  3701. GtkWidget *entry = NULL;
  3702. GtkWidget *popup;
  3703. if (strcmp(type, "Edit Job") == 0)
  3704. return _edit_jobs(model, iter, type, treeview);
  3705. job_msg = xmalloc(sizeof(job_desc_msg_t));
  3706. popup = gtk_dialog_new_with_buttons(
  3707. type,
  3708. GTK_WINDOW(main_window),
  3709. GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
  3710. NULL);
  3711. gtk_window_set_transient_for(GTK_WINDOW(popup), NULL);
  3712. gtk_tree_model_get(model, iter, SORTID_JOBID, &jobid, -1);
  3713. gtk_tree_model_get(model, iter, SORTID_ALLOC, &stepid, -1);
  3714. if (stepid)
  3715. stepid = NO_VAL;
  3716. else {
  3717. stepid = jobid;
  3718. gtk_tree_model_get(model, iter, SORTID_POS, &jobid, -1);
  3719. }
  3720. slurm_init_job_desc_msg(job_msg);
  3721. if (!strcasecmp("Signal", type)) {
  3722. label = gtk_dialog_add_button(GTK_DIALOG(popup),
  3723. GTK_STOCK_OK, GTK_RESPONSE_OK);
  3724. gtk_window_set_default(GTK_WINDOW(popup), label);
  3725. gtk_dialog_add_button(GTK_DIALOG(popup),
  3726. GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  3727. entry = create_entry();
  3728. label = gtk_label_new("Signal?");
  3729. edit_type = EDIT_SIGNAL;
  3730. } else if (!strcasecmp("Requeue", type)) {
  3731. label = gtk_dialog_add_button(GTK_DIALOG(popup),
  3732. GTK_STOCK_YES, GTK_RESPONSE_OK);
  3733. gtk_window_set_default(GTK_WINDOW(popup), label);
  3734. gtk_dialog_add_button(GTK_DIALOG(popup),
  3735. GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  3736. snprintf(tmp_char, sizeof(tmp_char),
  3737. "Are you sure you want to requeue these job(s)?");
  3738. label = gtk_label_new(tmp_char);
  3739. edit_type = EDIT_REQUEUE;
  3740. } else if (!strcasecmp("Cancel", type)) {
  3741. label = gtk_dialog_add_button(GTK_DIALOG(popup),
  3742. GTK_STOCK_YES, GTK_RESPONSE_OK);
  3743. gtk_window_set_default(GTK_WINDOW(popup), label);
  3744. gtk_dialog_add_button(GTK_DIALOG(popup),
  3745. GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  3746. if (stepid != NO_VAL)
  3747. snprintf(tmp_char, sizeof(tmp_char),
  3748. "Are you sure you want to cancel "
  3749. "these job step(s)?");
  3750. else
  3751. snprintf(tmp_char, sizeof(tmp_char),
  3752. "Are you sure you want to cancel "
  3753. "these job(s)?");
  3754. label = gtk_label_new(tmp_char);
  3755. edit_type = EDIT_CANCEL;
  3756. } else if (!strcasecmp("Suspend/Resume", type)) {
  3757. label = gtk_dialog_add_button(GTK_DIALOG(popup),
  3758. GTK_STOCK_YES, GTK_RESPONSE_OK);
  3759. gtk_window_set_default(GTK_WINDOW(popup), label);
  3760. gtk_dialog_add_button(GTK_DIALOG(popup),
  3761. GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
  3762. if (stepid != NO_VAL)
  3763. snprintf(tmp_char, sizeof(tmp_char),
  3764. "Are you sure you want to toggle "
  3765. "suspend/resume on these job steps?");
  3766. else
  3767. snprintf(tmp_char, sizeof(tmp_char),
  3768. "Are you sure you want to toggle "
  3769. "suspend/resume on these jobs?");
  3770. label = gtk_label_new(tmp_char);
  3771. edit_type = EDIT_SUSPEND;
  3772. }
  3773. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
  3774. label, FALSE, FALSE, 0);
  3775. if (entry)
  3776. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(popup)->vbox),
  3777. entry, TRUE, TRUE, 0);
  3778. gtk_widget_show_all(popup);
  3779. response = gtk_dialog_run (GTK_DIALOG(popup));
  3780. if (response == GTK_RESPONSE_OK) {
  3781. jobs_foreach_common_t job_foreach_common;
  3782. global_error_code = SLURM_SUCCESS;
  3783. /* setup params that applies to ALL selections */
  3784. memset(&job_foreach_common, 0, sizeof(jobs_foreach_common_t));
  3785. job_foreach_common.type = type;
  3786. job_foreach_common.edit_type = edit_type;
  3787. job_foreach_common.entry = entry;
  3788. /* pass this ptr for single job selections */
  3789. job_foreach_common.job_msg = job_msg;
  3790. /* create a list to stack the selected jobs */
  3791. foreach_list = list_create(_destroy_jobs_foreach);
  3792. /* build array of job(s) to process */
  3793. if (treeview)
  3794. gtk_tree_selection_selected_foreach(
  3795. gtk_tree_view_get_selection(treeview),
  3796. selected_foreach_build_list, NULL);
  3797. else
  3798. selected_foreach_build_list(model, NULL, iter, NULL);
  3799. /* determine what to do with them/it */
  3800. process_foreach_list(&job_foreach_common); /*go do them*/
  3801. list_destroy(foreach_list);
  3802. }/*response OK ^^*/
  3803. /* switch back to standard cursor*/
  3804. global_entry_changed = 0;
  3805. slurm_free_job_desc_msg(job_msg);
  3806. gtk_widget_destroy(popup);
  3807. if (got_edit_signal) {
  3808. type = got_edit_signal;
  3809. got_edit_signal = NULL;
  3810. admin_job(model, iter, type, treeview);
  3811. xfree(type);
  3812. }
  3813. return;
  3814. }
  3815. extern void cluster_change_job(void)
  3816. {
  3817. display_data_t *display_data = display_data_job;
  3818. while (display_data++) {
  3819. if (display_data->id == -1)
  3820. break;
  3821. if (cluster_flags & CLUSTER_FLAG_AIX) {
  3822. switch(display_data->id) {
  3823. case SORTID_NETWORK:
  3824. display_data->name = "Network";
  3825. break;
  3826. }
  3827. } else {
  3828. switch(display_data->id) {
  3829. case SORTID_NETWORK:
  3830. display_data->name = NULL;
  3831. break;
  3832. }
  3833. }
  3834. if (cluster_flags & CLUSTER_FLAG_CRAYXT) {
  3835. switch(display_data->id) {
  3836. case SORTID_ALPS_RESV_ID:
  3837. display_data->name = "ALPS";
  3838. break;
  3839. }
  3840. } else {
  3841. switch(display_data->id) {
  3842. case SORTID_ALPS_RESV_ID:
  3843. display_data->name = NULL;
  3844. break;
  3845. }
  3846. }
  3847. if (cluster_flags & CLUSTER_FLAG_BG) {
  3848. switch(display_data->id) {
  3849. case SORTID_BLOCK:
  3850. display_data->name = "BG Block";
  3851. break;
  3852. case SORTID_GEOMETRY:
  3853. display_data->name = "Geometry";
  3854. break;
  3855. case SORTID_ROTATE:
  3856. display_data->name = "Rotate";
  3857. break;
  3858. case SORTID_CONNECTION:
  3859. display_data->name = "Connection";
  3860. break;
  3861. case SORTID_IMAGE_MLOADER:
  3862. display_data->name = "Image Mloader";
  3863. break;
  3864. case SORTID_NODELIST:
  3865. display_data->name = "MidplaneList";
  3866. break;
  3867. case SORTID_NODELIST_EXC:
  3868. display_data->name = "MidplaneList Excluded";
  3869. break;
  3870. case SORTID_NODELIST_REQ:
  3871. display_data->name = "MidplaneList Requested";
  3872. break;
  3873. default:
  3874. break;
  3875. }
  3876. if (cluster_flags & CLUSTER_FLAG_BGL) {
  3877. switch(display_data->id) {
  3878. case SORTID_IMAGE_BLRTS:
  3879. display_data->name = "Image Blrts";
  3880. break;
  3881. case SORTID_IMAGE_LINUX:
  3882. display_data->name = "Image Linux";
  3883. break;
  3884. case SORTID_IMAGE_RAMDISK:
  3885. display_data->name = "Image Ramdisk";
  3886. break;
  3887. }
  3888. } else {
  3889. switch(display_data->id) {
  3890. case SORTID_IMAGE_BLRTS:
  3891. display_data->name = NULL;
  3892. break;
  3893. case SORTID_IMAGE_LINUX:
  3894. display_data->name = "Image Cnload";
  3895. break;
  3896. case SORTID_IMAGE_RAMDISK:
  3897. display_data->name = "Image Ioload";
  3898. break;
  3899. }
  3900. }
  3901. } else {
  3902. switch(display_data->id) {
  3903. case SORTID_BLOCK:
  3904. display_data->name = NULL;
  3905. break;
  3906. case SORTID_GEOMETRY:
  3907. display_data->name = NULL;
  3908. break;
  3909. case SORTID_ROTATE:
  3910. display_data->name = NULL;
  3911. break;
  3912. case SORTID_CONNECTION:
  3913. display_data->name = NULL;
  3914. break;
  3915. case SORTID_IMAGE_MLOADER:
  3916. display_data->name = NULL;
  3917. break;
  3918. case SORTID_NODELIST:
  3919. display_data->name = "NodeList";
  3920. break;
  3921. case SORTID_NODELIST_EXC:
  3922. display_data->name = "NodeList Excluded";
  3923. break;
  3924. case SORTID_NODELIST_REQ:
  3925. display_data->name = "NodeList Requested";
  3926. break;
  3927. case SORTID_IMAGE_BLRTS:
  3928. display_data->name = NULL;
  3929. break;
  3930. case SORTID_IMAGE_LINUX:
  3931. display_data->name = NULL;
  3932. break;
  3933. case SORTID_IMAGE_RAMDISK:
  3934. display_data->name = NULL;
  3935. break;
  3936. }
  3937. }
  3938. }
  3939. display_data = options_data_job;
  3940. while (display_data++) {
  3941. if (display_data->id == -1)
  3942. break;
  3943. if (cluster_flags & CLUSTER_FLAG_BG) {
  3944. switch(display_data->id) {
  3945. case BLOCK_PAGE:
  3946. display_data->name = "Blocks";
  3947. break;
  3948. case NODE_PAGE:
  3949. display_data->name = "Midplanes";
  3950. break;
  3951. }
  3952. } else {
  3953. switch(display_data->id) {
  3954. case BLOCK_PAGE:
  3955. display_data->name = NULL;
  3956. break;
  3957. case NODE_PAGE:
  3958. display_data->name = "Nodes";
  3959. break;
  3960. }
  3961. }
  3962. }
  3963. get_info_job(NULL, NULL);
  3964. }