Scribe.cc

Go to the documentation of this file.
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 <BaseApp.h>
00027 #include "Scribe.h"
00028 #include <GlobalStatistics.h>
00029 
00030 #include "Comparator.h"
00031 
00032 Define_Module(Scribe);
00033 
00034 using namespace std;
00035 
00036 Scribe::Scribe()
00037 {
00038     subscriptionTimer = new ScribeTimer("Subscription timer");
00039     subscriptionTimer->setTimerType( SCRIBE_SUBSCRIPTION_REFRESH );
00040     numJoins = 0;
00041     numChildTimeout = 0;
00042     numParentTimeout = 0;
00043     numForward = 0;
00044     forwardBytes = 0;
00045     numReceived = 0;
00046     receivedBytes = 0;
00047     numHeartbeat = 0;
00048     heartbeatBytes = 0;
00049     numSubscriptionRefresh = 0;
00050     subscriptionRefreshBytes = 0;
00051 }
00052 
00053 Scribe::~Scribe()
00054 {
00055     groupList.clear();
00056     cancelAndDelete(subscriptionTimer);
00057     // TODO: clear childTimeoutList
00058 }
00059 
00060 void Scribe::initializeApp(int stage)
00061 {
00062     if( stage != (numInitStages()-1))
00063     {
00064         return;
00065     }
00066     WATCH(groupList);
00067     WATCH(numJoins);
00068     WATCH(numForward);
00069     WATCH(forwardBytes);
00070     WATCH(numReceived);
00071     WATCH(receivedBytes);
00072     WATCH(numHeartbeat);
00073     WATCH(heartbeatBytes);
00074     WATCH(numSubscriptionRefresh);
00075     WATCH(subscriptionRefreshBytes);
00076     WATCH(numChildTimeout);
00077     WATCH(numParentTimeout);
00078 
00079     childTimeout = par("childTimeout");
00080     parentTimeout = par("parentTimeout");
00081 
00082 }
00083 
00084 void Scribe::finishApp()
00085 {
00086     simtime_t time = globalStatistics->calcMeasuredLifetime(creationTime);
00087     if (time < GlobalStatistics::MIN_MEASURED) return;
00088 
00089     globalStatistics->addStdDev("Scribe: Received JOIN Messages/s",
00090             numJoins / time);
00091     globalStatistics->addStdDev("Scribe: Forwarded Multicast Messages/s",
00092             numForward / time);
00093     globalStatistics->addStdDev("Scribe: Forwarded Multicast Bytes/s",
00094             forwardBytes / time);
00095     globalStatistics->addStdDev("Scribe: Received Multicast Messages/s (subscribed groups only)",
00096             numReceived / time);
00097     globalStatistics->addStdDev("Scribe: Received Multicast Bytes/s (subscribed groups only)",
00098             receivedBytes / time);
00099     globalStatistics->addStdDev("Scribe: Send Heartbeat Messages/s",
00100             numHeartbeat / time);
00101     globalStatistics->addStdDev("Scribe: Send Heartbeat Bytes/s",
00102             heartbeatBytes / time);
00103     globalStatistics->addStdDev("Scribe: Send Subscription Refresh Messages/s",
00104             numSubscriptionRefresh / time);
00105     globalStatistics->addStdDev("Scribe: Send Subscription Refresh Bytes/s",
00106             subscriptionRefreshBytes / time);
00107     globalStatistics->addStdDev("Scribe: Number of Child Timeouts/s",
00108             numChildTimeout / time);
00109     globalStatistics->addStdDev("Scribe: Number of Parent Timeouts/s",
00110             numParentTimeout / time);
00111 }
00112 
00113 void Scribe::forward(OverlayKey* key, cPacket** msg,
00114                 NodeHandle* nextHopNode)
00115 {
00116     ScribeJoinCall* joinMsg = dynamic_cast<ScribeJoinCall*> (*msg);
00117     if( joinMsg == NULL ) {
00118         // nothing to be done
00119         return;
00120     }
00121 
00122     if( joinMsg->getSrcNode() == overlay->getThisNode() ) return;
00123 
00124     handleJoinMessage( joinMsg, false );
00125 
00126     *msg = NULL;
00127 }
00128 
00129 void Scribe::update( const NodeHandle& node, bool joined )
00130 {
00131     // if node is closer to any group i'm root of, subscribe
00132     for( GroupList::iterator it = groupList.begin(); it != groupList.end(); ++it ){
00133         // if I'm root ...
00134         if( !it->second.getParent().isUnspecified()
00135                 && it->second.getParent() == overlay->getThisNode() ) {
00136             KeyDistanceComparator<KeyRingMetric> comp( it->second.getGroupId() );
00137             // ... and new node is closer to groupId
00138             if( comp.compare(node.getKey(), overlay->getThisNode().getKey()) < 0){
00139                 // then the new node is new group root, so send him a subscribe
00140                 ScribeJoinCall* m = new ScribeJoinCall;
00141                 m->setGroupId( it->second.getGroupId() );
00142                 m->setBitLength( SCRIBE_JOINCALL_L(m) );
00143                 sendRouteRpcCall(TIER1_COMP, node, m);
00144             }
00145         }
00146     }
00147 }
00148 
00149 bool Scribe::handleRpcCall(BaseCallMessage* msg)
00150 {
00151     RPC_SWITCH_START(msg);
00152     RPC_DELEGATE(ScribeJoin, handleJoinCall);
00153     RPC_DELEGATE(ScribePublish, handlePublishCall);
00154     RPC_SWITCH_END();
00155     return RPC_HANDLED;
00156 }
00157 
00158 void Scribe::handleRpcResponse(BaseResponseMessage* msg,
00159                                cPolymorphic* context, int rpcId,
00160                                simtime_t rtt)
00161 {
00162     RPC_SWITCH_START(msg);
00163     RPC_ON_RESPONSE( ScribeJoin ) {
00164         handleJoinResponse( _ScribeJoinResponse );
00165         EV << "[Scribe::handleRpcResponse() @ " << overlay->getThisNode().getAddress()
00166             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00167             << "    Received a ScribeJoin RPC Response: id=" << rpcId << "\n"
00168             << "    msg=" << *_ScribeJoinResponse << " rtt=" << rtt
00169             << endl;
00170         break;
00171     }
00172     RPC_ON_RESPONSE( ScribePublish ) {
00173         handlePublishResponse( _ScribePublishResponse );
00174     }
00175     RPC_SWITCH_END( );
00176 }
00177 
00178 void Scribe::deliver(OverlayKey& key, cMessage* msg)
00179 {
00180     if( ScribeSubscriptionRefreshMessage* refreshMsg =
00181             dynamic_cast<ScribeSubscriptionRefreshMessage*>(msg) ){
00182         // reset child timeout
00183         refreshChildTimer( refreshMsg->getSrc(), refreshMsg->getGroupId() );
00184         delete refreshMsg;
00185     } else if( ScribeDataMessage* data = dynamic_cast<ScribeDataMessage*>(msg) ){
00186         deliverALMDataToGroup( data );
00187     } else if( ScribeLeaveMessage* leaveMsg = dynamic_cast<ScribeLeaveMessage*>(msg) ){
00188         handleLeaveMessage( leaveMsg );
00189     }
00190 }
00191 
00192 void Scribe::handleUpperMessage( cMessage *msg )
00193 {
00194     if( ALMSubscribeMessage* subscribeMsg = dynamic_cast<ALMSubscribeMessage*>(msg)){
00195         subscribeToGroup( subscribeMsg->getGroupId() );
00196         delete msg;
00197     } else if( ALMLeaveMessage* leaveMsg = dynamic_cast<ALMLeaveMessage*>(msg)){
00198         leaveGroup( leaveMsg->getGroupId() );
00199         delete msg;
00200     } else if( ALMMulticastMessage* mcastMsg = dynamic_cast<ALMMulticastMessage*>(msg) ){
00201         deliverALMDataToRoot( mcastMsg );
00202     } else if( ALMAnycastMessage* acastMsg = dynamic_cast<ALMAnycastMessage*>(msg) ){
00203         // FIXME: anycast not implemented yet
00204         EV << "[Scribe::handleUpperMessage() @ " << overlay->getThisNode().getAddress()
00205             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00206             << "    Anycast message for group " << acastMsg->getGroupId() << "\n"
00207             << "    ignored: Not implemented yet!"
00208             << endl;
00209         delete msg;
00210     } else if( ALMCreateMessage* createMsg = dynamic_cast<ALMCreateMessage*>(msg) ){
00211         EV << "[Scribe::handleUpperMessage() @ " << overlay->getThisNode().getAddress()
00212             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00213             << "    Create message for group " << createMsg->getGroupId() << "\n"
00214             << "    ignored: Scribe has implicit create on SUBSCRIBE"
00215             << endl;
00216         delete msg;
00217     } else if( ALMDeleteMessage* deleteMsg = dynamic_cast<ALMDeleteMessage*>(msg) ){
00218         EV << "[Scribe::handleUpperMessage() @ " << overlay->getThisNode().getAddress()
00219             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00220             << "    Delete message for group " << deleteMsg->getGroupId() << "\n"
00221             << "    ignored: Scribe has implicit delete on LEAVE"
00222             << endl;
00223         delete msg;
00224     }
00225 }
00226 
00227 void Scribe::handleReadyMessage( CompReadyMessage* msg )
00228 {
00229     // process only ready messages from the tier below
00230     if( (getThisCompType() - msg->getComp() == 1) && msg->getReady() ) {
00231 
00232         // Send a ready message to the tier above
00233         CompReadyMessage* readyMsg = new CompReadyMessage;
00234         readyMsg->setReady( true );
00235         readyMsg->setComp( getThisCompType() );
00236 
00237         send( readyMsg, "to_upperTier" );
00238         
00239         startTimer( subscriptionTimer );
00240     }
00241     delete msg;
00242 }
00243 
00244 void Scribe::handleTimerEvent( cMessage *msg )
00245 {
00246     ScribeTimer* timer = dynamic_cast<ScribeTimer*>(msg);
00247     assert( timer );
00248     switch( timer->getTimerType() ) {
00249         case SCRIBE_SUBSCRIPTION_REFRESH:
00250             // renew subscriptions for all groups
00251             for( GroupList::iterator it = groupList.begin(); it != groupList.end(); ++it ) {
00252                 NodeHandle parent = it->second.getParent();
00253                 if( !parent.isUnspecified() ){
00254                     ScribeSubscriptionRefreshMessage* refreshMsg = new ScribeSubscriptionRefreshMessage;
00255                     refreshMsg->setGroupId( it->second.getGroupId() );
00256                     refreshMsg->setSrc( overlay->getThisNode() );
00257 
00258                     refreshMsg->setBitLength(SCRIBE_SUBSCRIPTIONREFRESH_L(refreshMsg));
00259                     RECORD_STATS(++numSubscriptionRefresh;
00260                             subscriptionRefreshBytes += refreshMsg->getByteLength()
00261                     );
00262                     callRoute( OverlayKey::UNSPECIFIED_KEY, refreshMsg, parent );
00263                 }
00264             }
00265             startTimer( subscriptionTimer );
00266             break;
00267 
00268         case SCRIBE_HEARTBEAT:
00269         {
00270             // Send heartbeat messages to all children in the group
00271             GroupList::iterator groupIt = groupList.find( timer->getGroup() );
00272             if( groupIt == groupList.end() ) {
00273                 // FIXME: should not happen
00274                 delete timer;
00275                 return;
00276             }
00277             for( set<NodeHandle>::iterator it = groupIt->second.getChildrenBegin();
00278                     it != groupIt->second.getChildrenEnd(); ++it ) {
00279                 ScribeDataMessage* heartbeatMsg = new ScribeDataMessage("Heartbeat");
00280                 heartbeatMsg->setEmpty( true );
00281                 heartbeatMsg->setGroupId( timer->getGroup() );
00282 
00283                 heartbeatMsg->setBitLength(SCRIBE_DATA_L(heartbeatMsg));
00284                 RECORD_STATS(++numHeartbeat; heartbeatBytes += heartbeatMsg->getByteLength());
00285                 callRoute( OverlayKey::UNSPECIFIED_KEY, heartbeatMsg, *it );
00286             }
00287             startTimer( timer );
00288             break;
00289         }
00290         case SCRIBE_CHILD_TIMEOUT:
00291             // Child failed, remove it from group
00292             RECORD_STATS(++numChildTimeout);
00293             removeChildFromGroup( timer );
00294             break;
00295 
00296         case SCRIBE_PARENT_TIMEOUT:
00297             // Parent failed, send new join to rejoin group
00298             RECORD_STATS(++numParentTimeout);
00299             OverlayKey key = timer->getGroup();
00300             EV << "[Scribe::handleTimerEvent() @ " << overlay->getThisNode().getAddress()
00301                 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00302                 << "    Parent of group " << key << "\n"
00303                 << "    failed to send heartbeat, trying to rejoin"
00304                 << endl;
00305 
00306             ScribeJoinCall* newJoin = new ScribeJoinCall;
00307             newJoin->setGroupId( key );
00308             newJoin->setBitLength( SCRIBE_JOINCALL_L(newJoin) );
00309             sendRouteRpcCall(TIER1_COMP, key, newJoin);
00310 
00311             GroupList::iterator groupIt = groupList.find( timer->getGroup() );
00312             if( groupIt == groupList.end() ) {
00313                 // FIXME: should not happen
00314                 delete timer;
00315                 return;
00316             }
00317             groupIt->second.setParentTimer( NULL );
00318             cancelAndDelete( timer );
00319             break;
00320     }
00321 
00322 }
00323 
00324 void Scribe::handleJoinCall( ScribeJoinCall* joinMsg)
00325 {
00326     handleJoinMessage( joinMsg, true );
00327 }
00328 
00329 void Scribe::handleJoinMessage( ScribeJoinCall* joinMsg, bool amIRoot)
00330 {
00331     RECORD_STATS(++numJoins);
00332     OverlayKey key = joinMsg->getGroupId();
00333 
00334     EV << "[Scribe::handleJoinMessage() @ " << overlay->getThisNode().getAddress()
00335         << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00336         << "    Received a ScribeJoin for group " << key << "\n"
00337         << "    msg=" << joinMsg
00338         << endl;
00339 
00340     // Insert group into grouplist, if not already there
00341     pair<GroupList::iterator, bool> groupInserter;
00342     groupInserter = groupList.insert( make_pair(key, ScribeGroup(key)) );
00343 
00344     // If group is new or no parent is known, send join to parent (unless I am root, so there is no parent)
00345     if ( !amIRoot && ( groupInserter.second || groupInserter.first->second.getParent().isUnspecified()) ) {
00346         ScribeJoinCall* newJoin = new ScribeJoinCall;
00347         newJoin->setGroupId( key );
00348         newJoin->setBitLength( SCRIBE_JOINCALL_L(newJoin) );
00349         sendRouteRpcCall(TIER1_COMP, key, newJoin);
00350     }
00351 
00352     // If group had no children, start heartbeat timer for group
00353     if( groupInserter.first->second.numChildren() == 0 ) {
00354         ScribeTimer* heartbeat = new ScribeTimer("HeartbeatTimer");
00355         heartbeat->setTimerType( SCRIBE_HEARTBEAT );
00356         heartbeat->setGroup( groupInserter.first->second.getGroupId() );
00357         startTimer( heartbeat );
00358         if( ScribeTimer* t = groupInserter.first->second.getHeartbeatTimer() ){
00359             // delete old timer, if any
00360             if( t ) cancelAndDelete( t );
00361         }
00362         groupInserter.first->second.setHeartbeatTimer( heartbeat );
00363     }
00364 
00365     // Add child to group
00366     addChildToGroup( joinMsg->getSrcNode(), groupInserter.first->second );
00367 
00368     // Send joinResponse
00369     ScribeJoinResponse* joinResponse = new ScribeJoinResponse;
00370     joinResponse->setGroupId( key );
00371     joinResponse->setBitLength( SCRIBE_JOINRESPONSE_L(joinResponse) );
00372     sendRpcResponse( joinMsg, joinResponse );
00373 }
00374 
00375 void Scribe::handlePublishCall( ScribePublishCall* publishCall )
00376 {
00377     // find group
00378     GroupList::iterator it = groupList.find( publishCall->getGroupId() );
00379     if( it == groupList.end() ||
00380             it->second.getParent().isUnspecified() ||
00381             it->second.getParent() != overlay->getThisNode() ){
00382         // if I don't know the group or I am not root, inform sender
00383         // TODO: forward message when I'm not root but know the rendevous point?
00384         ScribePublishResponse* msg = new ScribePublishResponse("Wrong Root");
00385         msg->setGroupId( publishCall->getGroupId() );
00386         msg->setWrongRoot( true );
00387         msg->setBitLength( SCRIBE_PUBLISHRESPONSE_L(msg) );
00388         sendRpcResponse( publishCall, msg );
00389     } else {
00390         ScribeDataMessage* data = dynamic_cast<ScribeDataMessage*>(publishCall->decapsulate());
00391 
00392         ScribePublishResponse* msg = new ScribePublishResponse("Publish Successful");
00393         msg->setGroupId( publishCall->getGroupId() );
00394         msg->setBitLength( SCRIBE_PUBLISHRESPONSE_L(msg) );
00395         sendRpcResponse( publishCall, msg );
00396 
00397         if( !data ) {
00398             // TODO: throw exception? this should never happen
00399             EV << "[Scribe::handlePublishCall() @ " << overlay->getThisNode().getAddress()
00400                 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00401                 << "    PublishCall for group " << msg->getGroupId()
00402                 << "    does not contain a calid ALM data message!\n"
00403                 << endl;
00404             return;
00405         }
00406         deliverALMDataToGroup( data );
00407     }
00408 }
00409 
00410 void Scribe::handleJoinResponse( ScribeJoinResponse* joinResponse )
00411 {
00412     GroupList::iterator it = groupList.find( joinResponse->getGroupId() );
00413     if( it == groupList.end() ) {
00414         EV << "[Scribe::handleJoinResponse() @ " << overlay->getThisNode().getAddress()
00415             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00416             << "Getting join response for an unknown group!\n";
00417         return;
00418     }
00419     it->second.setParent( joinResponse->getSrcNode() );
00420 
00421     // Create new heartbeat timer
00422     ScribeTimer* parentTimeout = new ScribeTimer("ParentTimeoutTimer");
00423     parentTimeout->setTimerType( SCRIBE_PARENT_TIMEOUT );
00424     parentTimeout->setGroup( it->second.getGroupId() );
00425     startTimer( parentTimeout );
00426     if( ScribeTimer* t = it->second.getParentTimer() ){
00427         // delete old timer, if any
00428         if( t ) cancelAndDelete( t );
00429     }
00430     it->second.setParentTimer( parentTimeout );
00431 }
00432 
00433 void Scribe::handlePublishResponse( ScribePublishResponse* publishResponse )
00434 {
00435     GroupList::iterator it = groupList.find( publishResponse->getGroupId() );
00436     if( it == groupList.end() ) {
00437         EV << "[Scribe::handlePublishResponse() @ " << overlay->getThisNode().getAddress()
00438             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00439             << "Getting publish response for an unknown group!\n";
00440         return;
00441     }
00442 
00443     if( publishResponse->getWrongRoot() ) {
00444         it->second.setRendezvousPoint( NodeHandle::UNSPECIFIED_NODE );
00445     } else {
00446         it->second.setRendezvousPoint( publishResponse->getSrcNode() );
00447     }
00448 }
00449 
00450 void Scribe::handleLeaveMessage( ScribeLeaveMessage* leaveMsg )
00451 {
00452     GroupList::iterator it = groupList.find( leaveMsg->getGroupId() );
00453     if( it != groupList.end() ){
00454         removeChildFromGroup( leaveMsg->getSrc(), it->second );
00455     }
00456     delete leaveMsg;
00457 }
00458 
00459 void Scribe::subscribeToGroup( const OverlayKey& groupId )
00460 {
00461     EV << "[Scribe::subscribeToGroup() @ " << overlay->getThisNode().getAddress()
00462         << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00463         << "   Trying to join group " << groupId << "\n";
00464 
00465     // Insert group into grouplist, if not known yet
00466     pair<GroupList::iterator, bool> groupInserter;
00467     groupInserter = groupList.insert( make_pair(groupId, ScribeGroup(groupId)) );
00468 
00469     // Set subscription status
00470     groupInserter.first->second.setSubscription(true);
00471 
00472     // Send join call if I'm not already a forwarder of this group
00473     if( groupInserter.second || groupInserter.first->second.getParent().isUnspecified()) {
00474         ScribeJoinCall* m = new ScribeJoinCall;
00475         m->setGroupId( groupId );
00476         m->setBitLength( SCRIBE_JOINCALL_L(m) );
00477         sendRouteRpcCall(TIER1_COMP, m->getGroupId(), m);
00478     }
00479 }
00480 
00481 void Scribe::leaveGroup( const OverlayKey& group )
00482 {
00483     GroupList::iterator it = groupList.find( group );
00484     if( it != groupList.end() ){
00485         it->second.setSubscription( false );
00486         checkGroupEmpty( it->second );
00487     }
00488 }
00489 
00490 void Scribe::addChildToGroup( const NodeHandle& child, ScribeGroup& group )
00491 {
00492     if( child == overlay->getThisNode() ) {
00493         // Join from ourself, ignore
00494         return;
00495     }
00496 
00497     // add child to group's children list
00498     pair<set<NodeHandle>::iterator, bool> inserter =
00499         group.addChild( child );
00500 
00501     if( inserter.second ) {
00502         // if child has not been in the list, create new timeout msg
00503         ScribeTimer* timeoutMsg = new ScribeTimer;
00504         timeoutMsg->setTimerType( SCRIBE_CHILD_TIMEOUT );
00505 
00506         // Remember child and group
00507         timeoutMsg->setChild( *inserter.first );
00508         timeoutMsg->setGroup( group.getGroupId() );
00509 
00510         startTimer( timeoutMsg );
00511         childTimeoutList.insert( make_pair(child, timeoutMsg) );
00512     }
00513 }
00514 
00515 void Scribe::removeChildFromGroup( const NodeHandle& child, ScribeGroup& group )
00516 {
00517     // find timer
00518     ScribeTimer* timer = NULL;
00519     pair<ChildTimeoutList::iterator, ChildTimeoutList::iterator> ret =
00520         childTimeoutList.equal_range( child );
00521     if( ret.first != childTimeoutList.end() ){
00522         for( ChildTimeoutList::iterator it = ret.first; it!=ret.second; ++it) {
00523             if( group == it->second->getGroup() ) {
00524                 timer = it->second;
00525                 childTimeoutList.erase( it );
00526                 cancelAndDelete( timer );
00527                 break;
00528             }
00529         }
00530     }
00531 
00532     // remove child from group's childrenlist
00533     group.removeChild( child );
00534 
00535     checkGroupEmpty( group );
00536 }
00537 
00538 void Scribe::removeChildFromGroup( ScribeTimer* timer )
00539 {
00540     NodeHandle& child = timer->getChild();
00541 
00542     GroupList::iterator groupIt = groupList.find( timer->getGroup() );
00543     if( groupIt != groupList.end() ) {
00544         ScribeGroup& group = groupIt->second;
00545         // remove child from group's childrenlist
00546         group.removeChild( child );
00547 
00548         checkGroupEmpty( group );
00549     }
00550 
00551     // remove timer from timeoutlist
00552     pair<ChildTimeoutList::iterator, ChildTimeoutList::iterator> ret =
00553         childTimeoutList.equal_range( child );
00554     if( ret.first != childTimeoutList.end() ) {
00555         for( ChildTimeoutList::iterator it = ret.first; it!=ret.second; ++it) {
00556             if( it->second == timer ) {
00557                 childTimeoutList.erase( it );
00558                 cancelAndDelete( timer );
00559                 break;
00560             }
00561         }
00562     }
00563 }
00564 
00565 void Scribe::checkGroupEmpty( ScribeGroup& group )
00566 {
00567     if( !group.isForwarder() && !group.getSubscription() && !group.getAmISource()){
00568 
00569         if( !group.getParent().isUnspecified() && group.getParent() != overlay->getThisNode() ) {
00570 
00571             ScribeLeaveMessage* msg = new ScribeLeaveMessage("Leave");
00572             msg->setGroupId( group.getGroupId() );
00573             msg->setSrc( overlay->getThisNode() );
00574             msg->setBitLength( SCRIBE_LEAVE_L(msg) );
00575             callRoute( OverlayKey::UNSPECIFIED_KEY, msg, group.getParent() );
00576         }
00577 
00578         if( group.getParentTimer() ) cancelAndDelete( group.getParentTimer() );
00579         if( group.getHeartbeatTimer() ) cancelAndDelete( group.getHeartbeatTimer() );
00580         groupList.erase( group.getGroupId() );
00581     }
00582 }
00583 
00584 void Scribe::refreshChildTimer( NodeHandle& child, OverlayKey& groupId )
00585 {
00586     // find timer
00587     pair<ChildTimeoutList::iterator, ChildTimeoutList::iterator> ret =
00588         childTimeoutList.equal_range( child );
00589     // no timer yet?
00590     if( ret.first == childTimeoutList.end() ) return;
00591 
00592     // restart timer
00593     for( ChildTimeoutList::iterator it = ret.first; it!=ret.second; ++it) {
00594         if( it->first == child && it->second->getGroup() == groupId ) {
00595             startTimer( it->second );
00596         }
00597     }
00598 }
00599 
00600 void Scribe::startTimer( ScribeTimer* timer )
00601 {
00602     if( timer->isScheduled() ) {
00603         cancelEvent( timer );
00604     }
00605 
00606     int duration = 0;
00607     switch( timer->getTimerType() ) {
00608         case SCRIBE_HEARTBEAT:
00609             duration = parentTimeout/2;
00610             break;
00611         case SCRIBE_SUBSCRIPTION_REFRESH:
00612             duration = childTimeout/2;
00613             break;
00614         case SCRIBE_PARENT_TIMEOUT:
00615             duration = parentTimeout;
00616             break;
00617         case SCRIBE_CHILD_TIMEOUT:
00618             duration = childTimeout;
00619             break;
00620     }
00621     scheduleAt(simTime() + duration, timer );
00622 }
00623 
00624 void Scribe::deliverALMDataToRoot( ALMMulticastMessage* mcastMsg )
00625 {
00626     // find group
00627     pair<GroupList::iterator, bool> groupInserter;
00628     groupInserter = groupList.insert( make_pair(mcastMsg->getGroupId(), ScribeGroup(mcastMsg->getGroupId())) );
00629 
00630     // Group is not known yet
00631     if( groupInserter.second ) {
00632         groupInserter.first->second.setAmISource( true );
00633         // TODO: Start/Restart timer to clean up cached groups
00634         // If the timer expires, the flag should be cleared and checkGroupEmpty should be called
00635         //
00636         // FIXME: amISource should be set allways if app publishes messages to the group
00637         // As the timer is not implemented yet, we only set the flag in "sender, but not receiver" mode
00638         // to reduce the amount of unneccessary cached groups
00639     }
00640 
00641     ScribeDataMessage* dataMsg = new ScribeDataMessage( mcastMsg->getName() );
00642     dataMsg->setGroupId( mcastMsg->getGroupId() );
00643     dataMsg->setBitLength( SCRIBE_DATA_L( dataMsg ));
00644     dataMsg->encapsulate( mcastMsg->decapsulate() );
00645 
00646     // Send publish ...
00647     ScribePublishCall* msg = new ScribePublishCall( "ScribePublish" );
00648     msg->setGroupId( dataMsg->getGroupId() );
00649     msg->setBitLength( SCRIBE_PUBLISHCALL_L(msg) );
00650     msg->encapsulate( dataMsg );
00651 
00652     if( !groupInserter.first->second.getRendezvousPoint().isUnspecified() ) {
00653         // ... directly to the rendevouz point, if known ...
00654         sendRouteRpcCall(TIER1_COMP, groupInserter.first->second.getRendezvousPoint(), msg);
00655     } else {
00656         // ... else route it via KBR
00657         sendRouteRpcCall(TIER1_COMP, msg->getGroupId(), msg);
00658     }
00659 
00660     delete mcastMsg;
00661 }
00662 
00663 
00664 void Scribe::deliverALMDataToGroup( ScribeDataMessage* dataMsg )
00665 {
00666     // find group
00667     GroupList::iterator it = groupList.find( dataMsg->getGroupId() );
00668     if( it == groupList.end() ) {
00669         EV << "[Scribe::deliverALMDataToGroup() @ " << overlay->getThisNode().getAddress()
00670             << "Getting ALM data message response for an unknown group!\n";
00671         delete dataMsg;
00672         return;
00673     }
00674     // FIXME: ignore message if not from designated parent to avoid duplicates
00675 
00676     // reset parent heartbeat Timer
00677     ScribeTimer *timer = it->second.getParentTimer();
00678     if( timer ) startTimer( timer );
00679 
00680     // Only empty heartbeat?
00681     if( dataMsg->getEmpty() ) {
00682         delete dataMsg;
00683         return;
00684     }
00685 
00686     // deliver data to children
00687     for( set<NodeHandle>::iterator cit = it->second.getChildrenBegin();
00688             cit != it->second.getChildrenEnd(); ++cit ) {
00689         ScribeDataMessage* newMsg = new ScribeDataMessage( *dataMsg );
00690         RECORD_STATS(++numForward; forwardBytes += newMsg->getByteLength());
00691         callRoute( OverlayKey::UNSPECIFIED_KEY, newMsg, *cit );
00692     }
00693 
00694     // deliver to myself if I'm subscribed to that group
00695     if( it->second.getSubscription() ) {
00696         ALMMulticastMessage* mcastMsg = new ALMMulticastMessage( dataMsg->getName() );
00697         mcastMsg->setGroupId( dataMsg->getGroupId() );
00698         mcastMsg->encapsulate( dataMsg->decapsulate() );
00699         RECORD_STATS(++numReceived; receivedBytes += dataMsg->getByteLength());
00700         send( mcastMsg, "to_upperTier" );
00701     }
00702 
00703     delete dataMsg;
00704 }
00705 
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3