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

nasa / trick / 21296718347

23 Jan 2026 06:24PM UTC coverage: 55.589% (+0.009%) from 55.58%
21296718347

Pull #2031

github

web-flow
Merge 050505a97 into e4390df66
Pull Request #2031: Frame log choose buffering

8 of 9 new or added lines in 1 file covered. (88.89%)

172 existing lines in 8 files now uncovered.

12507 of 22499 relevant lines covered (55.59%)

308951.89 hits per line

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

88.38
/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

22
int frame_log_on(Trick::DR_Buffering bufferType)
1✔
23
{
24

25
    if (the_fl != NULL) {
1✔
26
        return the_fl->framelog_on(bufferType) ;
1✔
27
    }
NEW
28
    return(0) ;
×
29
}
30

31

32

33
//Constructor.
34
Trick::FrameLog::FrameLog(Trick::Clock & in_clock) : 
184✔
35
 frame_log_flag(false),
36
 drg_trick(NULL),
37
 drg_frame(NULL),
38
 plots_per_page(6),
39
 timeline(NULL),
40
 timeline_other(NULL),
41
 num_threads(1),
42
 tl_max_samples(100000),
43
 tl_count(NULL),
44
 tl_other_count(NULL),
45
 log_init_start(false),
46
 log_init_end(false),
47
 fp_time_main(NULL),
48
 fp_time_other(NULL),
49
 clock(in_clock) {
184✔
50

51
    time_value_attr.type = TRICK_DOUBLE;
184✔
52
    time_value_attr.size = sizeof(double);
184✔
53
    time_value_attr.units = strdup("s") ;
184✔
54

55
    the_fl = this ;
184✔
56

57
}
184✔
58

59
Trick::FrameLog::~FrameLog() {
184✔
60
    free((char *)time_value_attr.units) ;
184✔
61
    // leaking all of the FrameDataRecordGroups
62
    // leaking timeline memory.
63
}
184✔
64

65
/**
66
@details
67

68
This routine is called during the "default_data" phase of initialization.  At that time
69
the number of threads in the sim will be known and this ensure that everything is
70
allocated before the input_processor is initially run.
71

72
-# Allocate a FrameDataRecordGroup to hold user job information on the main thread
73
-# Push the FrameDataRecordGroup to drg_users.
74
-# For each child thread in the sim
75
 -# Allocate a FrameDataRecordGroup to hold user job information on the child thread
76
 -# Push the FrameDataRecordGroup to drg_users.
77
-# Allocate a FrameDataRecordGroup to hold trick job information
78
-# Allocate a FrameDataRecordGroup to hold frame information
79
-# Allocate space for timeline for each thread.
80
*/
81
void Trick::FrameLog::allocate_recording_groups() {
184✔
82

83
    Trick::FrameDataRecordGroup * fdrg ;
84
    int ii ;
85

86
    /* Create log_user_jobs group and log_trick_jobs group to record job frame_times. */
87
    fdrg = new ("trick_frame_userjobs_main") Trick::FrameDataRecordGroup(0, "frame_userjobs_main") ;
184✔
88
    drg_users.push_back(fdrg) ;
184✔
89
    num_threads = exec_get_num_threads();
184✔
90
    for ( ii = 1 ; ii < num_threads ; ii++ ) {
189✔
91
        std::ostringstream group_name ;
10✔
92
        group_name << "trick_frame_userjobs_C" << ii ;
5✔
93
        fdrg = new (group_name.str().c_str()) Trick::FrameDataRecordGroup(ii, group_name.str()) ;
5✔
94
        drg_users.push_back(fdrg) ;
5✔
95
    }
96
    drg_trick = new ("trick_frame_trick_jobs") FrameDataRecordGroup(0, "frame_trickjobs") ;
184✔
97
    drg_frame = new ("trick_frame") FrameDataRecordGroup(0, "frame") ;
184✔
98

99
    /* Allocate space for timeline for each thread according to user settable tl_max_samples variable. */
100
    timeline = (Trick::timeline_t **)calloc( num_threads, sizeof(Trick::timeline_t*));
184✔
101
    timeline_other = (Trick::timeline_t **)calloc( num_threads, sizeof(Trick::timeline_t*));
184✔
102
    for (ii=0; ii<num_threads; ii++) {
373✔
103
        timeline[ii] = (Trick::timeline_t *)calloc( tl_max_samples, sizeof(Trick::timeline_t));
189✔
104
        timeline_other[ii] = (Trick::timeline_t *)calloc( tl_max_samples, sizeof(Trick::timeline_t));
189✔
105
    }
106
    tl_count = (int *)calloc( num_threads, sizeof(int));
184✔
107
    tl_other_count = (int *)calloc( num_threads, sizeof(int));
184✔
108
}
184✔
109

