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

nasa / trick / 15004044467

13 May 2025 06:29PM UTC coverage: 55.958% (+0.03%) from 55.933%
15004044467

Pull #1877

github

web-flow
Merge d70b5de90 into ff58ed109
Pull Request #1877: Resolved comments being parsed inside strings

12332 of 22038 relevant lines covered (55.96%)

264644.69 hits per line

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

88.47
/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) : 
181✔
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) {
181✔
38

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

43
    the_fl = this ;
181✔
44

45
}
181✔
46

47
Trick::FrameLog::~FrameLog() {
181✔
48
    free((char *)time_value_attr.units) ;
181✔
49
    // leaking all of the FrameDataRecordGroups
50
    // leaking timeline memory.
51
}
181✔
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() {
181✔
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") ;
181✔
76
    drg_users.push_back(fdrg) ;
181✔
77
    num_threads = exec_get_num_threads();
181✔
78
    for ( ii = 1 ; ii < num_threads ; ii++ ) {
186✔
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") ;
181✔
85
    drg_frame = new ("trick_frame") FrameDataRecordGroup(0, "frame") ;
181✔
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*));
181✔
89
    timeline_other = (Trick::timeline_t **)calloc( num_threads, sizeof(Trick::timeline_t*));
181✔
90
    for (ii=0; ii<num_threads; ii++) {
367✔
91
        timeline[ii] = (Trick::timeline_t *)calloc( tl_max_samples, sizeof(Trick::timeline_t));
186✔
92
        timeline_other[ii] = (Trick::timeline_t *)calloc( tl_max_samples, sizeof(Trick::timeline_t));
186✔
93
    }
94
    tl_count = (int *)calloc( num_threads, sizeof(int));
181✔
95
    tl_other_count = (int *)calloc( num_threads, sizeof(int));
181✔
96
}
181✔
97

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

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

105
    exec_get_all_jobs_vector(all_jobs_vector) ;
190✔
106

107
    for ( ii = 0 ; ii < all_jobs_vector.size() ; ii++ ) {
24,286✔
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,994✔
112
             (! all_jobs_vector[ii]->job_class_name.compare("integration")) ||
45,781✔
113
             (! all_jobs_vector[ii]->job_class_name.compare("derivative")) ||
45,735✔
114
             (! all_jobs_vector[ii]->job_class_name.compare("dynamic_event")) ||
45,695✔
115
             (! all_jobs_vector[ii]->job_class_name.compare("pre_integration")) ||
45,686✔
116
             (! all_jobs_vector[ii]->job_class_name.compare("post_integration")) ||
45,686✔
117
             (! all_jobs_vector[ii]->job_class_name.compare("system_thread_sync")) ||
45,496✔
118
             (! all_jobs_vector[ii]->job_class_name.compare("top_of_frame")) ||
69,647✔
119
             (! all_jobs_vector[ii]->job_class_name.compare("end_of_frame")))
22,076✔
120
           ) {
121
            dot = all_jobs_vector[ii]->name.find_first_of(".");
3,536✔
122
            if (!all_jobs_vector[ii]->name.compare(dot,11,".frame_log.")) {
3,536✔
123
                continue;
×
124
            }
125

126
            new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ;
3,536✔
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,536✔
129
                if ( all_jobs_vector[ii]->thread == 0 ) {
1,198✔
130
                    asprintf(&job_name, "JOB_%s.%2.2f(%s_%2.3f)", all_jobs_vector[ii]->name.c_str(),
1,187✔
131
                        all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str(), all_jobs_vector[ii]->cycle);
1,187✔
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,338✔
138
                    all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str());
2,338✔
139
            }
140
            // replace any colons in (C++) job name with underscores
141
            char *colon = strchr(job_name, ':') ;
3,536✔
142
            while (colon) {
3,536✔
143
                colon[0] = '#';
×
144
                colon = strchr(job_name, ':') ;
×
145
            }
146

147
            new_ref->reference = job_name;
3,536✔
148
            new_ref->address = &(all_jobs_vector[ii]->frame_time_seconds) ;
3,536✔
149
            new_ref->attr = &time_value_attr ;
3,536✔
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,536✔
153
                trick_jobs.push_back(std::string(job_name));
3,259✔
154
                drg_trick->add_variable(new_ref) ;
3,259✔
155
                drg_trick->add_rec_job(all_jobs_vector[ii]) ;
3,259✔
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,259✔
158
                    dr_sim_object_name = all_jobs_vector[ii]->parent_object->name;
190✔
159
                }
160
                if (!all_jobs_vector[ii]->name.compare(dot,8,".master.")) {
3,259✔
161
                    ms_sim_object_name = all_jobs_vector[ii]->parent_object->name;
372✔
162
                }
