Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 17a06e54

History | View | Annotate | Download (42.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
    maximumOverlapping = -1;
46

    
47
    biggestEarliestProcessingTime = 0;
48

    
49
    biggestEndTimeEvent = NULL;
50

    
51
    cachedParallelSet.clear();
52
    cachedCriticalPath.clear();
53
}
54

    
55
void SequenceChartFacade::synchronize(FileReader::FileChangedState change)
56
{
57
    if (change != FileReader::UNCHANGED) {
58
        EventLogFacade::synchronize(change);
59

    
60
        setNonLinearFocus(calculateNonLinearFocus());
61

    
62
        if (timelineCoordinateOriginEventNumber != -1) {
63
            IEvent *event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber);
64

    
65
            if (event)
66
                relocateTimelineCoordinateSystem(event);
67
            else
68
                undefineTimelineCoordinateSystem();
69
        }
70
    }
71
}
72

    
73
double SequenceChartFacade::calculateNonLinearFocus()
74
{
75
    if (!eventLog->isEmpty()) {
76
        double lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime().dbl();
77
        double firstEventSimulationTime = eventLog->getFirstEvent()->getSimulationTime().dbl();
78
        double totalSimulationTimeDelta = lastEventSimulationTime - firstEventSimulationTime;
79

    
80
        if (totalSimulationTimeDelta == 0)
81
            totalSimulationTimeDelta = firstEventSimulationTime;
82

    
83
        if (totalSimulationTimeDelta == 0)
84
            return 1;
85
        else
86
            return totalSimulationTimeDelta / eventLog->getApproximateNumberOfEvents() / 10;
87
    }
88
    else
89
        return 1;
90
}
91

    
92
void SequenceChartFacade::setNonLinearMinimumTimelineCoordinateDelta(double value)
93
{
94
    Assert(value >= 0);
95
    nonLinearMinimumTimelineCoordinateDelta = value;
96
}
97

    
98
void SequenceChartFacade::setNonLinearFocus(double nonLinearFocus)
99
{
100
    Assert(nonLinearFocus >= 0);
101
    this->nonLinearFocus = nonLinearFocus;
102
}
103

    
104
void SequenceChartFacade::undefineTimelineCoordinateSystem()
105
{
106
    timelineCoordinateSystemVersion++;
107
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = -1;
108
    timelineCoordinateOriginSimulationTime = simtime_nil;
109
    timelineCoordinateOriginRealTime = 0;
110
}
111

    
112
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
113
{
114
    Assert(event);
115

    
116
    timelineCoordinateSystemVersion++;
117
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = event->getEventNumber();
118
    timelineCoordinateOriginSimulationTime = event->getSimulationTime();
119
    timelineCoordinateOriginRealTime = event->getEarliestStartTime() / 1000000.0;
120
    event->cachedTimelineCoordinate = 0;
121
    event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
122
}
123

    
124
void SequenceChartFacade::setTimelineMode(TimelineMode timelineMode)
125
{
126
    this->timelineMode = timelineMode;
127

    
128
    if (timelineCoordinateOriginEventNumber != -1)
129
        relocateTimelineCoordinateSystem(eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber));
130
}
131

    
132
double SequenceChartFacade::IEvent_getTimelineCoordinate(ptr_t ptr)
133
{
134
    IEVENT_PTR(ptr);
135
    return getTimelineCoordinate((IEvent*)ptr);
136
}
137

    
138
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)
139
{
140
    IEVENT_PTR(ptr);
141
    return getTimelineEventEndCoordinate((IEvent*)ptr);
142
}
143

    
144
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
145
{
146
    Assert(nonLinearFocus > 0);
147

    
148
    if (timelineMode == STEP)
149
        return 1;
150
    else
151
        return nonLinearMinimumTimelineCoordinateDelta + (1 - nonLinearMinimumTimelineCoordinateDelta) * atan(fabs(simulationTimeDelta) / nonLinearFocus) / PI * 2;
152
}
153

    
154
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
155
{
156
    IEVENT_PTR(ptr);
157
    return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
158
}
159

    
160
double SequenceChartFacade::getTimelineEventEndCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
161
{
162
    IEVENT_PTR(ptr);
163
    return getTimelineEventEndCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
164
}
165

    
166
double SequenceChartFacade::getTimelineCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
167
{
168
    Assert(event);
169
    Assert(event->getEventLog() == eventLog);
170
    Assert(timelineCoordinateSystemVersion != -1);
171
    Assert(timelineCoordinateOriginEventNumber != -1);
172

    
173
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
174
        double timelineCoordinate;
175

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

    
194
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
195

    
196
                    // TODO: LONG RUNNING OPERATION
197
                    // does a linear search towards the event to calculate the non linear timeline coordinate
198
                    do {
199
                        eventLog->progress();
200

    
201
                        Assert(currentEvent);
202
                        previousEvent = currentEvent;
203
                        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
204
                        Assert(currentEvent);
205

    
206
                        simtime_t previousSimulationTime = previousEvent->getSimulationTime();
207
                        double previousTimelineCoordinate = previousEvent->cachedTimelineCoordinate;
208
                        simtime_t simulationTime = currentEvent->getSimulationTime();
209
                        double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime - previousSimulationTime).dbl());
