Project

General

Profile

Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 2595f1a9

History | View | Annotate | Download (38.6 KB)

1
//=========================================================================
2
//  SEQUENCECHARTFACADE.CC - part of
3
//                  OMNeT++/OMNEST
4
//           Discrete System Simulation in C++
5
//
6
//  Author: Levente Meszaros
7
//
8
//=========================================================================
9

    
10
/*--------------------------------------------------------------*
11
  Copyright (C) 2006-2008 OpenSim Ltd.
12

13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16

    
17
#include <stdio.h>
18
#include <algorithm>
19
#include <set>
20
#include <math.h>
21
#include "lcgrandom.h"
22
#include "ievent.h"
23
#include "ieventlog.h"
24
#include "event.h"
25
#include "messagedependency.h"
26
#include "sequencechartfacade.h"
27

    
28
USING_NAMESPACE
29

    
30
SequenceChartFacade::SequenceChartFacade(IEventLog *eventLog) : EventLogFacade(eventLog)
31
{
32
    timelineMode = NONLINEAR;
33
    timelineCoordinateSystemVersion = -1;
34
    undefineTimelineCoordinateSystem();
35

    
36
    nonLinearMinimumTimelineCoordinateDelta = 0.1;
37
    setNonLinearFocus(calculateNonLinearFocus());
38

    
39
    smallestComplexity = -1;
40
    largestComplexity = -1;
41

    
42
    smallestDuration = -1;
43
    largestDuration = -1;
44

    
45
    biggestEarliestProcessingTime = 0;
46

    
47
    cachedParallelSet.clear();
48
    cachedCriticalPath.clear();
49
}
50

    
51
void SequenceChartFacade::synchronize(FileReader::FileChangedState change)
52
{
53
    if (change != FileReader::UNCHANGED) {
54
        EventLogFacade::synchronize(change);
55

    
56
        setNonLinearFocus(calculateNonLinearFocus());
57

    
58
        if (timelineCoordinateOriginEventNumber != -1) {
59
            IEvent *event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber);
60

    
61
            if (event)
62
                relocateTimelineCoordinateSystem(event);
63
            else
64
                undefineTimelineCoordinateSystem();
65
        }
66
    }
67
}
68

    
69
double SequenceChartFacade::calculateNonLinearFocus()
70
{
71
    if (!eventLog->isEmpty()) {
72
        double lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime().dbl();
73
        double firstEventSimulationTime = eventLog->getFirstEvent()->getSimulationTime().dbl();
74
        double totalSimulationTimeDelta = lastEventSimulationTime - firstEventSimulationTime;
75

    
76
        if (totalSimulationTimeDelta == 0)
77
            totalSimulationTimeDelta = firstEventSimulationTime;
78

    
79
        if (totalSimulationTimeDelta == 0)
80
            return 1;
81
        else
82
            return totalSimulationTimeDelta / eventLog->getApproximateNumberOfEvents() / 10;
83
    }
84
    else
85
        return 1;
86
}
87

    
88
void SequenceChartFacade::setNonLinearMinimumTimelineCoordinateDelta(double value)
89
{
90
    Assert(value >= 0);
91
    nonLinearMinimumTimelineCoordinateDelta = value;
92
}
93

    
94
void SequenceChartFacade::setNonLinearFocus(double nonLinearFocus)
95
{
96
    Assert(nonLinearFocus >= 0);
97
    this->nonLinearFocus = nonLinearFocus;
98
}
99

    
100
void SequenceChartFacade::undefineTimelineCoordinateSystem()
101
{
102
    timelineCoordinateSystemVersion++;
103
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = -1;
104
    timelineCoordinateOriginSimulationTime = simtime_nil;
105
    timelineCoordinateOriginRealTime = 0;
106
}
107

    
108
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
109
{
110
    Assert(event);
111

    
112
    timelineCoordinateSystemVersion++;
113
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = event->getEventNumber();
114
    timelineCoordinateOriginSimulationTime = event->getSimulationTime();
115
    timelineCoordinateOriginRealTime = event->getEarliestStartTime() / 1000000.0;
116
    event->cachedTimelineCoordinate = 0;
117
    event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
118
}
119

    
120
void SequenceChartFacade::setTimelineMode(TimelineMode timelineMode)
121
{
122
    this->timelineMode = timelineMode;
123

    
124
    if (timelineCoordinateOriginEventNumber != -1)
125
        relocateTimelineCoordinateSystem(eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber));
126
}
127

    
128
double SequenceChartFacade::IEvent_getTimelineCoordinate(ptr_t ptr)
129
{
130
    IEVENT_PTR(ptr);
131
    return getTimelineCoordinate((IEvent*)ptr);
132
}
133

    
134
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)
135
{
136
    IEVENT_PTR(ptr);
137
    return getTimelineEventEndCoordinate((IEvent*)ptr);
138
}
139

    
140
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
141
{
142
    Assert(nonLinearFocus > 0);
143

    
144
    if (timelineMode == STEP)
145
        return 1;
146
    else
147
        return nonLinearMinimumTimelineCoordinateDelta + (1 - nonLinearMinimumTimelineCoordinateDelta) * atan(fabs(simulationTimeDelta) / nonLinearFocus) / PI * 2;
148
}
149

    
150
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
151
{
152
    IEVENT_PTR(ptr);
153
    return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
154
}
155

    
156
double SequenceChartFacade::getTimelineEventEndCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
157
{
158
    IEVENT_PTR(ptr);
159
    return getTimelineEventEndCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
160
}
161

    
162
double SequenceChartFacade::getTimelineCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
163
{
164
    Assert(event);
165
    Assert(event->getEventLog() == eventLog);
166
    Assert(timelineCoordinateSystemVersion != -1);
167
    Assert(timelineCoordinateOriginEventNumber != -1);
168

    
169
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
170
        double timelineCoordinate;
171

    
172
        switch (timelineMode) {
173
            case REAL_TIME:
174
                timelineCoordinate = ((event->getEarliestStartTime()/1000000.0 - timelineCoordinateOriginRealTime));
175
                break;
176
            case SIMULATION_TIME:
177
                timelineCoordinate = (event->getSimulationTime() - timelineCoordinateOriginSimulationTime).dbl();
178
                break;
179
            case EVENT_NUMBER:
180
                timelineCoordinate = event->getEventNumber() - timelineCoordinateOriginEventNumber;
181
                break;
182
            case STEP:
183
            case NONLINEAR:
184
                {
185
                    IEvent *previousEvent = NULL;
186
                    // do we go forward from end or backward from start of known range
187
                    bool forward = event->getEventNumber() > timelineCoordinateRangeEndEventNumber;
188
                    IEvent *currentEvent = eventLog->getEventForEventNumber(forward ? timelineCoordinateRangeEndEventNumber : timelineCoordinateRangeStartEventNumber);
189

    
190
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
191

    
192
                    // TODO: LONG RUNNING OPERATION
193
                    // does a linear search towards the event to calculate the non linear timeline coordinate
194
                    do {
195
                        eventLog->progress();
196

    
197
                        Assert(currentEvent);
198
                        previousEvent = currentEvent;
199
                        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
200
                        Assert(currentEvent);
201

    
202
                        simtime_t previousSimulationTime = previousEvent->getSimulationTime();
203
                        double previousTimelineCoordinate = previousEvent->cachedTimelineCoordinate;
204
                        simtime_t simulationTime = currentEvent->getSimulationTime();
205
                        double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime - previousSimulationTime).dbl());
206

    
207
                        if (forward) {
208
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
209

    
210
                            if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)
211
                                return NaN;
212
                        }
213
                        else {
214
                            timelineCoordinate = previousTimelineCoordinate - timelineCoordinateDelta;
215

    
216
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
217
                                return NaN;
218
                        }
219

    
220
                        currentEvent->cachedTimelineCoordinate = timelineCoordinate;
221
                        currentEvent->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
222
                    }
223
                    while (currentEvent != event);
224

    
225
                    if (forward)
226
                        timelineCoordinateRangeEndEventNumber = event->getEventNumber();
227
                    else
228
                        timelineCoordinateRangeStartEventNumber = event->getEventNumber();
229
                }
230
                break;
231
            default:
232
                throw opp_runtime_error("Unknown timeline mode");
233
        }
234

    
235
        event->cachedTimelineCoordinate = timelineCoordinate;
236
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
237
    }
238

    
239
    return event->cachedTimelineCoordinate;
240
}
241

    
242
double SequenceChartFacade::getTimelineEventEndCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
243
{
244
    Assert(event);
245
    Assert(event->getEventLog() == eventLog);
246
    if(!eventLog->isLegacyTrace()) {
247
        return getTimelineCoordinate(event);
248
    }
249
        double timelineEventEndCoordinate;
250
        switch (timelineMode) {
251
            case REAL_TIME:
252
                timelineEventEndCoordinate = (event->getEarliestProcessingTime()/ 1000000.0 - timelineCoordinateOriginRealTime) ;
253
                break;
254
            case SIMULATION_TIME:
255
                timelineEventEndCoordinate = (event->getSimulationTime()+event->getEventEntry()->duration - timelineCoordinateOriginSimulationTime).dbl();
256
                break;
257
            default:
258
                return getTimelineCoordinate(event);
259
        }
260
    return timelineEventEndCoordinate;
261
}
262

    
263
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)
264
{
265
    Assert(event);
266
    Assert(timelineCoordinateSystemVersion != -1);
267
    Assert(timelineCoordinateOriginEventNumber != -1);
268

    
269
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion)
270
        return -1;
271
    else
272
        return event->cachedTimelineCoordinate;
273
}
274

    
275
IEvent *SequenceChartFacade::getEventForNonLinearTimelineCoordinate(double timelineCoordinate, bool &forward)
276
{
277
    Assert(timelineCoordinateOriginEventNumber != -1);
278
    IEvent *timelineCoordinateRangeStartEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeStartEventNumber);
279
    IEvent *timelineCoordinateRangeEndEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeEndEventNumber);
280
    IEvent *currentEvent;
281

    
282
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
283

    
284
    if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {
285
        forward = false;
286
        currentEvent = timelineCoordinateRangeStartEvent;
287
    }
288
    else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) {
289
        forward = true;
290
        currentEvent = timelineCoordinateRangeEndEvent;
291
    }
292
    else {
293
        forward = true;
294
        currentEvent = timelineCoordinateRangeStartEvent;
295
    }
296

    
297
    // TODO: LONG RUNNING OPERATION
298
    // does a linear search towards requested non linear timeline coordinate
299
    while (currentEvent && (forward ? getTimelineCoordinate(currentEvent) < timelineCoordinate :
300
                                      timelineCoordinate <= getTimelineCoordinate(currentEvent)))
301
    {
302
        eventLog->progress();
303
        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
304
    }
305

    
306
    return currentEvent;
307
}
308

    
309
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)
310
{
311
    if (eventLog->isEmpty())
312
        return NULL;
313

    
314
    switch (timelineMode) {
315
        case REAL_TIME:
316
        {
317
            //TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!
318
            IEvent* res = eventLog->getFirstEvent();
319
            for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
320
                if ((double) current->getEarliestStartTime() / 1000000.0 < timelineCoordinate) {
321
                    if (current->getEarliestStartTime() > res->getEarliestStartTime()) {
322
                        res = current;
323
                    }
324
                }
325
            }
326
            return res;
327
        }
328
        case SIMULATION_TIME:
329
            return eventLog->getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
330
        case EVENT_NUMBER:
331
            {
332
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
333

    
334
                if (eventNumber < 0)
335
                    return NULL;
336
                else
337
                    return eventLog->getLastEventNotAfterEventNumber(eventNumber);
338
            }
339
        case STEP:
340
        case NONLINEAR:
341
            {
342
                bool forward;
343
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
344
                currentEvent = forward ? (currentEvent ? currentEvent->getPreviousEvent() : eventLog->getLastEvent()) : currentEvent;
345

    
346
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) <= timelineCoordinate);
347
                return currentEvent;
348
            }
349
        default:
350
            throw opp_runtime_error("Unknown timeline mode");
351
    }
352
}
353

    
354
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)
355
{
356
    if (eventLog->isEmpty())
357
        return NULL;
358

    
359
    switch (timelineMode) {
360
        case REAL_TIME:
361
        {
362
            //TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!
363
            IEvent* res = eventLog->getLastEvent();
364
            for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
365
                if ((double) current->getEarliestStartTime() / 1000000.0 > timelineCoordinate) {
366
                    if (current->getEarliestStartTime() < res->getEarliestStartTime()) {
367
                        res = current;
368
                    }
369
                }
370
            }
371
            return res;
372
        }
373
        case SIMULATION_TIME:
374
            return eventLog->getFirstEventNotBeforeSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
375
        case EVENT_NUMBER:
376
            {
377
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
378

    
379
                if (eventNumber < 0)
380
                    return eventLog->getFirstEvent();
381
                else
382
                    return eventLog->getFirstEventNotBeforeEventNumber(eventNumber);
383
            }
384
        case STEP:
385
        case NONLINEAR:
386
            {
387
                bool forward;
388
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
389
                currentEvent = forward ? currentEvent : (currentEvent ? currentEvent->getNextEvent() : eventLog->getFirstEvent());
390

    
391
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) >= timelineCoordinate);
392
                return currentEvent;
393
            }
394
        default:
395
            throw opp_runtime_error("Unknown timeline mode");
396
    }
397
}
398

    
399
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(
400
    IEvent *event, IEvent *&nextEvent,
401
    simtime_t &eventSimulationTime, double &eventTimelineCoordinate,
402
    simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,
403
    simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)
404
{
405
    // if before the first event
406
    if (event) {
407
        if (timelineMode==REAL_TIME) {
408
            eventSimulationTime = event->getEarliestStartTime() / 1000000.0;
409
        } else {
410
            eventSimulationTime = event->getSimulationTime();
411
        }
412
        eventTimelineCoordinate = getTimelineCoordinate(event);
413
    }
414
    else {
415
        eventSimulationTime = BigDecimal::Zero;
416
        IEvent *firstEvent = eventLog->getFirstEvent();
417
        eventTimelineCoordinate = getTimelineCoordinate(firstEvent);
418

    
419
        if (timelineMode == EVENT_NUMBER)
420
            eventTimelineCoordinate -= 1;
421
        else if (timelineMode == REAL_TIME)
422
            eventTimelineCoordinate -= getTimelineCoordinateDelta(0);
423
        else
424
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
425
    }
426

    
427
    // linear approximation between two enclosing events
428
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
429

    
430
    if (nextEvent) {
431
        if(timelineMode==REAL_TIME) {
432
            nextEventSimulationTime = nextEvent->getEarliestStartTime() / 1000000.0;
433
        } else {
434
            nextEventSimulationTime = nextEvent->getSimulationTime();
435
        }
436

    
437
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
438

    
439
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
440
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
441
    }
442
}
443

    
444
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
445
{
446
    Assert(!isNaN(timelineCoordinate));
447

    
448
    if (eventLog->isEmpty())
449
        return BigDecimal::Zero;
450

    
451
    simtime_t simulationTime;
452

    
453
    switch (timelineMode)
454
    {
455
        case REAL_TIME:
456
        {
457
            simulationTime = max(BigDecimal::Zero, min(biggestEarliestProcessingTime, (timelineCoordinate + timelineCoordinateOriginRealTime)));
458
        }
459
        break;
460
        case SIMULATION_TIME:
461
            {
462
                simtime_t lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime();
463
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
464
            }
465
            break;
466
        case EVENT_NUMBER:
467
        case STEP:
468
        case NONLINEAR:
469
            {
470
                IEvent *nextEvent;
471
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
472
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
473

    
474
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
475
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
476
                                                             eventSimulationTime, eventTimelineCoordinate,
477
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
478
                                                             simulationTimeDelta, timelineCoordinateDelta);
479

    
480
                if (nextEvent) {
481
                    if (timelineCoordinateDelta == 0) {
482
                        // IMPORTANT NOTE: this is just an approximation
483
                        if (upperLimit)
484
                            simulationTime = nextEventSimulationTime;
485
                        else
486
                            simulationTime = eventSimulationTime;
487
                    }
488
                    else {
489
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
490
                        simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate - eventTimelineCoordinate) / timelineCoordinateDelta;
491
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
492
                    }
493
                }
494
                else
495
                    simulationTime = eventSimulationTime;
496
            }
497
            break;
498
        default:
499
            throw opp_runtime_error("Unknown timeline mode");
500
    }
501

    
502
    Assert(!simulationTime.isNaN());
503
    Assert(simulationTime >= BigDecimal::Zero);
504
    if (timelineMode != REAL_TIME)
505
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
506

    
507
    return simulationTime;
508
}
509

    
510
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
511
{
512
    Assert(!simulationTime.isNaN());
513

    
514
    if (eventLog->isEmpty())
515
        return 0;
516

    
517
    Assert(simulationTime >= BigDecimal::Zero);
518
    if (timelineMode != REAL_TIME)
519
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
520

    
521

    
522
    double timelineCoordinate;
523

    
524
    switch (timelineMode)
525
    {
526
        case REAL_TIME:
527
            //treat simulationTime as real time:
528
            timelineCoordinate = simulationTime.dbl() - timelineCoordinateOriginRealTime;
529
            break;
530
        case SIMULATION_TIME:
531
            timelineCoordinate = (simulationTime - timelineCoordinateOriginSimulationTime).dbl();
532
            break;
533
        case EVENT_NUMBER:
534
        case STEP:
535
        case NONLINEAR:
536
            {
537
                IEvent *nextEvent;
538
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
539
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
540

    
541
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
542
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
543
                                                             eventSimulationTime, eventTimelineCoordinate,
544
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
545
                                                             simulationTimeDelta, timelineCoordinateDelta);
546

    
547
                if (nextEvent) {
548
                    if (simulationTimeDelta == BigDecimal::Zero) {
549
                        // IMPORTANT NOTE: this is just an approximation
550
                        if (upperLimit)
551
                            timelineCoordinate = nextEventTimelineCoordinate;
552
                        else
553
                            timelineCoordinate = eventTimelineCoordinate;
554
                    }
555
                    else {
556
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
557
                        timelineCoordinate = eventTimelineCoordinate + timelineCoordinateDelta * (simulationTime - eventSimulationTime).dbl() / simulationTimeDelta.dbl();
558
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
559
                    }
560
                }
561
                else
562
                    timelineCoordinate = eventTimelineCoordinate;
563
            }
564
            break;
565
        default:
566
            throw opp_runtime_error("Unknown timeline mode");
567
    }
568

    
569
    Assert(!isNaN(timelineCoordinate));
570

    
571
    return timelineCoordinate;
572
}
573

    
574
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
575
{
576
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
577

    
578
    while (event && event->getSimulationTime() == simulationTime) {
579
        if (event->getModuleId() == moduleId)
580
            return getTimelineCoordinate(event);
581

    
582
        event = event->getNextEvent();
583
    }
584

    
585
    return getTimelineCoordinateForSimulationTime(simulationTime);
586
}
587

    
588
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
589
{
590
    IEvent *startEvent = (IEvent *)startEventPtr;
591
    IEvent *endEvent = (IEvent *)endEventPtr;
592
    Assert(startEvent);
593
    Assert(endEvent);
594
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
595

    
596
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
597
        eventLog->progress();
598

    
599
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
600
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
601

    
602
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
603
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
604
        }
605

    
606
        if (event == endEvent)
607
            break;
608
    }
609

    
610
    return moduleMethodBeginEntries;
611
}
612

    
613
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
614
{
615
    IEvent *startEvent = (IEvent *)startEventPtr;
616
    IEvent *endEvent = (IEvent *)endEventPtr;
617
    Assert(startEvent);
618
    Assert(endEvent);
619
    std::set<ptr_t> messageDependencies;
620
    eventnumber_t startEventNumber = startEvent->getEventNumber();
621

    
622
    // TODO: LONG RUNNING OPERATION
623
    // this might take a while if start and end events are far away from each other
624
    // if not completed then some dependencies will not be included
625
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
626
        eventLog->progress();
627
        IMessageDependencyList *causes = event->getCauses();
628

    
629
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
630
            IMessageDependency *messageDependency = *it;
631

    
632
            if (messageDependency->getCauseEventNumber() < startEventNumber)
633
                messageDependencies.insert((ptr_t)messageDependency);
634
        }
635

    
636
        IMessageDependencyList *consequences = event->getConsequences();
637

    
638
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
639
            messageDependencies.insert((ptr_t)*it);
640

    
641
        if (event == endEvent)
642
            break;
643
    }
644

    
645
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
646
    result->resize(messageDependencies.size());
647
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
648

    
649
    return result;
650
}
651

    
652
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
653
{
654
    LCGRandom lcgRandom;
655
    std::vector<int> adjacencyMatrix;
656
    std::set<int> axisIndexSet;
657
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
658

    
659
    for (std::map<int, int>::iterator it = moduleIdToAxisIndexMap->begin(); it != moduleIdToAxisIndexMap->end(); it++)
660
        axisIndexSet.insert(it->second);
661

    
662
    int numberOfAxes = axisIndexSet.size();
663
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
664

    
665
    for (int i = 0; i < numberOfSamples; i++)
666
    {
667
        // draw random
668
        double percentage = lcgRandom.next01();
669
        IEvent *event = eventLog->getApproximateEventAt(percentage);
670
        eventNumberToEventMap[event->getEventNumber()] = event;
671

    
672
        // look before origin
673
        if (timelineCoordinateOriginEventNumber != -1) {
674
            if (timelineCoordinateOriginEventNumber - i >= 0) {
675
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
676
                if (event)
677
                    eventNumberToEventMap[event->getEventNumber()] = event;
678
            }
679

    
680
            // look after origin
681
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
682
            if (event)
683
                eventNumberToEventMap[event->getEventNumber()] = event;
684
        }
685
    }
686

    
687
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
688
        IEvent *event = it->second;
689
        IMessageDependencyList *causes = event->getCauses();
690

    
691
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
692
            IMessageDependency *messageDependency = *it;
693
            IEvent *causeEvent = messageDependency->getCauseEvent();
694
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
695
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
696

    
697
            if (causeEvent && consequenceEvent && weight != 0) {
698
                int causeModuleId = causeEvent->getModuleId();
699
                int consequenceModuleId = consequenceEvent->getModuleId();
700

    
701
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
702
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
703

    
704
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
705
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
706
            }
707
        }
708
    }
709

    
710
    return adjacencyMatrix;
711
}
712

    
713

    
714
long SequenceChartFacade::getSmallestEventComplexity() {
715
    long complexity = 0;
716
    if (smallestComplexity < 0) {
717
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
718
             if (event->getEventEndEntry()) {
719
                 complexity = event->getEventEndEntry()->complexity;
720
             } else {
721
                 continue;
722
             }
723
             if (complexity < smallestComplexity || smallestComplexity < 0) {
724
                 smallestComplexity = complexity;
725
             }
726
             if (complexity > largestComplexity || largestComplexity < 0) {
727
                 largestComplexity = complexity;
728
             }
729
        }
730
    }
731
    if (smallestComplexity < 0) {
732
        smallestComplexity = 0;
733
    }
734
    return smallestComplexity;
735
}
736

    
737
long SequenceChartFacade::getLargestEventComplexity() {
738
    if (largestComplexity < 0) {
739
        getSmallestEventComplexity();
740
    }
741
    if (largestComplexity < 0) {
742
        largestComplexity = 0;
743
    }
744
    return largestComplexity;
745
}
746

    
747
simtime_t SequenceChartFacade::getSmallestEventDuration() {
748
    simtime_t duration = 0;
749
    if (smallestDuration < 0) {
750
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
751
             if (event->getEventEntry()) {
752
                 duration = event->getEventEntry()->duration;
753
             } else {
754
                 continue;
755
             }
756
             if (duration < smallestDuration || smallestDuration < 0) {
757
                 smallestDuration = duration;
758
             }
759
             if (duration > largestDuration || largestDuration < 0) {
760
                 largestDuration = duration;
761
             }
762
        }
763
    }
764
    if (smallestDuration < 0) {
765
        smallestDuration = 0;
766
    }
767
    return smallestDuration;
768
}
769

    
770
simtime_t SequenceChartFacade::getLargestEventDuration() {
771
    if (largestDuration < 0) {
772
        getSmallestEventComplexity();
773
    }
774
    if (largestDuration < 0) {
775
        largestDuration = 0;
776
    }
777
    return largestDuration;
778
}
779

    
780

    
781
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) {
782
    IEvent* next = e->getPreviousEvent();
783
    while (next) {
784
        if (isBottleneck(next,threshold)) {
785
            return next;
786
        }
787
        next = next->getPreviousEvent();
788
    }
789
    return e;
790
}
791

    
792
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) {
793
    IEvent* next = e->getNextEvent();
794
    while (next) {
795
        if (isBottleneck(next,threshold)) {
796
            return next;
797
        }
798
        next = next->getNextEvent();
799
    }
800
    return e;
801
}
802

    
803
/*
804
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
805
 */
