Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00022 #include <assert.h>
00023 #include <sstream>
00024 #include <omnetpp.h>
00025 #include <GlobalStatisticsAccess.h>
00026 #include "MessageObserver.h"
00027 #include "ALMTestTracedMessage_m.h"
00028
00029 Define_Module(MessageObserver);
00030
00031 MessageObserver::MessageObserver() {
00032 gcTimer = new cMessage("garbage_collection");
00033 gcInterval = 1.0;
00034 cacheMaxAge = 10.0;
00035 numLooped = 0;
00036 }
00037
00038 MessageObserver::~MessageObserver() {
00039 cancelAndDelete(gcTimer);
00040 }
00041
00042 void MessageObserver::initialize() {
00043 WATCH_MAP(groups);
00044 WATCH_MAP(joinedAt);
00045 WATCH_MAP(receivedAt);
00046 WATCH(numLooped);
00047
00048 numLooped = 0;
00049 gcInterval = par("gcInterval");
00050 cacheMaxAge = par("cacheMaxAge");
00051
00052 if (gcInterval > 0.0)
00053 scheduleAt(OPP::simTime() + gcInterval, gcTimer);
00054
00055 creationTime = OPP::simTime();
00056 globalStatistics = GlobalStatisticsAccess().get();
00057 }
00058
00059 void MessageObserver::finish() {
00060 uint64_t totalSent = 0;
00061 uint64_t totalReceived = 0;
00062 for (std::map<OverlayKey, MulticastGroup>::iterator i = groups.begin(); i != groups.end(); ++i) {
00063 std::stringstream message;
00064 message << "MessageObserver: Group " << i->first;
00065 std::string name;
00066
00067 name = message.str() + " Sent Messages";
00068 recordScalar(name.c_str(), (double)i->second.sent);
00069
00070 name = message.str() + " Received Messages";
00071 recordScalar(name.c_str(), (double)i->second.received);
00072
00073 name = message.str() + " Delivered Percentage";
00074 recordScalar(name.c_str(), ((double)i->second.received * 100.0) / (double)i->second.sent);
00075
00076 totalSent += i->second.sent;
00077 totalReceived += i->second.received;
00078 }
00079
00080 recordScalar("MessageObserver: Total Sent Messages", (double)totalSent);
00081 recordScalar("MessageObserver: Total Received Messages", (double)totalReceived);
00082 recordScalar("MessageObserver: Total Delivered Percentage", ((double)totalReceived * 100.0) / (double)totalSent);
00083
00084 simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00085 if ( time >= GlobalStatistics::MIN_MEASURED ) {
00086 globalStatistics->addStdDev("MessageObserver: Looped messages/s", (double)numLooped / time);
00087 }
00088 }
00089
00090 void MessageObserver::handleMessage(cMessage* msg) {
00091 if (msg == gcTimer) {
00092 simtime_t now = OPP::simTime();
00093 std::map<NodeMessagePair, simtime_t>::iterator i, iPrev;
00094 i = receivedAt.begin();
00095 while (i != receivedAt.end()) {
00096 if (now - i->second >= cacheMaxAge) {
00097 iPrev = i;
00098 ++i;
00099 receivedAt.erase(iPrev);
00100 }
00101 else {
00102 ++i;
00103 }
00104 }
00105 scheduleAt(OPP::simTime() + gcInterval, gcTimer);
00106 }
00107 }
00108
00112 void MessageObserver::joinedGroup(int moduleId, OverlayKey groupId) {
00113 groups[groupId].size += 1;
00114 joinedAt[NodeGroupPair(moduleId, groupId)] = OPP::simTime();
00115 }
00116
00120 void MessageObserver::leftGroup(int moduleId, OverlayKey groupId) {
00121 std::map<OverlayKey, MulticastGroup>::iterator iter = groups.find(groupId);
00122 if (iter == groups.end()) {
00123 EV << "Warning: MessageObserver asked to remove node from nonexistent group " << groupId.toString();
00124 }
00125 else if (iter->second.size == 0) {
00126 EV << "Warning: MessageObserver asked to remove node from empty group " << groupId.toString();
00127 }
00128 else {
00129 iter->second.size -= 1;
00130 }
00131 joinedAt.erase(NodeGroupPair(moduleId, groupId));
00132 }
00133
00138 void MessageObserver::sentMessage(ALMTestTracedMessage* msg) {
00139 if (msg == NULL) {
00140 error("%s called with null message.", __PRETTY_FUNCTION__);
00141 }
00142
00143 std::map<OverlayKey, MulticastGroup>::iterator iter;
00144 iter = groups.find(msg->getGroupId());
00145 if (iter == groups.end()) {
00146 EV << "Warning: MessageObserver notified of sent message for nonexistent group " << msg->getGroupId().toString();
00147 }
00148 else if (iter->second.size == 0) {
00149 EV << "Warning: MessageObserver notified of sent message for empty group " << msg->getGroupId().toString();
00150 }
00151 else {
00152 iter->second.sent += iter->second.size - 1;
00153 }
00154 }
00155
00159 void MessageObserver::receivedMessage(ALMTestTracedMessage* msg) {
00160 if (msg == NULL) {
00161 error("%s called with null message.", __PRETTY_FUNCTION__);
00162 }
00163
00164 std::map<OverlayKey, MulticastGroup>::iterator iGroup;
00165 iGroup = groups.find(msg->getGroupId());
00166 if (iGroup == groups.end()) {
00167 EV << "Warning: MessageObserver notified of received message for nonexistent group " << msg->getGroupId().toString();
00168 }
00169 else if (iGroup->second.size == 0) {
00170 EV << "Warning: MessageObserver notified of received message for empty group " << msg->getGroupId().toString();
00171 }
00172 else if (msg->getSenderId() != msg->getReceiverId()) {
00173
00174
00175 std::map<NodeGroupPair, simtime_t>::iterator iJoinInfo;
00176 iJoinInfo = joinedAt.find(NodeGroupPair(msg->getReceiverId(), msg->getGroupId()));
00177
00178 if (iJoinInfo != joinedAt.end() && iJoinInfo->second < msg->getTimestamp()) {
00179
00180
00181 NodeMessagePair nmp = NodeMessagePair(msg->getReceiverId(), msg->getMcastId());
00182 if (receivedAt.find(nmp) == receivedAt.end()) {
00183 iGroup->second.received += 1;
00184 receivedAt[nmp] = msg->getTimestamp();
00185 }
00186 }
00187 }
00188 else {
00189 RECORD_STATS(++numLooped);
00190 }
00191 }
00192
00196 void MessageObserver::nodeDead(int moduleId) {
00197
00198
00199 for (std::map<OverlayKey, MulticastGroup>::iterator ig = groups.begin(); ig != groups.end(); ++ig) {
00200 NodeGroupPair ngp = NodeGroupPair(moduleId, ig->first);
00201 if (joinedAt.find(ngp) != joinedAt.end()) {
00202 ig->second.size--;
00203 joinedAt.erase(ngp);
00204 }
00205 }
00206 }
00207
00208 std::ostream& operator<< (std::ostream& os, MessageObserver::MulticastGroup const & mg) {
00209 return os << "Nodes: " << mg.size << "; Messages Sent: " << mg.sent
00210 << ", Received: " << mg.received << ", Dropped: " << (mg.sent - mg.received);
00211 }
00212
00213 std::ostream& operator<< (std::ostream& os, MessageObserver::NodeGroupPair const & ngp) {
00214 cModule* module = OPP::cSimulation::getActiveSimulation()->getModule(ngp.first);
00215 return os << "(" << (module != NULL ? module->getFullPath() : "Deleted node")
00216 << ", " << ngp.second << ")";
00217 }
00218