110
void Trick::FrameLog::add_recording_vars_for_jobs() {
194✔
111

112
    unsigned int ii , dot ;
113
    REF2 * new_ref ;
114
    char * job_name = NULL ;
194✔
115
    std::vector<Trick::JobData *> all_jobs_vector ;
388✔
116

117
    exec_get_all_jobs_vector(all_jobs_vector) ;
194✔
118

119
    for ( ii = 0 ; ii < all_jobs_vector.size() ; ii++ ) {
24,795✔
120
        /** @li only makes sense to record frame time for scheduled, integ, and end_of_frame jobs */
121
        /** @li exclude system jobs because they are excluded in instrument_before/after */
122
        /** @li exclude frame_log jobs */
123
        if ( (all_jobs_vector[ii]->job_class >= exec_get_scheduled_start_index() ||
47,980✔
124
             (! all_jobs_vector[ii]->job_class_name.compare("integration")) ||
46,743✔
125
             (! all_jobs_vector[ii]->job_class_name.compare("derivative")) ||
46,697✔
126
             (! all_jobs_vector[ii]->job_class_name.compare("dynamic_event")) ||
46,657✔
127
             (! all_jobs_vector[ii]->job_class_name.compare("pre_integration")) ||
46,648✔
128
             (! all_jobs_vector[ii]->job_class_name.compare("post_integration")) ||
46,648✔
129
             (! all_jobs_vector[ii]->job_class_name.compare("system_thread_sync")) ||
46,454✔
130
             (! all_jobs_vector[ii]->job_class_name.compare("top_of_frame")) ||
71,110✔
131
             (! all_jobs_vector[ii]->job_class_name.compare("end_of_frame")))
22,541✔
132
           ) {
133
            dot = all_jobs_vector[ii]->name.find_first_of(".");
3,609✔
134
            if (!all_jobs_vector[ii]->name.compare(dot,11,".frame_log.")) {
3,609✔
135
                continue;
×
136
            }
137

138
            new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ;
3,609✔
139
            /** @li add job frame id, job class and cycle time to displayed job name, and prepend "JOB_" so it stands out in quickplot */
140
            if ( all_jobs_vector[ii]->job_class >= exec_get_scheduled_start_index() ) {
3,609✔
141
                if ( all_jobs_vector[ii]->thread == 0 ) {
1,222✔
142
                    asprintf(&job_name, "JOB_%s.%2.2f(%s_%2.3f)", all_jobs_vector[ii]->name.c_str(),
1,211✔
143
                        all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str(), all_jobs_vector[ii]->cycle);
1,211✔
144
                } else { // add child thread # to name
145
                    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✔
146
                        all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str(), all_jobs_vector[ii]->cycle);
11✔
147
                }
148
            } else { // non-scheduled class
149
                asprintf(&job_name, "JOB_%s.%2.2f(%s)", all_jobs_vector[ii]->name.c_str(),
2,387✔
150
                    all_jobs_vector[ii]->frame_id, all_jobs_vector[ii]->job_class_name.c_str());
2,387✔
151
            }
152
            // replace any colons in (C++) job name with underscores
153
            char *colon = strchr(job_name, ':') ;
3,609✔
154
            while (colon) {
3,609✔
155
                colon[0] = '#';
×
156
                colon = strchr(job_name, ':') ;
×
157
            }
158

159
            new_ref->reference = job_name;
3,609✔
160
            new_ref->address = &(all_jobs_vector[ii]->frame_time_seconds) ;
3,609✔
161
            new_ref->attr = &time_value_attr ;
3,609✔
162
            /** @li use TRK tag in S_define to identify trick jobs */
163
            // trick jobs
164
            if ( all_jobs_vector[ii]->tags.count("TRK") ) {
3,609✔
165
                trick_jobs.push_back(std::string(job_name));
3,329✔
166
                drg_trick->add_variable(new_ref) ;
3,329✔
167
                drg_trick->add_rec_job(all_jobs_vector[ii]) ;
3,329✔
168
                // save names of trick sim objects (ones that user can change) so we can color code jobs in DP file
169
                if (!all_jobs_vector[ii]->name.compare(dot,5,".drd.")) {
3,329✔
170
                    dr_sim_object_name = all_jobs_vector[ii]->parent_object->name;
194✔
171
                }
172
                if (!all_jobs_vector[ii]->name.compare(dot,8,".master.")) {
3,329✔
173
                    ms_sim_object_name = all_jobs_vector[ii]->parent_object->name;
380✔
174
                }
175
                if (!all_jobs_vector[ii]->name.compare(dot,9,".rt_sync.")) {
3,329✔
176
                    rt_sim_object_name = all_jobs_vector[ii]->parent_object->name;
194✔
177
                }
178
                //TODO: no message jobs yet - fill this in when messaging has a job to look at here
179
                // if () {
180
                    msg_sim_object_name = std::string("message");
3,329✔
181
                //}
182
            // user jobs
183
            } else {
184
                user_jobs.push_back(std::string(job_name));
280✔
185
                drg_users[all_jobs_vector[ii]->thread]->add_variable(new_ref) ;
280✔
186
                drg_users[all_jobs_vector[ii]->thread]->add_rec_job(all_jobs_vector[ii]) ;
280✔
187
            }
188
        }
189
    }
190

191
    /* set the recoring job be and end of frame job.  Set each recording group to it's proper thread. */
192
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
194✔
193
    for ( fdrg_it = drg_users.begin() , ii = 0 ; fdrg_it != drg_users.end() ; ++fdrg_it , ii++ ) {
393✔
194
        (*fdrg_it)->set_job_class("end_of_frame") ;
199✔
195
        (*fdrg_it)->set_phase(65533);
199✔
196
        (*fdrg_it)->set_thread(ii);
199✔
197
        if ( ii > 0 ) {
199✔
198
            std::ostringstream group_name ;
5✔
199
            group_name << "trick_frame_userjobs_C" << ii ;
5✔
200
            (*fdrg_it)->add_variable( group_name.str() + ".frame_time") ;
5✔
201
        }
202
    }
203
    drg_trick->set_job_class("end_of_frame") ;
194✔
204
    drg_trick->set_phase(65535);
194✔
205

206
}
194✔
207

208
/**
209
@details
210
-# Add the log_userjob frame time we created above to the log_frame group
211
-# Add the log_trickjob frame time we created above to the log_frame group
212
-# Set the recording job data_record_group.frame to end of frame -
213
   phase it last (after rt_monitor) because time set in rt_monitor
214
*/
215
void Trick::FrameLog::add_recording_vars_for_frame() {
194✔
216

217
    REF2 * new_ref ;
218
    char * job_name = NULL ;
194✔
219
    int ii ;
220

221
    drg_frame->add_variable(rt_sim_object_name + std::string(".rt_sync.frame_time")) ;
194✔
222
    drg_frame->add_variable(rt_sim_object_name + std::string(".rt_sync.frame_overrun")) ;
194✔
223

224
    /* add the log_userjob frame time we created above to the log_frame group */
225
    for ( ii = 0 ; ii < num_threads ; ii++ ) {
393✔
226
        new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ;
199✔
227
        if (ii > 0) {
199✔
228
            asprintf(&job_name, "JOB_data_record_group_frame_userjobs_C%d.data_record.%2.2f(end_of_frame)",
5✔
229
             ii,drg_users[ii]->write_job->frame_id);
5✔
230
        } else {
231
            asprintf(&job_name, "JOB_data_record_group_frame_userjobs.data_record.%2.2f(end_of_frame)",
194✔
232
             drg_users[ii]->write_job->frame_id);
194✔
233
        }
234
        trick_jobs.push_back(std::string(job_name));
199✔
235
        new_ref->reference = job_name;
199✔
236
        new_ref->address = &(drg_users[ii]->write_job->frame_time_seconds);
199✔
237
        new_ref->attr = &time_value_attr ;
199✔
238
        drg_frame->add_variable(new_ref) ;
199✔
239
        drg_frame->add_rec_job(drg_users[ii]->write_job) ;
199✔
240
    }
241

242
    /* add the log_trickjob frame time we created above to the log_frame group */
243
    new_ref = (REF2 *)calloc(1 , sizeof(REF2)) ;
194✔
244
    asprintf(&job_name, "JOB_data_record_group.trickjobs.%2.2f(end_of_frame)",drg_trick->jobs[0]->frame_id);
194✔
245
    trick_jobs.push_back(std::string(job_name));
194✔
246
    new_ref->reference = job_name;
194✔
247
    new_ref->address = &(drg_trick->write_job->frame_time_seconds);
194✔
248
    new_ref->attr = &time_value_attr ;
194✔
249
    drg_frame->add_variable(new_ref) ;
194✔
250
    drg_frame->add_rec_job(drg_trick->write_job) ;
194✔
251

252
    /* set the recording job data_record_group.frame to end of frame -
253
       phase it last (after rt_monitor) because time set in rt_monitor */
254
    drg_frame->set_job_class("end_of_frame") ;
194✔
255
    drg_frame->set_phase(65535);
194✔
256
}
194✔
257