806
bool SequenceChartFacade::isBottleneck(IEvent* event, unsigned int threshold)
807
{
808
    return getLargestParallelSetSize(event) <= threshold;
809
}
810
/*
811
 * Returns whether event is in the largest parallel set of selected.
812
 */
813
bool SequenceChartFacade::isParallelWithEvent(IEvent* event, IEvent* selected) {
814

    
815
    if (lastSelected != selected) {
816
        getLargestParallelSet(selected, &cachedParallelSet);
817
    }
818
    return cachedParallelSet.find((ptr_t)event) != cachedParallelSet.end();
819
}
820
/*
821
 * Returns the size of the largest set that is parallel with event.
822
 *
823
 * Works by calculating the first parallel set which does not contain event by
824
 * successively going backwards through all events starting from event.
825
 */
826
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event)
827
{
828
    IEvent* prev = event;
829
    std::set<ptr_t> parallelSet;
830
    parallelSet.clear();
831
    unsigned int previousSize = 0;
832
    while (prev)
833
    {
834
        previousSize = parallelSet.size();
835

    
836
        getParallelSet(prev, &parallelSet);
837

    
838
        if (parallelSet.find((ptr_t) event) == parallelSet.end())
839
        {
840
            //The current set does not contain event.
841
            //Therefore the previous set was the largest Parallel Set.
842
            break;
843
        }
844
        prev = prev->getPreviousEvent();
845
    }
846
    return previousSize;
847
}
848
/*
849
 * Returns the largest set that is parallel with event.
850
 *
851
 * Works by calculating the first parallel set which does not contain event by
852
 * successively going backwards through all events starting from event.
853
 */
