00001 // 00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH) 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 // 00018 00024 #include <assert.h> 00025 00026 #include <omnetpp.h> 00027 #include "GiaMessageBookkeeping.h" 00028 00029 00030 GiaMessageBookkeeping::GiaMessageBookkeeping( GiaNeighbors* neighbors, uint32_t timeout ) 00031 { 00032 this->neighbors = neighbors; 00033 this->timeout = timeout; 00034 } 00035 00036 GiaMessageBookkeeping::~GiaMessageBookkeeping() 00037 {} 00038 00039 uint32_t GiaMessageBookkeeping::getSize() 00040 { 00041 return messages.size(); 00042 } 00043 00044 void GiaMessageBookkeeping::addMessage( GiaIDMessage* msg ) 00045 { 00046 assert(!(msg->getID().isUnspecified())); 00047 00048 std::vector<GiaNode> remainNodes; 00049 // push all neighbors except the node where message was comming from 00050 // to remainNodes 00051 for ( uint32_t i=0; i<neighbors->getSize(); i++ ) { 00052 if ( neighbors->get(i).getKey() != msg->getSrcNode().getKey()) 00053 remainNodes.push_back(neighbors->get(i)); 00054 } 00055 MessageItem messageItem; 00056 messageItem.remainNodes = remainNodes; 00057 messageItem.timestamp = simTime(); 00058 messages[msg->getID()] = messageItem; 00059 } 00060 00061 void GiaMessageBookkeeping::removeMessage( GiaIDMessage* msg ) 00062 { 00063 std::map<OverlayKey, MessageItem>::iterator it = messages.find(msg->getID()); 00064 // delete message if key is equal 00065 if ( it->first == msg->getID() ) 00066 messages.erase(messages.find(msg->getID())); 00067 } 00068 00069 bool GiaMessageBookkeeping::contains( GiaIDMessage* msg ) 00070 { 00071 std::map<OverlayKey, MessageItem>::iterator it = messages.find(msg->getID()); 00072 00073 if(it != messages.end()) 00074 return true; 00075 return false; 00076 } 00077 00078 NodeHandle GiaMessageBookkeeping::getNextHop( GiaIDMessage* msg ) 00079 { 00080 if ( neighbors->getSize() > 0 ) { 00081 std::map<OverlayKey, MessageItem>::iterator it = messages.find(msg->getID()); 00082 std::priority_queue<FullGiaNodeInfo, std::vector<FullGiaNodeInfo>, GiaNodeQueueCompare> nodeQueue; 00083 00084 if ( it != messages.end() && it->first == msg->getID() ) { 00085 MessageItem messageItem = it->second; 00086 std::vector<GiaNode> remNodes = messageItem.remainNodes; 00087 if ( remNodes.size() == 0) { 00088 for ( uint32_t i=0; i<neighbors->getSize(); i++ ) { 00089 remNodes.push_back(neighbors->get(i)); 00090 } 00091 } 00092 00093 for ( uint32_t i=0; i<remNodes.size(); i++ ) { 00094 if(!(remNodes[i].isUnspecified())) { 00095 FullGiaNodeInfo temp; 00096 temp.node = remNodes[i]; 00097 temp.info = neighbors->get(temp.node); 00098 if (temp.info) nodeQueue.push(temp); 00099 } 00100 } 00101 00102 if (!nodeQueue.empty()) { 00103 NodeHandle nextHop = nodeQueue.top().node; 00104 GiaNeighborInfo* nextHopInfo = neighbors->get(nextHop); 00105 nodeQueue.pop(); 00106 00107 if (nextHopInfo != NULL && nextHopInfo->receivedTokens > 0 ) { 00108 remNodes.clear(); 00109 while ( !nodeQueue.empty() ) { 00110 remNodes.push_back(nodeQueue.top().node); 00111 nodeQueue.pop(); 00112 } 00113 messageItem.remainNodes = remNodes; 00114 messageItem.timestamp = simTime(); 00115 messages[msg->getID()] = messageItem; 00116 return nextHop; 00117 } 00118 } 00119 } 00120 } 00121 return NodeHandle::UNSPECIFIED_NODE; 00122 } 00123 00124 void GiaMessageBookkeeping::removeTimedoutMessages() 00125 { 00126 std::map<OverlayKey, MessageItem>::iterator it = messages.begin(); 00127 std::map<OverlayKey, MessageItem>::iterator it2 = messages.begin(); 00128 for ( uint32_t i=0; i<messages.size(); i++) { 00129 OverlayKey key = it->first; 00130 MessageItem messageItem = it->second; 00131 it2 = it++; 00132 if (simTime() > (messageItem.timestamp + timeout)) 00133 messages.erase(it2); 00134 } 00135 } 00136 00137 bool GiaMessageBookkeeping::GiaNodeQueueCompare::operator()(const FullGiaNodeInfo& x, 00138 const FullGiaNodeInfo& y) 00139 { 00140 if (x.info->receivedTokens > y.info->receivedTokens) { 00141 if (y.info->receivedTokens == 0) 00142 return false; 00143 else { 00144 if (x.node.getCapacity() >= y.node.getCapacity()) 00145 return false; 00146 else 00147 return true; 00148 } 00149 } 00150 else if (x.info->receivedTokens < y.info->receivedTokens) { 00151 if (x.info->receivedTokens == 0) 00152 return true; 00153 else { 00154 if (x.node.getCapacity() > y.node.getCapacity()) 00155 return false; 00156 else 00157 return true; 00158 } 00159 } 00160 else { 00161 if (x.info->receivedTokens == 0) 00162 return true; 00163 else { 00164 if (x.node.getCapacity() > y.node.getCapacity()) 00165 return false; 00166 else 00167 return true; 00168 } 00169 } 00170 }