Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 1c72663d

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

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

    
53
        setNonLinearFocus(calculateNonLinearFocus());
54

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

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

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

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

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

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

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

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

    
104
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
105
{
106
    Assert(event);
107

    
108
    timelineCoordinateSystemVersion++;
109
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = event->getEventNumber();
110
    timelineCoordinateOriginSimulationTime = event->getSimulationTime();
111
    event->cachedTimelineCoordinate = 0;
112
    event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
113
}
114

    
115
void SequenceChartFacade::setTimelineMode(TimelineMode timelineMode)
116
{
117
    this->timelineMode = timelineMode;
118

    
119
    if (timelineCoordinateOriginEventNumber != -1)
120
        relocateTimelineCoordinateSystem(eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber));
121
}
122

    
123
double SequenceChartFacade::IEvent_getTimelineCoordinate(ptr_t ptr)
124
{
125
    IEVENT_PTR(ptr);
126
    return getTimelineCoordinate((IEvent*)ptr);
127
}
128

    
129
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)
130
{
131
    IEVENT_PTR(ptr);
132
    return getTimelineEventEndCoordinate((IEvent*)ptr);
133
}
134

    
135
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
136
{
137
    Assert(nonLinearFocus > 0);
138

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

    
145
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
146
{
147
    IEVENT_PTR(ptr);
148
    return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
149
}
150

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

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

    
164
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
165
        double timelineCoordinate;
166

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

    
182
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
183

    
184
                    // TODO: LONG RUNNING OPERATION
185
                    // does a linear search towards the event to calculate the non linear timeline coordinate
186
                    do {
187
                        eventLog->progress();
188

    
189
                        Assert(currentEvent);
190
                        previousEvent = currentEvent;
191
                        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
192
                        Assert(currentEvent);
193

    
194
                        simtime_t previousSimulationTime = previousEvent->getSimulationTime();
195
                        double previousTimelineCoordinate = previousEvent->cachedTimelineCoordinate;
196
                        simtime_t simulationTime = currentEvent->getSimulationTime();
197
                        double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime - previousSimulationTime).dbl());
198

    
199
                        if (forward) {
200
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
201

    
202
                            if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)
203
                                return NaN;
204
                        }
205
                        else {
206
                            timelineCoordinate = previousTimelineCoordinate - timelineCoordinateDelta;
207

    
208
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
209
                                return NaN;
210
                        }
211

    
212
                        currentEvent->cachedTimelineCoordinate = timelineCoordinate;
213
                        currentEvent->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
214
                    }
215
                    while (currentEvent != event);
216

    
217
                    if (forward)
218
                        timelineCoordinateRangeEndEventNumber = event->getEventNumber();
219
                    else
220
                        timelineCoordinateRangeStartEventNumber = event->getEventNumber();
221
                }
222
                break;
223
            default:
224
                throw opp_runtime_error("Unknown timeline mode");
225
        }
226

    
227
        event->cachedTimelineCoordinate = timelineCoordinate;
228
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
229
    }
230

    
231
    return event->cachedTimelineCoordinate;
232
}
233

    
234
double SequenceChartFacade::getTimelineEventEndCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
235
{
236
    Assert(event);
237
    Assert(event->getEventLog() == eventLog);
238
    if(!eventLog->isLegacyTrace()) {
239
        return getTimelineCoordinate(event);
240
    }
241
        double timelineEventEndCoordinate;
242
        switch (timelineMode) {
243
            case SIMULATION_TIME:
244
                timelineEventEndCoordinate = (event->getSimulationTime()+event->getEventEntry()->duration - timelineCoordinateOriginSimulationTime).dbl();
245
                break;
246
            default:
247
                return getTimelineCoordinate(event);
248
        }
249
    return timelineEventEndCoordinate;
250
}
251

    
252
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)
253
{
254
    Assert(event);
255
    Assert(timelineCoordinateSystemVersion != -1);
256
    Assert(timelineCoordinateOriginEventNumber != -1);
257

    
258
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion)
259
        return -1;
260
    else
261
        return event->cachedTimelineCoordinate;