854
std::set<ptr_t>* SequenceChartFacade::getLargestParallelSet(IEvent* event, std::set<ptr_t>* parallelSet) {
855
    IEvent* prev = event;
856
    parallelSet->clear();
857
    while (prev)
858
    {
859
        getParallelSet(prev, parallelSet);
860
        if (parallelSet->find((ptr_t) event) == parallelSet->end())
861
        {
862
            //The current set does not contain event.
863
            //Therefore the previous set was the largest Parallel Set.
864
            break;
865
        }
866
        prev = prev->getPreviousEvent();
867
    }
868
    if (prev != event) {
869
        getParallelSet(prev->getNextEvent(), parallelSet);
870
    }
871
    return parallelSet;
872
}
873

    
874
/*
875
 * Calculates a set of those events that start after event but are still in parallel to event.
876
 * This means that no other event must end before the latest start time in this set.
877
 */
878
void SequenceChartFacade::getParallelSet(IEvent* event,
879
        std::set<ptr_t>* parallelSet)
880
{
881
    IEvent* next = event->getNextEvent();
882
    simtime_t smallestParallelEndtime = getSmallestParallelEndtime(event);
883
    parallelSet->clear();
884
    parallelSet->insert((ptr_t) event);
885
    while (next)
886
    {
887
        if ((next->getSimulationTime() >= event->getSimulationTime())
888
                && (smallestParallelEndtime >= next->getSimulationTime()))
889
        {
890
            if(parallelSet->find((ptr_t)(next->getCauseEvent())) == parallelSet->end()) {
891
                parallelSet->insert((ptr_t) next);
892
            }
893
        }
894
        else
895
        {
896
            break;
897
        }
898
        next = next->getNextEvent();
899
    }
900
}
901
/*
902
 *
903
 */
