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

nasa / trick / 12167577434

04 Dec 2024 08:16PM UTC coverage: 55.899% (+0.01%) from 55.885%
12167577434

Pull #1785

github

web-flow
Merge 590c3dda9 into f9d9d6ea0
Pull Request #1785: Frame Performance Tool- jperf

18 of 21 new or added lines in 1 file covered. (85.71%)

131 existing lines in 13 files now uncovered.

12315 of 22031 relevant lines covered (55.9%)

82299.51 hits per line

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

87.95
/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("post_integration")) ||
44,836✔
116
             (! all_jobs_vector[ii]->job_class_name.compare("system_thread_sync")) ||
44,650✔
117
             (! all_jobs_vector[ii]->job_class_name.compare("top_of_frame")) ||
68,331✔
118
             (! all_jobs_vector[ii]->job_class_name.compare("end_of_frame")))
21,664✔
119
           ) {
120
            dot = all_jobs_vector[ii]->name.find_first_of(".");
3,464✔
121
            if (!all_jobs_vector[ii]->name.compare(dot,11,".frame_log.")) {
3,464✔
122
                continue;
×
123
            }
124

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

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

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

193
}
186✔
194

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

356
}
357

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

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

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

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

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

420
}
421

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

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

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

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

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

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

510
/**
511
@details
512

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

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

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

530
    remove_recording_groups_from_sim() ;
9✔
531

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

539
    return 0 ;
9✔
540
}
541

542
/**
543
@details
544

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

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

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

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

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

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

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

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

588

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

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

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

606
        fprintf(fp_log,"jobID,isTopOfFrame,isEndOfFrame,startTime,stopTime\n");
1✔
607

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

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

625

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

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

639

640

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

649

650

651
    }
652

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

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

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

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

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

735
    fclose(fp_time_main);
1✔
736
    fclose(fp_time_other);
1✔
737

738
    return(0) ;
1✔
739

740
}
741

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

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

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

757
    return ret ;
154✔
758
}
759

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

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

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

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

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

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

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

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

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

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

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

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

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

978
    return(0) ;
154✔
979
}
980

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

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

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

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

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

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

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

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

1089
    return(0);
154✔
1090

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