262
}
263

    
264
IEvent *SequenceChartFacade::getEventForNonLinearTimelineCoordinate(double timelineCoordinate, bool &forward)
265
{
266
    Assert(timelineCoordinateOriginEventNumber != -1);
267
    IEvent *timelineCoordinateRangeStartEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeStartEventNumber);
268
    IEvent *timelineCoordinateRangeEndEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeEndEventNumber);
269
    IEvent *currentEvent;
270

    
271
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
272

    
273
    if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {
274
        forward = false;
275
        currentEvent = timelineCoordinateRangeStartEvent;
276
    }
277
    else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) {
278
        forward = true;
279
        currentEvent = timelineCoordinateRangeEndEvent;
280
    }
281
    else {
282
        forward = true;
283
        currentEvent = timelineCoordinateRangeStartEvent;
284
    }
285

    
286
    // TODO: LONG RUNNING OPERATION
287
    // does a linear search towards requested non linear timeline coordinate
288
    while (currentEvent && (forward ? getTimelineCoordinate(currentEvent) < timelineCoordinate :
289
                                      timelineCoordinate <= getTimelineCoordinate(currentEvent)))
290
    {
291
        eventLog->progress();
292
        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
293
    }
294

    
295
    return currentEvent;
296
}
297

    
298
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)
299
{
300
    if (eventLog->isEmpty())
301
        return NULL;
302

    
303
    switch (timelineMode) {
304
        case SIMULATION_TIME:
305
            return eventLog->getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
306
        case EVENT_NUMBER:
307
            {
308
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
309

    
310
                if (eventNumber < 0)
311
                    return NULL;
312
                else
313
                    return eventLog->getLastEventNotAfterEventNumber(eventNumber);
314
            }
315
        case STEP:
316
        case NONLINEAR:
317
            {
318
                bool forward;
319
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
320
                currentEvent = forward ? (currentEvent ? currentEvent->getPreviousEvent() : eventLog->getLastEvent()) : currentEvent;
321

    
322
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) <= timelineCoordinate);
323
                return currentEvent;
324
            }
325
        default:
326
            throw opp_runtime_error("Unknown timeline mode");
327
    }
328
}
329

    
330
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)
331
{
332
    if (eventLog->isEmpty())
333
        return NULL;
334

    
335
    switch (timelineMode) {
336
        case SIMULATION_TIME:
337
            return eventLog->getFirstEventNotBeforeSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
338
        case EVENT_NUMBER:
339
            {
340
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
341

    
342
                if (eventNumber < 0)
343
                    return eventLog->getFirstEvent();
344
                else
345
                    return eventLog->getFirstEventNotBeforeEventNumber(eventNumber);
346
            }
347
        case STEP:
348
        case NONLINEAR:
349
            {
350
                bool forward;
351
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
352
                currentEvent = forward ? currentEvent : (currentEvent ? currentEvent->getNextEvent() : eventLog->getFirstEvent());
353

    
354
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) >= timelineCoordinate);
355
                return currentEvent;
356
            }
357
        default:
358
            throw opp_runtime_error("Unknown timeline mode");
359
    }
360
}
361

    
362
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(
363
    IEvent *event, IEvent *&nextEvent,
364
    simtime_t &eventSimulationTime, double &eventTimelineCoordinate,
365
    simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,
366
    simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)