904
simtime_t SequenceChartFacade::getSmallestParallelEndtime(IEvent* event)
905
{
906
    simtime_t minimum = event->getSimulationTime()
907
            + event->getEventEntry()->duration;
908
    for (IEvent *current = eventLog->getFirstEvent(); current; current
909
            = current->getNextEvent())
910
    {
911
        if (current->getSimulationTime() >= event->getSimulationTime())
912
        {
913
            if ((current->getSimulationTime()
914
                    + current->getEventEntry()->duration)
915
                    > event->getSimulationTime())
916
            {
917
                if (minimum > (current->getSimulationTime()
918
                        + current->getEventEntry()->duration))
919
                {
920
                    minimum = current->getSimulationTime()
921
                            + current->getEventEntry()->duration;
922
                }
923
            }
924
            if (current->getSimulationTime() > minimum)
925
            { // After this, no overlapping can follow
926
                break;
927
            }
928
        }
929
    }
930
    return minimum;
931
}
932

    
933
/*
934
 * Determines whether the event lies on the critical path
935
 */
936
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {
937
    if (cachedCriticalPath.empty()) {
938
        calculateCriticalPath();
939
    }
940
    return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());
941
}
942

    
943
/*
944
 * Calculates the critical path of the run and stores it in the set cachedCriticalPath
945
 */
