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

nasa / trick / 13019895822

28 Jan 2025 09:28PM UTC coverage: 55.877% (-0.008%) from 55.885%
13019895822

Pull #1785

github

web-flow
Merge 759572821 into bffb021a4
Pull Request #1785: Frame Performance Tool- jperf

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

131 existing lines in 13 files now uncovered.

12307 of 22025 relevant lines covered (55.88%)

85798.04 hits per line

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

87.88
/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,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
            fprintf(fp_log,"%5.2f, %f, %f\n", tl[ii].id, start, stop);
100,000✔
614
        }
615
        fflush(fp_log);
1✔
616
        fclose(fp_log);
1✔
617
    }
618

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

622

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

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

636

637

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

646

647

648
    }
649

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

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

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

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

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

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

735
    return(0) ;
1✔
736

737
}
738

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

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

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

754
    return ret ;
154✔
755
}
756

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

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

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

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

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

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

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

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

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

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

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

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

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

975
    return(0) ;
154✔
976
}
977

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

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

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

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

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

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

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

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

1086
    return(0);
154✔
1087

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