367
{
368
    // if before the first event
369
    if (event) {
370
        eventSimulationTime = event->getSimulationTime();
371
        eventTimelineCoordinate = getTimelineCoordinate(event);
372
    }
373
    else {
374
        eventSimulationTime = BigDecimal::Zero;
375
        IEvent *firstEvent = eventLog->getFirstEvent();
376
        eventTimelineCoordinate = getTimelineCoordinate(firstEvent);
377

    
378
        if (timelineMode == EVENT_NUMBER)
379
            eventTimelineCoordinate -= 1;
380
        else
381
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
382
    }
383

    
384
    // linear approximation between two enclosing events
385
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
386

    
387
    if (nextEvent) {
388
        nextEventSimulationTime = nextEvent->getSimulationTime();
389
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
390

    
391
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
392
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
393
    }
394
}
395

    
396
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
397
{
398
    Assert(!isNaN(timelineCoordinate));
399

    
400
    if (eventLog->isEmpty())
401
        return BigDecimal::Zero;
402

    
403
    simtime_t simulationTime;
404

    
405
    switch (timelineMode)
406
    {
407
        case SIMULATION_TIME:
408
            {
409
                simtime_t lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime();
410
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
411
            }
412
            break;
413
        case EVENT_NUMBER:
414
        case STEP:
415
        case NONLINEAR:
416
            {
417
                IEvent *nextEvent;
418
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
419
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
420

    
421
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
422
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
423
                                                             eventSimulationTime, eventTimelineCoordinate,
424
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
425
                                                             simulationTimeDelta, timelineCoordinateDelta);
426

    
427
                if (nextEvent) {
428
                    if (timelineCoordinateDelta == 0) {
429
                        // IMPORTANT NOTE: this is just an approximation
430
                        if (upperLimit)
431
                            simulationTime = nextEventSimulationTime;
432
                        else
433
                            simulationTime = eventSimulationTime;
434
                    }
435
                    else {
436
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
437
                        simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate - eventTimelineCoordinate) / timelineCoordinateDelta;
438
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
439
                    }
440
                }
441
                else
442
                    simulationTime = eventSimulationTime;
443
            }
444
            break;
445
        default:
446
            throw opp_runtime_error("Unknown timeline mode");
447
    }
448

    
449
    Assert(!simulationTime.isNaN());
450
    Assert(simulationTime >= BigDecimal::Zero);
451
    Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
452

    
453
    return simulationTime;
454
}
455

    
456
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
457
{
458
    Assert(!simulationTime.isNaN());
459

    
460
    if (eventLog->isEmpty())
461
        return 0;
462

    
463
    Assert(simulationTime >= BigDecimal::Zero);
464
    Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
465

    
466
    double timelineCoordinate;
467

    
468
    switch (timelineMode)
469
    {
470
        case SIMULATION_TIME:
471
            timelineCoordinate = (simulationTime - timelineCoordinateOriginSimulationTime).dbl();
472
            break;
473
        case EVENT_NUMBER:
474
        case STEP:
475
        case NONLINEAR:
476
            {
477
                IEvent *nextEvent;
478
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
479
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
480

    
481
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
482
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
483
                                                             eventSimulationTime, eventTimelineCoordinate,
484
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
485
                                                             simulationTimeDelta, timelineCoordinateDelta);
486

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

    
509
    Assert(!isNaN(timelineCoordinate));
510

    
511
    return timelineCoordinate;
512
}
513

    
514
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
515
{
516
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
517

    
518
    while (event && event->getSimulationTime() == simulationTime) {
519
        if (event->getModuleId() == moduleId)
520
            return getTimelineCoordinate(event);
521

    
522
        event = event->getNextEvent();
523
    }
524

    
525
    return getTimelineCoordinateForSimulationTime(simulationTime);
526
}
527

    
528
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
529
{
530
    IEvent *startEvent = (IEvent *)startEventPtr;
531
    IEvent *endEvent = (IEvent *)endEventPtr;
532
    Assert(startEvent);
533
    Assert(endEvent);
534
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
535

    
536
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
537
        eventLog->progress();
538

    
539
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
540
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
541

    
542
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
543
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
544
        }
545

    
546
        if (event == endEvent)
547
            break;
548
    }
549

    
550
    return moduleMethodBeginEntries;
551
}
552

    
553
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
554
{
555
    IEvent *startEvent = (IEvent *)startEventPtr;
556
    IEvent *endEvent = (IEvent *)endEventPtr;
557
    Assert(startEvent);
558
    Assert(endEvent);
559
    std::set<ptr_t> messageDependencies;
560
    eventnumber_t startEventNumber = startEvent->getEventNumber();
561

    
562
    // TODO: LONG RUNNING OPERATION
563
    // this might take a while if start and end events are far away from each other
564
    // if not completed then some dependencies will not be included
565
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
566
        eventLog->progress();
567
        IMessageDependencyList *causes = event->getCauses();
568

    
569
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
570
            IMessageDependency *messageDependency = *it;
571

    
572
            if (messageDependency->getCauseEventNumber() < startEventNumber)
573
                messageDependencies.insert((ptr_t)messageDependency);
574
        }
