1 /*
2  * step.c - convert data between step related messages and perl HVs
3  */
4 
5 #include <EXTERN.h>
6 #include <perl.h>
7 #include <XSUB.h>
8 #include <slurm/slurm.h>
9 #include "ppport.h"
10 
11 #include "slurm-perl.h"
12 
13 
14 /*
15  * convert job_step_info_t to perl HV
16  */
17 int
job_step_info_to_hv(job_step_info_t * step_info,HV * hv)18 job_step_info_to_hv(job_step_info_t *step_info, HV *hv)
19 {
20 	int j;
21 	AV *av;
22 
23 	STORE_FIELD(hv, step_info, array_job_id, uint32_t);
24 	STORE_FIELD(hv, step_info, array_task_id, uint32_t);
25 	if (step_info->tres_per_node)
26 		STORE_FIELD(hv, step_info, tres_per_node, charp);
27 	STORE_FIELD(hv, step_info, job_id, uint32_t);
28 	if (step_info->name)
29 		STORE_FIELD(hv, step_info, name, charp);
30 	if (step_info->network)
31 		STORE_FIELD(hv, step_info, network, charp);
32 	if (step_info->nodes)
33 		STORE_FIELD(hv, step_info, nodes, charp);
34 	av = newAV();
35 	for (j = 0; ; j += 2) {
36 		if(step_info->node_inx[j] == -1)
37 			break;
38 		av_store_int(av, j, step_info->node_inx[j]);
39 		av_store_int(av, j+1, step_info->node_inx[j+1]);
40 	}
41 	hv_store_sv(hv, "node_inx", newRV_noinc((SV*)av));
42 	STORE_FIELD(hv, step_info, num_cpus, uint32_t);
43 	STORE_FIELD(hv, step_info, num_tasks, uint32_t);
44 	if(step_info->partition)
45 		STORE_FIELD(hv, step_info, partition, charp);
46 	if(step_info->resv_ports)
47 		STORE_FIELD(hv, step_info, resv_ports, charp);
48 	STORE_FIELD(hv, step_info, run_time, time_t);
49 	STORE_FIELD(hv, step_info, start_time, time_t);
50 	STORE_FIELD(hv, step_info, step_id, uint32_t);
51 	STORE_FIELD(hv, step_info, time_limit, uint32_t);
52 	STORE_FIELD(hv, step_info, user_id, uint32_t);
53 	STORE_FIELD(hv, step_info, state, uint32_t);
54 
55 	return 0;
56 }
57 
58 /*
59  * convert perl HV to job_step_info_t
60  */
61 int
hv_to_job_step_info(HV * hv,job_step_info_t * step_info)62 hv_to_job_step_info(HV *hv, job_step_info_t *step_info)
63 {
64 	SV **svp;
65 	AV *av;
66 	int i, n;
67 
68 	memset(step_info, 0, sizeof(job_step_info_t));
69 
70 	FETCH_FIELD(hv, step_info, array_job_id, uint32_t, TRUE);
71 	FETCH_FIELD(hv, step_info, array_task_id, uint32_t, TRUE);
72 	FETCH_FIELD(hv, step_info, tres_per_node, charp, FALSE);
73 	FETCH_FIELD(hv, step_info, job_id, uint16_t, TRUE);
74 	FETCH_FIELD(hv, step_info, name, charp, FALSE);
75 	FETCH_FIELD(hv, step_info, network, charp, FALSE);
76 	FETCH_FIELD(hv, step_info, nodes, charp, FALSE);
77 
78 	svp = hv_fetch(hv, "node_inx", 8, FALSE);
79 	if (svp && SvROK(*svp) && SvTYPE(SvRV(*svp)) == SVt_PVAV) {
80 		av = (AV*)SvRV(*svp);
81 		n = av_len(av) + 2; /* for trailing -1 */
82 		step_info->node_inx = xmalloc(n * sizeof(int));
83 		for (i = 0 ; i < n-1; i += 2) {
84 			step_info->node_inx[i] = (int)SvIV(*(av_fetch(av, i ,FALSE)));
85 			step_info->node_inx[i+1] = (int)SvIV(*(av_fetch(av, i+1 ,FALSE)));
86 		}
87 		step_info->node_inx[n-1] = -1;
88 	} else {
89 		/* nothing to do */
90 	}
91 
92 	FETCH_FIELD(hv, step_info, num_cpus, uint32_t, TRUE);
93 	FETCH_FIELD(hv, step_info, num_tasks, uint32_t, TRUE);
94 	FETCH_FIELD(hv, step_info, partition, charp, FALSE);
95 	FETCH_FIELD(hv, step_info, resv_ports, charp, FALSE);
96 	FETCH_FIELD(hv, step_info, run_time, time_t, TRUE);
97 	FETCH_FIELD(hv, step_info, start_time, time_t, TRUE);
98 	FETCH_FIELD(hv, step_info, step_id, uint32_t, TRUE);
99 	FETCH_FIELD(hv, step_info, time_limit, uint32_t, TRUE);
100 	FETCH_FIELD(hv, step_info, user_id, uint32_t, TRUE);
101 	FETCH_FIELD(hv, step_info, state, uint32_t, TRUE);
102 
103 	return 0;
104 }
105 
106 /*
107  * convert job_step_info_response_msg_t to perl HV
108  */
109 int
job_step_info_response_msg_to_hv(job_step_info_response_msg_t * job_step_info_msg,HV * hv)110 job_step_info_response_msg_to_hv(
111 	job_step_info_response_msg_t *job_step_info_msg, HV *hv)
112 {
113 	int i;
114 	AV* av;
115 	HV* hv_info;
116 
117 	STORE_FIELD(hv, job_step_info_msg, last_update, time_t);
118 	/* job_step_count implied in job_steps */
119 	av = newAV();
120 	for(i = 0; i < job_step_info_msg->job_step_count; i ++) {
121 		hv_info = newHV();
122 		if (job_step_info_to_hv(
123 			    job_step_info_msg->job_steps + i, hv_info) < 0) {
124 			SvREFCNT_dec(hv_info);
125 			SvREFCNT_dec(av);
126 			return -1;
127 		}
128 		av_store(av, i, newRV_noinc((SV*)hv_info));
129 	}
130 	hv_store_sv(hv, "job_steps", newRV_noinc((SV*)av));
131 	return 0;
132 }
133 
134 /*
135  * convert perl HV to job_step_info_response_msg_t
136  */
137 int
hv_to_job_step_info_response_msg(HV * hv,job_step_info_response_msg_t * step_info_msg)138 hv_to_job_step_info_response_msg(HV *hv,
139 		job_step_info_response_msg_t *step_info_msg)
140 {
141 	int i, n;
142 	SV **svp;
143 	AV *av;
144 
145 	memset(step_info_msg, 0, sizeof(job_step_info_response_msg_t));
146 
147 	FETCH_FIELD(hv, step_info_msg, last_update, time_t, TRUE);
148 
149 	svp = hv_fetch(hv, "job_steps", 9, FALSE);
150 	if (! (svp && SvROK(*svp) && SvTYPE(SvRV(*svp)) == SVt_PVAV)) {
151 		Perl_warn (aTHX_ "job_steps is not an array reference in HV for job_step_info_response_msg_t");
152 		return -1;
153 	}
154 
155 	av = (AV*)SvRV(*svp);
156 	n = av_len(av) + 1;
157 	step_info_msg->job_step_count = n;
158 
159 	step_info_msg->job_steps = xmalloc(n * sizeof(job_step_info_t));
160 	for (i = 0; i < n; i ++) {
161 		svp = av_fetch(av, i, FALSE);
162 		if (! (svp && SvROK(*svp) && SvTYPE(SvRV(*svp)) == SVt_PVHV)) {
163 			Perl_warn (aTHX_ "element %d in job_steps is not valid", i);
164 			return -1;
165 		}
166 		if (hv_to_job_step_info((HV*)SvRV(*svp), &step_info_msg->job_steps[i]) < 0) {
167 			Perl_warn (aTHX_ "failed to convert element %d in job_steps", i);
168 			return -1;
169 		}
170 	}
171 	return 0;
172 }
173 
174 
175 /*
176  * convert slurm_step_layout_t to perl HV
177  */
178 int
slurm_step_layout_to_hv(slurm_step_layout_t * step_layout,HV * hv)179 slurm_step_layout_to_hv(slurm_step_layout_t *step_layout, HV *hv)
180 {
181 	AV* av, *av2;
182 	int i, j;
183 
184 	if (step_layout->front_end)
185 		STORE_FIELD(hv, step_layout, front_end, charp);
186 	STORE_FIELD(hv, step_layout, node_cnt, uint16_t);
187 	if (step_layout->node_list)
188 		STORE_FIELD(hv, step_layout, node_list, charp);
189 	else {
190 		Perl_warn(aTHX_ "node_list missing in slurm_step_layout_t");
191 		return -1;
192 	}
193 	STORE_FIELD(hv, step_layout, plane_size, uint16_t);
194 	av = newAV();
195 	for (i = 0; i < step_layout->node_cnt; i ++)
196 		av_store_uint16_t(av, i, step_layout->tasks[i]);
197 	hv_store_sv(hv, "tasks", newRV_noinc((SV*)av));
198 	STORE_FIELD(hv, step_layout, task_cnt, uint32_t);
199 	STORE_FIELD(hv, step_layout, task_dist, uint16_t);
200 	av = newAV();
201 	for (i = 0; i < step_layout->node_cnt; i ++) {
202 		av2 = newAV();
203 		for (j = 0; j < step_layout->tasks[i]; j ++)
204 			av_store_uint32_t(av2, i, step_layout->tids[i][j]);
205 		av_store(av, i, newRV_noinc((SV*)av2));
206 	}
207 	hv_store_sv(hv, "tids", newRV_noinc((SV*)av));
208 
209 	return 0;
210 }
211 
212 /* convert job_step_pids_t to perl HV */
213 int
job_step_pids_to_hv(job_step_pids_t * pids,HV * hv)214 job_step_pids_to_hv(job_step_pids_t *pids, HV *hv)
215 {
216 	int i;
217 	AV *av;
218 
219 	STORE_FIELD(hv, pids, node_name, charp);
220 	/* pid_cnt implied in pid array */
221 	av = newAV();
222 	for (i = 0; i < pids->pid_cnt; i ++) {
223 		av_store_uint32_t(av, i, pids->pid[i]);
224 	}
225 	hv_store_sv(hv, "pid", newRV_noinc((SV*)av));
226 
227 	return 0;
228 }
229 
230 /* convert job_step_pids_response_msg_t to HV */
231 int
job_step_pids_response_msg_to_hv(job_step_pids_response_msg_t * pids_msg,HV * hv)232 job_step_pids_response_msg_to_hv(job_step_pids_response_msg_t *pids_msg, HV *hv)
233 {
234 	int i = 0;
235 	ListIterator itr;
236 	AV *av;
237 	HV *hv_pids;
238 	job_step_pids_t *pids;
239 
240 	STORE_FIELD(hv, pids_msg, job_id, uint32_t);
241 	STORE_FIELD(hv, pids_msg, step_id, uint32_t);
242 
243 	av = newAV();
244 	itr = slurm_list_iterator_create(pids_msg->pid_list);
245 	while ((pids = (job_step_pids_t *)slurm_list_next(itr))) {
246 		hv_pids = newHV();
247 		if (job_step_pids_to_hv(pids, hv_pids) < 0) {
248 			Perl_warn(aTHX_ "failed to convert job_step_pids_t to hv for job_step_pids_response_msg_t");
249 			SvREFCNT_dec(hv_pids);
250 			SvREFCNT_dec(av);
251 			slurm_list_iterator_destroy(itr);
252 			return -1;
253 		}
254 		av_store(av, i++, newRV_noinc((SV*)hv_pids));
255 	}
256 	slurm_list_iterator_destroy(itr);
257 	hv_store_sv(hv, "pid_list", newRV_noinc((SV*)av));
258 
259 	return 0;
260 }
261 
262 /*
263  * convert job_step_stat_t to perl HV
264  */
265 int
job_step_stat_to_hv(job_step_stat_t * stat,HV * hv)266 job_step_stat_to_hv(job_step_stat_t *stat, HV *hv)
267 {
268 	HV *hv_pids;
269 
270 	STORE_PTR_FIELD(hv, stat, jobacct, "Slurm::jobacctinfo_t");
271 	STORE_FIELD(hv, stat, num_tasks, uint32_t);
272 	STORE_FIELD(hv, stat, return_code, uint32_t);
273 	hv_pids = newHV();
274 	if (job_step_pids_to_hv(stat->step_pids, hv_pids) < 0) {
275 		Perl_warn(aTHX_ "failed to convert job_step_pids_t to hv for job_step_stat_t");
276 		SvREFCNT_dec(hv_pids);
277 		return -1;
278 	}
279 	hv_store_sv(hv, "step_pids", newRV_noinc((SV*)hv_pids));
280 
281 	return 0;
282 }
283 
284 /*
285  * convert job_step_stat_response_msg_t to perl HV
286  */
287 int
job_step_stat_response_msg_to_hv(job_step_stat_response_msg_t * stat_msg,HV * hv)288 job_step_stat_response_msg_to_hv(job_step_stat_response_msg_t *stat_msg, HV *hv)
289 {
290 	int i = 0;
291 	ListIterator itr;
292 	job_step_stat_t *stat;
293 	AV *av;
294 	HV *hv_stat;
295 
296 	STORE_FIELD(hv, stat_msg, job_id, uint32_t);
297 	STORE_FIELD(hv, stat_msg, step_id, uint32_t);
298 
299 	av = newAV();
300 	itr = slurm_list_iterator_create(stat_msg->stats_list);
301 	while ((stat = (job_step_stat_t *)slurm_list_next(itr))) {
302 		hv_stat = newHV();
303 		if(job_step_stat_to_hv(stat, hv_stat) < 0) {
304 			Perl_warn(aTHX_ "failed to convert job_step_stat_t to hv for job_step_stat_response_msg_t");
305 			SvREFCNT_dec(hv_stat);
306 			SvREFCNT_dec(av);
307 			slurm_list_iterator_destroy(itr);
308 			return -1;
309 		}
310 		av_store(av, i++, newRV_noinc((SV*)hv_stat));
311 	}
312 	slurm_list_iterator_destroy(itr);
313 	hv_store_sv(hv, "stats_list", newRV_noinc((SV*)av));
314 
315 	return 0;
316 }
317