210

    
211
                        if (forward) {
212
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
213

    
214
                            if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)
215
                                return NaN;
216
                        }
217
                        else {
218
                            timelineCoordinate = previousTimelineCoordinate - timelineCoordinateDelta;
219

    
220
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
221
                                return NaN;
222
                        }
223

    
224
                        currentEvent->cachedTimelineCoordinate = timelineCoordinate;
225
                        currentEvent->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
226
                    }
227
                    while (currentEvent != event);
228

    
229
                    if (forward)
230
                        timelineCoordinateRangeEndEventNumber = event->getEventNumber();
231
                    else
232
                        timelineCoordinateRangeStartEventNumber = event->getEventNumber();
233
                }
234
                break;
235
            default:
236
                throw opp_runtime_error("Unknown timeline mode");
237
        }
238

    
239
        event->cachedTimelineCoordinate = timelineCoordinate;
240
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
241
    }
242

    
243
    return event->cachedTimelineCoordinate;
244
}
245

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

    
267
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)
268
{
269
    Assert(event);
270
    Assert(timelineCoordinateSystemVersion != -1);
271
    Assert(timelineCoordinateOriginEventNumber != -1);
272

    
273
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion)
274
        return -1;
275
    else
276
        return event->cachedTimelineCoordinate;
277
}
278

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

    
286
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
287

    
288
    if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {
289
        forward = false;
290
        currentEvent = timelineCoordinateRangeStartEvent;
291
    }
292
    else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) {
293
        forward = true;
294
        currentEvent = timelineCoordinateRangeEndEvent;
295
    }
296
    else {
297
        forward = true;
298
        currentEvent = timelineCoordinateRangeStartEvent;
299
    }
300

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

    
310
    return currentEvent;
311
}
312

    
313
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)
314
{
315
    if (eventLog->isEmpty())
316
        return NULL;
317

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

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

    
350
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) <= timelineCoordinate);
351
                return currentEvent;
352
            }
353
        default:
354
            throw opp_runtime_error("Unknown timeline mode");
355
    }
356
}
357

    
358
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)
359
{
360
    if (eventLog->isEmpty())
361
        return NULL;
362

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

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

    
395
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) >= timelineCoordinate);
396
                return currentEvent;
397
            }
398
        default:
399
            throw opp_runtime_error("Unknown timeline mode");
400
    }
401
}
402

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

    
423
        if (timelineMode == EVENT_NUMBER)
424
            eventTimelineCoordinate -= 1;
425
        else if (timelineMode == REAL_TIME)
426
            eventTimelineCoordinate -= getTimelineCoordinateDelta(0);
427
        else
428
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
429
    }
430

    
431
    // linear approximation between two enclosing events
432
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
433

    
434
    if (nextEvent) {
435
        if(timelineMode==REAL_TIME) {
436
            nextEventSimulationTime = nextEvent->getEarliestStartTime() / 1000000.0;
437
        } else {
438
            nextEventSimulationTime = nextEvent->getSimulationTime();
439
        }
440

    
441
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
442

    
443
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
444
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
445
    }
