Line data Source code
1 : /*
2 : START OF LICENSE STUB
3 : DeDOS: Declarative Dispersion-Oriented Software
4 : Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 :
6 : This program is free software: you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation, either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : END OF LICENSE STUB
19 : */
20 : /**
21 : * @file dfg_reader.c
22 : *
23 : * Defines conversion of JSON strings to dedos_dfg
24 : */
25 :
26 : #include "dfg_reader.h"
27 : #include "dfg.h"
28 : #include "jsmn_parser.h"
29 : #include "jsmn.h"
30 : #include "logging.h"
31 :
32 : #include <strings.h>
33 : #include <stdbool.h>
34 : #include <string.h>
35 :
36 : /** The objects types which can be located in the json DFG
37 : * See ::key_map for usage.
38 : * */
39 : enum object_type {
40 : ROOT=0, RUNTIMES=1, ROUTES=2, DESTINATIONS=3, MSUS=4, PROFILING=5,
41 : META_ROUTING=6, SOURCE_TYPES=7, SCHEDULING=8, DEPENDENCIES=9, MSU_TYPES = 10
42 : };
43 :
44 : /**
45 : * Fixes the thread assignment within the DFG such that the
46 : * pinned and unpinned threads are accurate.
47 : * Must be run, because during execution the only hint of pinned/unpinned is
48 : * msu blocking mode.
49 : * To be run after DFG is fully parsed.
50 : * @return 0 on success, -1 on error
51 : */
52 3 : static int fix_num_threads(struct dedos_dfg *dfg) {
53 5 : for (int i=0; i<dfg->n_runtimes; i++) {
54 3 : struct dfg_runtime *rt = dfg->runtimes[i];
55 :
56 3 : int n_pinned = rt->n_pinned_threads;
57 3 : int n_unpinned = rt->n_unpinned_threads;
58 3 : int total = n_pinned + n_unpinned;
59 21 : for (int t=0; t < total; t++) {
60 18 : struct dfg_thread *thread = rt->threads[t];
61 18 : if (thread->mode == PINNED_THREAD) {
62 7 : n_pinned--;
63 11 : } else if (thread->mode == UNPINNED_THREAD) {
64 5 : n_unpinned--;
65 : } else {
66 6 : if (n_pinned > 0) {
67 2 : thread->mode = PINNED_THREAD;
68 2 : log(LOG_DFG_READER, "Setting thread %d with no MSUs to pinned", t);
69 2 : n_pinned--;
70 4 : } else if (n_unpinned > 0) {
71 4 : thread->mode = UNPINNED_THREAD;
72 4 : log(LOG_DFG_READER, "Setting thread %d with no MSUs to unpinned", t);
73 4 : n_unpinned--;
74 : } else {
75 0 : log_error("Cannot determine pinned/unpinned status of threads "
76 : "based on number of blocking/nonblock MSUs");
77 0 : return -1;
78 : }
79 : }
80 : }
81 3 : if (n_pinned < 0 || n_unpinned < 0) {
82 1 : log_error("More pinned/unpinned threads specified by MSUs than by DFG on rt %d: "
83 : "%d more pinned, %d more unpinned", rt->id, -1 * n_pinned, -1 * n_unpinned);
84 1 : return -1;
85 : }
86 : }
87 2 : return 0;
88 : }
89 :
90 : /**
91 : * Provides the mapping between the keys in the JSON and the functions which are called
92 : * when those keys are encountered.
93 : */
94 : static struct key_mapping key_map[];
95 :
96 1 : struct dedos_dfg *parse_dfg_json_file(const char *filename){
97 :
98 1 : struct dedos_dfg *dfg = calloc(1, sizeof(*dfg));
99 :
100 1 : set_dfg(dfg);
101 :
102 1 : int rtn = parse_file_into_obj(filename, dfg, key_map);
103 :
104 1 : if (rtn >= 0){
105 1 : rtn = fix_num_threads(dfg);
106 1 : if (rtn < 0) {
107 0 : return NULL;
108 : }
109 1 : return dfg;
110 : } else {
111 0 : log_error("Failed to parse jsmn");
112 0 : return NULL;
113 : }
114 : }
115 :
116 : /** Key: "application_name", Object: ::ROOT */
117 1 : PARSE_FN(set_app_name) {
118 1 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
119 1 : char *name = GET_STR_TOK();
120 1 : if (strlen(name) > MAX_APP_NAME_LENGTH) {
121 0 : log_error("Application name '%s' is too long", name);
122 0 : return -1;
123 : }
124 1 : strcpy(dfg->application_name, name);
125 1 : return 0;
126 : }
127 :
128 : /** Key: "global_ctl_ip", Object: ::ROOT */
129 1 : PARSE_FN(set_ctl_ip) {
130 1 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
131 1 : char *ip = GET_STR_TOK();
132 : struct in_addr addr;
133 1 : int rtn = inet_pton(AF_INET, ip, &addr);
134 1 : if (rtn <= 0) {
135 0 : log_perror("Error converting '%s' to IP address", ip);
136 0 : return -1;
137 : }
138 1 : dfg->global_ctl_ip = addr.s_addr;
139 1 : return 0;
140 : }
141 :
142 : /** Key: "global_ctl_port", Object: ::ROOT */
143 1 : PARSE_FN(set_ctl_port) {
144 1 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
145 1 : dfg->global_ctl_port = GET_INT_TOK();
146 1 : return 0;
147 : }
148 :
149 : /** Key: "db_ip", Object: ::ROOT */
150 0 : PARSE_FN(set_db_ip) {
151 0 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
152 0 : char *ip = GET_STR_TOK();
153 : struct in_addr addr;
154 0 : int rtn = inet_pton(AF_INET, ip, &addr);
155 0 : if (rtn <= 0) {
156 0 : log_perror("Error converting '%s' to IP address", ip);
157 0 : return -1;
158 : }
159 0 : dfg->db.ip = addr.s_addr;
160 :
161 0 : return 0;
162 : }
163 :
164 : /** Key: "global_ctl_port", Object: ::ROOT */
165 0 : PARSE_FN(set_db_port) {
166 0 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
167 0 : dfg->db.port = GET_INT_TOK();
168 :
169 0 : return 0;
170 : }
171 :
172 : /** Key: "db_user", Object ::ROOT */
173 0 : PARSE_FN(set_db_user) {
174 0 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
175 0 : char *str_db_user = GET_STR_TOK();
176 0 : memcpy(dfg->db.user, str_db_user, strlen(str_db_user));
177 :
178 0 : return 0;
179 : }
180 :
181 : /** Key: "db_pwd", Object ::ROOT */
182 0 : PARSE_FN(set_db_pwd) {
183 0 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
184 0 : char *str_db_pwd = GET_STR_TOK();
185 0 : memcpy(dfg->db.pwd, str_db_pwd, strlen(str_db_pwd));
186 :
187 0 : return 0;
188 : }
189 :
190 : /** Key: "db_name", Object ::ROOT */
191 0 : PARSE_FN(set_db_name) {
192 0 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
193 0 : char *str_db_name = GET_STR_TOK();
194 0 : memcpy(dfg->db.name, str_db_name, strlen(str_db_name));
195 :
196 0 : return 0;
197 : }
198 :
199 : /** Key: element in "runtimes", Object ::ROOT */
200 1 : INIT_OBJ_FN(init_runtime) {
201 1 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
202 1 : int index = GET_OBJ_INDEX();
203 :
204 1 : dfg->n_runtimes++;
205 1 : dfg->runtimes[index] = calloc(1, sizeof(*dfg->runtimes[index]));
206 :
207 1 : RETURN_OBJ(dfg->runtimes[index], RUNTIMES);
208 : }
209 :
210 : /** Key: "runtimes", Object ::ROOT */
211 1 : PARSE_OBJ_LIST_FN(set_runtimes, init_runtime);
212 :
213 : /** Key: element in "MSUs", Object ::ROOT */
214 3 : INIT_OBJ_FN(init_dfg_msu_from_json) {
215 3 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
216 3 : int index = GET_OBJ_INDEX();
217 :
218 3 : dfg->n_msus++;
219 3 : dfg->msus[index] = calloc(1, sizeof(struct dfg_msu));
220 :
221 3 : RETURN_OBJ(dfg->msus[index], MSUS);
222 : }
223 :
224 : /** Key: "MSUs", Object ::ROOT */
225 1 : PARSE_OBJ_LIST_FN(set_msus, init_dfg_msu_from_json);
226 :
227 : /** Key: element in "MSU_types", Object ::ROOT */
228 2 : INIT_OBJ_FN(init_dfg_msu_type) {
229 2 : struct dedos_dfg *dfg = GET_PARSE_OBJ();
230 :
231 2 : int index = GET_OBJ_INDEX();
232 :
233 2 : dfg->n_msu_types++;
234 2 : dfg->msu_types[index] = calloc(1, sizeof(**dfg->msu_types));
235 :
236 2 : RETURN_OBJ(dfg->msu_types[index], MSU_TYPES);
237 : }
238 :
239 : /** Key: "MSU_types", Object: ::ROOT */
240 1 : PARSE_OBJ_LIST_FN(set_msu_types, init_dfg_msu_type);
241 :
242 : /** Key: "id", Object: ::MSU_TYPES */
243 2 : PARSE_FN(set_msu_type_id) {
244 2 : struct dfg_msu_type *type = GET_PARSE_OBJ();
245 2 : type->id = GET_INT_TOK();
246 2 : return 0;
247 : }
248 :
249 : /** Key: "name", Object: ::MSU_TYPES */
250 2 : PARSE_FN(set_msu_type_name) {
251 2 : struct dfg_msu_type *type = GET_PARSE_OBJ();
252 2 : char *name = GET_STR_TOK();
253 :
254 2 : if (strlen(name) > MAX_MSU_NAME_LEN) {
255 0 : log_error("MSU name %s too long", name);
256 0 : return -1;
257 : }
258 2 : strcpy(type->name, name);
259 2 : return 0;
260 : }
261 :
262 : /** Key: "meta_routing", Object: ::MSU_TYPES */
263 0 : PARSE_OBJ_FN(set_meta_routing, struct dfg_msu_type, meta_routing, META_ROUTING);
264 :
265 : /** Key: Element in "dependencies", Object: ::MSU_TYPES */
266 0 : INIT_OBJ_FN(init_dependencies) {
267 0 : struct dfg_msu_type *type = GET_PARSE_OBJ();
268 0 : int index = GET_OBJ_INDEX();
269 :
270 0 : type->n_dependencies++;
271 0 : type->dependencies[index] = calloc(1, sizeof(*type->dependencies[index]));
272 :
273 0 : RETURN_OBJ(type->dependencies[index], DEPENDENCIES);
274 : }
275 :
276 : /** Key: "dependencies", Object ::MSU_TYPES */
277 0 : PARSE_OBJ_LIST_FN(set_dependencies, init_dependencies);
278 :
279 : /** Key: "cloneable", Object ::MSU_TYPES */
280 0 : PARSE_FN(set_cloneable) {
281 0 : struct dfg_msu_type *type = GET_PARSE_OBJ();
282 0 : type->cloneable = GET_INT_TOK();
283 0 : return 0;
284 : }
285 :
286 : /** Key: "colocation_group", object ::MSU_TYPES */
287 0 : PARSE_FN(set_colocation_group) {
288 0 : struct dfg_msu_type *type = GET_PARSE_OBJ();
289 0 : type->colocation_group = GET_INT_TOK();
290 0 : return 0;
291 : }
292 :
293 : /** Key: "init_data", Object: ::MSUS */
294 0 : PARSE_FN(set_msu_init_data) {
295 0 : struct dfg_msu *vertex = GET_PARSE_OBJ();
296 :
297 0 : char *init_data = GET_STR_TOK();
298 0 : if (strlen(init_data) > MAX_INIT_DATA_LEN) {
299 0 : log_error("Init data '%s' too long", init_data);
300 0 : return -1;
301 : }
302 0 : strcpy(vertex->init_data.init_data, init_data);
303 0 : return 0;
304 : }
305 :
306 : /** Key: "id", Object ::MSUS */
307 3 : PARSE_FN(set_msu_id) {
308 3 : struct dfg_msu *msu = GET_PARSE_OBJ();
309 3 : msu->id = GET_INT_TOK();
310 3 : return 0;
311 : }
312 :
313 : /** Key: "vertex_type", Object ::MSUS */
314 2 : PARSE_FN(set_msu_vertex_type) {
315 2 : struct dfg_msu *msu = GET_PARSE_OBJ();
316 2 : char *str_type = GET_STR_TOK();
317 2 : msu->vertex_type = str_to_vertex_type(str_type);
318 2 : return 0;
319 : }
320 :
321 : /** Key "type", Object ::MSUS */
322 3 : PARSE_FN(set_msu_type) {
323 3 : struct dfg_msu *vertex = GET_PARSE_OBJ();
324 :
325 3 : struct dfg_msu_type *type = get_dfg_msu_type(GET_INT_TOK());
326 3 : if (type == NULL) {
327 : // Return once type has been instantiated
328 0 : return 1;
329 : }
330 3 : vertex->type = type;
331 :
332 3 : type->instances[type->n_instances] = vertex;
333 3 : type->n_instances++;
334 3 : return 0;
335 : }
336 :
337 : /** key: "blocking_mode", object: ::MSUS */
338 6 : PARSE_FN(set_blocking_mode) {
339 6 : struct dfg_msu *vertex = GET_PARSE_OBJ();
340 :
341 6 : char *str_mode = GET_STR_TOK();
342 :
343 6 : vertex->blocking_mode = str_to_blocking_mode(str_mode);
344 6 : if (vertex->blocking_mode == UNKNOWN_BLOCKING_MODE) {
345 0 : log_error("Unknown blocking mode specified: %s", str_mode);
346 0 : return -1;
347 : }
348 :
349 6 : struct dfg_runtime *rt = vertex->scheduling.runtime;
350 6 : if (rt == NULL) {
351 3 : return 1;
352 : }
353 :
354 3 : struct dfg_thread *thread = vertex->scheduling.thread;
355 3 : if (thread == NULL) {
356 0 : log(LOG_DFG_READER, "Waiting for thread instantiation");
357 0 : return 1;
358 : }
359 :
360 3 : if (thread->mode == UNSPECIFIED_THREAD_MODE) {
361 3 : thread->mode = (vertex->blocking_mode == NONBLOCK_MSU) ? PINNED_THREAD : UNPINNED_THREAD;
362 : }
363 :
364 3 : if ((thread->mode == PINNED_THREAD) ^ (vertex->blocking_mode == NONBLOCK_MSU)) {
365 0 : log_error("Can only put blocking MSUs on pinned threads, and nonblock MSUs on unpinned");
366 0 : return -1;
367 : }
368 3 : return 0;
369 : }
370 :
371 : /** Key: "scheduling", Object ::MSUS */
372 3 : PARSE_OBJ_FN(set_scheduling, struct dfg_msu, scheduling, SCHEDULING);
373 :
374 : /** Key: id, Object ::RUNTIMES */
375 1 : PARSE_FN(set_rt_id) {
376 1 : struct dfg_runtime *rt = GET_PARSE_OBJ();
377 1 : rt->id = GET_INT_TOK();
378 1 : return 0;
379 : }
380 :
381 : /** Key: ip, Object ::RUNTIMES */
382 1 : PARSE_FN(set_rt_ip) {
383 1 : struct dfg_runtime *rt = GET_PARSE_OBJ();
384 1 : char *ip = GET_STR_TOK();
385 : struct in_addr addr;
386 1 : int rtn = inet_pton(AF_INET, ip, &addr);
387 1 : if (rtn <= 0) {
388 0 : log_perror("Error converting '%s' to IP address", ip);
389 0 : return -1;
390 : }
391 1 : rt->ip = addr.s_addr;
392 1 : return 0;
393 : }
394 :
395 : /** Key: port, object ::RUNTIMES */
396 1 : PARSE_FN(set_rt_port) {
397 1 : struct dfg_runtime *rt = GET_PARSE_OBJ();
398 1 : rt->port = GET_INT_TOK();
399 1 : return 0;
400 : }
401 :
402 : /** Key: num_cores, object ::RUNTIMES */
403 1 : PARSE_FN(set_rt_n_cores) {
404 1 : struct dfg_runtime *rt = GET_PARSE_OBJ();
405 1 : rt->n_cores = GET_INT_TOK();
406 1 : return 0;
407 : }
408 :
409 : /** Key: num_pinned_threads, object ::RUNTIMES */
410 1 : PARSE_FN(set_num_pinned_threads) {
411 1 : struct dfg_runtime *rt = GET_PARSE_OBJ();
412 :
413 1 : int n_existing = rt->n_unpinned_threads;
414 1 : int n_new = GET_INT_TOK();
415 :
416 3 : for (int i=n_existing; i<n_existing+n_new; i++) {
417 2 : rt->threads[i] = calloc(1, sizeof(**rt->threads));
418 2 : rt->threads[i]->id = i+1;
419 : }
420 1 : rt->n_pinned_threads = n_new;
421 1 : return 0;
422 : }
423 :
424 : /** Key: num_unpinned_threads, object ::RUNTIMES */
425 1 : PARSE_FN(set_num_unpinned_threads) {
426 1 : struct dfg_runtime *rt = GET_PARSE_OBJ();
427 :
428 1 : int n_existing = rt->n_pinned_threads;
429 1 : int n_new = GET_INT_TOK();
430 :
431 2 : for (int i=n_existing; i < n_existing + n_new; i++) {
432 1 : rt->threads[i] = calloc(1, sizeof(**rt->threads));
433 1 : rt->threads[i]->id = i+1;
434 : }
435 1 : rt->n_unpinned_threads = n_new;
436 1 : return 0;
437 : }
438 :
439 : /** Key: Element in "routes", object ::RUNTIMES */
440 2 : INIT_OBJ_FN(init_route) {
441 2 : struct dfg_runtime *rt = GET_PARSE_OBJ();
442 2 : int index = GET_OBJ_INDEX();
443 2 : rt->n_routes++;
444 2 : rt->routes[index] = calloc(1, sizeof(**rt->routes));
445 2 : rt->routes[index]->runtime = rt;
446 :
447 2 : RETURN_OBJ(rt->routes[index], ROUTES);
448 : }
449 :
450 : /** Key: "routes", object ::RUNTIMES */
451 1 : PARSE_OBJ_LIST_FN(set_rt_routes, init_route);
452 :
453 : /** Key: "id", object ::ROUTES */
454 2 : PARSE_FN(set_route_id) {
455 2 : struct dfg_route *route = GET_PARSE_OBJ();
456 2 : int id = GET_INT_TOK();
457 2 : struct dfg_route *existing = get_dfg_route(id);
458 2 : if (existing != NULL) {
459 0 : log_error("Route with ID %d exists twice in DFG", id);
460 0 : return -1;
461 : }
462 2 : route->id = id;
463 2 : log(LOG_DFG_PARSING, "Created route with id: %d", id);
464 2 : return 0;
465 : }
466 :
467 : /** Key: "type", object ::ROUTES */
468 2 : PARSE_FN(set_route_type) {
469 2 : struct dfg_route *route = GET_PARSE_OBJ();
470 2 : int type_id = GET_INT_TOK();
471 2 : struct dfg_msu_type *type = get_dfg_msu_type(type_id);
472 2 : if (type == NULL) {
473 : // Return once type is instantiated
474 0 : return -1;
475 : }
476 2 : route->msu_type = type;
477 2 : return 0;
478 : }
479 :
480 : /** Key: Element in "endpoints", object ::ROUTES */
481 2 : INIT_OBJ_FN(init_endpoint) {
482 2 : struct dfg_route *route = GET_PARSE_OBJ();
483 :
484 2 : int index = GET_OBJ_INDEX();
485 2 : route->n_endpoints++;
486 2 : route->endpoints[index] = calloc(1, sizeof(**route->endpoints));
487 :
488 2 : RETURN_OBJ(route->endpoints[index], DESTINATIONS);
489 : }
490 :
491 : /** Key: "endpoints", object ::ROUTES */
492 2 : PARSE_OBJ_LIST_FN(set_route_endpoints, init_endpoint);
493 :
494 : /** Key: "key", object ::DESTINATIONS */
495 2 : PARSE_FN(set_dest_key) {
496 2 : struct dfg_route_endpoint *dest = GET_PARSE_OBJ();
497 2 : dest->key = GET_INT_TOK();
498 2 : return 0;
499 : }
500 :
501 : /** Key: "msu", object ::DESTINATIONS */
502 4 : PARSE_FN(set_dest_msu) {
503 4 : struct dfg_route_endpoint *dest = GET_PARSE_OBJ();
504 4 : int msu_id = GET_INT_TOK();
505 :
506 4 : struct dfg_msu *msu = get_dfg_msu(msu_id);
507 4 : if (msu == NULL) {
508 : // Wait for MSU to be instantiated
509 2 : log(LOG_DFG_PARSING, "MSU %d is not yet instantiated", msu_id);
510 2 : return 1;
511 : }
512 2 : dest->msu = msu;
513 2 : return 0;
514 : }
515 :
516 : /** Key: "source_types", object ::META_ROUTING */
517 0 : PARSE_FN(set_source_types) {
518 0 : struct dfg_meta_routing *meta = GET_PARSE_OBJ();
519 : int i;
520 0 : bool found_types = true;
521 0 : START_ITER_TOK_LIST(i) {
522 0 : int str_type = GET_INT_TOK();
523 0 : struct dfg_msu_type *type = get_dfg_msu_type(str_type);
524 0 : if (type == NULL) {
525 : // Wait for type to be instantiated
526 0 : log(LOG_DFG_PARSING, "Type %d is not yet instantiated", str_type);
527 0 : found_types = false;
528 : } else {
529 0 : meta->src_types[i] = type;
530 : }
531 0 : } END_ITER_TOK_LIST(i)
532 0 : meta->n_src_types = i;
533 0 : if (found_types == false)
534 0 : return 1;
535 0 : return 0;
536 : }
537 :
538 : /** Key: "dst_types", object ::META_ROUTING */
539 0 : PARSE_FN(set_dst_types) {
540 0 : struct dfg_meta_routing *meta = GET_PARSE_OBJ();
541 0 : bool found_types = true;
542 : int i;
543 0 : START_ITER_TOK_LIST(i) {
544 0 : int str_type = GET_INT_TOK();
545 0 : struct dfg_msu_type *type = get_dfg_msu_type(str_type);
546 0 : if (type == NULL) {
547 0 : log(LOG_DFG_PARSING, "Type %d is not yet instantiated", str_type);
548 0 : found_types = false;
549 : } else {
550 0 : meta->dst_types[i] = type;
551 : }
552 0 : } END_ITER_TOK_LIST(i)
553 :
554 0 : meta->n_dst_types = i;
555 0 : if (found_types == false) {
556 0 : return 1;
557 : }
558 0 : return 0;
559 : }
560 :
561 : /** key: "type", object ::DEPENDENCIES */
562 0 : PARSE_FN(set_dep_type) {
563 0 : struct dfg_dependency *dep = GET_PARSE_OBJ();
564 :
565 0 : int type_id = GET_INT_TOK();
566 0 : struct dfg_msu_type *type = get_dfg_msu_type(type_id);
567 :
568 0 : if (type == NULL) {
569 : // Return once type has been instantiated
570 0 : log(LOG_DFG_PARSING, "Type %d is not yet instantiated", type_id);
571 0 : return 1;
572 : }
573 0 : dep->type = type;
574 0 : return 0;
575 : }
576 :
577 : /** Key: "locality", object: ::DEPENDENCIES */
578 0 : PARSE_FN(set_dep_locality) {
579 0 : struct dfg_dependency *dep = GET_PARSE_OBJ();
580 :
581 0 : char *str_loc = GET_STR_TOK();
582 0 : if (strcasecmp(str_loc, "local") == 0) {
583 0 : dep->locality = MSU_IS_LOCAL;
584 0 : } else if (strcasecmp(str_loc, "remote") == 0) {
585 0 : dep->locality = MSU_IS_REMOTE;
586 : } else {
587 0 : log_error("Unknown locality %s specified. Must be 'local' or 'remote'", str_loc);
588 : }
589 0 : return 0;
590 : }
591 :
592 : /** Key: "runtime", object: ::SCHEDULING */
593 3 : PARSE_FN(set_msu_runtime) {
594 3 : struct dfg_scheduling *sched = GET_PARSE_OBJ();
595 :
596 3 : int id = GET_INT_TOK();
597 3 : struct dfg_runtime *rt = get_dfg_runtime(id);
598 3 : if (rt == NULL) {
599 0 : log(LOG_DFG_PARSING, "Runtime %d is not yet instantiated", id);
600 0 : return 1;
601 : }
602 3 : sched->runtime = rt;
603 3 : return 0;
604 : }
605 :
606 : /** Key: "thread_id", object: ::SCHEDULING */
607 3 : PARSE_FN(set_msu_thread) {
608 3 : struct dfg_scheduling *sched = GET_PARSE_OBJ();
609 :
610 3 : if (sched->runtime == NULL) {
611 : // Runtime must be instantiated before thread
612 0 : log(LOG_DFG_PARSING, "MSU runtime not yet instantiated");
613 0 : return 1;
614 : }
615 3 : int id = GET_INT_TOK();
616 3 : struct dfg_thread *thread = get_dfg_thread(sched->runtime, id);
617 3 : if (thread == NULL) {
618 : // Thread must be instantiated too
619 0 : log(LOG_DFG_PARSING, "Thread %d not yet instantiated", id);
620 0 : return 1;
621 : }
622 3 : sched->thread = thread;
623 :
624 : // This is frustrating...
625 : // Have to iterate through all MSUs to find the one this scheduling object refers to
626 : // Should perhaps provide parse object as a linked list so you can traverse upwards?
627 3 : struct dedos_dfg *dfg = get_root_jsmn_obj();
628 3 : struct dfg_msu *msu = NULL;
629 6 : for (int i=0; i<dfg->n_msus; i++) {
630 6 : if (&dfg->msus[i]->scheduling == sched) {
631 3 : msu = dfg->msus[i];
632 3 : break;
633 : }
634 : }
635 : // Shouldn't happen, really...
636 3 : if (msu == NULL) {
637 0 : log(LOG_DFG_PARSING, "Msu for thead %d not yet instantiated", id);
638 0 : return 1;
639 : }
640 3 : thread->msus[thread->n_msus] = msu;
641 3 : thread->n_msus++;
642 :
643 3 : return 0;
644 : }
645 :
646 : /** key: "routes", object ::SCHEDULING */
647 2 : PARSE_FN(set_msu_routes) {
648 2 : struct dfg_scheduling *sched = GET_PARSE_OBJ();
649 :
650 2 : bool set_routes = true;
651 : int i;
652 2 : log(LOG_DFG_PARSING, "MSU_ROUTE pre TOK: %s", GET_STR_TOK());
653 4 : START_ITER_TOK_LIST(i) {
654 2 : log(LOG_DFG_PARSING, "MSU_ROUTE TOK: %s", GET_STR_TOK());
655 2 : int route_id = GET_INT_TOK();
656 2 : struct dfg_route *route = get_dfg_route(route_id);
657 2 : if (route == NULL) {
658 0 : log(LOG_DFG_PARSING, "Route %d not yet instantiated for msu", route_id);
659 0 : set_routes = false;
660 : } else {
661 2 : sched->routes[i] = route;
662 : }
663 2 : } END_ITER_TOK_LIST(i)
664 :
665 2 : sched->n_routes = i;
666 2 : if (!set_routes) {
667 0 : return 1;
668 : }
669 2 : return 0;
670 : }
671 :
672 : /** To be used to raise an error when a JSON key is deprecated */
673 0 : static int not_implemented(jsmntok_t **tok, char *j, struct json_state *in, struct json_state **saved) {
674 0 : log_warn("JSON key %s is not implemented in DFG reader", tok_to_str((*tok)-1, j));
675 0 : return 0;
676 : }
677 :
678 : /**
679 : * (See jsmn_parser.h for details of key_mapping structure)
680 : */
681 : static struct key_mapping key_map[] = {
682 : { "application_name", ROOT, set_app_name },
683 : { "global_ctl_ip", ROOT, set_ctl_ip },
684 : { "global_ctl_port", ROOT, set_ctl_port },
685 : { "db_ip", ROOT, set_db_ip },
686 : { "db_port", ROOT, set_db_port },
687 : { "db_user", ROOT, set_db_user },
688 : { "db_pwd", ROOT, set_db_pwd },
689 : { "db_name", ROOT, set_db_name },
690 :
691 : { "MSU_types", ROOT, set_msu_types },
692 : { "MSUs", ROOT, set_msus },
693 : { "runtimes", ROOT, set_runtimes },
694 :
695 : { "id", MSU_TYPES, set_msu_type_id},
696 : { "name", MSU_TYPES, set_msu_type_name },
697 : { "meta_routing", MSU_TYPES, set_meta_routing },
698 : { "dependencies", MSU_TYPES, set_dependencies },
699 : { "cloneable", MSU_TYPES, set_cloneable },
700 : { "colocation_group", MSU_TYPES, set_colocation_group },
701 :
702 : { "id", MSUS, set_msu_id },
703 : { "vertex_type", MSUS, set_msu_vertex_type },
704 : { "init_data", MSUS, set_msu_init_data },
705 : { "type", MSUS, set_msu_type },
706 : { "blocking_mode", MSUS, set_blocking_mode },
707 : { "scheduling", MSUS, set_scheduling },
708 :
709 : { "id", RUNTIMES, set_rt_id },
710 : { "ip", RUNTIMES, set_rt_ip },
711 : { "port", RUNTIMES, set_rt_port },
712 : { "num_cores", RUNTIMES, set_rt_n_cores },
713 : { "num_pinned_threads", RUNTIMES, set_num_pinned_threads },
714 : { "num_unpinned_threads", RUNTIMES, set_num_unpinned_threads },
715 : { "routes", RUNTIMES, set_rt_routes },
716 :
717 : { "id", ROUTES, set_route_id },
718 : { "type", ROUTES, set_route_type },
719 : { "endpoints", ROUTES, set_route_endpoints },
720 :
721 : { "key", DESTINATIONS, set_dest_key },
722 : { "msu", DESTINATIONS, set_dest_msu },
723 :
724 : { "source_types", META_ROUTING, set_source_types },
725 : { "dst_types", META_ROUTING, set_dst_types },
726 :
727 : { "type", DEPENDENCIES, set_dep_type },
728 : { "locality", DEPENDENCIES, set_dep_locality },
729 :
730 : { "runtime", SCHEDULING, set_msu_runtime },
731 : { "thread_id", SCHEDULING, set_msu_thread },
732 : { "routes", SCHEDULING, set_msu_routes },
733 :
734 : { "load_mode", ROOT, not_implemented },
735 : { "application_deadline", ROOT, not_implemented },
736 : { "profiling", MSUS, not_implemented },
737 : { "statistics", MSUS, not_implemented },
738 : { "dram", RUNTIMES, not_implemented },
739 : { "io_network_bw", RUNTIMES, not_implemented},
740 : { "deadline", SCHEDULING, not_implemented},
741 : { NULL, 0, NULL }
742 : };
743 :
|