258
/**
259
@details
260
-# For each FrameDataRecordGroup in drg_users
261
 -# Call add_data_record_group
262
-# Call add_data_record_group for drg_trick
263
-# Call add_data_record_group for drg_frame
264
*/
265
void Trick::FrameLog::add_recording_groups_to_sim(Trick::DR_Buffering bufferType) {
1✔
266
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
1✔
267
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
2✔
268
        add_data_record_group( *fdrg_it , Trick::DR_Ring_Buffer) ;
1✔
269
    }
270
    add_data_record_group(drg_trick, bufferType) ;
1✔
271
    add_data_record_group(drg_frame, bufferType) ;
1✔
272
}
1✔
273

274
/**
275
@details
276
-# For each FrameDataRecordGroup in drg_users
277
 -# Call remove_data_record_group
278
-# Call remove_data_record_group for drg_trick
279
-# Call remove_data_record_group for drg_frame
280
*/
281
void Trick::FrameLog::remove_recording_groups_from_sim() {
10✔
282
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
10✔
283
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
20✔
284
        remove_data_record_group( *fdrg_it) ;
10✔
285
    }
286
    remove_data_record_group(drg_trick) ;
10✔
287
    remove_data_record_group(drg_frame) ;
10✔
288
}
10✔
289

290
/**
291
@details
292
-# For each FrameDataRecordGroup in drg_users
293
 -# Call enable
294
-# Call enable for drg_trick
295
-# Call enable for drg_frame
296
*/
297
void Trick::FrameLog::enable_recording_groups() {
1✔
298
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
1✔
299
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
2✔
300
        (*fdrg_it)->enable() ;
1✔
301
    }
302
    drg_trick->enable() ;
1✔
303
    drg_frame->enable() ;
1✔
304
}
1✔
305

306
/**
307
@details
308
-# For each FrameDataRecordGroup in drg_users
309
 -# Call disable
310
-# Call disable for drg_trick
311
-# Call disable for drg_frame
312
*/
313
void Trick::FrameLog::disable_recording_groups() {
×
314
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
×
315
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
×
316
        (*fdrg_it)->disable() ;
×
317
    }
318
    drg_trick->disable() ;
×
319
    drg_frame->disable() ;
×
320
}
×
321

322
/**
323
@details
324
-# For each FrameDataRecordGroup in drg_users
325
 -# Call init
326
-# Call init for drg_trick
327
-# Call init for drg_frame
328
*/
329
void Trick::FrameLog::init_recording_groups() {
1✔
330
    std::vector< Trick::FrameDataRecordGroup *>::iterator fdrg_it ;
1✔
331
    for ( fdrg_it = drg_users.begin() ; fdrg_it != drg_users.end() ; ++fdrg_it ) {
2✔
332
        (*fdrg_it)->init() ;
1✔
333
    }
334
    drg_trick->init() ;
1✔
335
    drg_frame->init() ;
1✔
336
}
1✔
337

338
/**
339
@details
340
-# Insert frame log clock jobs in queue before and after all jobs we want to log the time of.
341
*/
342
void Trick::FrameLog::add_instrument_jobs() {
1✔
343
    exec_instrument_before("trick_frame_log.frame_log.frame_clock_start") ;
1✔
344
    exec_instrument_after("trick_frame_log.frame_log.frame_clock_stop") ;
1✔
345
}
1✔
346

347
/**
348
@details
349
-# Removes frame log clock jobs in queue before and after all jobs.
350
*/
351
void Trick::FrameLog::remove_instrument_jobs() {
×
352
    exec_instrument_remove("trick_frame_log.frame_log.frame_clock_start") ;
×
353
    exec_instrument_remove("trick_frame_log.frame_log.frame_clock_stop") ;
×
354
}
×
355

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

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

361
    /** @par Detailed Design: */
362
    if ( target_job != NULL ) {
1,987,336✔
363
        /** @li Set target job's start time. */
364
        target_job->rt_start_time = clock.clock_time() ;
1,987,336✔
365
    }
366

367
    return(0) ;
1,987,336✔
368

369
}
370

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

374
    Trick::JobData * target_job = (Trick::JobData *)curr_job->sup_class_data ;
1,987,336✔
375
    int thread, mode;
376
    double time_scale;
377
    
378
    /** @par Detailed Design: */