446
}
447

    
448
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
449
{
450
    Assert(!isNaN(timelineCoordinate));
451

    
452
    if (eventLog->isEmpty())
453
        return BigDecimal::Zero;
454

    
455
    simtime_t simulationTime;
456

    
457
    switch (timelineMode)
458
    {
459
        case REAL_TIME:
460
        {
461
            simulationTime = max(BigDecimal::Zero, min(biggestEarliestProcessingTime, (timelineCoordinate + timelineCoordinateOriginRealTime)));
462
        }
463
        break;
464
        case SIMULATION_TIME:
465
            {
466
                IEvent* largestEvent = (IEvent*) getLargestEndtimeInEventRange((ptr_t)(eventLog->getFirstEvent()),(ptr_t)(eventLog->getLastEvent()), upperLimit);
467
                simtime_t lastEventSimulationTime= largestEvent->getSimulationTime() + largestEvent->getEventEntry()->duration;
468
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
469
            }
470
            break;
471
        case EVENT_NUMBER:
472
        case STEP:
473
        case NONLINEAR:
474
            {
475
                IEvent *nextEvent;
476
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
477
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
478

    
479
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
480
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
481
                                                             eventSimulationTime, eventTimelineCoordinate,
482
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
483
                                                             simulationTimeDelta, timelineCoordinateDelta);
484

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

    
507
    Assert(!simulationTime.isNaN());
508
    Assert(simulationTime >= BigDecimal::Zero);
509
    /*if (timelineMode != REAL_TIME)
510
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
511
    */
512
    return simulationTime;
513
}
514

    
515
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
516
{
517
    Assert(!simulationTime.isNaN());
518

    
519
    if (eventLog->isEmpty())
520
        return 0;
521

    
522
    Assert(simulationTime >= BigDecimal::Zero);
523
    /*if (timelineMode != REAL_TIME)
524
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
525
    */
526

    
527
    double timelineCoordinate;
528

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

    
546
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
547
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
548
                                                             eventSimulationTime, eventTimelineCoordinate,
549
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
550
                                                             simulationTimeDelta, timelineCoordinateDelta);
551

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

    
574
    Assert(!isNaN(timelineCoordinate));
575

    
576
    return timelineCoordinate;
577
}
578

    
579
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
580
{
581
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
582

    
583
    while (event && event->getSimulationTime() == simulationTime) {
584
        if (event->getModuleId() == moduleId)
585
            return getTimelineCoordinate(event);
586

    
587
        event = event->getNextEvent();
588
    }
589

    
590
    return getTimelineCoordinateForSimulationTime(simulationTime);
591
}
592

    
593
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
594
{
595
    IEvent *startEvent = (IEvent *)startEventPtr;
596
    IEvent *endEvent = (IEvent *)endEventPtr;
597
    Assert(startEvent);
598
    Assert(endEvent);
599
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
600

    
601
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
602
        eventLog->progress();
603

    
604
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
605
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
606

    
607
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
608
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
609
        }
610

    
611
        if (event == endEvent)
612
            break;
613
    }
614

    
615
    return moduleMethodBeginEntries;
616
}
617

    
618
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
619
{
620
    IEvent *startEvent = (IEvent *)startEventPtr;
621
    IEvent *endEvent = (IEvent *)endEventPtr;
622
    Assert(startEvent);
623
    Assert(endEvent);
624
    std::set<ptr_t> messageDependencies;
625
    eventnumber_t startEventNumber = startEvent->getEventNumber();
626

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

    
634
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
635
            IMessageDependency *messageDependency = *it;
636

    
637
            if (messageDependency->getCauseEventNumber() < startEventNumber)
638
                messageDependencies.insert((ptr_t)messageDependency);
639
        }
640

    
641
        IMessageDependencyList *consequences = event->getConsequences();
642

    
643
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
644
            messageDependencies.insert((ptr_t)*it);
645

    
646
        if (event == endEvent)
647
            break;
648
    }
649

    
650
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
651
    result->resize(messageDependencies.size());
652
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
653

    
654
    return result;
