• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 13396893645

18 Feb 2025 05:48PM UTC coverage: 55.886% (+0.008%) from 55.878%
13396893645

push

github

web-flow
Frame Performance Tool- jperf (#1785)

* Initial Commit of Frame Performance - jperf

* Fix KeyStroke.getKeyStroke call.

* Separate reading of file from processing it.

* Refactor JobPerf.java to clean up names and organization.

* Add statistics reporting to jperf.

* Fix min/max issue, and rename types and variables for clarity.

* Break up and document the classes that compose JobPerf.

* Frame range selection and speed improvements.

* Indicate selected frame

* Added Jobs-stats and, Frame-details windows, job names,classes, contained jobs and so forth.

* Refactor timeline log and improve frame boundary determination.

* Fix check of whether one job executes within the bounds of another.

* Handle case where and id in the timeline is not found in the S-job_execution file.

* Add Trick Logo and Buttons that will be activated in the near future.

* Add functionality for advance retreat buttons.

* Fix replacement of minIndex with 0.

15 of 18 new or added lines in 1 file covered. (83.33%)

5 existing lines in 3 files now uncovered.

12310 of 22027 relevant lines covered (55.89%)

72607.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.9
/trick_source/sim_services/FrameLog/FrameLog.cpp
1

2
#include <iostream>
3
#include <algorithm>
4
#include <sstream>
5
#include <string.h>
6
#include <sys/stat.h>
7
#include <sys/types.h>
8
#include <errno.h>
9

10
#include "trick/FrameLog.hh"
11
#include "trick/FrameDataRecordGroup.hh"
12
#include "trick/exec_proto.hh"
13
#include "trick/exec_proto.h"
14
#include "trick/data_record_proto.h"
15
#include "trick/command_line_protos.h"
16
#include "trick/message_proto.h"
17
#include "trick/message_type.h"
18

19
Trick::FrameLog * the_fl = NULL ;
20

21
//Constructor.
22
Trick::FrameLog::FrameLog(Trick::Clock & in_clock) : 
177✔
23
 frame_log_flag(false),
24
 drg_trick(NULL),
25
 drg_frame(NULL),
26
 plots_per_page(6),
27
 timeline(NULL),
28
 timeline_other(NULL),
29
 num_threads(1),
30
 tl_max_samples(100000),
31
 tl_count(NULL),
32
 tl_other_count(NULL),
33
 log_init_start(false),
34
 log_init_end(false),
35
 fp_time_main(NULL),
36
 fp_time_other(NULL),
37
 clock(in_clock) {
177✔
38

39
    time_value_attr.type = TRICK_DOUBLE;
177✔
40
    time_value_attr.size = sizeof(double);
177✔
41
    time_value_attr.units = strdup("s") ;
177✔
42

43
    the_fl = this ;
177✔
44

45
}
177✔
46

47
Trick::FrameLog::~FrameLog() {
177✔
48
    free((char *)time_value_attr.units) ;
177✔
49
    // leaking all of the FrameDataRecordGroups
50
    // leaking timeline memory.
51
}
177✔
52

53
/**
54
@details
55

56
This routine is called during the "default_data" phase of initialization.  At that time
57
the number of threads in the sim will be known and this ensure that everything is
58
allocated before the input_processor is initially run.
59

60
-# Allocate a FrameDataRecordGroup to hold user job information on the main thread
61
-# Push the FrameDataRecordGroup to drg_users.
62
-# For each child thread in the sim
63
 -# Allocate a FrameDataRecordGroup to hold user job information on the child thread
64
 -# Push the FrameDataRecordGroup to drg_users.
65
-# Allocate a FrameDataRecordGroup to hold trick job information
66
-# Allocate a FrameDataRecordGroup to hold frame information
67
-# Allocate space for timeline for each thread.
68
*/
69
void Trick::FrameLog::allocate_recording_groups() {
177✔
70

71
    Trick::FrameDataRecordGroup * fdrg ;
72
    int ii ;
73

74
    /* Create log_user_jobs group and log_trick_jobs group to record job frame_times. */
75
    fdrg = new ("trick_frame_userjobs_main") Trick::FrameDataRecordGroup(0, "frame_userjobs_main") ;
177✔
76
    drg_users.push_back(fdrg) ;
177✔
77
    num_threads = exec_get_num_threads();
177✔
78
    for ( ii = 1 ; ii < num_threads ; ii++ ) {
182✔
79
        std::ostringstream group_name ;
10✔
80
        group_name << "trick_frame_userjobs_C" << ii ;
5✔
81
        fdrg = new (group_name.str().c_str()) Trick::FrameDataRecordGroup(ii, group_name.str()) ;
5✔
82
        drg_users.push_back(fdrg) ;
5✔
83
    }
84
    drg_trick = new ("trick_frame_trick_jobs") FrameDataRecordGroup(0, "frame_trickjobs") ;
177✔
85
    drg_frame = new ("trick_frame") FrameDataRecordGroup(0, "frame") ;
177✔
86

87
    /* Allocate space for timeline for each thread according to user settable tl_max_samples variable. */
88
    timeline = (Trick::timeline_t **)calloc( num_threads, sizeof(Trick::timeline_t*));
177✔
89
    timeline_other = (Trick::timeline_t **)calloc( num_threads, sizeof(Trick::timeline_t*));
177✔
90
    for (ii=0; ii<num_threads; ii++) {
359✔
91
        timeline[ii] = (Trick::timeline_t *)calloc( tl_max_samples, sizeof(Trick::timeline_t));
182✔
92
        timeline_other[ii] = (Trick::timeline_t *)calloc( tl_max_samples, sizeof(Trick::timeline_t));
182✔
93
    }
94
    tl_count = (int *)calloc( num_threads, sizeof(int));
177✔
95
    tl_other_count = (int *)calloc( num_threads, sizeof(int));
177✔
96
}
177✔
97

98
void Trick::FrameLog::add_recording_vars_for_jobs() {
186✔
99

100
    unsigned int ii , dot ;
101
    REF2 * new_ref ;
102
    char * job_name = NULL ;
186✔
103
    std::vector<Trick::JobData *> all_jobs_vector ;
372✔
104

105
    exec_get_all_jobs_vector(all_jobs_vector) ;
186✔
106

107
    for ( ii = 0 ; ii < all_jobs_vector.size() ; ii++ ) {
23,821✔
108
        /** @li only makes sense to record frame time for scheduled, integ, and end_of_frame jobs */
109
        /** @li exclude system jobs because they are excluded in instrument_before/after */
110
        /** @li exclude frame_log jobs */
111
        if ( (all_jobs_vector[ii]->job_class >= exec_get_scheduled_start_index() ||
46,099✔
112
             (! all_jobs_vector[ii]->job_class_name.compare("integration")) ||
44,917✔
113
             (! all_jobs_vector[ii]->job_class_name.compare("derivative")) ||
44,880✔
114
             (! all_jobs_vector[ii]->job_class_name.compare("dynamic_event")) ||
44,845✔
115
             (! all_jobs_vector[ii]->job_class_name.compare("pre_integration")) ||
44,836✔
116
             (! all_jobs_vector[ii]->job_class_name.compare("post_integration")) ||
44,836✔
117
             (! all_jobs_vector[ii]->job_class_name.compare("system_thread_sync")) ||
44,650✔
118
             (! all_jobs_vector[ii]->job_class_name.compare("top_of_frame")) ||
68,331✔
119
             (! all_jobs_vector[ii]->job_class_name.compare("end_of_frame")))
21,664✔
120
           ) {
121
            dot = all_jobs_vector[ii]->name.find_first_of(".");
3,464✔
122
            if (!all_jobs_vector[ii]->name.compare(dot,11,".frame_log.")) {
3,464✔
123
                continue;
×
124
            }
125

126
            new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ;
3,464✔
127
            /** @li add job frame id, job class and cycle time to displayed job name, and prepend "JOB_" so it stands out in quickplot */
128
            if ( all_jobs_vector[ii]->job_class >= exec_get_scheduled_start_index() ) {
3,464✔
129
                if ( all_jobs_vector[ii]->thread == 0 ) {
1,171✔
130
                    asprintf(&job_name, "JOB_%s.%2.2f(%s_%2.3f)", all_jobs_vector[ii]->name.c_str(),
1,160✔
131
                        all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str(), all_jobs_vector[ii]->cycle);
1,160✔
132
                } else { // add child thread # to name
133
                    asprintf(&job_name, "JOB_%s_C%d.%2.2f(%s_%2.3f)",  all_jobs_vector[ii]->name.c_str(), all_jobs_vector[ii]->thread,
11✔
134
                        all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str(), all_jobs_vector[ii]->cycle);
11✔
135
                }
136
            } else { // non-scheduled class
137
                asprintf(&job_name, "JOB_%s.%2.2f(%s)", all_jobs_vector[ii]->name.c_str(),
2,293✔
138
                    all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str());
2,293✔
139
            }
140
            // replace any colons in (C++) job name with underscores
141
            char *colon = strchr(job_name, ':') ;
3,464✔
142
            while (colon) {
3,464✔
143
                colon[0] = '#';
×
144
                colon = strchr(job_name, ':') ;
×
145
            }
146

147
            new_ref->reference = job_name;
3,464✔
148
            new_ref->address = &(all_jobs_vector[ii]->frame_time_seconds) ;
3,464✔
149
            new_ref->attr = &time_value_attr ;
3,464✔
150
            /** @li use TRK tag in S_define to identify trick jobs */
151
            // trick jobs
152
            if ( all_jobs_vector[ii]->tags.count("TRK") ) {
3,464✔
153
                trick_jobs.push_back(std::string(job_name));
3,199✔
154
                drg_trick->add_variable(new_ref) ;
3,199✔
155
                drg_trick->add_rec_job(all_jobs_vector[ii]) ;
3,199✔
156
                // save names of trick sim objects (ones that user can change) so we can color code jobs in DP file
157
                if (!all_jobs_vector[ii]->name.compare(dot,5,".drd.")) {
3,199✔
158
                    dr_sim_object_name = all_jobs_vector[ii]->parent_object->name;
186✔
159
                }
160
                if (!all_jobs_vector[ii]->name.compare(dot,8,".master.")) {
3,199✔
161
                    ms_sim_object_name = all_jobs_vector[ii]->parent_object->name;
370✔
162
                }
163
                if (!all_jobs_vector[ii]->name.compare(dot,9,".rt_sync.")) {
3,199✔
164
                    rt_sim_object_name = all_jobs_vector[ii]->parent_object->name;
186✔
165
                }
166
                //TODO: no message jobs yet - fill this in when messaging has a job to look at here
167
                // if () {
168
                    msg_sim_object_name = std::string("message");
3,199✔
169
                //}
170
            // user jobs
171
            } else {
172
                user_jobs.push_back(std::string(job_name));
265✔
173
                drg_users[all_jobs_vector[ii]->thread]->add_variable(new_ref) ;
265✔
174
                drg_users[all_jobs_vector[ii]->thread]->add_rec_job(all_jobs_vector[ii]) ;
265✔
175
            }
176
        }
177
    }
178

179
    /* set the recoring job be and end of frame job.  Set each recording group to it's proper thread. */
180
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
186✔
181
    for ( fdrg_it = drg_users.begin() , ii = 0 ; fdrg_it != drg_users.end() ; ++fdrg_it , ii++ ) {
377✔
182
        (*fdrg_it)->set_job_class("end_of_frame") ;
191✔
183
        (*fdrg_it)->set_phase(65533);
191✔
184
        (*fdrg_it)->set_thread(ii);
191✔
185
        if ( ii > 0 ) {
191✔
186
            std::ostringstream group_name ;
5✔
187
            group_name << "trick_frame_userjobs_C" << ii ;
5✔
188
            (*fdrg_it)->add_variable( group_name.str() + ".frame_time") ;
5✔
189
        }
190
    }
191
    drg_trick->set_job_class("end_of_frame") ;
186✔
192
    drg_trick->set_phase(65535);
186✔
193

194
}
186✔
195

196
/**
197
@details
198
-# Add the log_userjob frame time we created above to the log_frame group
199
-# Add the log_trickjob frame time we created above to the log_frame group
200
-# Set the recording job data_record_group.frame to end of frame -
201
   phase it last (after rt_monitor) because time set in rt_monitor
202
*/
203
void Trick::FrameLog::add_recording_vars_for_frame() {
186✔
204

205
    REF2 * new_ref ;
206
    char * job_name = NULL ;
186✔
207
    int ii ;
208

209
    drg_frame->add_variable(rt_sim_object_name + std::string(".rt_sync.frame_time")) ;
186✔
210
    drg_frame->add_variable(rt_sim_object_name + std::string(".rt_sync.frame_overrun")) ;
186✔
211

212
    /* add the log_userjob frame time we created above to the log_frame group */
213
    for ( ii = 0 ; ii < num_threads ; ii++ ) {
377✔
214
        new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ;
191✔
215
        if (ii > 0) {
191✔
216
            asprintf(&job_name, "JOB_data_record_group_frame_userjobs_C%d.data_record.%2.2f(end_of_frame)",
5✔
217
             ii,drg_users[ii]->write_job->frame_id);
5✔
218
        } else {
219
            asprintf(&job_name, "JOB_data_record_group_frame_userjobs.data_record.%2.2f(end_of_frame)",
186✔
220
             drg_users[ii]->write_job->frame_id);
186✔
221
        }
222
        trick_jobs.push_back(std::string(job_name));
191✔
223
        new_ref->reference = job_name;
191✔
224
        new_ref->address = &(drg_users[ii]->write_job->frame_time_seconds);
191✔
225
        new_ref->attr = &time_value_attr ;
191✔
226
        drg_frame->add_variable(new_ref) ;
191✔
227
        drg_frame->add_rec_job(drg_users[ii]->write_job) ;
191✔
228
    }
229

230
    /* add the log_trickjob frame time we created above to the log_frame group */
231
    new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ;
186✔
232
    asprintf(&job_name, "JOB_data_record_group.trickjobs.%2.2f(end_of_frame)",drg_trick->jobs[0]->frame_id);
186✔
233
    trick_jobs.push_back(std::string(job_name));
186✔
234
    new_ref->reference = job_name;
186✔
235
    new_ref->address = &(drg_trick->write_job->frame_time_seconds);
186✔
236
    new_ref->attr = &time_value_attr ;
186✔
237
    drg_frame->add_variable(new_ref) ;
186✔
238
    drg_frame->add_rec_job(drg_trick->write_job) ;
186✔
239

240
    /* set the recording job data_record_group.frame to end of frame -
241
       phase it last (after rt_monitor) because time set in rt_monitor */
242
    drg_frame->set_job_class("end_of_frame") ;
186✔
243
    drg_frame->set_phase(65535);
186✔
244
}
186✔
245

246
/**
247
@details
248
-# For each FrameDataRecordGroup in drg_users
249
 -# Call add_data_record_group
250
-# Call add_data_record_group for drg_trick
251
-# Call add_data_record_group for drg_frame
252
*/
253
void Trick::FrameLog::add_recording_groups_to_sim() {
1✔
254
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
1✔
255
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
2✔
256
        add_data_record_group( *fdrg_it , Trick::DR_Ring_Buffer) ;
1✔
257
    }
258
    add_data_record_group(drg_trick, Trick::DR_Ring_Buffer) ;
1✔
259
    add_data_record_group(drg_frame, Trick::DR_Ring_Buffer) ;
1✔
260
}
1✔
261