946
void SequenceChartFacade::calculateCriticalPath() {
947
    long maxEarliestProcessingTime = 0;
948
    IEvent* maxEarliestProcessingTimeEvent;
949

    
950
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
951
        simtime_t startTime = current->getSimulationTime();
952
        int moduleId = current->getModuleId();
953
        if(current->getEventEndEntry()) {
954
            current->_earliestProcessingTime = current->getComplexity();
955
        }
956

    
957
        current->setCriticalPredecessor(eventLog->getFirstEvent());
958

    
959
        for (IEvent *antecessor = eventLog->getFirstEvent(); antecessor; antecessor = antecessor->getNextEvent()) {
960
            if(antecessor==current) {
961
                break; //We have to consider earlier events only
962
            }
963
            if(antecessor->getModuleId() != moduleId && current->getCauseEvent() != antecessor) {
964
                continue; // Check if this is an antecesor
965
            }
966
            if(antecessor->_earliestProcessingTime+current->getComplexity() > current->_earliestProcessingTime) {
967
                current->_earliestProcessingTime = antecessor->_earliestProcessingTime+current->getComplexity();
968
                current->setCriticalPredecessor(antecessor);
969
            }
970
        }
971
        // Memorize max event
972
        if (maxEarliestProcessingTime < current->_earliestProcessingTime) {
973
            maxEarliestProcessingTime = current->_earliestProcessingTime;
974
            maxEarliestProcessingTimeEvent = current;
975
        }
976
    }
