void rmsummary_print(FILE *stream, struct rmsummary *s, struct jx *verbatim_fields) { struct jx *jsum = rmsummary_to_json(s, 0); if(verbatim_fields) { if(!jx_istype(verbatim_fields, JX_OBJECT)) { fatal("Vebatim fields are not a json object."); } struct jx_pair *head = verbatim_fields->u.pairs; while(head) { jx_insert(jsum, jx_copy(head->key), jx_copy(head->value)); head = head->next; } } jx_pretty_print_stream(jsum, stream); jx_delete(jsum); }
/* Write the task and run info to the task directory * These files are hardcoded to task_info and run_info */ static int makeflow_archive_write_task_info(struct archive_instance *a, struct dag_node *n, struct batch_task *t, char *archive_path) { struct batch_file *f; /* task_info : * COMMAND: Tasks command that was run * SRC_COMMAND: Origin node's command for reference * SRC_LINE: Line of origin node in SRC_MAKEFLOW * SRC_MAKEFLOW: ID of file for the original Makeflow stored in archive * INPUT_FILES: Alphabetic list of input files checksum IDs * OUTPUT_FILES: Alphabetic list of output file inner_names */ struct jx *task_jx = jx_object(NULL); jx_insert(task_jx, jx_string("COMMAND"), jx_string(t->command)); jx_insert(task_jx, jx_string("SRC_COMMAND"), jx_string(n->command)); jx_insert(task_jx, jx_string("SRC_LINE"), jx_integer(n->linenum)); jx_insert(task_jx, jx_string("SRC_MAKEFLOW"), jx_string(a->source_makeflow)); struct jx * input_files = jx_object(NULL); struct list_cursor *cur = list_cursor_create(t->input_files); for(list_seek(cur, 0); list_get(cur, (void**)&f); list_next(cur)) { /* Generate the file archive id (content based) if does not exist. */ char * id; if(path_is_dir(f->inner_name) == 1){ f->hash = batch_file_generate_id_dir(f->inner_name); id = xxstrdup(f->hash); } else{ id = batch_file_generate_id(f); } jx_insert(input_files, jx_string(f->inner_name), jx_string(id)); free(id); } list_cursor_destroy(cur); jx_insert(task_jx, jx_string("INPUT_FILES"), input_files); struct jx * output_files = jx_object(NULL); cur = list_cursor_create(t->output_files); for(list_seek(cur, 0); list_get(cur, (void**)&f); list_next(cur)) { /* Generate the file archive id (content based) if does not exist. */ char * id; if(path_is_dir(f->inner_name) == 1){ f->hash = batch_file_generate_id_dir(f->inner_name); id = xxstrdup(f->hash); } else{ id = batch_file_generate_id(f); } jx_insert(output_files, jx_string(f->inner_name), jx_string(id)); free(id); } list_cursor_destroy(cur); jx_insert(task_jx, jx_string("OUTPUT_FILES"), output_files); char *task_info = string_format("%s/task_info", archive_path); FILE *fp = fopen(task_info, "w"); if (fp == NULL) { free(task_info); debug(D_ERROR|D_MAKEFLOW_HOOK, "could not create task_info for node %d archive", n->nodeid); return 0; } else { jx_pretty_print_stream(task_jx, fp); } fclose(fp); free(task_info); jx_delete(task_jx); /* run_info : * SUBMITTED : Time task was submitted * STARTED : Time task was started * FINISHED : Time task was completed * EXIT_NORMALLY : 0 if abnormal exit, 1 is normal * EXIT_CODE : Task's exit code * EXIT_SIGNAL : Int value of signal if occurred */ struct jx * run_jx = jx_object(NULL); jx_insert(run_jx, jx_string("SUBMITTED"), jx_integer(t->info->submitted)); jx_insert(run_jx, jx_string("STARTED"), jx_integer(t->info->started)); jx_insert(run_jx, jx_string("FINISHED"), jx_integer(t->info->finished)); jx_insert(run_jx, jx_string("EXIT_NORMAL"), jx_integer(t->info->exited_normally)); jx_insert(run_jx, jx_string("EXIT_CODE"), jx_integer(t->info->exit_code)); jx_insert(run_jx, jx_string("EXIT_SIGNAL"), jx_integer(t->info->exit_signal)); task_info = string_format("%s/run_info", archive_path); fp = fopen(task_info, "w"); if (fp == NULL) { free(task_info); debug(D_ERROR|D_MAKEFLOW_HOOK, "could not create run_info for node %d archive", n->nodeid); return 0; } else { jx_pretty_print_stream(run_jx, fp); } fclose(fp); free(task_info); jx_delete(run_jx); return 1; }