262
/**
263
@details
264
-# For each FrameDataRecordGroup in drg_users
265
 -# Call remove_data_record_group
266
-# Call remove_data_record_group for drg_trick
267
-# Call remove_data_record_group for drg_frame
268
*/
269
void Trick::FrameLog::remove_recording_groups_from_sim() {
9✔
270
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
9✔
271
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
18✔
272
        remove_data_record_group( *fdrg_it) ;
9✔
273
    }
274
    remove_data_record_group(drg_trick) ;
9✔
275
    remove_data_record_group(drg_frame) ;
9✔
276
}
9✔
277

278
/**
279
@details
280
-# For each FrameDataRecordGroup in drg_users
281
 -# Call enable
282
-# Call enable for drg_trick
283
-# Call enable for drg_frame
284
*/
285
void Trick::FrameLog::enable_recording_groups() {
1✔
286
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
1✔
287
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
2✔
288
        (*fdrg_it)->enable() ;
1✔
289
    }
290
    drg_trick->enable() ;
1✔
291
    drg_frame->enable() ;
1✔
292
}
1✔
293

294
/**
295
@details
296
-# For each FrameDataRecordGroup in drg_users
297
 -# Call disable
298
-# Call disable for drg_trick
299
-# Call disable for drg_frame
300
*/
301
void Trick::FrameLog::disable_recording_groups() {
×
302
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
×
303
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
×
304
        (*fdrg_it)->disable() ;
×
305
    }
