Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ bcffd494

History | View | Annotate | Download (36.7 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
    cachedParallelSet.clear();
46
    cachedCriticalPath.clear();
47
}
48

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

    
54
        setNonLinearFocus(calculateNonLinearFocus());
55

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

    
59
            if (event)
60
                relocateTimelineCoordinateSystem(event);
61
            else
62
                undefineTimelineCoordinateSystem();
63
        }
64
    }
65
}
66

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

    
74
        if (totalSimulationTimeDelta == 0)
75
            totalSimulationTimeDelta = firstEventSimulationTime;
76

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

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

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

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

    
106
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
107
{
108
    Assert(event);
109

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

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

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

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

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

    
138
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
139
{
140
    Assert(nonLinearFocus > 0);
141

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

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

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

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

    
167
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
168
        double timelineCoordinate;
169

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

    
188
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
189

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

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

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

    
205
                        if (forward) {
206
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
207

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

    
214
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
215
                                return NaN;
216
                        }
217

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

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

    
233
        event->cachedTimelineCoordinate = timelineCoordinate;
234
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
235
    }
236

    
237
    return event->cachedTimelineCoordinate;
238
}
239

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

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

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

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

    
280
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
281

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

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

    
304
    return currentEvent;
305
}
306

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

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

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

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

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

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

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

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

    
397
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(
398
    IEvent *event, IEvent *&nextEvent,
399
    simtime_t &eventSimulationTime, double &eventTimelineCoordinate,
400
    simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,
401
    simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)
402
{
403
    //TODO: REAL_TIME
404

    
405
    // if before the first event
406
    if (event) {
407
        eventSimulationTime = event->getSimulationTime();
408
        eventTimelineCoordinate = getTimelineCoordinate(event);
409
    }
410
    else {
411
        eventSimulationTime = BigDecimal::Zero;
412
        IEvent *firstEvent = eventLog->getFirstEvent();
413
        eventTimelineCoordinate = getTimelineCoordinate(firstEvent);
414

    
415
        if (timelineMode == EVENT_NUMBER)
416
            eventTimelineCoordinate -= 1;
417
        else
418
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
419
    }
420

    
421
    // linear approximation between two enclosing events
422
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
423

    
424
    if (nextEvent) {
425
        nextEventSimulationTime = nextEvent->getSimulationTime();
426
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
427

    
428
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
429
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
430
    }
431
}
432

    
433
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
434
{
435
    Assert(!isNaN(timelineCoordinate));
436

    
437
    if (eventLog->isEmpty())
438
        return BigDecimal::Zero;
439

    
440
    simtime_t simulationTime;
441

    
442
    switch (timelineMode)
443
    {
444
        case REAL_TIME:
445
        {
446
            simtime_t lastEventSimulationTime = (eventLog->getLastEvent()->getEarliestStartTime()/1000000.0); //TODO: Change this to getEarliestStartTime();
447
            //NOTE: This sometimes crashes the Sequencechart because the returned value might be too big
448
            simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, (timelineCoordinate + timelineCoordinateOriginRealTime)/1000000.0));
449
        }
450
            //Fall back to SIMULATION_TIME (TODO)
451
        case SIMULATION_TIME:
452
            {
453
                simtime_t lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime();
454
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
455
            }
456
            break;
457
        case EVENT_NUMBER:
458
        case STEP:
459
        case NONLINEAR:
460
            {
461
                IEvent *nextEvent;
462
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
463
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
464

    
465
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
466
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
467
                                                             eventSimulationTime, eventTimelineCoordinate,
468
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
469
                                                             simulationTimeDelta, timelineCoordinateDelta);
470

    
471
                if (nextEvent) {
472
                    if (timelineCoordinateDelta == 0) {
473
                        // IMPORTANT NOTE: this is just an approximation
474
                        if (upperLimit)
475
                            simulationTime = nextEventSimulationTime;
476
                        else
477
                            simulationTime = eventSimulationTime;
478
                    }
479
                    else {
480
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
481
                        simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate - eventTimelineCoordinate) / timelineCoordinateDelta;
482
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
483
                    }
484
                }
485
                else
486
                    simulationTime = eventSimulationTime;
487
            }
488
            break;
489
        default:
490
            throw opp_runtime_error("Unknown timeline mode");
491
    }
