Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ a3b7e786

History | View | Annotate | Download (33.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
    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
}
104

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
232
    return event->cachedTimelineCoordinate;
233
}
234

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

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

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

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

    
272
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
273

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

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

    
296
    return currentEvent;
297
}
298

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
404
    simtime_t simulationTime;
405

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

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

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

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

    
454
    return simulationTime;
455
}
456

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

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

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

    
467
    double timelineCoordinate;
468

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

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

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

    
510
    Assert(!isNaN(timelineCoordinate));
511

    
512
    return timelineCoordinate;
513
}
514

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

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

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

    
526
    return getTimelineCoordinateForSimulationTime(simulationTime);
527
}
528

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

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

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

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

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

    
551
    return moduleMethodBeginEntries;
552
}
553

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

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

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

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

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

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

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

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

    
590
    return result;
591
}
592

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

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

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

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

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

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

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

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

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

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

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

    
651
    return adjacencyMatrix;
652
}
653

    
654

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

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

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

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

    
721

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

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

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

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

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

    
772
        getParallelSet(prev, &parallelSet);
773

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

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

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

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

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

    
855
/*
856
 * Determines whether the event lies on the critical path
857
 */
858
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {
859
    if (cachedCriticalPath.empty()) {
860
        calculateCriticalPath();
861
    }
862
    return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());
863
}
864

    
865
/*
866
 * Calculates the critical path of the run and stores it in the set cachedCriticalPath
867
 */
868
void SequenceChartFacade::calculateCriticalPath() {
869
    long maxEarliestProcessingTime = 0;
870
    IEvent* maxEarliestProcessingTimeEvent;
871

    
872
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
873
        simtime_t startTime = current->getSimulationTime();
874
        if(current->getEventEndEntry()) {
875
            current->earliestProcessingTime = current->getComplexity();
876
        }
877
        for (IEvent *antecessor = eventLog->getFirstEvent(); antecessor; antecessor = antecessor->getNextEvent()) {
878
            if(antecessor==current) {
879
                break; //We have to consider earlier events only
880
            }
881
            if(antecessor->getSimulationTime() + antecessor->getEventEntry()->duration > startTime) {
882
                continue; // Check if this is an antecesor
883
            }
884
            if(antecessor->earliestProcessingTime+current->getComplexity() > current->earliestProcessingTime) {
885
                current->earliestProcessingTime = antecessor->earliestProcessingTime+current->getComplexity();
886
            }
887
        }
888
        // Memorize max event
889
        if (maxEarliestProcessingTime < current->earliestProcessingTime) {
890
            maxEarliestProcessingTime = current->earliestProcessingTime;
891
            maxEarliestProcessingTimeEvent = current;
892
        }
893
    }
894
    //Now produce the convex hull of predecessors:
895
    cachedCriticalPath.clear();
896
    for (IEvent *predecessor = maxEarliestProcessingTimeEvent; predecessor; predecessor = predecessor->getCauseEvent()) {
897
        cachedCriticalPath.insert((ptr_t)predecessor);
898
    }
899
}
900