306
    drg_trick->disable() ;
×
307
    drg_frame->disable() ;
×
308
}
×
309

310
/**
311
@details
312
-# For each FrameDataRecordGroup in drg_users
313
 -# Call init
314
-# Call init for drg_trick
315
-# Call init for drg_frame
316
*/
317
void Trick::FrameLog::init_recording_groups() {
1✔
318
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
1✔
319
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
2✔
320
        (*fdrg_it)->init() ;
1✔
321
    }
322
    drg_trick->init() ;
1✔
323
    drg_frame->init() ;
1✔
324
}
1✔
325

326
/**
327
@details
328
-# Insert frame log clock jobs in queue before and after all jobs we want to log the time of.
329
*/
330
void Trick::FrameLog::add_instrument_jobs() {
1✔
331
    exec_instrument_before("trick_frame_log.frame_log.frame_clock_start") ;
1✔
332
    exec_instrument_after("trick_frame_log.frame_log.frame_clock_stop") ;
1✔
333
}
1✔
334

335
/**
336
@details
337
-# Removes frame log clock jobs in queue before and after all jobs.
338
*/
339
void Trick::FrameLog::remove_instrument_jobs() {
×
340
    exec_instrument_remove("trick_frame_log.frame_log.frame_clock_start") ;
×
341
    exec_instrument_remove("trick_frame_log.frame_log.frame_clock_stop") ;
×
342
}
×
343

344
//Instrumentation job to save job timeline start time.
345
int Trick::FrameLog::frame_clock_start(Trick::JobData * curr_job ) {
1,987,336✔
346

347
    Trick::JobData * target_job = (Trick::JobData *)curr_job->sup_class_data ;
1,987,336✔
348

349
    /** @par Detailed Design: */
350
    if ( target_job != NULL ) {
1,987,336✔
351
        /** @li Set target job's start time. */
352
        target_job->rt_start_time = clock.clock_time() ;
1,987,336✔
353
    }
354

355
    return(0) ;
1,987,336✔
356

357
}
358

359
//Instrumentation job to save job timeline stop time and frame time.
360
int Trick::FrameLog::frame_clock_stop(Trick::JobData * curr_job) {
1,987,336✔
361

362
    Trick::JobData * target_job = (Trick::JobData *)curr_job->sup_class_data ;
1,987,336✔
363
    int thread, mode;
364
    double time_scale;
365
    
366
    /** @par Detailed Design: */
367
    if ( target_job != NULL ) {
1,987,336✔
368
        if ( target_job->rt_start_time >= 0 ) {
1,987,336✔
369
            /** @li Set current job's stop time and frame time. */
370
            target_job->rt_stop_time = clock.clock_time() ;
1,987,336✔
371
            time_scale = 1.0 / target_job->time_tic_value;
1,987,336✔
372
            target_job->frame_time += (target_job->rt_stop_time - target_job->rt_start_time);
1,987,336✔
373
            target_job->frame_time_seconds = target_job->frame_time * time_scale;
1,987,336✔
374
            thread = target_job->thread;
1,987,336✔
375

376
            mode = exec_get_mode();
1,987,336✔
377
            /** @li Whatever inits run after & including start_realtime, make them be timelined as cyclic. */
378
            if (mode == Initialization) {
1,987,336✔
379
                if (! target_job->name.compare(rt_sim_object_name + std::string(".rt_sync.start_realtime")) ) {
28✔
380
                    log_init_end = true;
1✔
381
                    // fixup: set start_realtime function's start time to 0 because it will have reset the clock
382
                    target_job->rt_start_time = 0;
1✔
383
                }
384
                if (log_init_end) {
28✔
385
                    mode = Run;
2✔
386
                }
387
            }
388

389
            /** @li Save all cyclic job start & stop times for this frame into timeline structure. */
390
            if ((mode==Run) || (mode==Step)) {                            // cyclic job
1,987,336✔
391
                if (tl_count[thread] < tl_max_samples) {
2,087,295✔
392
                    timeline[thread][tl_count[thread]].id    = target_job->frame_id;
100,000✔
393
                    timeline[thread][tl_count[thread]].start = target_job->rt_start_time;
100,000✔
394
                    timeline[thread][tl_count[thread]].stop  = target_job->rt_stop_time;
100,000✔
395
                    timeline[thread][tl_count[thread]].trick_job = target_job->tags.count("TRK");
100,000✔
396
                    timeline[thread][tl_count[thread]].isEndOfFrame = target_job->isEndOfFrame;
100,000✔
397
                    timeline[thread][tl_count[thread]].isTopOfFrame = target_job->isTopOfFrame;
100,000✔
398
                    tl_count[thread]++;
100,000✔
399
                }
400
            /** @li Save all non-cyclic job start & stop times for this frame into timeline_other structure. */
401
            } else {                                                      // non-cyclic job
402
                if (tl_other_count[thread] < tl_max_samples) {
41✔
403
                    timeline_other[thread][tl_other_count[thread]].id    = target_job->frame_id;
41✔
404
                    timeline_other[thread][tl_other_count[thread]].start = target_job->rt_start_time;
41✔
405
                    timeline_other[thread][tl_other_count[thread]].stop  = target_job->rt_stop_time;
41✔
406
                    timeline_other[thread][tl_other_count[thread]].trick_job = target_job->tags.count("TRK");
41✔
407
                    tl_other_count[thread]++;
41✔
408
                }
409
            }
410
            // start timeline over
411
            target_job->rt_start_time = 0;
1,987,336✔
412
            target_job->rt_stop_time = 0;
1,987,336✔
413
        } else {
414
            target_job->frame_time = 0 ;
×
415
            target_job->frame_time_seconds = 0.0;
×
416
        }
417
    }
418

419
    return(0) ;
1,987,336✔
420

421
}
422