655
}
656

    
657
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
658
{
659
    LCGRandom lcgRandom;
660
    std::vector<int> adjacencyMatrix;
661
    std::set<int> axisIndexSet;
662
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
663

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

    
667
    int numberOfAxes = axisIndexSet.size();
668
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
669

    
670
    for (int i = 0; i < numberOfSamples; i++)
671
    {
672
        // draw random
673
        double percentage = lcgRandom.next01();
674
        IEvent *event = eventLog->getApproximateEventAt(percentage);
675
        eventNumberToEventMap[event->getEventNumber()] = event;
676

    
677
        // look before origin
678
        if (timelineCoordinateOriginEventNumber != -1) {
679
            if (timelineCoordinateOriginEventNumber - i >= 0) {
680
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
681
                if (event)
682
                    eventNumberToEventMap[event->getEventNumber()] = event;
683
            }
684

    
685
            // look after origin
686
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
687
            if (event)
688
                eventNumberToEventMap[event->getEventNumber()] = event;
689
        }
690
    }
691

    
692
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
693
        IEvent *event = it->second;
694
        IMessageDependencyList *causes = event->getCauses();
695

    
696
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
697
            IMessageDependency *messageDependency = *it;
698
            IEvent *causeEvent = messageDependency->getCauseEvent();
699
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
700
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
701

    
702
            if (causeEvent && consequenceEvent && weight != 0) {
703
                int causeModuleId = causeEvent->getModuleId();
704
                int consequenceModuleId = consequenceEvent->getModuleId();
705

    
706
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
707
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
708

    
709
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
710
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
711
            }
712
        }
713
    }
714

    
715
    return adjacencyMatrix;
716
}
717

    
718

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

    
742
long SequenceChartFacade::getLargestEventComplexity() {
743
    if (largestComplexity < 0) {
744
        getSmallestEventComplexity();
745
    }
746
    if (largestComplexity < 0) {
747
        largestComplexity = 0;
748
    }
749
    return largestComplexity;
750
}
751

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

    
775
simtime_t SequenceChartFacade::getLargestEventDuration() {
776
    if (largestDuration < 0) {
777
        getSmallestEventComplexity();
778
    }
779
    if (largestDuration < 0) {
780
        largestDuration = 0;
781
    }
782
    return largestDuration;
783
}
784

    
785

    
786
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) {
787
    IEvent* next = e->getPreviousEvent();
788
    while (next) {
789
        if (isBottleneck(next,threshold)) {
790
            return next;
791
        }
792
        next = next->getPreviousEvent();
793
    }
794
    return e;
795
}
796

    
797
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) {
798
    IEvent* next = e->getNextEvent();
799
    while (next) {
800
        if (isBottleneck(next,threshold)) {
801
            return next;
802
        }
803
        next = next->getNextEvent();
804
    }
805
    return e;
806
}
807

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

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

    
841
        getParallelSet(prev, &parallelSet);
842

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

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

    
938
/*
939
 * Determines whether the event lies on the critical path
940
 */
941
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {
942
    if (cachedCriticalPath.empty()) {
943
        calculateCriticalPath();
944
    }
945
    return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());
946
}
947

    
948
/*
949
 * Calculates the critical path of the run and stores it in the set cachedCriticalPath
950
 */
951
void SequenceChartFacade::calculateCriticalPath() {
952
    long maxEarliestProcessingTime = 0;
953
    IEvent* maxEarliestProcessingTimeEvent;
954

    
955
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
956
        simtime_t startTime = current->getSimulationTime();
957
        int moduleId = current->getModuleId();
958
        if(current->getEventEndEntry()) {
959
            current->_earliestProcessingTime = current->getComplexity();
960
        }
961

    
962
        current->setCriticalPredecessor(eventLog->getFirstEvent());
963

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

    
1014
        long largest = 0;
1015
        IEvent* largestEvent = startEvent;
1016

    
1017
        for (IEvent* current = startEvent; current; current
1018
                = current->getNextEvent())
1019
        {
1020
            long temp = current->getEarliestProcessingTime();
1021
            if (temp > largest)
1022
            {
1023
                largest = temp;
1024
                largestEvent = current;
1025
            }
1026
            if (current == endEvent)
1027
            {
1028
                break;
1029
            }
1030
        }
1031
        return (ptr_t) largestEvent;
1032
    }
1033
    case SIMULATION_TIME:
1034
    case EVENT_NUMBER:
1035
    case STEP:
1036
    case NONLINEAR:
1037
    default:
1038
    {
1039
        if (!duration) {
1040
            return endEventPtr;
1041
        }
1042
        //Use cached result when range contains all events
1043
        if (startEvent == eventLog->getFirstEvent() && endEvent
1044
                == eventLog->getLastEvent() && biggestEndTimeEvent != NULL)
1045
        {
1046
            return (ptr_t) biggestEndTimeEvent;
1047
        }
1048
        simtime_t largest = 0;
1049
        IEvent* largestEvent = endEvent;
1050

    
1051
        for (IEvent* current = endEvent; current; current
1052
                = current->getPreviousEvent())
1053
        {
1054
            simtime_t temp = current->getSimulationTime()
1055
                    + current->getEventEntry()->duration;
1056
            if (temp > largest)
1057
            {
1058
                largest = temp;
1059
                largestEvent = current;
1060
            }
1061
            if (current == startEvent)
1062
            {
1063
                break;
1064
            }
1065
        }
1066
        if (startEvent == eventLog->getFirstEvent() && endEvent
1067
                == eventLog->getLastEvent())
1068
        {
1069
            biggestEndTimeEvent = largestEvent;
1070
        }
1071

    
1072
        return (ptr_t) largestEvent;
1073
    }
1074
    }
1075

    
1076
}
1077

    
1078
double SequenceChartFacade::getOverlapping(ptr_t eventPtr) {
1079
    long overlapping = 0;
1080
    IEvent* event = (IEvent*) eventPtr;
1081

    
1082
    long eventProcessingTime = event->getEarliestProcessingTime();
1083
    long eventStartTime = event->getEarliestStartTime();
1084

    
1085
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1086

    
1087
        if(current->getComplexity() == 0) {
1088
            continue;
1089
        }
1090

    
1091
        long currentStartTime = current->getEarliestStartTime();
1092
        long currentProcessingTime = current->getEarliestProcessingTime();
1093

    
1094
        if(eventStartTime <= currentStartTime && eventProcessingTime >= currentStartTime) {
1095
            overlapping += eventProcessingTime - currentStartTime;
1096
        } else if (currentStartTime <= eventStartTime && currentProcessingTime >= eventStartTime) {
1097
            overlapping += currentProcessingTime - eventStartTime;
1098
        } else if (currentStartTime <= eventStartTime && currentProcessingTime >= eventProcessingTime) {
1099
            overlapping += event->getComplexity();
1100
        }
1101
    }
1102
    return overlapping / (event->getComplexity() * 1.0);
1103
}
1104

    
1105
double SequenceChartFacade::getMaximumOverlapping() {
1106
    double maxOverlapping = 0;
1107
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1108
        if(!isOnCriticalPath(current) || current->getComplexity() == 0) {
1109
            continue;
1110
        }
1111
        double overlapping = getOverlapping((ptr_t) current);
1112
        if (overlapping > maxOverlapping){
1113
            maxOverlapping = overlapping;
1114
        }
1115
    }
1116
    return maxOverlapping;
1117
}
1118

    
1119
/*
1120
 * returns the quotient of
1121
 * relative overlapping cputime with the event / maximum relative overlapping
1122
 * cputime with any event of the critical path
1123
 */
1124
double SequenceChartFacade::getOverlappingQuotient(ptr_t eventPtr) {
1125

    
1126
    if (((IEvent*)eventPtr)->getComplexity() == 0) {
1127
        return 0;
1128
    }
1129
    double overlapping = getOverlapping(eventPtr);
1130

    
1131
    if (maximumOverlapping == -1) {
1132
        maximumOverlapping = getMaximumOverlapping();
1133
    }
1134

    
1135
    return overlapping / maximumOverlapping;
1136
}
1137

    
1138
bool SequenceChartFacade::isOverlappingInRealTimeDomain(ptr_t eventPtr1, ptr_t eventPtr2) {
1139
    long eventProcessingTime1 = ((IEvent*)eventPtr1)->getEarliestProcessingTime();
1140
    long eventStartTime1 = ((IEvent*)eventPtr1)->getEarliestStartTime();
1141
    long eventProcessingTime2 = ((IEvent*)eventPtr2)->getEarliestProcessingTime();
1142
    long eventStartTime2 = ((IEvent*)eventPtr2)->getEarliestStartTime();
1143

    
1144
    return !(eventProcessingTime1 < eventStartTime2 || eventProcessingTime2 < eventStartTime1);
1145
}