575

    
576
        IMessageDependencyList *consequences = event->getConsequences();
577

    
578
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
579
            messageDependencies.insert((ptr_t)*it);
580

    
581
        if (event == endEvent)
582
            break;
583
    }
584

    
585
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
586
    result->resize(messageDependencies.size());
587
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
588

    
589
    return result;
590
}
591

    
592
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
593
{
594
    LCGRandom lcgRandom;
595
    std::vector<int> adjacencyMatrix;
596
    std::set<int> axisIndexSet;
597
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
598

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

    
602
    int numberOfAxes = axisIndexSet.size();
603
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
604

    
605
    for (int i = 0; i < numberOfSamples; i++)
606
    {
607
        // draw random
608
        double percentage = lcgRandom.next01();
609
        IEvent *event = eventLog->getApproximateEventAt(percentage);
610
        eventNumberToEventMap[event->getEventNumber()] = event;
611

    
612
        // look before origin
613
        if (timelineCoordinateOriginEventNumber != -1) {
614
            if (timelineCoordinateOriginEventNumber - i >= 0) {
615
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
616
                if (event)
617
                    eventNumberToEventMap[event->getEventNumber()] = event;
618
            }
619

    
620
            // look after origin
621
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
622
            if (event)
623
                eventNumberToEventMap[event->getEventNumber()] = event;
624
        }
625
    }
626

    
627
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
628
        IEvent *event = it->second;
629
        IMessageDependencyList *causes = event->getCauses();
630

    
631
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
632
            IMessageDependency *messageDependency = *it;
633
            IEvent *causeEvent = messageDependency->getCauseEvent();
634
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
635
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
636

    
637
            if (causeEvent && consequenceEvent && weight != 0) {
638
                int causeModuleId = causeEvent->getModuleId();
639
                int consequenceModuleId = consequenceEvent->getModuleId();
640

    
641
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
642
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
643

    
644
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
645
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
646
            }
647
        }
648
    }
649

    
650
    return adjacencyMatrix;
651
}
652

    
653

    
654
long SequenceChartFacade::getSmallestEventComplexity() {
655
    long complexity = 0;
656
    if (smallestComplexity < 0) {
657
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
658
             if (event->getEventEndEntry()) {
659
                 complexity = event->getEventEndEntry()->complexity;
660
             } else {
661
                 continue;
662
             }
663
             if (complexity < smallestComplexity || smallestComplexity < 0) {
664
                 smallestComplexity = complexity;
665
             }
666
             if (complexity > largestComplexity || largestComplexity < 0) {
667
                 largestComplexity = complexity;
668
             }
669
        }
670
    }
671
    if (smallestComplexity < 0) {
672
        smallestComplexity = 0;
673
    }
674
    return smallestComplexity;
675
}
676

    
677
long SequenceChartFacade::getLargestEventComplexity() {
678
    if (largestComplexity < 0) {
679
        getSmallestEventComplexity();
680
    }
681
    if (largestComplexity < 0) {
682
        largestComplexity = 0;
683
    }
684
    return largestComplexity;
685
}
686

    
687
simtime_t SequenceChartFacade::getSmallestEventDuration() {
688
    simtime_t duration = 0;
689
    if (smallestDuration < 0) {
690
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
691
             if (event->getEventEntry()) {
692
                 duration = event->getEventEntry()->duration;
693
             } else {
694
                 continue;
695
             }
696
             if (duration < smallestDuration || smallestDuration < 0) {
697
                 smallestDuration = duration;
698
             }
699
             if (duration > largestDuration || largestDuration < 0) {
700
                 largestDuration = duration;
701
             }
702
        }
703
    }
704
    if (smallestDuration < 0) {
705
        smallestDuration = 0;
706
    }
707
    return smallestDuration;