423
/**
424
@details
425
-# If we are enabled already, return
426
-# If the frame log data recording groups are not in the sim
427
 -# Add the frame log data recording groups to the sim
428
 -# Initialize the frame log data recording groups.
429
-# Add instrument jobs
430
-# Enable the recording groups
431
-# Set the frame log flag to true
432
*/
433
int Trick::FrameLog::framelog_on() {
1✔
434

435
    if ( frame_log_flag == true ) {
1✔
436
        return(0) ;
×
437
    }
438
    // test if we have added the frame logging objects to the sim or not.
439
    // If we haven't add them now and initialize the data recording groups.
440
    // We do this in framelog_on so we don't add unnecessary jobs and create
441
    // log_rt files until we have to.
442
    if ( get_data_record_group(drg_trick->get_group_name()) == NULL ) {
1✔
443
        add_recording_groups_to_sim() ;
1✔
444
        init_recording_groups() ;
1✔
445
    }
446
    add_instrument_jobs() ;
1✔
447
    enable_recording_groups() ;
1✔
448
    frame_log_flag = true ;
1✔
449
    return(0) ;
1✔
450
}
451

452
/**
453
@details
454
-# If we are disabled already, return
455
-# Remove instrument jobs
456
-# Disable the recording groups
457
-# Set the frame log flag to false.
458
*/
459
int Trick::FrameLog::framelog_off() {
×
460

461
    if ( frame_log_flag == false ) {
×
462
        return(0) ;
×
463
    }
464
    remove_instrument_jobs() ;
×
465
    disable_recording_groups() ;
×
466
    frame_log_flag = false ;
×
467
    return(0) ;
×
468
}
469

470
/**
471
@details
472
Command to set the maximum number of job timeline samples to be taken (default = 100000).
473
-# If num > 0
474
 -# Set new maximum to num.
475
 -# For each thread
476
  -# Reallocate the timeline data array
477
  -# Reallocate the timeline_other data array
478
*/
479
int Trick::FrameLog::set_max_samples(int num) {
×
480
    int ii ;
481
    if (num > 0) {
×
482
        tl_max_samples = num ;
×
483
        for (ii=0; ii<num_threads; ii++) {
×
484
            timeline[ii] = (Trick::timeline_t *)realloc( timeline[ii], tl_max_samples*sizeof(Trick::timeline_t));
×
485
            timeline_other[ii] = (Trick::timeline_t *)realloc( timeline_other[ii], tl_max_samples*sizeof(Trick::timeline_t));
×
486
        }
487
        std::vector< Trick::FrameDataRecordGroup *>::iterator it ;
×
488
        for ( it = drg_users.begin() ; it != drg_users.end() ; ++it ) {
×
489
            (*it)->set_max_buffer_size(num) ;
×
490
        }
491
        drg_trick->set_max_buffer_size(num) ;
×
492
        drg_frame->set_max_buffer_size(num) ;
×
493
    }
494
    return(0) ;
×
495
}
496

497
/**
498
@details
499
-# Allocate memory for all of the frame log recording groups.
500
-# Add variables for both frame and individual job recording groups.
501
-# Create DP files.
502
*/
503
void Trick::FrameLog::default_data() {
177✔
504
    allocate_recording_groups() ;
177✔
505
    add_recording_vars_for_jobs() ;
177✔
506
    add_recording_vars_for_frame() ;
177✔
507
    // reset clock before frame logging
508
    clock.clock_reset(0);
177✔
509
}
177✔
510

511
/**
512
@details
513

514
Clears any data_record information related to frame logging from the checkpoint reload.
515
This job must run before DataRecordGroup::restart.
516

517
DataRecordGroups save the list of variables it was recording when a checkpoint is taken.
518
This list is used by DataRecordGroups to restart data recording.
519
This list doesn't work with frame log groups because frame logging creates the
520
data record list of varaibles differently than normal recording groups.  So, we need
521
to erase the checkpointed list of frame log variables.  The correct variables will
522
be inserted during FrameLog::restart which is run after DataRecordGroup::restart.
523

524
-# For each FrameDataRecordGroup in drg_users
525
 -# Call clear_checkpoint_vars
526
-# Call clear_checkpoint_vars for drg_trick
527
-# Call clear_checkpoint_vars for drg_frame
528
*/
529
int Trick::FrameLog::clear_data_record_info() {
9✔
530

531
    remove_recording_groups_from_sim() ;
9✔
532

533
    std::vector< Trick::FrameDataRecordGroup *>::iterator it ;
9✔
534
    for ( it = drg_users.begin() ; it != drg_users.end() ; ++it ) {
18✔
535
        (*it)->clear_checkpoint_vars() ;
9✔
536
    }
537
    drg_trick->clear_checkpoint_vars() ;
9✔
538
    drg_frame->clear_checkpoint_vars() ;
9✔
539

540
    return 0 ;
9✔
541
}
542

543
/**
544
@details
545

546
Restart job that restores framelogging on checkpoint restart.  This is run after
547
clear_data_record_info.
548

549
-# Call data record group restart jobs
550
-# Add data recording variables for the jobs and frame
551
-# If frame log is on in checkpoint, turn frame log on.
552
*/
553
int Trick::FrameLog::restart() {
9✔
554
// removing the data record groups removed the restart jobs too.  call them here.
555
    std::vector< Trick::FrameDataRecordGroup *>::iterator it ;
9✔
556
    for ( it = drg_users.begin() ; it != drg_users.end() ; ++it ) {
18✔
557
        (*it)->restart() ;
9✔
558
    }
559
    drg_trick->restart() ;
9✔
560
    drg_frame->restart() ;
9✔
561

562
    add_recording_vars_for_jobs() ;
9✔
563
    add_recording_vars_for_frame() ;
9✔
564
    create_DP_files();
9✔
565

566
    // if frame log is on in the checkpoint, turn it back on now
567
    if ( frame_log_flag == true ) {
9✔
568
        frame_log_flag = false ;
×
569
        remove_instrument_jobs() ; // these will be added back when frame log turned on
×
570
        framelog_on() ;
×
571
    }
572
    return 0 ;
9✔
573
}
574