163
                if (!all_jobs_vector[ii]->name.compare(dot,9,".rt_sync.")) {
3,259✔
164
                    rt_sim_object_name = all_jobs_vector[ii]->parent_object->name;
190✔
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,259✔
169
                //}
170
            // user jobs
171
            } else {
172
                user_jobs.push_back(std::string(job_name));
277✔
173
                drg_users[all_jobs_vector[ii]->thread]->add_variable(new_ref) ;
277✔
174
                drg_users[all_jobs_vector[ii]->thread]->add_rec_job(all_jobs_vector[ii]) ;
277✔
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 ;
190✔
181
    for ( fdrg_it = drg_users.begin() , ii = 0 ; fdrg_it != drg_users.end() ; ++fdrg_it , ii++ ) {
385✔
182
        (*fdrg_it)->set_job_class("end_of_frame") ;
195✔
183
        (*fdrg_it)->set_phase(65533);
195✔
184
        (*fdrg_it)->set_thread(ii);
195✔
185
        if ( ii > 0 ) {
195✔
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") ;
190✔
192
    drg_trick->set_phase(65535);
190✔
193

194
}
190✔
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() {
190✔
204

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

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

212
    /* add the log_userjob frame time we created above to the log_frame group */
213
    for ( ii = 0 ; ii < num_threads ; ii++ ) {
385✔
214
        new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ;
195✔
215
        if (ii > 0) {
195✔
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)",
190✔
220
             drg_users[ii]->write_job->frame_id);
190✔
221
        }
222
        trick_jobs.push_back(std::string(job_name));
195✔
223
        new_ref->reference = job_name;
195✔
224
        new_ref->address = &(drg_users[ii]->write_job->frame_time_seconds);
195✔
225
        new_ref->attr = &time_value_attr ;
195✔
226
        drg_frame->add_variable(new_ref) ;
195✔
227
        drg_frame->add_rec_job(drg_users[ii]->write_job) ;
195✔
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)) ;
190✔
232
    asprintf(&job_name, "JOB_data_record_group.trickjobs.%2.2f(end_of_frame)",drg_trick->jobs[0]->frame_id);
190✔
233
    trick_jobs.push_back(std::string(job_name));
190✔
234
    new_ref->reference = job_name;
190✔
235
    new_ref->address = &(drg_trick->write_job->frame_time_seconds);
190✔
236
    new_ref->attr = &time_value_attr ;
190✔
237
    drg_frame->add_variable(new_ref) ;
190✔
238
    drg_frame->add_rec_job(drg_trick->write_job) ;
190✔
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") ;
190✔
243
    drg_frame->set_phase(65535);
190✔
244
}
190✔
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() {
1✔
460

461
    if ( frame_log_flag == false ) {
1✔
462
        return(0) ;
1✔
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() {
181✔
504
    allocate_recording_groups() ;
181✔
505
    add_recording_vars_for_jobs() ;
181✔
506
    add_recording_vars_for_frame() ;
181✔
507
    // reset clock before frame logging
508
    clock.clock_reset(0);
181✔
509
}
181✔
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() {
149✔
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 ) {
149✔
586
        return(0) ;
148✔
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 {
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✔
603
            message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ;
×
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() {
158✔
746
    int ret=0;
158✔
747

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

755
    return ret ;
158✔
756
}
757

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

785
    if (ret == -1) {
158✔
786
        message_publish(MSG_WARNING, "Could not create DP_Product directory for Frame Logging. DP files not created.\n") ;
×
787
        perror("mkdir");
×
788
    }
789
    return ret;
158✔
790
}
791

792
//Create the DP files to display trick and user job execution times.
793
int Trick::FrameLog::create_DP_job_files() {
158✔
794

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

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

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

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

872
    // sort the saved job names
873
    sort(user_jobs.begin(), user_jobs.end());
158✔
874
    sort(trick_jobs.begin(), trick_jobs.end());
158✔
875

876
    // DP_rt_userjobs --------------------------------------------------------------
877
    int ii ;
878
    char numstr[21];
879
    for ( ii = 0 ; ii < num_threads ; ii++ ) {
321✔
880
        if ( ii == 0 ) {
163✔
881
             DP_buff = DP_dir + "/DP_rt_userjobs.xml";
158✔
882
        } else {
883
             snprintf(numstr, sizeof(numstr), "%d", ii);
5✔
884
             DP_buff = DP_dir + "/DP_rt_userjobs_C" + numstr + ".xml";
5✔
885
        }
886

887
        if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
163✔
888
            message_publish(MSG_WARNING, "Could not open DP_rt_userjobs.xml file for Frame Logging\n") ;
×
889
            return(0);
×
890
        }
891

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

919
        }
920
        fprintf(fpx, "    </page>\n</product>");
163✔
921
        fclose(fpx);
163✔
922
    }
923

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

981
    return(0) ;
158✔
982
}
983

984
//Create the DP files to display job timelines.
985
int Trick::FrameLog::create_DP_timeline_files() {
158✔
986

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

995
    // DP_rt_timeline --------------------------------------------------------------
996
    DP_buff = DP_dir + "/DP_rt_timeline.xml";
158✔
997
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
158✔
998
        message_publish(MSG_WARNING, "Could not open DP_rt_timeline.xml file for Frame Logging\n") ;
×
999
        return(0);
×
1000
    }
1001

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

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

1053
    // DP_rt_timeline_init ---------------------------------------------------------
1054
    DP_buff = DP_dir + "/DP_rt_timeline_init.xml";
158✔
1055
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
158✔
1056
        message_publish(MSG_WARNING, "Could not open DP_rt_timeline_init.xml file for Frame Logging\n") ;
×
1057
        return(0);
×
1058
    }
1059

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

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

1092
    return(0);
158✔
1093

1094
}
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