977
    //Now produce the convex hull of critical antecessors/predecessors:
978
    cachedCriticalPath.clear();
979
    //Cache largest processing time:
980
    biggestEarliestProcessingTime = maxEarliestProcessingTime / 1000000.0;
981
    biggestEarliestProcessingTimeEvent = maxEarliestProcessingTimeEvent;
982
    for (IEvent *predecessor = maxEarliestProcessingTimeEvent; predecessor ; predecessor = predecessor->getCriticalPredecessor()) {
983
        cachedCriticalPath.insert((ptr_t)predecessor);
984
        if(predecessor->getEventNumber() == 0) {
985
            break;
986
        }
987
    }
988
}
989
/*
990
 * Returns the event with the largest calculated earliest Processing time in REAL_TIME mode
991
 * or the largest endtime in other modes within the given event range.
992
 */
993
ptr_t SequenceChartFacade::getLargestEndtimeInEventRange(ptr_t startEventPtr, ptr_t endEventPtr) {
994
    IEvent *startEvent = (IEvent *)startEventPtr;
995
    IEvent *endEvent = (IEvent *)endEventPtr;
996
    switch (timelineMode)
997
    {
998
    case REAL_TIME:
999
    {
1000
        //Use cached result when range contains all events
1001
        if(startEvent == eventLog->getFirstEvent() && endEvent == eventLog->getLastEvent()) {
1002
            return (ptr_t)biggestEarliestProcessingTimeEvent;
1003
        }
1004

    
1005
        long largest = 0;
1006
        IEvent* largestEvent = startEvent;
1007

    
1008
        for (IEvent* current = startEvent; current; current = current->getNextEvent()) {
1009
            long temp = current->getEarliestProcessingTime();
1010
            if (temp > largest) {
1011
                largest = temp;
1012
                largestEvent = current;
1013
            }
1014
            if (current==endEvent) {
1015
                break;
1016
            }
1017
        }
1018
        return (ptr_t) largestEvent;
1019
    }
1020
    case SIMULATION_TIME:
1021
    case EVENT_NUMBER:
1022
    case STEP:
1023
    case NONLINEAR:
1024
    default:
1025
        return endEventPtr;
1026
    }
1027

    
1028
}