//========================================================================= // MESSAGEDEPENDENCY.CC - part of // OMNeT++/OMNEST // Discrete System Simulation in C++ // // Author: Levente Meszaros // //========================================================================= /*--------------------------------------------------------------* Copyright (C) 2006-2017 OpenSim Ltd. This file is distributed WITHOUT ANY WARRANTY. See the file `license' for details on this and other legal matters. *--------------------------------------------------------------*/ #include <cstdio> #include "eventlogdefs.h" #include "ievent.h" #include "ieventlog.h" #include "event.h" #include "eventlogentry.h" #include "messagedependency.h" namespace omnetpp { namespace eventlog { /**************************************************/ IMessageDependency::IMessageDependency(IEventLog *eventLog) { this->eventLog = eventLog; } bool IMessageDependency::corresponds(IMessageDependency *dependency1, IMessageDependency *dependency2) { if (!dependency1 || !dependency2) return false; else { MessageEntry *entry1 = dependency1->getMessageEntry(); MessageEntry *entry2 = dependency2->getMessageEntry(); if (!entry1 || !entry2) return false; else return (entry1->messageId != -1 && entry1->messageId == entry2->messageId) || (entry1->messageTreeId != -1 && entry1->messageTreeId == entry2->messageTreeId) || (entry1->messageEncapsulationId != -1 && entry1->messageEncapsulationId == entry2->messageEncapsulationId) || (entry1->messageEncapsulationTreeId != -1 && entry1->messageEncapsulationTreeId == entry2->messageEncapsulationTreeId); } } bool IMessageDependency::equals(IMessageDependency *other) { Assert(eventLog == other->eventLog); return true; } /**************************************************/ MessageSendDependency::MessageSendDependency(IEventLog *eventLog, eventnumber_t eventNumber, int eventLogEntryIndex) : IMessageDependency(eventLog) { Assert(eventNumber >= 0 && eventLogEntryIndex >= 0); this->causeEventNumber = eventNumber; this->eventLogEntryIndex = eventLogEntryIndex; this->consequenceEventNumber = EVENT_NOT_YET_CALCULATED; } IEvent *MessageSendDependency::getCauseEvent() { return eventLog->getEventForEventNumber(causeEventNumber); } simtime_t MessageSendDependency::getCauseSimulationTime() { return getCauseEvent()->getSimulationTime(); } eventnumber_t MessageSendDependency::getConsequenceEventNumber() { if (consequenceEventNumber == EVENT_NOT_YET_CALCULATED || consequenceEventNumber == EVENT_NOT_YET_REACHED) { // only cause is present, calculate consequence from it. // // when a message is scheduled/sent, we don't know the arrival event number // yet, only the simulation time is recorded in the event log file. // So here we have to look through all events at the arrival time, // and find the one "caused by" our message. simtime_t consequenceTime = getConsequenceSimulationTime(); if (consequenceTime == simtime_nil) consequenceEventNumber = NO_SUCH_EVENT; else { IEvent *event = eventLog->getEventForSimulationTime(consequenceTime, FIRST_OR_PREVIOUS); MessageEntry *messageEntry = getMessageEntry(); // TODO: LONG RUNNING OPERATION while (event) { eventLog->progress(); if (event->getCauseEventNumber() == getCauseEventNumber() && event->getMessageId() == messageEntry->messageId) { consequenceEventNumber = event->getEventNumber(); break; } if (event->getSimulationTime() > consequenceTime) { // no more event at that simulation time, and consequence event // still not found. It must have been cancelled (self message), // or it is not in the file (filtered out by the user, etc). consequenceEventNumber = NO_SUCH_EVENT; break; } event = event->getNextEvent(); } // end of file if (!event) consequenceEventNumber = EVENT_NOT_YET_REACHED; } } return consequenceEventNumber; } IEvent *MessageSendDependency::getConsequenceEvent() { eventnumber_t consequenceEventNumber = getConsequenceEventNumber(); if (consequenceEventNumber < 0) return nullptr; else return eventLog->getEventForEventNumber(consequenceEventNumber); } simtime_t MessageSendDependency::getConsequenceSimulationTime() { if (consequenceEventNumber >= 0) return getConsequenceEvent()->getSimulationTime(); else { // find the arrival time of the message IEvent *event = getCauseEvent(); BeginSendEntry *beginSendEntry = (BeginSendEntry *)(event->getEventLogEntry(eventLogEntryIndex)); EndSendEntry *endSendEntry = event->getEndSendEntry(beginSendEntry); if (endSendEntry) return endSendEntry->arrivalTime; else return simtime_nil; } } MessageEntry *MessageSendDependency::getMessageEntry() { Assert(eventLogEntryIndex != -1); IEvent *event = getCauseEvent(); Assert(event); return (MessageEntry *)event->getEventLogEntry(eventLogEntryIndex); } MessageSendDependency *MessageSendDependency::duplicate(IEventLog *eventLog) { MessageSendDependency *messageSendDependency = new MessageSendDependency(*this); messageSendDependency->eventLog = eventLog; return messageSendDependency; } bool MessageSendDependency::equals(IMessageDependency *other) { MessageSendDependency *otherMessageSendDependency = dynamic_cast<MessageSendDependency *>(other); return IMessageDependency::equals(other) && otherMessageSendDependency && causeEventNumber == otherMessageSendDependency->causeEventNumber && consequenceEventNumber == otherMessageSendDependency->consequenceEventNumber && eventLogEntryIndex == otherMessageSendDependency->eventLogEntryIndex; } void MessageSendDependency::print(FILE *file) { getCauseEvent()->getEventEntry()->print(file); getMessageEntry()->print(file); } /**************************************************/ MessageReuseDependency::MessageReuseDependency(IEventLog *eventLog, eventnumber_t eventNumber, int eventLogEntryIndex) : IMessageDependency(eventLog) { Assert(eventNumber >= 0 && eventLogEntryIndex >= 0); this->causeEventNumber = EVENT_NOT_YET_CALCULATED; this->consequenceEventNumber = eventNumber; this->eventLogEntryIndex = eventLogEntryIndex; } eventnumber_t MessageReuseDependency::getCauseEventNumber() { if (causeEventNumber == EVENT_NOT_YET_CALCULATED) { // only consequence is present, calculate cause from it IEvent *consequenceEvent = getConsequenceEvent(); Assert(consequenceEvent); MessageEntry *messageEntry = (MessageEntry *)consequenceEvent->getEventLogEntry(eventLogEntryIndex); causeEventNumber = messageEntry->previousEventNumber; } return causeEventNumber; } IEvent *MessageReuseDependency::getCauseEvent() { eventnumber_t causeEventNumber = getCauseEventNumber(); if (causeEventNumber < 0) return nullptr; else return eventLog->getEventForEventNumber(causeEventNumber); } simtime_t MessageReuseDependency::getCauseSimulationTime() { if (causeEventNumber >= 0) return getCauseEvent()->getSimulationTime(); else return simtime_nil; } IEvent *MessageReuseDependency::getConsequenceEvent() { return eventLog->getEventForEventNumber(consequenceEventNumber); } simtime_t MessageReuseDependency::getConsequenceSimulationTime() { return getConsequenceEvent()->getSimulationTime(); } MessageEntry *MessageReuseDependency::getMessageEntry() { Assert(eventLogEntryIndex != -1); IEvent *event = getConsequenceEvent(); Assert(event); return (MessageEntry *)event->getEventLogEntry(eventLogEntryIndex); } MessageReuseDependency *MessageReuseDependency::duplicate(IEventLog *eventLog) { MessageReuseDependency *messageReuseDependency = new MessageReuseDependency(*this); messageReuseDependency->eventLog = eventLog; return messageReuseDependency; } bool MessageReuseDependency::equals(IMessageDependency *other) { MessageReuseDependency *otherMessageReuseDependency = dynamic_cast<MessageReuseDependency *>(other); return IMessageDependency::equals(other) && otherMessageReuseDependency && causeEventNumber == otherMessageReuseDependency->causeEventNumber && consequenceEventNumber == otherMessageReuseDependency->consequenceEventNumber && eventLogEntryIndex == otherMessageReuseDependency->eventLogEntryIndex; } void MessageReuseDependency::print(FILE *file) { getConsequenceEvent()->getEventEntry()->print(file); getMessageEntry()->print(file); } /**************************************************/ FilteredMessageDependency::FilteredMessageDependency(IEventLog *eventLog, Kind kind, IMessageDependency *beginMessageDependency, IMessageDependency *endMessageDependency) : IMessageDependency(eventLog) { this->beginMessageDependency = beginMessageDependency; this->endMessageDependency = endMessageDependency; this->kind = kind; } FilteredMessageDependency::~FilteredMessageDependency() { delete beginMessageDependency; delete endMessageDependency; } FilteredMessageDependency *FilteredMessageDependency::duplicate(IEventLog *eventLog) { return new FilteredMessageDependency(eventLog, kind, beginMessageDependency->duplicate(eventLog), endMessageDependency->duplicate(eventLog)); } IEvent *FilteredMessageDependency::getCauseEvent() { eventnumber_t causeEventNumber = beginMessageDependency->getCauseEventNumber(); if (causeEventNumber < 0) return nullptr; else return eventLog->getEventForEventNumber(causeEventNumber); } IEvent *FilteredMessageDependency::getConsequenceEvent() { eventnumber_t consequenceEventNumber = endMessageDependency->getConsequenceEventNumber(); if (consequenceEventNumber < 0) return nullptr; else return eventLog->getEventForEventNumber(consequenceEventNumber); } bool FilteredMessageDependency::equals(IMessageDependency *other) { FilteredMessageDependency *otherFiltered = dynamic_cast<FilteredMessageDependency *>(other); return IMessageDependency::equals(other) && otherFiltered && beginMessageDependency->equals(otherFiltered->beginMessageDependency) && endMessageDependency->equals(otherFiltered->endMessageDependency); } void FilteredMessageDependency::print(FILE *file) { beginMessageDependency->print(file); endMessageDependency->print(file); } } // namespace eventlog } // namespace omnetpp