379
    if ( target_job != NULL ) {
1,987,336✔
380
        if ( target_job->rt_start_time >= 0 ) {
1,987,336✔
381
            /** @li Set current job's stop time and frame time. */
382
            target_job->rt_stop_time = clock.clock_time() ;
1,987,336✔
383
            time_scale = 1.0 / target_job->time_tic_value;
1,987,336✔
384
            target_job->frame_time += (target_job->rt_stop_time - target_job->rt_start_time);
1,987,336✔
385
            target_job->frame_time_seconds = target_job->frame_time * time_scale;
1,987,336✔
386
            thread = target_job->thread;
1,987,336✔
387

388
            mode = exec_get_mode();
1,987,336✔
389
            /** @li Whatever inits run after & including start_realtime, make them be timelined as cyclic. */
390
            if (mode == Initialization) {
1,987,336✔
391
                if (! target_job->name.compare(rt_sim_object_name + std::string(".rt_sync.start_realtime")) ) {
28✔
392
                    log_init_end = true;
1✔
393
                    // fixup: set start_realtime function's start time to 0 because it will have reset the clock
394
                    target_job->rt_start_time = 0;
1✔
395
                }
396
                if (log_init_end) {
28✔
397
                    mode = Run;
2✔
398
                }
399
            }
400

401
            /** @li Save all cyclic job start & stop times for this frame into timeline structure. */
402
            if ((mode==Run) || (mode==Step)) {                            // cyclic job
1,987,336✔
403
                if (tl_count[thread] < tl_max_samples) {
2,087,295✔
404
                    timeline[thread][tl_count[thread]].id    = target_job->frame_id;
100,000✔
405
                    timeline[thread][tl_count[thread]].start = target_job->rt_start_time;
100,000✔
406
                    timeline[thread][tl_count[thread]].stop  = target_job->rt_stop_time;
100,000✔
407
                    timeline[thread][tl_count[thread]].trick_job = target_job->tags.count("TRK");
100,000✔
408
                    timeline[thread][tl_count[thread]].isEndOfFrame = target_job->isEndOfFrame;
100,000✔
409
                    timeline[thread][tl_count[thread]].isTopOfFrame = target_job->isTopOfFrame;
100,000✔
410
                    tl_count[thread]++;
100,000✔
411
                }
412
            /** @li Save all non-cyclic job start & stop times for this frame into timeline_other structure. */
413
            } else {                                                      // non-cyclic job
414
                if (tl_other_count[thread] < tl_max_samples) {
41✔
415
                    timeline_other[thread][tl_other_count[thread]].id    = target_job->frame_id;
41✔
416
                    timeline_other[thread][tl_other_count[thread]].start = target_job->rt_start_time;
41✔
417
                    timeline_other[thread][tl_other_count[thread]].stop  = target_job->rt_stop_time;
41✔
418
                    timeline_other[thread][tl_other_count[thread]].trick_job = target_job->tags.count("TRK");
41✔
419
                    tl_other_count[thread]++;
41✔
420
                }
421
            }
422
            // start timeline over
423
            target_job->rt_start_time = 0;
1,987,336✔
424
            target_job->rt_stop_time = 0;
1,987,336✔
425
        } else {
426
            target_job->frame_time = 0 ;
×
427
            target_job->frame_time_seconds = 0.0;
×
428
        }
429
    }
430

431
    return(0) ;
1,987,336✔
432

433
}
434

435
/**
436
@details
437
-# If we are enabled already, return
438
-# If the frame log data recording groups are not in the sim
439
 -# Add the frame log data recording groups to the sim
440
 -# Initialize the frame log data recording groups.
441
-# Add instrument jobs
442
-# Enable the recording groups
443
-# Set the frame log flag to true
444
*/
445
int Trick::FrameLog::framelog_on(Trick::DR_Buffering bufferType) {
1✔
446

447
    if ( frame_log_flag == true ) {
1✔
448
        return(0) ;
×
449
    }
450
    // test if we have added the frame logging objects to the sim or not.
451
    // If we haven't add them now and initialize the data recording groups.
452
    // We do this in framelog_on so we don't add unnecessary jobs and create
453
    // log_rt files until we have to.
454
    if ( get_data_record_group(drg_trick->get_group_name()) == NULL ) {
1✔
455
        add_recording_groups_to_sim(bufferType) ;
1✔
456
        init_recording_groups() ;
1✔
457
    }
458
    add_instrument_jobs() ;
1✔
459
    enable_recording_groups() ;
1✔
460
    frame_log_flag = true ;
1✔
461
    return(0) ;
1✔
462
}
463

464
/**
465
@details
466
-# If we are disabled already, return
467
-# Remove instrument jobs
468
-# Disable the recording groups
469
-# Set the frame log flag to false.
470
*/
471
int Trick::FrameLog::framelog_off() {
1✔
472

473
    if ( frame_log_flag == false ) {
1✔
474
        return(0) ;
1✔
475
    }
476
    remove_instrument_jobs() ;
×
477
    disable_recording_groups() ;
×
478
    frame_log_flag = false ;
×
479
    return(0) ;
×
480
}
481

482
/**
483
@details
484
Command to set the maximum number of job timeline samples to be taken (default = 100000).
485
-# If num > 0
486
 -# Set new maximum to num.
487
 -# For each thread
488
  -# Reallocate the timeline data array
489
  -# Reallocate the timeline_other data array
490
*/
491
int Trick::FrameLog::set_max_samples(int num) {
×
492
    int ii ;
493
    if (num > 0) {
×
494
        tl_max_samples = num ;
×
495
        for (ii=0; ii<num_threads; ii++) {
×
496
            timeline[ii] = (Trick::timeline_t *)realloc( timeline[ii], tl_max_samples*sizeof(Trick::timeline_t));
×
497
            timeline_other[ii] = (Trick::timeline_t *)realloc( timeline_other[ii], tl_max_samples*sizeof(Trick::timeline_t));
×
498
        }
499
        std::vector< Trick::FrameDataRecordGroup *>::iterator it ;
×
500
        for ( it = drg_users.begin() ; it != drg_users.end() ; ++it ) {
×
501
            (*it)->set_max_buffer_size(num) ;
×
502
        }
503
        drg_trick->set_max_buffer_size(num) ;
×
504
        drg_frame->set_max_buffer_size(num) ;
×
505
    }
506
    return(0) ;
×
507
}
508

509
/**
510
@details
511
-# Allocate memory for all of the frame log recording groups.
512
-# Add variables for both frame and individual job recording groups.
513
-# Create DP files.
514
*/
515
void Trick::FrameLog::default_data() {
184✔
516
    allocate_recording_groups() ;
184✔
517
    add_recording_vars_for_jobs() ;
184✔
518
    add_recording_vars_for_frame() ;
184✔
519
    // reset clock before frame logging
520
    clock.clock_reset(0);
184✔
521
}
184✔
522

