#include #include #include #include #include #include #include #include "trick/FrameLog.hh" #include "trick/FrameDataRecordGroup.hh" #include "trick/exec_proto.hh" #include "trick/exec_proto.h" #include "trick/data_record_proto.h" #include "trick/command_line_protos.h" #include "trick/message_proto.h" #include "trick/message_type.h" Trick::FrameLog * the_fl = NULL ; //Constructor. Trick::FrameLog::FrameLog(Trick::Clock & in_clock) : frame_log_flag(false), drg_trick(NULL), drg_frame(NULL), plots_per_page(6), timeline(NULL), timeline_other(NULL), num_threads(1), tl_max_samples(100000), tl_count(NULL), tl_other_count(NULL), log_init_start(false), log_init_end(false), fp_time_main(NULL), fp_time_other(NULL), clock(in_clock) { time_value_attr.type = TRICK_LONG_LONG ; time_value_attr.size = sizeof(long long) ; time_value_attr.units = strdup("s") ; the_fl = this ; } Trick::FrameLog::~FrameLog() { free((char *)time_value_attr.units) ; // leaking all of the FrameDataRecordGroups // leaking timeline memory. } /** @details This routine is called during the "default_data" phase of initialization. At that time the number of threads in the sim will be known and this ensure that everything is allocated before the input_processor is initially run. -# Allocate a FrameDataRecordGroup to hold user job information on the main thread -# Push the FrameDataRecordGroup to drg_users. -# For each child thread in the sim -# Allocate a FrameDataRecordGroup to hold user job information on the child thread -# Push the FrameDataRecordGroup to drg_users. -# Allocate a FrameDataRecordGroup to hold trick job information -# Allocate a FrameDataRecordGroup to hold frame information -# Allocate space for timeline for each thread. */ void Trick::FrameLog::allocate_recording_groups() { Trick::FrameDataRecordGroup * fdrg ; int ii ; /* Create log_user_jobs group and log_trick_jobs group to record job frame_times. */ fdrg = new ("trick_frame_userjobs_main") Trick::FrameDataRecordGroup(0, "frame_userjobs_main") ; drg_users.push_back(fdrg) ; num_threads = exec_get_num_threads(); for ( ii = 1 ; ii < num_threads ; ii++ ) { std::ostringstream group_name ; group_name << "trick_frame_userjobs_C" << ii ; fdrg = new (group_name.str().c_str()) Trick::FrameDataRecordGroup(ii, group_name.str()) ; drg_users.push_back(fdrg) ; } drg_trick = new ("trick_frame_trick_jobs") FrameDataRecordGroup(0, "frame_trickjobs") ; drg_frame = new ("trick_frame") FrameDataRecordGroup(0, "frame") ; /* Allocate space for timeline for each thread according to user settable tl_max_samples variable. */ timeline = (Trick::timeline_t **)calloc( num_threads, sizeof(Trick::timeline_t*)); timeline_other = (Trick::timeline_t **)calloc( num_threads, sizeof(Trick::timeline_t*)); for (ii=0; ii all_jobs_vector ; exec_get_all_jobs_vector(all_jobs_vector) ; for ( ii = 0 ; ii < all_jobs_vector.size() ; ii++ ) { /** @li only makes sense to record frame time for scheduled, integ, and end_of_frame jobs */ /** @li exclude system jobs because they are excluded in instrument_before/after */ /** @li exclude frame_log jobs */ if ( (all_jobs_vector[ii]->job_class >= exec_get_scheduled_start_index() || (! all_jobs_vector[ii]->job_class_name.compare("integration")) || (! all_jobs_vector[ii]->job_class_name.compare("derivative")) || (! all_jobs_vector[ii]->job_class_name.compare("dynamic_event")) || (! all_jobs_vector[ii]->job_class_name.compare("post_integration")) || (! all_jobs_vector[ii]->job_class_name.compare("system_thread_sync")) || (! all_jobs_vector[ii]->job_class_name.compare("top_of_frame")) || (! all_jobs_vector[ii]->job_class_name.compare("end_of_frame"))) ) { dot = all_jobs_vector[ii]->name.find_first_of("."); if (!all_jobs_vector[ii]->name.compare(dot,11,".frame_log.")) { continue; } new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ; /** @li add job frame id, job class and cycle time to displayed job name, and prepend "JOB_" so it stands out in quickplot */ if ( all_jobs_vector[ii]->job_class >= exec_get_scheduled_start_index() ) { if ( all_jobs_vector[ii]->thread == 0 ) { asprintf(&job_name, "JOB_%s.%2.2f(%s_%2.3f)", all_jobs_vector[ii]->name.c_str(), all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str(), all_jobs_vector[ii]->cycle); } else { // add child thread # to name asprintf(&job_name, "JOB_%s_C%d.%2.2f(%s_%2.3f)", all_jobs_vector[ii]->name.c_str(), all_jobs_vector[ii]->thread, all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str(), all_jobs_vector[ii]->cycle); } } else { // non-scheduled class asprintf(&job_name, "JOB_%s.%2.2f(%s)", all_jobs_vector[ii]->name.c_str(), all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str()); } // replace any colons in (C++) job name with underscores char *colon = strchr(job_name, ':') ; while (colon) { colon[0] = '#'; colon = strchr(job_name, ':') ; } new_ref->reference = job_name; new_ref->address = &(all_jobs_vector[ii]->frame_time) ; new_ref->attr = &time_value_attr ; /** @li use TRK tag in S_define to identify trick jobs */ // trick jobs if ( all_jobs_vector[ii]->tags.count("TRK") ) { trick_jobs.push_back(std::string(job_name)); drg_trick->add_variable(new_ref) ; drg_trick->add_rec_job(all_jobs_vector[ii]) ; // save names of trick sim objects (ones that user can change) so we can color code jobs in DP file if (!all_jobs_vector[ii]->name.compare(dot,5,".drd.")) { dr_sim_object_name = all_jobs_vector[ii]->parent_object->name; } if (!all_jobs_vector[ii]->name.compare(dot,8,".master.")) { ms_sim_object_name = all_jobs_vector[ii]->parent_object->name; } if (!all_jobs_vector[ii]->name.compare(dot,9,".rt_sync.")) { rt_sim_object_name = all_jobs_vector[ii]->parent_object->name; } //TODO: no message jobs yet - fill this in when messaging has a job to look at here // if () { msg_sim_object_name = std::string("message"); //} // user jobs } else { user_jobs.push_back(std::string(job_name)); drg_users[all_jobs_vector[ii]->thread]->add_variable(new_ref) ; drg_users[all_jobs_vector[ii]->thread]->add_rec_job(all_jobs_vector[ii]) ; } } } /* set the recoring job be and end of frame job. Set each recording group to it's proper thread. */ std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ; for ( fdrg_it = drg_users.begin() , ii = 0 ; fdrg_it != drg_users.end() ; fdrg_it++ , ii++ ) { (*fdrg_it)->set_job_class("end_of_frame") ; (*fdrg_it)->set_phase(65533); (*fdrg_it)->set_thread(ii); if ( ii > 0 ) { std::ostringstream group_name ; group_name << "trick_frame_userjobs_C" << ii ; (*fdrg_it)->add_variable( group_name.str() + ".frame_sched_time") ; } } drg_trick->set_job_class("end_of_frame") ; drg_trick->set_phase(65535); } /** @details -# Add the log_userjob frame time we created above to the log_frame group -# Add the log_trickjob frame time we created above to the log_frame group -# Set the recording job data_record_group.frame to end of frame - phase it last (after rt_monitor) because time set in rt_monitor */ void Trick::FrameLog::add_recording_vars_for_frame() { REF2 * new_ref ; char * job_name = NULL ; int ii ; drg_frame->add_variable(rt_sim_object_name + std::string(".rt_sync.frame_sched_time")) ; drg_frame->add_variable(rt_sim_object_name + std::string(".rt_sync.frame_overrun_time")) ; /* add the log_userjob frame time we created above to the log_frame group */ for ( ii = 0 ; ii < num_threads ; ii++ ) { new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ; if (ii > 0) { asprintf(&job_name, "JOB_data_record_group_frame_userjobs_C%d.data_record.%2.2f(end_of_frame)", ii,drg_users[ii]->write_job->frame_id); } else { asprintf(&job_name, "JOB_data_record_group_frame_userjobs.data_record.%2.2f(end_of_frame)", drg_users[ii]->write_job->frame_id); } trick_jobs.push_back(std::string(job_name)); new_ref->reference = job_name; new_ref->address = &(drg_users[ii]->write_job->frame_time); new_ref->attr = &time_value_attr ; drg_frame->add_variable(new_ref) ; drg_frame->add_rec_job(drg_users[ii]->write_job) ; } /* add the log_trickjob frame time we created above to the log_frame group */ new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ; asprintf(&job_name, "JOB_data_record_group.trickjobs.%2.2f(end_of_frame)",drg_trick->jobs[0]->frame_id); trick_jobs.push_back(std::string(job_name)); new_ref->reference = job_name; new_ref->address = &(drg_trick->write_job->frame_time); new_ref->attr = &time_value_attr ; drg_frame->add_variable(new_ref) ; drg_frame->add_rec_job(drg_trick->write_job) ; /* set the recording job data_record_group.frame to end of frame - phase it last (after rt_monitor) because time set in rt_monitor */ drg_frame->set_job_class("end_of_frame") ; drg_frame->set_phase(65535); } /** @details -# For each FrameDataRecordGroup in drg_users -# Call add_data_record_group -# Call add_data_record_group for drg_trick -# Call add_data_record_group for drg_frame */ void Trick::FrameLog::add_recording_groups_to_sim() { std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ; for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; fdrg_it++ ) { add_data_record_group( *fdrg_it , Trick::DR_Ring_Buffer) ; } add_data_record_group(drg_trick, Trick::DR_Ring_Buffer) ; add_data_record_group(drg_frame, Trick::DR_Ring_Buffer) ; } /** @details -# For each FrameDataRecordGroup in drg_users -# Call remove_data_record_group -# Call remove_data_record_group for drg_trick -# Call remove_data_record_group for drg_frame */ void Trick::FrameLog::remove_recording_groups_from_sim() { std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ; for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; fdrg_it++ ) { remove_data_record_group( *fdrg_it) ; } remove_data_record_group(drg_trick) ; remove_data_record_group(drg_frame) ; } /** @details -# For each FrameDataRecordGroup in drg_users -# Call enable -# Call enable for drg_trick -# Call enable for drg_frame */ void Trick::FrameLog::enable_recording_groups() { std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ; for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; fdrg_it++ ) { (*fdrg_it)->enable() ; } drg_trick->enable() ; drg_frame->enable() ; } /** @details -# For each FrameDataRecordGroup in drg_users -# Call disable -# Call disable for drg_trick -# Call disable for drg_frame */ void Trick::FrameLog::disable_recording_groups() { std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ; for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; fdrg_it++ ) { (*fdrg_it)->disable() ; } drg_trick->disable() ; drg_frame->disable() ; } /** @details -# For each FrameDataRecordGroup in drg_users -# Call init -# Call init for drg_trick -# Call init for drg_frame */ void Trick::FrameLog::init_recording_groups() { std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ; for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; fdrg_it++ ) { (*fdrg_it)->init() ; } drg_trick->init() ; drg_frame->init() ; } /** @details -# Insert frame log clock jobs in queue before and after all jobs we want to log the time of. */ void Trick::FrameLog::add_instrument_jobs() { exec_instrument_before("trick_frame_log.frame_log.frame_clock_start") ; exec_instrument_after("trick_frame_log.frame_log.frame_clock_stop") ; } /** @details -# Removes frame log clock jobs in queue before and after all jobs. */ void Trick::FrameLog::remove_instrument_jobs() { exec_instrument_remove("trick_frame_log.frame_log.frame_clock_start") ; exec_instrument_remove("trick_frame_log.frame_log.frame_clock_stop") ; } //Instrumentation job to save job timeline start time. int Trick::FrameLog::frame_clock_start(Trick::JobData * curr_job ) { Trick::JobData * target_job = (Trick::JobData *)curr_job->sup_class_data ; /** @par Detailed Design: */ if ( target_job != NULL ) { /** @li Set target job's start time. */ target_job->rt_start_time = clock.clock_time() ; } return(0) ; } //Instrumentation job to save job timeline stop time and frame time. int Trick::FrameLog::frame_clock_stop(Trick::JobData * curr_job) { Trick::JobData * target_job = (Trick::JobData *)curr_job->sup_class_data ; int thread, mode; /** @par Detailed Design: */ if ( target_job != NULL ) { if ( target_job->rt_start_time >= 0 ) { /** @li Set current job's stop time and frame time. */ target_job->rt_stop_time = clock.clock_time() ; target_job->frame_time += (target_job->rt_stop_time - target_job->rt_start_time); thread = target_job->thread; mode = exec_get_mode(); /** @li Whatever inits run after & including start_realtime, make them be timelined as cyclic. */ if (mode == Initialization) { if (! target_job->name.compare(rt_sim_object_name + std::string(".rt_sync.start_realtime")) ) { log_init_end = true; // fixup: set start_realtime function's start time to 0 because it will have reset the clock target_job->rt_start_time = 0; } if (log_init_end) { mode = Run; } } /** @li Save all cyclic job start & stop times for this frame into timeline structure. */ if ((mode==Run) || (mode==Step)) { // cyclic job if (tl_count[thread] < tl_max_samples) { timeline[thread][tl_count[thread]].id = target_job->frame_id; timeline[thread][tl_count[thread]].start = target_job->rt_start_time; timeline[thread][tl_count[thread]].stop = target_job->rt_stop_time; timeline[thread][tl_count[thread]].trick_job = target_job->tags.count("TRK"); tl_count[thread]++; } /** @li Save all non-cyclic job start & stop times for this frame into timeline_other structure. */ } else { // non-cyclic job if (tl_other_count[thread] < tl_max_samples) { timeline_other[thread][tl_other_count[thread]].id = target_job->frame_id; timeline_other[thread][tl_other_count[thread]].start = target_job->rt_start_time; timeline_other[thread][tl_other_count[thread]].stop = target_job->rt_stop_time; timeline_other[thread][tl_other_count[thread]].trick_job = target_job->tags.count("TRK"); tl_other_count[thread]++; } } // start timeline over target_job->rt_start_time = 0; target_job->rt_stop_time = 0; } else { target_job->frame_time = 0 ; } } return(0) ; } /** @details -# If we are enabled already, return -# If the frame log data recording groups are not in the sim -# Add the frame log data recording groups to the sim -# Initialize the frame log data recording groups. -# Add instrument jobs -# Enable the recording groups -# Set the frame log flag to true */ int Trick::FrameLog::framelog_on() { if ( frame_log_flag == true ) { return(0) ; } // test if we have added the frame logging objects to the sim or not. // If we haven't add them now and initialize the data recording groups. // We do this in framelog_on so we don't add unnecessary jobs and create // log_rt files until we have to. if ( get_data_record_group(drg_trick->get_group_name()) == NULL ) { add_recording_groups_to_sim() ; init_recording_groups() ; } add_instrument_jobs() ; enable_recording_groups() ; frame_log_flag = true ; return(0) ; } /** @details -# If we are disabled already, return -# Remove instrument jobs -# Disable the recording groups -# Set the frame log flag to false. */ int Trick::FrameLog::framelog_off() { if ( frame_log_flag == false ) { return(0) ; } remove_instrument_jobs() ; disable_recording_groups() ; frame_log_flag = false ; return(0) ; } /** @details Command to set the maximum number of job timeline samples to be taken (default = 100000). -# If num > 0 -# Set new maximum to num. -# For each thread -# Reallocate the timeline data array -# Reallocate the timeline_other data array */ int Trick::FrameLog::set_max_samples(int num) { int ii ; if (num > 0) { tl_max_samples = num ; for (ii=0; ii::iterator it ; for ( it = drg_users.begin() ; it != drg_users.end() ; it++ ) { (*it)->set_max_buffer_size(num) ; } drg_trick->set_max_buffer_size(num) ; drg_frame->set_max_buffer_size(num) ; } return(0) ; } /** @details -# Allocate memory for all of the frame log recording groups. -# Add variables for both frame and individual job recording groups. -# Create DP files. */ void Trick::FrameLog::default_data() { allocate_recording_groups() ; add_recording_vars_for_jobs() ; add_recording_vars_for_frame() ; } /** @details Clears any data_record information related to frame logging from the checkpoint reload. This job must run before DataRecordGroup::restart. DataRecordGroups save the list of variables it was recording when a checkpoint is taken. This list is used by DataRecordGroups to restart data recording. This list doesn't work with frame log groups because frame logging creates the data record list of varaibles differently than normal recording groups. So, we need to erase the checkpointed list of frame log variables. The correct variables will be inserted during FrameLog::restart which is run after DataRecordGroup::restart. -# For each FrameDataRecordGroup in drg_users -# Call clear_checkpoint_vars -# Call clear_checkpoint_vars for drg_trick -# Call clear_checkpoint_vars for drg_frame */ int Trick::FrameLog::clear_data_record_info() { remove_recording_groups_from_sim() ; std::vector< Trick::FrameDataRecordGroup *>::iterator it ; for ( it = drg_users.begin() ; it != drg_users.end() ; it++ ) { (*it)->clear_checkpoint_vars() ; } drg_trick->clear_checkpoint_vars() ; drg_frame->clear_checkpoint_vars() ; return 0 ; } /** @details Restart job that restores framelogging on checkpoint restart. This is run after clear_data_record_info. -# Call data record group restart jobs -# Add data recording variables for the jobs and frame -# If frame log is on in checkpoint, turn frame log on. */ int Trick::FrameLog::restart() { // removing the data record groups removed the restart jobs too. call them here. std::vector< Trick::FrameDataRecordGroup *>::iterator it ; for ( it = drg_users.begin() ; it != drg_users.end() ; it++ ) { (*it)->restart() ; } drg_trick->restart() ; drg_frame->restart() ; add_recording_vars_for_jobs() ; add_recording_vars_for_frame() ; create_DP_files(); // if frame log is on in the checkpoint, turn it back on now if ( frame_log_flag == true ) { frame_log_flag = false ; remove_instrument_jobs() ; // these will be added back when frame log turned on framelog_on() ; } return 0 ; } //Shutdown job that writes the job timeline data to disk and closes log files. int Trick::FrameLog::shutdown() { /** @par Detailed Design: */ int thread, ii, jj; char log_buff[128]; Trick::timeline_t *tl; double start, stop, time_scale; if ( frame_log_flag == false ) { return(0) ; } /** @li Manually create the log_timeline and log_timeline_init files from saved timeline data. */ if (fp_time_main == NULL) { sprintf(log_buff, "%s/log_timeline.csv", command_line_args_get_output_dir()); if ((fp_time_main = fopen(log_buff, "w")) == NULL) { message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ; exit(0); } fprintf(fp_time_main, "trick_frame_log.frame_log.job_time {s},"); fprintf(fp_time_main, "trick_frame_log.frame_log.job_trick_id {--},frame_log.frame_log.job_user_id {--}"); for (jj=1; jj::iterator job_iterator; FILE *fpx; int pages, plots, total_plots, vcells, dot; char *bg_color; double time_scale; std::string DP_buff; const char *headerx = "\n" \ "\n\n" \ "\n\n" \ "\n"; time_scale = 1.0 / exec_get_time_tic_value(); DP_buff = DP_dir + "/DP_rt_frame.xml"; if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) { message_publish(MSG_WARNING, "Could not open DP_rt_frame.xml file for Frame Logging\n") ; return(0); } fprintf(fpx, "%s", headerx); fprintf(fpx, " Real-Time Frame Overrun/Underrun History\n \n Real-Time Scheduling Frame\n"); fprintf(fpx, " \n Frame Overrun/Underrun\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " %s.rt_sync.frame_overrun_time\n", time_scale,rt_sim_object_name.c_str()); fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n Frame Scheduled Jobs Time\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " %s.rt_sync.frame_sched_time\n", time_scale,rt_sim_object_name.c_str()); fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n"); //unsigned int total_pages = (unsigned int)(drg_users.size() / plots_per_page) + 1 ; unsigned int total_pages ; if ( drg_users.size() <= 1 ) { total_pages = 1 ; } else { total_pages = (unsigned int)((drg_users.size() - 2)/ plots_per_page) + 1 ; } unsigned int page_count ; for ( page_count = 0 ; page_count < total_pages ; page_count++ ) { unsigned int ii = 0 ; // this check is to avoid empty page creation if ((page_count * plots_per_page + ii + 1) >= drg_users.size()) { continue; } fprintf(fpx, " \n"); for ( ii = 0 ; ii < plots_per_page and (page_count * plots_per_page + ii + 1) < drg_users.size() ; ii++ ) { fprintf(fpx, " \n"); fprintf(fpx, " Child thread %u Frame Scheduled Jobs\n", (page_count * plots_per_page + ii + 1)); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " sys.exec.out.time\n"); std::ostringstream group_name ; group_name << "trick_frame_userjobs_C" << (page_count * plots_per_page + ii + 1) ; fprintf(fpx, " %s.frame_sched_time\n", time_scale,group_name.str().c_str()); fprintf(fpx, " \n"); fprintf(fpx, " \n"); } fprintf(fpx, " \n"); } fprintf(fpx, " \n Real-Time Frame Overrun/Underrun History\n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n %s.rt_sync.frame_overrun_time\n", time_scale,rt_sim_object_name.c_str()); fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n %s.rt_sync.frame_sched_time\n", time_scale,rt_sim_object_name.c_str()); fprintf(fpx, " \n"); fprintf(fpx, "
\n
"); fclose(fpx); // sort the saved job names sort(user_jobs.begin(), user_jobs.end()); sort(trick_jobs.begin(), trick_jobs.end()); // DP_rt_userjobs -------------------------------------------------------------- int ii ; char numstr[21]; for ( ii = 0 ; ii < num_threads ; ii++ ) { if ( ii == 0 ) { DP_buff = DP_dir + "/DP_rt_userjobs.xml"; } else { sprintf(numstr, "%d", ii); DP_buff = DP_dir + "/DP_rt_userjobs_C" + numstr + ".xml"; } if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) { message_publish(MSG_WARNING, "Could not open DP_rt_userjobs.xml file for Frame Logging\n") ; return(0); } fprintf(fpx, "%s", headerx); fprintf(fpx, " User Job Execution History\n"); pages = 0; plots = 0; total_plots = drg_users[ii]->rec_buffer.size(); std::vector ::iterator drb_it ; bg_color = (char *)"cornsilk2"; for ( drb_it = drg_users[ii]->rec_buffer.begin() + 1 ; drb_it != drg_users[ii]->rec_buffer.end() ; drb_it++ ) { if ( ! (*drb_it)->name.compare(0, 5, "frame") ) continue ; // plots_per_page job plots per page if ((plots == 0) || (plots > plots_per_page)) { pages++; vcells = (total_plots/pages > plots_per_page) * 4; if (pages > 1) { fprintf(fpx, " \n"); } fprintf(fpx, " \n User Job Execution Times\n", vcells); plots = 1; } fprintf(fpx, " \n %s\n", bg_color, (*drb_it)->name.c_str()); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " %s\n", time_scale, (*drb_it)->name.c_str()); fprintf(fpx, " \n"); fprintf(fpx, " \n"); plots++; } fprintf(fpx, " \n"); fclose(fpx); } // DP_rt_trickjobs ------------------------------------------------------------- DP_buff = DP_dir + "/DP_rt_trickjobs.xml"; if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) { message_publish(MSG_WARNING, "Could not open DP_rt_trickjobs.xml file for Frame Logging\n") ; return(0); } fprintf(fpx, "%s", headerx); fprintf(fpx, " Trick Job Execution History\n"); pages = 0; plots = 0; total_plots = trick_jobs.size(); job_iterator = trick_jobs.begin(); while (job_iterator != trick_jobs.end()) { dot = (*job_iterator).find_first_of("."); // default background color, for trick_whatever jobs and anything else we don't list here bg_color = (char *)"cornsilk3"; // give the different types of trick jobs a different background color if (!(*job_iterator).compare(0,dot,std::string("JOB_") + msg_sim_object_name)) { bg_color = (char *)"lavenderblush3"; } if (!(*job_iterator).compare(0,dot,std::string("JOB_") + dr_sim_object_name) || !(*job_iterator).compare(0,21,std::string("JOB_data_record_group")) ) { bg_color = (char *)"slategray2"; } if (!(*job_iterator).compare(0,dot,std::string("JOB_") + rt_sim_object_name)) { bg_color = (char *)"honeydew3"; } if (!(*job_iterator).compare(0,dot,std::string("JOB_") + ms_sim_object_name)) { bg_color = (char *)"bisque2"; } if (strncmp((*job_iterator).c_str(),"JOB_sys_integ",13)==0) { bg_color = (char *)"burlywood"; } //other good colors in case you need more: //bg_color = "khaki3"; // plots_per_page job plots per page if ((plots == 0) || (plots > plots_per_page)) { pages++; vcells = (total_plots/pages > plots_per_page) * 4; if (pages > 1) { fprintf(fpx, " \n"); } fprintf(fpx, " \n Trick Job Execution Times\n", vcells); plots = 1; } fprintf(fpx, " \n %s\n", bg_color, (*job_iterator).c_str()); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " %s\n", time_scale, (*job_iterator).c_str()); fprintf(fpx, " \n"); fprintf(fpx, " \n"); job_iterator++; plots++; } fprintf(fpx, " \n"); fclose(fpx); return(0) ; } //Create the DP files to display job timelines. int Trick::FrameLog::create_DP_timeline_files() { FILE *fpx; int jj; std::string DP_buff; const char *headerx = "\n" \ "\n\n" \ "\n\n" \ "\n"; // DP_rt_timeline -------------------------------------------------------------- DP_buff = DP_dir + "/DP_rt_timeline.xml"; if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) { message_publish(MSG_WARNING, "Could not open DP_rt_timeline.xml file for Frame Logging\n") ; return(0); } fprintf(fpx, "%s", headerx); fprintf(fpx, " Job Timeline\n \n Job Timeline\n"); fprintf(fpx, " \n User Job Timeline\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_user_id\n") ; fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n Trick Job Timeline\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_trick_id\n") ; fprintf(fpx, " \n"); fprintf(fpx, " \n"); // don't generate the plot without a curve if (num_threads > 1) { fprintf(fpx, " \n Child Job Timeline\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); for (jj=1; jj\n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_userC%d_id\n", jj,jj); fprintf(fpx, " \n"); } fprintf(fpx, " \n"); } fprintf(fpx, " \n"); fprintf(fpx, " \n Job Timeline (combined)\n"); fprintf(fpx, " \n User and Trick Job Timeline\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_trick_id\n") ; fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_user_id\n"); fprintf(fpx, " \n"); for (jj=1; jj\n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_userC%d_id\n", jj,jj); fprintf(fpx, " \n"); } fprintf(fpx, " \n"); fprintf(fpx, " \n"); fclose(fpx); // DP_rt_timeline_init --------------------------------------------------------- DP_buff = DP_dir + "/DP_rt_timeline_init.xml"; if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) { message_publish(MSG_WARNING, "Could not open DP_rt_timeline_init.xml file for Frame Logging\n") ; return(0); } fprintf(fpx, "%s", headerx); fprintf(fpx, " Non-cyclic Job Timeline\n \n Non-cyclic Job Timeline\n"); fprintf(fpx, " \n User Job Timeline\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_userinit_id\n") ; fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n Trick Job Timeline\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_trickinit_id\n") ; fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n Non-cyclic Job Timeline (combined)\n"); fprintf(fpx, " \n User and Trick Job Timeline\n"); fprintf(fpx, " s \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_trickinit_id\n"); fprintf(fpx, " \n"); fprintf(fpx, " \n sys.exec.out.time\n"); fprintf(fpx, " trick_frame_log.frame_log.job_userinit_id\n"); fprintf(fpx, " \n"); fprintf(fpx, " \n"); fprintf(fpx, " \n"); fclose(fpx); return(0); }