575
//Shutdown job that writes the job timeline data to disk and closes log files.
576
int Trick::FrameLog::shutdown() {
145✔
577

578
    /** @par Detailed Design: */
579

580
    int thread, ii, jj;
581
    char log_buff[128];
582
    Trick::timeline_t *tl;
583
    double start, stop, time_scale;
584

585
    if ( frame_log_flag == false ) {
145✔
586
        return(0) ;
144✔
587
    }
588

589

590
// ================================================================
591
// NEW Time-line for Jperf
592
// ================================================================
593
    for (int thread_num = 0; thread_num < num_threads; thread_num ++) {
2✔
594

595
        if (thread_num == 0) {
1✔
596
            snprintf(log_buff, sizeof(log_buff), "%s/log_newtimeline.csv", command_line_args_get_output_dir());
1✔
597
        } else {
NEW
598
            snprintf(log_buff, sizeof(log_buff), "%s/log_newtimelineC%d.csv", command_line_args_get_output_dir(), thread_num);
×
599
        }
600

601
        FILE *fp_log;
602
        if ((fp_log = fopen(log_buff, "w")) == NULL) {
1✔
NEW
603
            message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ;
×
NEW
604
            exit(0);
×
605
        }
606

607
        fprintf(fp_log,"jobID,startTime,stopTime\n");
1✔
608

609
        time_scale = 1.0 / exec_get_time_tic_value();
1✔
610
        tl = timeline[thread_num];
1✔
611
        for ( ii = 0 ; ii < tl_count[thread_num] ; ii++ ) {
100,001✔
612
            start = tl[ii].start * time_scale;
100,000✔
613
            stop =  tl[ii].stop  * time_scale;
100,000✔
614
            fprintf(fp_log,"%5.2f, %f, %f\n", tl[ii].id, start, stop);
100,000✔
615
        }
616
        fflush(fp_log);
1✔
617
        fclose(fp_log);
1✔
618
    }
619

620
    /** @li Manually create the log_timeline and log_timeline_init files from saved timeline data. */
621
    if (fp_time_main == NULL) {
1✔
622

623

624
        snprintf(log_buff, sizeof(log_buff), "%s/log_timeline.csv", command_line_args_get_output_dir());
1✔
625
        if ((fp_time_main = fopen(log_buff, "w")) == NULL) {
1✔
626
            message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ;
×
627
            exit(0);
×
628
        }
629
        fprintf(fp_time_main, "trick_frame_log.frame_log.job_time {s},");
1✔
630
        fprintf(fp_time_main, "trick_frame_log.frame_log.job_trick_id {--},frame_log.frame_log.job_user_id {--}");
1✔
631

632
        for (jj=1; jj<num_threads; jj++) {
1✔
633
            fprintf(fp_time_main, ",trick_frame_log.frame_log.job_userC%d_id {--}",jj);
×
634
        }
635
        fprintf(fp_time_main, "\n");
1✔
636

637

638

639
        snprintf(log_buff, sizeof(log_buff), "%s/log_timeline_init.csv", command_line_args_get_output_dir());
1✔
640
        if ((fp_time_other = fopen(log_buff, "w")) == NULL) {
1✔
641
            message_publish(MSG_ERROR, "Could not open log_timeline_init.csv file for Job Timeline Logging\n") ;
×
642
            exit(0);
×
643
        }
644
        fprintf(fp_time_other, "trick_frame_log.frame_log.job_init_time {s},");
1✔
645
        fprintf(fp_time_other, "trick_frame_log.frame_log.job_trickinit_id {--},trick_frame_log.frame_log.job_userinit_id {--}\n");
1✔
646

647

648

649
    }
650

651
    time_scale = 1.0 / exec_get_time_tic_value();
1✔
652
            // print to log like this:
653
            // (only one of the job ids will be filled in depending on what type of job this is)
654
            //               start job time, 0, 0
655
            //               start job time, trick job id, user job id
656
            //               stop  job time, trick job id, user job id
657
            //               stop  job time, 0, 0
658
    /** @li print a 0 id before each start time & after each stop time for a stairstep effect in plot. */
659
    // cyclic jobs
660

661
    for ( thread = 0 ; thread < num_threads ; thread++ ) {
2✔
662
        tl = timeline[thread];
1✔
663
        for ( ii = 0 ; ii < tl_count[thread] ; ii++ ) {
100,001✔
664
            // start & stop time are in tics, so convert to seconds
665
            start = tl[ii].start * time_scale;
100,000✔
666
            stop =  tl[ii].stop  * time_scale;
100,000✔
667

668
            fprintf(fp_time_main,      "%f,0", start);        // start stairstep
100,000✔
669
            for (jj=0; jj<num_threads; jj++) {
200,000✔
670
                fprintf(fp_time_main,  ",0");
100,000✔
671
            }
672
            fprintf(fp_time_main,      "\n");
100,000✔
673

674
            if (tl[ii].trick_job) {
100,000✔
675
                fprintf(fp_time_main, "%f,%f", start, tl[ii].id);    // trick job start
95,647✔
676
                for (jj=0; jj<num_threads; jj++) {
191,294✔
677
                    fprintf(fp_time_main, ",0");
95,647✔
678
                }
679
            } else { // user job
680
                fprintf(fp_time_main, "%f,0", start);         // user job start
4,353✔
681
                for (jj=0; jj<num_threads; jj++) {
8,706✔
682
                    if (jj==thread) {
4,353✔
683
                        fprintf(fp_time_main, ",%f", tl[ii].id);     // user thread id (0=main)
4,353✔
684
                    } else {
685
                        fprintf(fp_time_main, ",0");
×
686
                    }
687
                }
688
            }
689
            fprintf(fp_time_main,      "\n");
100,000✔
690
            if (tl[ii].trick_job) {
100,000✔
691
                fprintf(fp_time_main, "%f,%f", stop, tl[ii].id);    // trick job end
95,647✔
692
                for (jj=0; jj<num_threads; jj++) {
191,294✔
693
                    fprintf(fp_time_main, ",0");
95,647✔
694
                }
695
            } else { // user job
696
                fprintf(fp_time_main, "%f,0", stop);         // user job end
4,353✔
697
                for (jj=0; jj<num_threads; jj++) {
8,706✔
698
                    if (jj==thread) {
4,353✔
699
                        fprintf(fp_time_main, ",%f", tl[ii].id);    // user thread id (0=main)
4,353✔
700
                    } else {
701
                        fprintf(fp_time_main, ",0");
×
702
                    }
703
                }
704
            }
705
            fprintf(fp_time_main,      "\n");
100,000✔
706
            fprintf(fp_time_main,      "%f,0", stop);        // end stairstep
100,000✔
707
            for (jj=0; jj<num_threads; jj++) {
200,000✔
708
                fprintf(fp_time_main,  ",0");
100,000✔
709
            }
710
            fprintf(fp_time_main,      "\n");
100,000✔
711
        } // end for thread
712
    } // end for ii
713

714
    // non-cyclic jobs
715
    for ( thread = 0 ; thread < num_threads ; thread++ ) {
2✔
716
        tl = timeline_other[thread];
1✔
717
        for ( ii = 0 ; ii < tl_other_count[thread] ; ii++ ) {
40✔
718
            // start & stop time are in tics, so convert to seconds
719
            start = tl[ii].start * time_scale;
39✔
720
            stop =  tl[ii].stop  * time_scale;
39✔
721
            fprintf(fp_time_other, "%f,0,0\n", start);          // start stairstep
39✔
722
            if (tl[ii].trick_job) {
39✔
723
                fprintf(fp_time_other, "%f,%f,0\n", start, tl[ii].id); // trick job start
37✔
724
                fprintf(fp_time_other, "%f,%f,0\n", stop, tl[ii].id);  // trick job end
37✔
725
            } else { // user job
726
                fprintf(fp_time_other, "%f,0,%f\n", start, tl[ii].id); // user job start
2✔
727
                fprintf(fp_time_other, "%f,0,%f\n", stop, tl[ii].id);  // user job end
2✔
728
            }
729
            fprintf(fp_time_other, "%f,0,0\n", stop);           // end stairstep
39✔
730
        } // end for thread
731
    } // end for ii
732

733
    fclose(fp_time_main);
1✔
734
    fclose(fp_time_other);
1✔
735

736
    return(0) ;
1✔
737

738
}
739