523
/**
524
@details
525

526
Clears any data_record information related to frame logging from the checkpoint reload.
527
This job must run before DataRecordGroup::restart.
528

529
DataRecordGroups save the list of variables it was recording when a checkpoint is taken.
530
This list is used by DataRecordGroups to restart data recording.
531
This list doesn't work with frame log groups because frame logging creates the
532
data record list of varaibles differently than normal recording groups.  So, we need
533
to erase the checkpointed list of frame log variables.  The correct variables will
534
be inserted during FrameLog::restart which is run after DataRecordGroup::restart.
535

536
-# For each FrameDataRecordGroup in drg_users
537
 -# Call clear_checkpoint_vars
538
-# Call clear_checkpoint_vars for drg_trick
539
-# Call clear_checkpoint_vars for drg_frame
540
*/
541
int Trick::FrameLog::clear_data_record_info() {
10✔
542

543
    remove_recording_groups_from_sim() ;
10✔
544

545
    std::vector< Trick::FrameDataRecordGroup *>::iterator it ;
10✔
546
    for ( it = drg_users.begin() ; it != drg_users.end() ; ++it ) {
20✔
547
        (*it)->clear_checkpoint_vars() ;
10✔
548
    }
549
    drg_trick->clear_checkpoint_vars() ;
10✔
550
    drg_frame->clear_checkpoint_vars() ;
10✔
551

552
    return 0 ;
10✔
553
}
554

555
/**
556
@details
557

558
Restart job that restores framelogging on checkpoint restart.  This is run after
559
clear_data_record_info.
560

561
-# Call data record group restart jobs
562
-# Add data recording variables for the jobs and frame
563
-# If frame log is on in checkpoint, turn frame log on.
564
*/
565
int Trick::FrameLog::restart() {
10✔
566
// removing the data record groups removed the restart jobs too.  call them here.
567
    std::vector< Trick::FrameDataRecordGroup *>::iterator it ;
10✔
568
    for ( it = drg_users.begin() ; it != drg_users.end() ; ++it ) {
20✔
569
        (*it)->restart() ;
10✔
570
    }
571
    drg_trick->restart() ;
10✔
572
    drg_frame->restart() ;
10✔
573

574
    add_recording_vars_for_jobs() ;
10✔
575
    add_recording_vars_for_frame() ;
10✔
576
    create_DP_files();
10✔
577

578
    // if frame log is on in the checkpoint, turn it back on now
579
    if ( frame_log_flag == true ) {
10✔
580
        frame_log_flag = false ;
×
581
        remove_instrument_jobs() ; // these will be added back when frame log turned on
×
582
        framelog_on() ;
×
583
    }
584
    return 0 ;
10✔
585
}
586

587
//Shutdown job that writes the job timeline data to disk and closes log files.
588
int Trick::FrameLog::shutdown() {
152✔
589

590
    /** @par Detailed Design: */
591

592
    int thread, ii, jj;
593
    char log_buff[128];
594
    Trick::timeline_t *tl;
595
    double start, stop, time_scale;
596

597
    if ( frame_log_flag == false ) {
152✔
598
        return(0) ;
151✔
599
    }
600

601

602
// ================================================================
603
// NEW Time-line for Jperf
604
// ================================================================
605
    for (int thread_num = 0; thread_num < num_threads; thread_num ++) {
2✔
606

607
        if (thread_num == 0) {
1✔
608
            snprintf(log_buff, sizeof(log_buff), "%s/log_newtimeline.csv", command_line_args_get_output_dir());
1✔
609
        } else {
610
            snprintf(log_buff, sizeof(log_buff), "%s/log_newtimelineC%d.csv", command_line_args_get_output_dir(), thread_num);
×
611
        }
612

613
        FILE *fp_log;
614
        if ((fp_log = fopen(log_buff, "w")) == NULL) {
1✔
615
            message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ;
×
616
            exit(0);
×
617
        }
618

619
        fprintf(fp_log,"jobID,startTime,stopTime\n");
1✔
620

621
        time_scale = 1.0 / exec_get_time_tic_value();
1✔
622
        tl = timeline[thread_num];
1✔
623
        for ( ii = 0 ; ii < tl_count[thread_num] ; ii++ ) {
100,001✔
624
            start = tl[ii].start * time_scale;
100,000✔
625
            stop =  tl[ii].stop  * time_scale;
100,000✔
626
            fprintf(fp_log,"%5.2f, %f, %f\n", tl[ii].id, start, stop);
100,000✔
627
        }
628
        fflush(fp_log);
1✔
629
        fclose(fp_log);
1✔
630
    }
631

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

635

636
        snprintf(log_buff, sizeof(log_buff), "%s/log_timeline.csv", command_line_args_get_output_dir());
1✔
637
        if ((fp_time_main = fopen(log_buff, "w")) == NULL) {
1✔
638
            message_publish(MSG_ERROR, "Could not open log_timeline.csv file for Job Timeline Logging\n") ;
×
639
            exit(0);
×
640
        }
641
        fprintf(fp_time_main, "trick_frame_log.frame_log.job_time {s},");
1✔
642
        fprintf(fp_time_main, "trick_frame_log.frame_log.job_trick_id {--},frame_log.frame_log.job_user_id {--}");
1✔
643

644
        for (jj=1; jj<num_threads; jj++) {
1✔
645
            fprintf(fp_time_main, ",trick_frame_log.frame_log.job_userC%d_id {--}",jj);
×
646
        }
647
        fprintf(fp_time_main, "\n");
1✔
648

649

650

651
        snprintf(log_buff, sizeof(log_buff), "%s/log_timeline_init.csv", command_line_args_get_output_dir());
1✔
652
        if ((fp_time_other = fopen(log_buff, "w")) == NULL) {
1✔
653
            message_publish(MSG_ERROR, "Could not open log_timeline_init.csv file for Job Timeline Logging\n") ;
×
654
            exit(0);
×
655
        }
656
        fprintf(fp_time_other, "trick_frame_log.frame_log.job_init_time {s},");
1✔
657
        fprintf(fp_time_other, "trick_frame_log.frame_log.job_trickinit_id {--},trick_frame_log.frame_log.job_userinit_id {--}\n");
1✔
658

659

660

661
    }
662

663
    time_scale = 1.0 / exec_get_time_tic_value();
1✔
664
            // print to log like this:
665
            // (only one of the job ids will be filled in depending on what type of job this is)
666
            //               start job time, 0, 0
667
            //               start job time, trick job id, user job id
668
            //               stop  job time, trick job id, user job id
669
            //               stop  job time, 0, 0