492

    
493
    Assert(!simulationTime.isNaN());
494
    Assert(simulationTime >= BigDecimal::Zero);
495
    Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
496

    
497
    return simulationTime;
498
}
499

    
500
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
501
{
502
    Assert(!simulationTime.isNaN());
503

    
504
    if (eventLog->isEmpty())
505
        return 0;
506

    
507
    Assert(simulationTime >= BigDecimal::Zero);
508
    Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
509

    
510
    double timelineCoordinate;
511

    
512
    switch (timelineMode)
513
    {
514
        case REAL_TIME:
515
        //Fall back to SIMULATION_TIME (TODO)
516
        case SIMULATION_TIME:
517
            timelineCoordinate = (simulationTime - timelineCoordinateOriginSimulationTime).dbl();
518
            break;
519
        case EVENT_NUMBER:
520
        case STEP:
521
        case NONLINEAR:
522
            {
523
                IEvent *nextEvent;
524
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
525
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
526

    
527
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
528
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
529
                                                             eventSimulationTime, eventTimelineCoordinate,
530
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
531
                                                             simulationTimeDelta, timelineCoordinateDelta);
532

    
533
                if (nextEvent) {
534
                    if (simulationTimeDelta == BigDecimal::Zero) {
535
                        // IMPORTANT NOTE: this is just an approximation
536
                        if (upperLimit)
537
                            timelineCoordinate = nextEventTimelineCoordinate;
538
                        else
539
                            timelineCoordinate = eventTimelineCoordinate;
540
                    }
541
                    else {
542
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
543
                        timelineCoordinate = eventTimelineCoordinate + timelineCoordinateDelta * (simulationTime - eventSimulationTime).dbl() / simulationTimeDelta.dbl();
544
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
545
                    }
546
                }
547
                else
548
                    timelineCoordinate = eventTimelineCoordinate;
549
            }
550
            break;
551
        default:
552
            throw opp_runtime_error("Unknown timeline mode");
553
    }
554

    
555
    Assert(!isNaN(timelineCoordinate));
556

    
557
    return timelineCoordinate;
558
}
559

    
560
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
561
{
562
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
563

    
564
    while (event && event->getSimulationTime() == simulationTime) {
565
        if (event->getModuleId() == moduleId)
566
            return getTimelineCoordinate(event);
567

    
568
        event = event->getNextEvent();
569
    }
570

    
571
    return getTimelineCoordinateForSimulationTime(simulationTime);
572
}
573

    
574
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
575
{
576
    IEvent *startEvent = (IEvent *)startEventPtr;
577
    IEvent *endEvent = (IEvent *)endEventPtr;
578
    Assert(startEvent);
579
    Assert(endEvent);
580
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
581

    
582
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
583
        eventLog->progress();
584

    
585
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
586
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
587

    
588
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
589
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
590
        }
591

    
592
        if (event == endEvent)
593
            break;
594
    }
595

    
596
    return moduleMethodBeginEntries;
597
}
598

    
599
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
600
{
601
    IEvent *startEvent = (IEvent *)startEventPtr;
602
    IEvent *endEvent = (IEvent *)endEventPtr;
603
    Assert(startEvent);
604
    Assert(endEvent);
605
    std::set<ptr_t> messageDependencies;
606
    eventnumber_t startEventNumber = startEvent->getEventNumber();
607

    
608
    // TODO: LONG RUNNING OPERATION
609
    // this might take a while if start and end events are far away from each other
610
    // if not completed then some dependencies will not be included
611
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
612
        eventLog->progress();
613
        IMessageDependencyList *causes = event->getCauses();
614

    
615
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
616
            IMessageDependency *messageDependency = *it;
617

    
618
            if (messageDependency->getCauseEventNumber() < startEventNumber)
619
                messageDependencies.insert((ptr_t)messageDependency);
620
        }
621

    
622
        IMessageDependencyList *consequences = event->getConsequences();
623

    
624
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
625
            messageDependencies.insert((ptr_t)*it);
626

    
627
        if (event == endEvent)
628
            break;
629
    }
630

    
631
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
632
    result->resize(messageDependencies.size());
633
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
634

    
635
    return result;