740
void Trick::FrameLog::set_clock(Trick::Clock & in_clock) {
×
741
    clock = in_clock ;
×
742
}
×
743

744
//Call all the Create routines for the DP directory and all DP files.
745
int Trick::FrameLog::create_DP_files() {
154✔
746
    int ret=0;
154✔
747

748
    ret = create_DP_Product_dir();
154✔
749
    if (ret==0) {
154✔
750
        // Only create DP files if we successfully created the directory
751
        create_DP_job_files();
154✔
752
        create_DP_timeline_files();
154✔
753
    }
754

755
    return ret ;
154✔
756
}
757

758
//Create the DP_Product directory where the DP files will be stored.
759
int Trick::FrameLog::create_DP_Product_dir() {
154✔
760
    int ret=0;
154✔
761
    DP_dir = "DP_Product";
154✔
762
    ret = mkdir(DP_dir.c_str(), 0777);
154✔
763
    if (ret == -1) {
154✔
764
        if (errno == EEXIST) {
130✔
765
            // it's ok if the directory is already there
766
            ret = 0;
130✔
767
        } else {
768
            // if you can't create the DP_Product dir in the current directory, try in the output dir (-O)
769
            DP_dir = std::string(command_line_args_get_output_dir()) + "/DP_Product";
×
770
            ret = mkdir(DP_dir.c_str(), 0777);
×
771
            if (ret == -1) {
×
772
                if (errno == EEXIST) {
×
773
                    // it's ok if the directory is already there
774
                    ret = 0;
×
775
                }
776
            }
777
        }
778
    }
779

780
    if (ret == -1) {
154✔
781
        message_publish(MSG_WARNING, "Could not create DP_Product directory for Frame Logging. DP files not created.\n") ;
×
782
        perror("mkdir");
×
783
    }
784
    return ret;
154✔
785
}
786

787
//Create the DP files to display trick and user job execution times.
788
int Trick::FrameLog::create_DP_job_files() {
154✔
789

790
    std::vector<std::string>::iterator job_iterator;
154✔
791
    FILE *fpx;
792
    unsigned int pages, plots, total_plots, vcells, dot;
793
    char *bg_color;
794
    std::string DP_buff;
308✔
795
    const char *headerx = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" \
154✔
796
                    "<!DOCTYPE product PUBLIC \"-//Tricklab//DTD Product V1.0//EN\" \"Product.dtd\">\n\n" \
797
                    "<!-- Description: Plot of Y(t) vs. t, with attributes, titles, labels, units -->\n\n" \
798
                    "<product version=\"1.0\">\n";
799

800
    DP_buff = DP_dir + "/DP_rt_frame.xml";
154✔
801
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
154✔
802
        message_publish(MSG_WARNING, "Could not open DP_rt_frame.xml file for Frame Logging\n") ;
×
803
        return(0);
×
804
    }
805
    fprintf(fpx, "%s", headerx);
154✔
806
    fprintf(fpx, "    <title>Real-Time Frame Overrun/Underrun History</title>\n    <page>\n        <title>Real-Time Scheduling Frame</title>\n");
154✔
807
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Frame Overrun/Underrun</title>\n");
154✔
808
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
154✔
809
    fprintf(fpx, "            <yaxis> <label>Frame Overrun/Underrun</label> </yaxis>\n");
154✔
810
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
811
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Overrun/Underrun\">%s.rt_sync.frame_overrun</var>\n", rt_sim_object_name.c_str());
154✔
812
    fprintf(fpx, "            </curve>\n");
154✔
813
    fprintf(fpx, "        </plot>\n");
154✔
814
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Frame Scheduled Jobs Time</title>\n");
154✔
815
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
154✔
816
    fprintf(fpx, "            <yaxis> <label>Frame Scheduled Jobs Time</label> </yaxis>\n");
154✔
817
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
818
    fprintf(fpx, "                <var line_color=\"red\" label=\"Frame Sched Time\">%s.rt_sync.frame_time</var>\n", rt_sim_object_name.c_str());
154✔
819
    fprintf(fpx, "            </curve>\n");
154✔
820
    fprintf(fpx, "        </plot>\n");
154✔
821
    fprintf(fpx, "    </page>\n");
154✔
822

823
    //unsigned int total_pages = (unsigned int)(drg_users.size() / plots_per_page) + 1 ;
824
    unsigned int total_pages ;
825
    if ( drg_users.size() <= 1 ) {
154✔
826
        total_pages = 1 ;
152✔
827
    } else {
828
        total_pages = (unsigned int)((drg_users.size() - 2)/ plots_per_page) + 1 ;
2✔
829
    }
830
    unsigned int page_count ;
831
    for ( page_count = 0 ; page_count < total_pages ; page_count++ ) {
308✔
832
        unsigned int ii = 0 ;
154✔
833
        // this check is to avoid empty page creation
834
        if ((page_count * plots_per_page + ii + 1) >= drg_users.size()) {
154✔
835
                continue;
152✔
836
        }
837
        fprintf(fpx, "    <page>\n");
2✔
838
        for ( ii = 0 ; ii < plots_per_page and (page_count * plots_per_page + ii + 1) < drg_users.size() ; ii++ ) {
7✔
839
            fprintf(fpx, "        <plot grid=\"yes\">\n");
5✔
840
            fprintf(fpx, "            <title>Child thread %u Frame Scheduled Jobs</title>\n", (page_count * plots_per_page + ii + 1));
5✔
841
            fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
5✔
842
            fprintf(fpx, "            <yaxis> <label>Frame Scheduled Jobs Time</label> </yaxis>\n");
5✔
843
            fprintf(fpx, "            <curve>\n");
5✔
844
            fprintf(fpx, "                <var>sys.exec.out.time</var>\n");
5✔
845
            std::ostringstream group_name ;
10✔
846
            group_name << "trick_frame_userjobs_C" << (page_count * plots_per_page + ii + 1) ;
5✔
847
            fprintf(fpx, "                <var line_color=\"red\" label=\"Frame Sched Time\">%s.frame_time</var>\n", group_name.str().c_str());
5✔
848
            fprintf(fpx, "            </curve>\n");
5✔
849
            fprintf(fpx, "        </plot>\n");
5✔
850
        }
851
        fprintf(fpx, "    </page>\n");
2✔
852
    }