670
    /** @li print a 0 id before each start time & after each stop time for a stairstep effect in plot. */
671
    // cyclic jobs
672

673
    for ( thread = 0 ; thread < num_threads ; thread++ ) {
2✔
674
        tl = timeline[thread];
1✔
675
        for ( ii = 0 ; ii < tl_count[thread] ; ii++ ) {
100,001✔
676
            // start & stop time are in tics, so convert to seconds
677
            start = tl[ii].start * time_scale;
100,000✔
678
            stop =  tl[ii].stop  * time_scale;
100,000✔
679

680
            fprintf(fp_time_main,      "%f,0", start);        // start stairstep
100,000✔
681
            for (jj=0; jj<num_threads; jj++) {
200,000✔
682
                fprintf(fp_time_main,  ",0");
100,000✔
683
            }
684
            fprintf(fp_time_main,      "\n");
100,000✔
685

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

726
    // non-cyclic jobs
727
    for ( thread = 0 ; thread < num_threads ; thread++ ) {
2✔
728
        tl = timeline_other[thread];
1✔
729
        for ( ii = 0 ; ii < tl_other_count[thread] ; ii++ ) {
40✔
730
            // start & stop time are in tics, so convert to seconds
731
            start = tl[ii].start * time_scale;
39✔
732
            stop =  tl[ii].stop  * time_scale;
39✔
733
            fprintf(fp_time_other, "%f,0,0\n", start);          // start stairstep
39✔
734
            if (tl[ii].trick_job) {
39✔
735
                fprintf(fp_time_other, "%f,%f,0\n", start, tl[ii].id); // trick job start
37✔
736
                fprintf(fp_time_other, "%f,%f,0\n", stop, tl[ii].id);  // trick job end
37✔
737
            } else { // user job
738
                fprintf(fp_time_other, "%f,0,%f\n", start, tl[ii].id); // user job start
2✔
739
                fprintf(fp_time_other, "%f,0,%f\n", stop, tl[ii].id);  // user job end
2✔
740
            }
741
            fprintf(fp_time_other, "%f,0,0\n", stop);           // end stairstep
39✔
742
        } // end for thread
743
    } // end for ii
744

745
    fclose(fp_time_main);
1✔
746
    fclose(fp_time_other);
1✔
747

748
    return(0) ;
1✔
749

750
}
751

752
void Trick::FrameLog::set_clock(Trick::Clock & in_clock) {
×
753
    clock = in_clock ;
×
754
}
×
755

756
//Call all the Create routines for the DP directory and all DP files.
757
int Trick::FrameLog::create_DP_files() {
162✔
758
    int ret=0;
162✔
759

760
    ret = create_DP_Product_dir();
162✔
761
    if (ret==0) {
162✔
762
        // Only create DP files if we successfully created the directory
763
        create_DP_job_files();
162✔
764
        create_DP_timeline_files();
162✔
765
    }
766

767
    return ret ;
162✔
768
}
769

770
//Create the DP_Product directory where the DP files will be stored.
771
int Trick::FrameLog::create_DP_Product_dir() {
162✔
772
    int ret=0;
162✔
773
    DP_dir = "DP_Product";
162✔
774
    if (std::string(command_line_args_get_user_output_dir()) != std::string(command_line_args_get_output_dir())) {
162✔
775
        if (!std::string(command_line_args_get_user_output_dir()).empty()) {
162✔
776
            DP_dir = std::string(command_line_args_get_user_output_dir()) + "/DP_Product";
1✔
777
        }
778
    } 
779
    ret = mkdir(DP_dir.c_str(), 0777);
162✔
780
    if (ret == -1) {
162✔
781
        if (errno == EEXIST) {
134✔
782
            // it's ok if the directory is already there
783
            ret = 0;
134✔
784
        } else {
785
            // if you can't create the DP_Product dir in the current directory, try in the output dir (-O)
786
            DP_dir = std::string(command_line_args_get_output_dir()) + "/DP_Product";
×
787
            ret = mkdir(DP_dir.c_str(), 0777);
×
788
            if (ret == -1) {
×
789
                if (errno == EEXIST) {
×
790
                    // it's ok if the directory is already there
791
                    ret = 0;
×
792
                }
793
            }
794
        }
795
    }
796

797
    if (ret == -1) {
162✔
798
        message_publish(MSG_WARNING, "Could not create DP_Product directory for Frame Logging. DP files not created.\n") ;
×
799
        perror("mkdir");
×
800
    }
801
    return ret;
162✔
802
}
803

804
//Create the DP files to display trick and user job execution times.
805
int Trick::FrameLog::create_DP_job_files() {
162✔
806

807
    std::vector<std::string>::iterator job_iterator;
162✔
808
    FILE *fpx;
809
    unsigned int pages, plots, total_plots, vcells, dot;
810
    char *bg_color;
811
    std::string DP_buff;
324✔
812
    const char *headerx = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" \
162✔
813
                    "<!DOCTYPE product PUBLIC \"-//Tricklab//DTD Product V1.0//EN\" \"Product.dtd\">\n\n" \
814
                    "<!-- Description: Plot of Y(t) vs. t, with attributes, titles, labels, units -->\n\n" \
815
                    "<product version=\"1.0\">\n";
816

817
    DP_buff = DP_dir + "/DP_rt_frame.xml";
162✔
818
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
162✔
819
        message_publish(MSG_WARNING, "Could not open DP_rt_frame.xml file for Frame Logging\n") ;
×
820
        return(0);
×
821
    }
822
    fprintf(fpx, "%s", headerx);
162✔
823
    fprintf(fpx, "    <title>Real-Time Frame Overrun/Underrun History</title>\n    <page>\n        <title>Real-Time Scheduling Frame</title>\n");
162✔
824
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Frame Overrun/Underrun</title>\n");
162✔
825
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
162✔
826
    fprintf(fpx, "            <yaxis> <label>Frame Overrun/Underrun</label> </yaxis>\n");
162✔
827
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
162✔
828
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Overrun/Underrun\">%s.rt_sync.frame_overrun</var>\n", rt_sim_object_name.c_str());
162✔
829
    fprintf(fpx, "            </curve>\n");
162✔
830
    fprintf(fpx, "        </plot>\n");