636
}
637

    
638
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
639
{
640
    LCGRandom lcgRandom;
641
    std::vector<int> adjacencyMatrix;
642
    std::set<int> axisIndexSet;
643
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
644

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

    
648
    int numberOfAxes = axisIndexSet.size();
649
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
650

    
651
    for (int i = 0; i < numberOfSamples; i++)
652
    {
653
        // draw random
654
        double percentage = lcgRandom.next01();
655
        IEvent *event = eventLog->getApproximateEventAt(percentage);
656
        eventNumberToEventMap[event->getEventNumber()] = event;
657

    
658
        // look before origin
659
        if (timelineCoordinateOriginEventNumber != -1) {
660
            if (timelineCoordinateOriginEventNumber - i >= 0) {
661
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
662
                if (event)
663
                    eventNumberToEventMap[event->getEventNumber()] = event;
664
            }
665

    
666
            // look after origin
667
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
668
            if (event)
669
                eventNumberToEventMap[event->getEventNumber()] = event;
670
        }
671
    }
672

    
673
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
674
        IEvent *event = it->second;
675
        IMessageDependencyList *causes = event->getCauses();
676

    
677
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
678
            IMessageDependency *messageDependency = *it;
679
            IEvent *causeEvent = messageDependency->getCauseEvent();
680
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
681
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
682

    
683
            if (causeEvent && consequenceEvent && weight != 0) {
684
                int causeModuleId = causeEvent->getModuleId();
685
                int consequenceModuleId = consequenceEvent->getModuleId();
686

    
687
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
688
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
689

    
690
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
691
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
692
            }
693
        }
694
    }
695

    
696
    return adjacencyMatrix;
697
}
698

    
699

    
700
long SequenceChartFacade::getSmallestEventComplexity() {
701
    long complexity = 0;
702
    if (smallestComplexity < 0) {
703
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
704
             if (event->getEventEndEntry()) {
705
                 complexity = event->getEventEndEntry()->complexity;
706
             } else {
707
                 continue;
708
             }
709
             if (complexity < smallestComplexity || smallestComplexity < 0) {
710
                 smallestComplexity = complexity;
711
             }
712
             if (complexity > largestComplexity || largestComplexity < 0) {
713
                 largestComplexity = complexity;
714
             }
715
        }
716
    }
717
    if (smallestComplexity < 0) {
718
        smallestComplexity = 0;
719
    }
720
    return smallestComplexity;
721
}
722

    
723
long SequenceChartFacade::getLargestEventComplexity() {
724
    if (largestComplexity < 0) {
725
        getSmallestEventComplexity();
726
    }
727
    if (largestComplexity < 0) {
728
        largestComplexity = 0;
729
    }
730
    return largestComplexity;
731
}
732

    
733
simtime_t SequenceChartFacade::getSmallestEventDuration() {
734
    simtime_t duration = 0;
735
    if (smallestDuration < 0) {
736
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
737
             if (event->getEventEntry()) {
738
                 duration = event->getEventEntry()->duration;
739
             } else {
740
                 continue;
741
             }
742
             if (duration < smallestDuration || smallestDuration < 0) {
743
                 smallestDuration = duration;
744
             }
745
             if (duration > largestDuration || largestDuration < 0) {
746
                 largestDuration = duration;
747
             }
748
        }
749
    }
750
    if (smallestDuration < 0) {
751
        smallestDuration = 0;
752
    }
753
    return smallestDuration;
754
}
755

    
756
simtime_t SequenceChartFacade::getLargestEventDuration() {
757
    if (largestDuration < 0) {
758
        getSmallestEventComplexity();
759
    }
760
    if (largestDuration < 0) {
761
        largestDuration = 0;
762
    }
763
    return largestDuration;
764
}
765

    
766

    
767
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) {
768
    IEvent* next = e->getPreviousEvent();
769
    while (next) {
770
        if (isBottleneck(next,threshold)) {
771
            return next;
772
        }
773
        next = next->getPreviousEvent();
774
    }
775
    return e;
776
}
777

    
778
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) {
779
    IEvent* next = e->getNextEvent();
780
    while (next) {
781
        if (isBottleneck(next,threshold)) {
782
            return next;
783
        }
784
        next = next->getNextEvent();
785
    }
786
    return e;
787
}
788

    
789
/*
790
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
791
 */
792
bool SequenceChartFacade::isBottleneck(IEvent* event, unsigned int threshold)
793
{
794
    return getLargestParallelSetSize(event) <= threshold;
795
}
796
/*
797
 * Returns whether event is in the largest parallel set of selected.
798
 */