853

854
    fprintf(fpx, "    <table>\n        <title>Real-Time Frame Overrun/Underrun History</title>\n");
154✔
855
    fprintf(fpx, "        <column format=\"%%13.6f\">\n");
154✔
856
    fprintf(fpx, "            <label>Sim Time</label>\n            <var>sys.exec.out.time</var>\n");
154✔
857
    fprintf(fpx, "        </column>\n");
154✔
858
    fprintf(fpx, "        <column format=\"%%13.6f\">\n");
154✔
859
    fprintf(fpx, "            <label>Overrun/Underrun</label>\n            <var>%s.rt_sync.frame_overrun</var>\n", rt_sim_object_name.c_str());
154✔
860
    fprintf(fpx, "        </column>\n");
154✔
861
    fprintf(fpx, "        <column format=\"%%13.6f\">\n");
154✔
862
    fprintf(fpx, "            <label>Frame Sched Time</label>\n            <var>%s.rt_sync.frame_time</var>\n", rt_sim_object_name.c_str());
154✔
863
    fprintf(fpx, "        </column>\n");
154✔
864
    fprintf(fpx, "    </table>\n</product>");
154✔
865
    fclose(fpx);
154✔
866

867
    // sort the saved job names
868
    sort(user_jobs.begin(), user_jobs.end());
154✔
869
    sort(trick_jobs.begin(), trick_jobs.end());
154✔
870

871
    // DP_rt_userjobs --------------------------------------------------------------
872
    int ii ;
873
    char numstr[21];
874
    for ( ii = 0 ; ii < num_threads ; ii++ ) {
313✔
875
        if ( ii == 0 ) {
159✔
876
             DP_buff = DP_dir + "/DP_rt_userjobs.xml";
154✔
877
        } else {
878
             snprintf(numstr, sizeof(numstr), "%d", ii);
5✔
879
             DP_buff = DP_dir + "/DP_rt_userjobs_C" + numstr + ".xml";
5✔
880
        }
881

882
        if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
159✔
883
            message_publish(MSG_WARNING, "Could not open DP_rt_userjobs.xml file for Frame Logging\n") ;
×
884
            return(0);
×
885
        }
886

887
        fprintf(fpx, "%s", headerx);
159✔
888
        fprintf(fpx, "    <title>User Job Execution History</title>\n");
159✔
889
        pages = 0; plots = 0;
159✔
890
        total_plots = drg_users[ii]->rec_buffer.size();
159✔
891
        std::vector <Trick::DataRecordBuffer *>::iterator drb_it ;
159✔
892
        bg_color = (char *)"cornsilk2";
159✔
893
        for ( drb_it = drg_users[ii]->rec_buffer.begin() + 1 ; drb_it != drg_users[ii]->rec_buffer.end() ; ++drb_it ) {
415✔
894
            if ( ! (*drb_it)->name.compare(0, 5, "frame") ) continue ;
256✔
895
            // plots_per_page job plots per page
896
            if ((plots == 0) || (plots > plots_per_page)) {
256✔
897
                pages++;
161✔
898
                vcells = (total_plots/pages > plots_per_page) * 4;
161✔
899
                if (pages > 1) {
161✔
900
                    fprintf(fpx, "    </page>\n");
7✔
901
                }
902
                fprintf(fpx, "    <page vcells=\"%d\">\n        <title>User Job Execution Times</title>\n", vcells);
161✔
903
                plots = 1;
161✔
904
            }
905
            fprintf(fpx, "        <plot grid=\"yes\" background_color=\"%s\">\n            <title>%s</title>\n", bg_color, (*drb_it)->name.c_str());
256✔
906
            fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
256✔
907
            fprintf(fpx, "            <yaxis> <label>Execution Time</label> </yaxis>\n");
256✔
908
            fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
256✔
909
            fprintf(fpx, "                <var line_color=\"red\">%s</var>\n", (*drb_it)->name.c_str());
256✔
910
            fprintf(fpx, "            </curve>\n");
256✔
911
            fprintf(fpx, "        </plot>\n");
256✔
912
            plots++;
256✔
913

914
        }
915
        fprintf(fpx, "    </page>\n</product>");
159✔
916
        fclose(fpx);
159✔
917
    }
918

919
    // DP_rt_trickjobs -------------------------------------------------------------
920
    DP_buff = DP_dir +  "/DP_rt_trickjobs.xml";
154✔
921
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
154✔
922
        message_publish(MSG_WARNING, "Could not open DP_rt_trickjobs.xml file for Frame Logging\n") ;
×
923
        return(0);
×
924
    }
925
    fprintf(fpx, "%s", headerx);
154✔
926
    fprintf(fpx, "    <title>Trick Job Execution History</title>\n");
154✔
927
    pages = 0; plots = 0;
154✔
928
    total_plots = trick_jobs.size();
154✔
929
    job_iterator = trick_jobs.begin();
154✔
930
    while (job_iterator != trick_jobs.end()) {
3,293✔
931
        dot = (*job_iterator).find_first_of(".");
3,139✔
932
        // default background color, for trick_whatever jobs and anything else we don't list here
933
        bg_color = (char *)"cornsilk3";
3,139✔
934
        // give the different types of trick jobs a different background color
935
        if (!(*job_iterator).compare(0,dot,std::string("JOB_") + msg_sim_object_name)) {
3,139✔
936
            bg_color = (char *)"lavenderblush3";
×
937
        }
938
        if (!(*job_iterator).compare(0,dot,std::string("JOB_") + dr_sim_object_name) ||
9,254✔
939
            !(*job_iterator).compare(0,21,std::string("JOB_data_record_group")) ) {
6,115✔
940
            bg_color = (char *)"slategray2";
494✔
941
        }
942
        if (!(*job_iterator).compare(0,dot,std::string("JOB_") + rt_sim_object_name)) {
3,139✔
943
            bg_color = (char *)"honeydew3";
163✔
944
        }
945
        if (!(*job_iterator).compare(0,dot,std::string("JOB_") + ms_sim_object_name)) {
3,139✔
946
            bg_color = (char *)"bisque2";
486✔
947
        }
948
        if (strncmp((*job_iterator).c_str(),"JOB_sys_integ",13)==0) {
3,139✔
949
            bg_color = (char *)"burlywood";
×
950
        }
951
        //other good colors in case you need more:
952
            //bg_color = "khaki3";
953
        // plots_per_page job plots per page
954
        if ((plots == 0) || (plots > plots_per_page)) {
3,139✔
955
            pages++;
645✔
956
            vcells = (total_plots/pages > plots_per_page) * 4;
645✔
957
            if (pages > 1) {
645✔
958
                fprintf(fpx, "    </page>\n");
491✔
959
            }
960
            fprintf(fpx, "    <page vcells=\"%d\">\n        <title>Trick Job Execution Times</title>\n", vcells);
645✔
961
            plots = 1;
645✔
962
        }
963
        fprintf(fpx, "        <plot grid=\"yes\" background_color=\"%s\">\n            <title>%s</title>\n", bg_color, (*job_iterator).c_str());
3,139✔
964
        fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
3,139✔
965
        fprintf(fpx, "            <yaxis> <label>Execution Time</label> </yaxis>\n");
3,139✔
966
        fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
3,139✔
967
        fprintf(fpx, "                <var line_color=\"darkgreen\">%s</var>\n", (*job_iterator).c_str());
3,139✔
968
        fprintf(fpx, "            </curve>\n");
3,139✔
969
        fprintf(fpx, "        </plot>\n");
3,139✔
970
        job_iterator++;
3,139✔
971
        plots++;
3,139✔
972
    }