162✔
831
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Frame Scheduled Jobs Time</title>\n");
162✔
832
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
162✔
833
    fprintf(fpx, "            <yaxis> <label>Frame Scheduled Jobs Time</label> </yaxis>\n");
162✔
834
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
162✔
835
    fprintf(fpx, "                <var line_color=\"red\" label=\"Frame Sched Time\">%s.rt_sync.frame_time</var>\n", rt_sim_object_name.c_str());
162✔
836
    fprintf(fpx, "            </curve>\n");
162✔
837
    fprintf(fpx, "        </plot>\n");
162✔
838
    fprintf(fpx, "    </page>\n");
162✔
839

840
    //unsigned int total_pages = (unsigned int)(drg_users.size() / plots_per_page) + 1 ;
841
    unsigned int total_pages ;
842
    if ( drg_users.size() <= 1 ) {
162✔
843
        total_pages = 1 ;
160✔
844
    } else {
845
        total_pages = (unsigned int)((drg_users.size() - 2)/ plots_per_page) + 1 ;
2✔
846
    }
847
    unsigned int page_count ;
848
    for ( page_count = 0 ; page_count < total_pages ; page_count++ ) {
324✔
849
        unsigned int ii = 0 ;
162✔
850
        // this check is to avoid empty page creation
851
        if ((page_count * plots_per_page + ii + 1) >= drg_users.size()) {
162✔
852
                continue;
160✔
853
        }
854
        fprintf(fpx, "    <page>\n");
2✔
855
        for ( ii = 0 ; ii < plots_per_page and (page_count * plots_per_page + ii + 1) < drg_users.size() ; ii++ ) {
7✔
856
            fprintf(fpx, "        <plot grid=\"yes\">\n");
5✔
857
            fprintf(fpx, "            <title>Child thread %u Frame Scheduled Jobs</title>\n", (page_count * plots_per_page + ii + 1));
5✔
858
            fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
5✔
859
            fprintf(fpx, "            <yaxis> <label>Frame Scheduled Jobs Time</label> </yaxis>\n");
5✔
860
            fprintf(fpx, "            <curve>\n");
5✔
861
            fprintf(fpx, "                <var>sys.exec.out.time</var>\n");
5✔
862
            std::ostringstream group_name ;
10✔
863
            group_name << "trick_frame_userjobs_C" << (page_count * plots_per_page + ii + 1) ;
5✔
864
            fprintf(fpx, "                <var line_color=\"red\" label=\"Frame Sched Time\">%s.frame_time</var>\n", group_name.str().c_str());
5✔
865
            fprintf(fpx, "            </curve>\n");
5✔
866
            fprintf(fpx, "        </plot>\n");
5✔
867
        }
868
        fprintf(fpx, "    </page>\n");
2✔
869
    }
870

871
    fprintf(fpx, "    <table>\n        <title>Real-Time Frame Overrun/Underrun History</title>\n");
162✔
872
    fprintf(fpx, "        <column format=\"%%13.6f\">\n");
162✔
873
    fprintf(fpx, "            <label>Sim Time</label>\n            <var>sys.exec.out.time</var>\n");
162✔
874
    fprintf(fpx, "        </column>\n");
162✔
875
    fprintf(fpx, "        <column format=\"%%13.6f\">\n");
162✔
876
    fprintf(fpx, "            <label>Overrun/Underrun</label>\n            <var>%s.rt_sync.frame_overrun</var>\n", rt_sim_object_name.c_str());
162✔
877
    fprintf(fpx, "        </column>\n");
162✔
878
    fprintf(fpx, "        <column format=\"%%13.6f\">\n");
162✔
879
    fprintf(fpx, "            <label>Frame Sched Time</label>\n            <var>%s.rt_sync.frame_time</var>\n", rt_sim_object_name.c_str());
162✔
880
    fprintf(fpx, "        </column>\n");
162✔
881
    fprintf(fpx, "    </table>\n</product>");
162✔
882
    fclose(fpx);
162✔
883

884
    // sort the saved job names
885
    sort(user_jobs.begin(), user_jobs.end());
162✔
886
    sort(trick_jobs.begin(), trick_jobs.end());
162✔
887

888
    // DP_rt_userjobs --------------------------------------------------------------
889
    int ii ;
890
    char numstr[21];
891
    for ( ii = 0 ; ii < num_threads ; ii++ ) {
329✔
892
        if ( ii == 0 ) {
167✔
893
             DP_buff = DP_dir + "/DP_rt_userjobs.xml";
162✔
894
        } else {
895
             snprintf(numstr, sizeof(numstr), "%d", ii);
5✔
896
             DP_buff = DP_dir + "/DP_rt_userjobs_C" + numstr + ".xml";
5✔
897
        }
898

899
        if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
167✔
900
            message_publish(MSG_WARNING, "Could not open DP_rt_userjobs.xml file for Frame Logging\n") ;
×
901
            return(0);
×
902
        }
903

904
        fprintf(fpx, "%s", headerx);
167✔
905
        fprintf(fpx, "    <title>User Job Execution History</title>\n");
167✔
906
        pages = 0; plots = 0;
167✔
907
        total_plots = drg_users[ii]->rec_buffer.size();
167✔
908
        std::vector <Trick::DataRecordBuffer *>::iterator drb_it ;
167✔
909
        bg_color = (char *)"cornsilk2";
167✔
910
        for ( drb_it = drg_users[ii]->rec_buffer.begin() + 1 ; drb_it != drg_users[ii]->rec_buffer.end() ; ++drb_it ) {
440✔
911
            if ( ! (*drb_it)->name.compare(0, 5, "frame") ) continue ;
273✔
912
            // plots_per_page job plots per page
913
            if ((plots == 0) || (plots > plots_per_page)) {
273✔
914
                pages++;
168✔
915
                vcells = (total_plots/pages > plots_per_page) * 4;
168✔
916
                if (pages > 1) {
168✔
917
                    fprintf(fpx, "    </page>\n");
7✔
918
                }
919
                fprintf(fpx, "    <page vcells=\"%d\">\n        <title>User Job Execution Times</title>\n", vcells);
168✔
920
                plots = 1;
168✔
921
            }
922
            fprintf(fpx, "        <plot grid=\"yes\" background_color=\"%s\">\n            <title>%s</title>\n", bg_color, (*drb_it)->name.c_str());
273✔
923
            fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
273✔
924
            fprintf(fpx, "            <yaxis> <label>Execution Time</label> </yaxis>\n");
273✔
925
            fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
273✔
926
            fprintf(fpx, "                <var line_color=\"red\">%s</var>\n", (*drb_it)->name.c_str());
273✔
927
            fprintf(fpx, "            </curve>\n");
273✔
928
            fprintf(fpx, "        </plot>\n");
273✔
929
            plots++;
273✔
930

931
        }