799
bool SequenceChartFacade::isParallelWithEvent(IEvent* event, IEvent* selected) {
800

    
801
    if (lastSelected != selected) {
802
        getLargestParallelSet(selected, &cachedParallelSet);
803
    }
804
    return cachedParallelSet.find((ptr_t)event) != cachedParallelSet.end();
805
}
806
/*
807
 * Returns the size of the largest set that is parallel with event.
808
 *
809
 * Works by calculating the first parallel set which does not contain event by
810
 * successively going backwards through all events starting from event.
811
 */
812
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event)
813
{
814
    IEvent* prev = event;
815
    std::set<ptr_t> parallelSet;
816
    parallelSet.clear();
817
    unsigned int previousSize = 0;
818
    while (prev)
819
    {
820
        previousSize = parallelSet.size();
821

    
822
        getParallelSet(prev, &parallelSet);
823

    
824
        if (parallelSet.find((ptr_t) event) == parallelSet.end())
825
        {
826
            //The current set does not contain event.
827
            //Therefore the previous set was the largest Parallel Set.
828
            break;
829
        }
830
        prev = prev->getPreviousEvent();
831
    }
832
    return previousSize;
833
}
834
/*
835
 * Returns the largest set that is parallel with event.
836
 *
837
 * Works by calculating the first parallel set which does not contain event by
838
 * successively going backwards through all events starting from event.
839
 */
840
std::set<ptr_t>* SequenceChartFacade::getLargestParallelSet(IEvent* event, std::set<ptr_t>* parallelSet) {
841
    IEvent* prev = event;
842
    parallelSet->clear();
843
    while (prev)
844
    {
845
        getParallelSet(prev, parallelSet);
846
        if (parallelSet->find((ptr_t) event) == parallelSet->end())
847
        {
848
            //The current set does not contain event.
849
            //Therefore the previous set was the largest Parallel Set.
850
            break;
851
        }
852
        prev = prev->getPreviousEvent();
853
    }
854
    if (prev != event) {
855
        getParallelSet(prev->getNextEvent(), parallelSet);
856
    }
857
    return parallelSet;
858
}
859

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

    
919
/*
920
 * Determines whether the event lies on the critical path
921
 */
922
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {
923
    if (cachedCriticalPath.empty()) {
924
        calculateCriticalPath();
925
    }
926
    return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());
927
}
928

    
929
/*
930
 * Calculates the critical path of the run and stores it in the set cachedCriticalPath
931
 */
932
void SequenceChartFacade::calculateCriticalPath() {
933
    long maxEarliestProcessingTime = 0;
934
    IEvent* maxEarliestProcessingTimeEvent;
935

    
936
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
937
        simtime_t startTime = current->getSimulationTime();
938
        int moduleId = current->getModuleId();
939
        if(current->getEventEndEntry()) {
940
            current->_earliestProcessingTime = current->getComplexity();
941
        }
942
        for (IEvent *antecessor = eventLog->getFirstEvent(); antecessor; antecessor = antecessor->getNextEvent()) {
943
            if(antecessor==current) {
944
                break; //We have to consider earlier events only
945
            }
946
            if(antecessor->getModuleId() != moduleId && current->getCauseEvent() != antecessor) {
947
                continue; // Check if this is an antecesor
948
            }
949
            if(antecessor->_earliestProcessingTime+current->getComplexity() > current->_earliestProcessingTime) {
950
                current->_earliestProcessingTime = antecessor->_earliestProcessingTime+current->getComplexity();
951
            }
952
        }
953
        // Memorize max event
954
        if (maxEarliestProcessingTime < current->_earliestProcessingTime) {
955
            maxEarliestProcessingTime = current->_earliestProcessingTime;
956
            maxEarliestProcessingTimeEvent = current;
957
        }
958
    }
959
    //Now produce the convex hull of predecessors:
960
    cachedCriticalPath.clear();
961
    for (IEvent *predecessor = maxEarliestProcessingTimeEvent; predecessor ; predecessor = predecessor->getCauseEvent()) {
962
        cachedCriticalPath.insert((ptr_t)predecessor);
963
        if(predecessor->getEventNumber() == 0) {
964
            break;
965
        }
966
    }
967
}
968