708
}
709

    
710
simtime_t SequenceChartFacade::getLargestEventDuration() {
711
    if (largestDuration < 0) {
712
        getSmallestEventComplexity();
713
    }
714
    if (largestDuration < 0) {
715
        largestDuration = 0;
716
    }
717
    return largestDuration;
718
}
719

    
720

    
721
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, unsigned int threshold) {
722
    IEvent* next = e->getPreviousEvent();
723
    while (next) {
724
        if (isBottleneck(next,threshold)) {
725
            return next;
726
        }
727
        next = next->getPreviousEvent();
728
    }
729
    return e;
730
}
731

    
732
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, unsigned int threshold) {
733
    IEvent* next = e->getNextEvent();
734
    while (next) {
735
        if (isBottleneck(next,threshold)) {
736
            return next;
737
        }
738
        next = next->getNextEvent();
739
    }
740
    return e;
741
}
742

    
743
/*
744
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
745
 */
746
bool SequenceChartFacade::isBottleneck(IEvent* event, unsigned int threshold)
747
{
748
    return getLargestParallelSetSize(event) <= threshold;
749
}
750
/*
751
 * Returns whether event is in the largest parallel set of selected.
752
 */
753
bool SequenceChartFacade::isParallelWithEvent(IEvent* event, IEvent* selected) {
754

    
755
    if (lastSelected != selected) {
756
        getLargestParallelSet(selected, &cachedParallelSet);
757
    }
758
    return cachedParallelSet.find((ptr_t)event) != cachedParallelSet.end();
759
}
760

    
761
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event)
762
{
763
    IEvent* prev = event;
764
    std::set<ptr_t> parallelSet;
765
    parallelSet.clear();
766
    unsigned int previousSize = 0;
767
    while (prev)
768
    {
769
        previousSize = parallelSet.size();
770

    
771
        getParallelSet(prev, &parallelSet);
772

    
773
        if (parallelSet.find((ptr_t) event) == parallelSet.end())
774
        {
775
            break;
776
        }
777
        prev = prev->getPreviousEvent();
778
    }
779
    return previousSize;
780
}
781

    
782
std::set<ptr_t>* SequenceChartFacade::getLargestParallelSet(IEvent* event, std::set<ptr_t>* parallelSet) {
783
    IEvent* prev = event;
784
    parallelSet->clear();
785
    while (prev)
786
    {
787
        getParallelSet(prev, parallelSet);
788
        if (parallelSet->find((ptr_t) event) == parallelSet->end())
789
        {
790
            break;
791
        }
792
        prev = prev->getPreviousEvent();
793
    }
794

    
795
    if (prev != event) {
796
        getParallelSet(prev->getNextEvent(), parallelSet);
797
    }
798
    return parallelSet;
799
}
800

    
801
void SequenceChartFacade::getParallelSet(IEvent* event,
802
        std::set<ptr_t>* parallelSet)
803
{
804
    IEvent* next = event->getNextEvent();
805
    simtime_t smallestParallelEndtime = getSmallestParallelEndtime(event);
806
    parallelSet->clear();
807
    parallelSet->insert((ptr_t) event);
808
    while (next)
809
    {
810
        if ((next->getSimulationTime() >= event->getSimulationTime())
811
                && (smallestParallelEndtime >= next->getSimulationTime()))
812
        {
813
            if(parallelSet->find((ptr_t)(next->getCauseEvent())) == parallelSet->end()) {
814
                parallelSet->insert((ptr_t) next);
815
            }
816
        }
817
        else
818
        {
819
            break;
820
        }
821
        next = next->getNextEvent();
822
    }
823
}
824

    
825
simtime_t SequenceChartFacade::getSmallestParallelEndtime(IEvent* event)
826
{
827
    simtime_t minimum = event->getSimulationTime()
828
            + event->getEventEntry()->duration;
829
    for (IEvent *current = eventLog->getFirstEvent(); current; current
830
            = current->getNextEvent())
831
    {
832
        if (current->getSimulationTime() >= event->getSimulationTime())
833
        {
834
            if ((current->getSimulationTime()
835
                    + current->getEventEntry()->duration)
836
                    > event->getSimulationTime())
837
            {
838
                if (minimum > (current->getSimulationTime()
839
                        + current->getEventEntry()->duration))
840
                {
841
                    minimum = current->getSimulationTime()
842
                            + current->getEventEntry()->duration;
843
                }
844
            }
845
            if (current->getSimulationTime() > minimum)
846
            { // After this, no overlapping can follow
847
                break;
848
            }
849
        }
850
    }
851
    return minimum;
852
}