932
        fprintf(fpx, "    </page>\n</product>");
167✔
933
        fclose(fpx);
167✔
934
    }
935

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

993
    return(0) ;
162✔
994
}
995

996
//Create the DP files to display job timelines.
997
int Trick::FrameLog::create_DP_timeline_files() {
162✔
998

999
    FILE *fpx;
1000
    int jj;
1001
    std::string DP_buff;
324✔
1002
    const char *headerx = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n" \
162✔
1003
                    "<!DOCTYPE product PUBLIC \"-//Tricklab//DTD Product V1.0//EN\" \"Product.dtd\">\n\n" \
1004
                    "<!-- Description: Plot of Y(t) vs. t, with attributes, titles, labels, units -->\n\n" \
1005
                    "<product version=\"1.0\">\n";
1006

1007
    // DP_rt_timeline --------------------------------------------------------------
1008
    DP_buff = DP_dir + "/DP_rt_timeline.xml";
162✔
1009
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
162✔
1010
        message_publish(MSG_WARNING, "Could not open DP_rt_timeline.xml file for Frame Logging\n") ;
×
1011
        return(0);
×
1012
    }
1013

1014
    fprintf(fpx, "%s", headerx);
162✔
1015
    fprintf(fpx, "    <title>Job Timeline</title>\n    <page vcells=\"3\">\n        <title>Job Timeline</title>\n");
162✔
1016
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>User Job Timeline</title>\n");
162✔
1017
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
162✔
1018
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
162✔
1019
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
162✔
1020
    fprintf(fpx, "                <var line_color=\"red\" label=\"User Job Id\">trick_frame_log.frame_log.job_user_id</var>\n") ;
162✔
1021
    fprintf(fpx, "            </curve>\n");
162✔
1022
    fprintf(fpx, "        </plot>\n");
162✔
1023
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Trick Job Timeline</title>\n");
162✔
1024
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
162✔
1025
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
162✔
1026
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
162✔
1027
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_trick_id</var>\n") ;
162✔
1028
    fprintf(fpx, "            </curve>\n");
162✔
1029
    fprintf(fpx, "        </plot>\n");
162✔
1030
    // don't generate the plot without a curve
1031
    if (num_threads > 1) {
162✔
1032
        fprintf(fpx, "        <plot grid=\"yes\">\n            <title>Child Job Timeline</title>\n");
2✔
1033
        fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
2✔
1034
        fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
2✔
1035
        for (jj=1; jj<num_threads; jj++) {
7✔
1036
            fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
5✔
1037
            fprintf(fpx, "                <var line_color=\"blue\" label=\"Child%d Job Id\">trick_frame_log.frame_log.job_userC%d_id</var>\n",
5✔
1038
             jj,jj);
1039
            fprintf(fpx, "            </curve>\n");
5✔
1040
        }
1041
        fprintf(fpx, "        </plot>\n");
2✔
1042
    }
1043
    fprintf(fpx, "    </page>\n");
162✔
1044

1045
    fprintf(fpx, "    <page>\n        <title>Job Timeline (combined)</title>\n");
162✔
1046
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>User and Trick Job Timeline</title>\n");
162✔
1047
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
162✔
1048
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
162✔
1049
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
162✔
1050
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_trick_id</var>\n") ;
162✔
1051
    fprintf(fpx, "            </curve>\n");
162✔
1052
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
162✔
1053
    fprintf(fpx, "                <var line_color=\"red\" label=\"User Job Id\">trick_frame_log.frame_log.job_user_id</var>\n");
162✔
1054
    fprintf(fpx, "            </curve>\n");
162✔
1055
    for (jj=1; jj<num_threads; jj++) {
167✔
1056
        fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
5✔
1057
        fprintf(fpx, "                <var line_color=\"blue\" label=\"Child%d Job Id\">trick_frame_log.frame_log.job_userC%d_id</var>\n",
5✔
1058
                     jj,jj);
1059
        fprintf(fpx, "            </curve>\n");
5✔
1060
    }
1061
    fprintf(fpx, "        </plot>\n");
162✔
1062
    fprintf(fpx, "    </page>\n</product>");
162✔
1063
    fclose(fpx);
162✔
1064

1065
    // DP_rt_timeline_init ---------------------------------------------------------
1066
    DP_buff = DP_dir + "/DP_rt_timeline_init.xml";
162✔
1067
    if ((fpx = fopen(DP_buff.c_str(), "w")) == NULL) {
162✔
1068
        message_publish(MSG_WARNING, "Could not open DP_rt_timeline_init.xml file for Frame Logging\n") ;
×
1069
        return(0);
×
1070
    }
1071

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

1090
    fprintf(fpx, "    <page>\n        <title>Non-cyclic Job Timeline (combined)</title>\n");
162✔
1091
    fprintf(fpx, "        <plot grid=\"yes\">\n            <title>User and Trick Job Timeline</title>\n");
162✔
1092
    fprintf(fpx, "            <xaxis> <label>Time</label> <units>s</units> </xaxis>\n");
162✔
1093
    fprintf(fpx, "            <yaxis> <label>Job Id</label> </yaxis>\n");
162✔
1094
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
162✔
1095
    fprintf(fpx, "                <var line_color=\"darkgreen\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_trickinit_id</var>\n");
162✔
1096
    fprintf(fpx, "            </curve>\n");
162✔
1097
    fprintf(fpx, "            <curve>\n                <var>sys.exec.out.time</var>\n");
162✔
1098
    fprintf(fpx, "                <var line_color=\"red\" label=\"Trick Job Id\">trick_frame_log.frame_log.job_userinit_id</var>\n");
162✔
1099
    fprintf(fpx, "            </curve>\n");
162✔
1100
    fprintf(fpx, "        </plot>\n");
162✔
1101
    fprintf(fpx, "    </page>\n</product>");
162✔
1102
    fclose(fpx);
162✔
1103

1104
    return(0);
162✔
1105

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