973
    fprintf(fpx, "    </page>\n</product>");
154✔
974
    fclose(fpx);
154✔
975

976
    return(0) ;
154✔
977
}
978

979
//Create the DP files to display job timelines.
980
int Trick::FrameLog::create_DP_timeline_files() {
154✔
981

982
    FILE *fpx;
983
    int jj;
984
    std::string DP_buff;
308✔
985
    const char *headerx = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" \
154✔
986
                    "<!DOCTYPE product PUBLIC \"-//Tricklab//DTD Product V1.0//EN\" \"Product.dtd\">\n\n" \
987
                    "<!-- Description: Plot of Y(t) vs. t, with attributes, titles, labels, units -->\n\n" \
988
                    "<product version=\"1.0\">\n";
989

990
    // DP_rt_timeline --------------------------------------------------------------
991
    DP_buff = DP_dir + "/DP_rt_timeline.xml";
154✔
992
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
154✔
993
        message_publish(MSG_WARNING, "Could not open DP_rt_timeline.xml file for Frame Logging\n") ;
×
994
        return(0);
×
995
    }
996

997
    fprintf(fpx, "%s", headerx);
154✔
998
    fprintf(fpx, "    <title>Job Timeline</title>\n    <page vcells=\"3\">\n        <title>Job Timeline</title>\n");
154✔
999
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>User Job Timeline</title>\n");
154✔
1000
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
154✔
1001
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
154✔
1002
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
1003
    fprintf(fpx, "                <var line_color=\"red\" label=\"User Job Id\">trick_frame_log.frame_log.job_user_id</var>\n") ;
154✔
1004
    fprintf(fpx, "            </curve>\n");
154✔
1005
    fprintf(fpx, "        </plot>\n");
154✔
1006
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Trick Job Timeline</title>\n");
154✔
1007
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
154✔
1008
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
154✔
1009
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
1010
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_trick_id</var>\n") ;
154✔
1011
    fprintf(fpx, "            </curve>\n");
154✔
1012
    fprintf(fpx, "        </plot>\n");
154✔
1013
    // don't generate the plot without a curve
1014
    if (num_threads > 1) {
154✔
1015
        fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Child Job Timeline</title>\n");
2✔
1016
        fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
2✔
1017
        fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
2✔
1018
        for (jj=1; jj<num_threads; jj++) {
7✔
1019
            fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
5✔
1020
            fprintf(fpx, "                <var line_color=\"blue\" label=\"Child%d Job Id\">trick_frame_log.frame_log.job_userC%d_id</var>\n",
5✔
1021
             jj,jj);
1022
            fprintf(fpx, "            </curve>\n");
5✔
1023
        }
1024
        fprintf(fpx, "        </plot>\n");
2✔
1025
    }
1026
    fprintf(fpx, "    </page>\n");
154✔
1027

1028
    fprintf(fpx, "    <page>\n        <title>Job Timeline (combined)</title>\n");
154✔
1029
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>User and Trick Job Timeline</title>\n");
154✔
1030
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
154✔
1031
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
154✔
1032
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
1033
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_trick_id</var>\n") ;
154✔
1034
    fprintf(fpx, "            </curve>\n");
154✔
1035
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
1036
    fprintf(fpx, "                <var line_color=\"red\" label=\"User Job Id\">trick_frame_log.frame_log.job_user_id</var>\n");
154✔
1037
    fprintf(fpx, "            </curve>\n");
154✔
1038
    for (jj=1; jj<num_threads; jj++) {
159✔
1039
        fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
5✔
1040
        fprintf(fpx, "                <var line_color=\"blue\" label=\"Child%d Job Id\">trick_frame_log.frame_log.job_userC%d_id</var>\n",
5✔
1041
                     jj,jj);
1042
        fprintf(fpx, "            </curve>\n");
5✔
1043
    }
1044
    fprintf(fpx, "        </plot>\n");
154✔
1045
    fprintf(fpx, "    </page>\n</product>");
154✔
1046
    fclose(fpx);
154✔
1047

1048
    // DP_rt_timeline_init ---------------------------------------------------------
1049
    DP_buff = DP_dir + "/DP_rt_timeline_init.xml";
154✔
1050
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
154✔
1051
        message_publish(MSG_WARNING, "Could not open DP_rt_timeline_init.xml file for Frame Logging\n") ;
×
1052
        return(0);
×
1053
    }
1054

1055
    fprintf(fpx, "%s", headerx);
154✔
1056
    fprintf(fpx, "    <title>Non-cyclic Job Timeline</title>\n    <page>\n        <title>Non-cyclic Job Timeline</title>\n");
154✔
1057
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>User Job Timeline</title>\n");
154✔
1058
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
154✔
1059
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
154✔
1060
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
1061
    fprintf(fpx, "                <var line_color=\"red\" label=\"User Job Id\">trick_frame_log.frame_log.job_userinit_id</var>\n") ;
154✔
1062
    fprintf(fpx, "            </curve>\n");
154✔
1063
    fprintf(fpx, "        </plot>\n");
154✔
1064
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Trick Job Timeline</title>\n");
154✔
1065
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
154✔
1066
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
154✔
1067
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
1068
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_trickinit_id</var>\n") ;
154✔
1069
    fprintf(fpx, "            </curve>\n");
154✔
1070
    fprintf(fpx, "        </plot>\n");
154✔
1071
    fprintf(fpx, "    </page>\n");
154✔
1072

1073
    fprintf(fpx, "    <page>\n        <title>Non-cyclic Job Timeline (combined)</title>\n");
154✔
1074
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>User and Trick Job Timeline</title>\n");
154✔
1075
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
154✔
1076
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
154✔
1077
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
1078
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_trickinit_id</var>\n");
154✔
1079
    fprintf(fpx, "            </curve>\n");
154✔
1080
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
154✔
1081
    fprintf(fpx, "                <var line_color=\"red\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_userinit_id</var>\n");
154✔
1082
    fprintf(fpx, "            </curve>\n");
154✔
1083
    fprintf(fpx, "        </plot>\n");
154✔
1084
    fprintf(fpx, "    </page>\n</product>");
154✔
1085
    fclose(fpx);
154✔
1086

1087
    return(0);
154✔
1088

1089
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc