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 ){
00231         if( !msg->getReady() ) {
00232             delete msg;
00233             return;
00234         }
00235 
00236         // TODO/FIXME: use overlay->sendMessageToAllComp(msg, getThisCompType())?
00237         msg->setComp(getThisCompType());
00238         send( msg, "to_upperTier" );
00239         startTimer( subscriptionTimer );
00240     } else {
00241         delete msg;
00242     }
00243 }
00244 
00245 void Scribe::handleTimerEvent( cMessage *msg )
00246 {
00247     ScribeTimer* timer = dynamic_cast<ScribeTimer*>(msg);
00248     assert( timer );
00249     switch( timer->getTimerType() ) {
00250         case SCRIBE_SUBSCRIPTION_REFRESH:
00251             // renew subscriptions for all groups
00252             for( GroupList::iterator it = groupList.begin(); it != groupList.end(); ++it ) {
00253                 NodeHandle parent = it->second.getParent();
00254                 if( !parent.isUnspecified() ){
00255                     ScribeSubscriptionRefreshMessage* refreshMsg = new ScribeSubscriptionRefreshMessage;
00256                     refreshMsg->setGroupId( it->second.getGroupId() );
00257                     refreshMsg->setSrc( overlay->getThisNode() );
00258 
00259                     refreshMsg->setBitLength(SCRIBE_SUBSCRIPTIONREFRESH_L(refreshMsg));
00260                     RECORD_STATS(++numSubscriptionRefresh;
00261                             subscriptionRefreshBytes += refreshMsg->getByteLength()
00262                     );
00263                     callRoute( OverlayKey::UNSPECIFIED_KEY, refreshMsg, parent );
00264                 }
00265             }
00266             startTimer( subscriptionTimer );
00267             break;
00268 
00269         case SCRIBE_HEARTBEAT:
00270         {
00271             // Send heartbeat messages to all children in the group
00272             GroupList::iterator groupIt = groupList.find( timer->getGroup() );
00273             if( groupIt == groupList.end() ) {
00274                 // FIXME: should not happen
00275                 delete timer;
00276                 return;
00277             }
00278             for( set<NodeHandle>::iterator it = groupIt->second.getChildrenBegin();
00279                     it != groupIt->second.getChildrenEnd(); ++it ) {
00280                 ScribeDataMessage* heartbeatMsg = new ScribeDataMessage("Heartbeat");
00281                 heartbeatMsg->setEmpty( true );
00282                 heartbeatMsg->setGroupId( timer->getGroup() );
00283 
00284                 heartbeatMsg->setBitLength(SCRIBE_DATA_L(heartbeatMsg));
00285                 RECORD_STATS(++numHeartbeat; heartbeatBytes += heartbeatMsg->getByteLength());
00286                 callRoute( OverlayKey::UNSPECIFIED_KEY, heartbeatMsg, *it );
00287             }
00288             startTimer( timer );
00289             break;
00290         }
00291         case SCRIBE_CHILD_TIMEOUT:
00292             // Child failed, remove it from group
00293             RECORD_STATS(++numChildTimeout);
00294             removeChildFromGroup( timer );
00295             break;
00296 
00297         case SCRIBE_PARENT_TIMEOUT:
00298             // Parent failed, send new join to rejoin group
00299             RECORD_STATS(++numParentTimeout);
00300             OverlayKey key = timer->getGroup();
00301             EV << "[Scribe::handleTimerEvent() @ " << overlay->getThisNode().getAddress()
00302                 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00303                 << "    Parent of group " << key << "\n"
00304                 << "    failed to send heartbeat, trying to rejoin"
00305                 << endl;
00306 
00307             ScribeJoinCall* newJoin = new ScribeJoinCall;
00308             newJoin->setGroupId( key );
00309             newJoin->setBitLength( SCRIBE_JOINCALL_L(newJoin) );
00310             sendRouteRpcCall(TIER1_COMP, key, newJoin);
00311 
00312             GroupList::iterator groupIt = groupList.find( timer->getGroup() );
00313             if( groupIt == groupList.end() ) {
00314                 // FIXME: should not happen
00315                 delete timer;
00316                 return;
00317             }
00318             groupIt->second.setParentTimer( NULL );
00319             cancelAndDelete( timer );
00320             break;
00321     }
00322 
00323 }
00324 
00325 void Scribe::handleJoinCall( ScribeJoinCall* joinMsg)
00326 {
00327     handleJoinMessage( joinMsg, true );
00328 }
00329 
00330 void Scribe::handleJoinMessage( ScribeJoinCall* joinMsg, bool amIRoot)
00331 {
00332     RECORD_STATS(++numJoins);
00333     OverlayKey key = joinMsg->getGroupId();
00334 
00335     EV << "[Scribe::handleJoinMessage() @ " << overlay->getThisNode().getAddress()
00336         << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00337         << "    Received a ScribeJoin for group " << key << "\n"
00338         << "    msg=" << joinMsg
00339         << endl;
00340 
00341     // Insert group into grouplist, if not already there
00342     pair<GroupList::iterator, bool> groupInserter;
00343     groupInserter = groupList.insert( make_pair(key, ScribeGroup(key)) );
00344 
00345     // If group is new or no parent is known, send join to parent (unless I am root, so there is no parent)
00346     if ( !amIRoot && ( groupInserter.second || groupInserter.first->second.getParent().isUnspecified()) ) {
00347         ScribeJoinCall* newJoin = new ScribeJoinCall;
00348         newJoin->setGroupId( key );
00349         newJoin->setBitLength( SCRIBE_JOINCALL_L(newJoin) );
00350         sendRouteRpcCall(TIER1_COMP, key, newJoin);
00351     }
00352 
00353     // If group had no children, start heartbeat timer for group
00354     if( groupInserter.first->second.numChildren() == 0 ) {
00355         ScribeTimer* heartbeat = new ScribeTimer("HeartbeatTimer");
00356         heartbeat->setTimerType( SCRIBE_HEARTBEAT );
00357         heartbeat->setGroup( groupInserter.first->second.getGroupId() );
00358         startTimer( heartbeat );
00359         if( ScribeTimer* t = groupInserter.first->second.getHeartbeatTimer() ){
00360             // delete old timer, if any
00361             if( t ) cancelAndDelete( t );
00362         }
00363         groupInserter.first->second.setHeartbeatTimer( heartbeat );
00364     }
00365 
00366     // Add child to group
00367     addChildToGroup( joinMsg->getSrcNode(), groupInserter.first->second );
00368 
00369     // Send joinResponse
00370     ScribeJoinResponse* joinResponse = new ScribeJoinResponse;
00371     joinResponse->setGroupId( key );
00372     joinResponse->setBitLength( SCRIBE_JOINRESPONSE_L(joinResponse) );
00373     sendRpcResponse( joinMsg, joinResponse );
00374 }
00375 
00376 void Scribe::handlePublishCall( ScribePublishCall* publishCall )
00377 {
00378     // find group
00379     GroupList::iterator it = groupList.find( publishCall->getGroupId() );
00380     if( it == groupList.end() ||
00381             it->second.getParent().isUnspecified() ||
00382             it->second.getParent() != overlay->getThisNode() ){
00383         // if I don't know the group or I am not root, inform sender
00384         // TODO: forward message when I'm not root but know the rendevous point?
00385         ScribePublishResponse* msg = new ScribePublishResponse("Wrong Root");
00386         msg->setGroupId( publishCall->getGroupId() );
00387         msg->setWrongRoot( true );
00388         msg->setBitLength( SCRIBE_PUBLISHRESPONSE_L(msg) );
00389         sendRpcResponse( publishCall, msg );
00390     } else {
00391         ScribeDataMessage* data = dynamic_cast<ScribeDataMessage*>(publishCall->decapsulate());
00392 
00393         ScribePublishResponse* msg = new ScribePublishResponse("Publish Successful");
00394         msg->setGroupId( publishCall->getGroupId() );
00395         msg->setBitLength( SCRIBE_PUBLISHRESPONSE_L(msg) );
00396         sendRpcResponse( publishCall, msg );
00397 
00398         if( !data ) {
00399             // TODO: throw exception? this should never happen
00400             EV << "[Scribe::handlePublishCall() @ " << overlay->getThisNode().getAddress()
00401                 << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00402                 << "    PublishCall for group " << msg->getGroupId()
00403                 << "    does not contain a calid ALM data message!\n"
00404                 << endl;
00405             return;
00406         }
00407         deliverALMDataToGroup( data );
00408     }
00409 }
00410 
00411 void Scribe::handleJoinResponse( ScribeJoinResponse* joinResponse )
00412 {
00413     GroupList::iterator it = groupList.find( joinResponse->getGroupId() );
00414     if( it == groupList.end() ) {
00415         EV << "[Scribe::handleJoinResponse() @ " << overlay->getThisNode().getAddress()
00416             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00417             << "Getting join response for an unknown group!\n";
00418         return;
00419     }
00420     it->second.setParent( joinResponse->getSrcNode() );
00421 
00422     // Create new heartbeat timer
00423     ScribeTimer* parentTimeout = new ScribeTimer("ParentTimeoutTimer");
00424     parentTimeout->setTimerType( SCRIBE_PARENT_TIMEOUT );
00425     parentTimeout->setGroup( it->second.getGroupId() );
00426     startTimer( parentTimeout );
00427     if( ScribeTimer* t = it->second.getParentTimer() ){
00428         // delete old timer, if any
00429         if( t ) cancelAndDelete( t );
00430     }
00431     it->second.setParentTimer( parentTimeout );
00432 }
00433 
00434 void Scribe::handlePublishResponse( ScribePublishResponse* publishResponse )
00435 {
00436     GroupList::iterator it = groupList.find( publishResponse->getGroupId() );
00437     if( it == groupList.end() ) {
00438         EV << "[Scribe::handlePublishResponse() @ " << overlay->getThisNode().getAddress()
00439             << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00440             << "Getting publish response for an unknown group!\n";
00441         return;
00442     }
00443 
00444     if( publishResponse->getWrongRoot() ) {
00445         it->second.setRendezvousPoint( NodeHandle::UNSPECIFIED_NODE );
00446     } else {
00447         it->second.setRendezvousPoint( publishResponse->getSrcNode() );
00448     }
00449 }
00450 
00451 void Scribe::handleLeaveMessage( ScribeLeaveMessage* leaveMsg )
00452 {
00453     GroupList::iterator it = groupList.find( leaveMsg->getGroupId() );
00454     if( it != groupList.end() ){
00455         removeChildFromGroup( leaveMsg->getSrc(), it->second );
00456     }
00457     delete leaveMsg;
00458 }
00459 
00460 void Scribe::subscribeToGroup( const OverlayKey& groupId )
00461 {
00462     EV << "[Scribe::subscribeToGroup() @ " << overlay->getThisNode().getAddress()
00463         << " (" << overlay->getThisNode().getKey().toString(16) << ")]\n"
00464         << "   Trying to join group " << groupId << "\n";
00465 
00466     // Insert group into grouplist, if not known yet
00467     pair<GroupList::iterator, bool> groupInserter;
00468     groupInserter = groupList.insert( make_pair(groupId, ScribeGroup(groupId)) );
00469 
00470     // Set subscription status
00471     groupInserter.first->second.setSubscription(true);
00472 
00473     // Send join call if I'm not already a forwarder of this group
00474     if( groupInserter.second || groupInserter.first->second.getParent().isUnspecified()) {
00475         ScribeJoinCall* m = new ScribeJoinCall;
00476         m->setGroupId( groupId );
00477         m->setBitLength( SCRIBE_JOINCALL_L(m) );
00478         sendRouteRpcCall(TIER1_COMP, m->getGroupId(), m);
00479     }
00480 }
00481 
00482 void Scribe::leaveGroup( const OverlayKey& group )
00483 {
00484     GroupList::iterator it = groupList.find( group );
00485     if( it != groupList.end() ){
00486         it->second.setSubscription( false );
00487         checkGroupEmpty( it->second );
00488     }
00489 }
00490 
00491 void Scribe::addChildToGroup( const NodeHandle& child, ScribeGroup& group )
00492 {
00493     if( child == overlay->getThisNode() ) {
00494         // Join from ourself, ignore
00495         return;
00496     }
00497 
00498     // add child to group's children list
00499     pair<set<NodeHandle>::iterator, bool> inserter =
00500         group.addChild( child );
00501 
00502     if( inserter.second ) {
00503         // if child has not been in the list, create new timeout msg
00504         ScribeTimer* timeoutMsg = new ScribeTimer;
00505         timeoutMsg->setTimerType( SCRIBE_CHILD_TIMEOUT );
00506 
00507         // Remember child and group
00508         timeoutMsg->setChild( *inserter.first );
00509         timeoutMsg->setGroup( group.getGroupId() );
00510 
00511         startTimer( timeoutMsg );
00512         childTimeoutList.insert( make_pair(child, timeoutMsg) );
00513     }
00514 }
00515 
00516 void Scribe::removeChildFromGroup( const NodeHandle& child, ScribeGroup& group )
00517 {
00518     // find timer
00519     ScribeTimer* timer = NULL;
00520     pair<ChildTimeoutList::iterator, ChildTimeoutList::iterator> ret =
00521         childTimeoutList.equal_range( child );
00522     if( ret.first != childTimeoutList.end() ){
00523         for( ChildTimeoutList::iterator it = ret.first; it!=ret.second; ++it) {
00524             if( group == it->second->getGroup() ) {
00525                 timer = it->second;
00526                 childTimeoutList.erase( it );
00527                 cancelAndDelete( timer );
00528                 break;
00529             }
00530         }
00531     }
00532 
00533     // remove child from group's childrenlist
00534     group.removeChild( child );
00535 
00536     checkGroupEmpty( group );
00537 }
00538 
00539 void Scribe::removeChildFromGroup( ScribeTimer* timer )
00540 {
00541     NodeHandle& child = timer->getChild();
00542 
00543     GroupList::iterator groupIt = groupList.find( timer->getGroup() );
00544     if( groupIt != groupList.end() ) {
00545         ScribeGroup& group = groupIt->second;
00546         // remove child from group's childrenlist
00547         group.removeChild( child );
00548 
00549         checkGroupEmpty( group );
00550     }
00551 
00552     // remove timer from timeoutlist
00553     pair<ChildTimeoutList::iterator, ChildTimeoutList::iterator> ret =
00554         childTimeoutList.equal_range( child );
00555     if( ret.first != childTimeoutList.end() ) {
00556         for( ChildTimeoutList::iterator it = ret.first; it!=ret.second; ++it) {
00557             if( it->second == timer ) {
00558                 childTimeoutList.erase( it );
00559                 cancelAndDelete( timer );
00560                 break;
00561             }
00562         }
00563     }
00564 }
00565 
00566 void Scribe::checkGroupEmpty( ScribeGroup& group )
00567 {
00568     if( !group.isForwarder() && !group.getSubscription() && !group.getAmISource()){
00569 
00570         if( !group.getParent().isUnspecified() && group.getParent() != overlay->getThisNode() ) {
00571 
00572             ScribeLeaveMessage* msg = new ScribeLeaveMessage("Leave");
00573             msg->setGroupId( group.getGroupId() );
00574             msg->setSrc( overlay->getThisNode() );
00575             msg->setBitLength( SCRIBE_LEAVE_L(msg) );
00576             callRoute( OverlayKey::UNSPECIFIED_KEY, msg, group.getParent() );
00577         }
00578 
00579         if( group.getParentTimer() ) cancelAndDelete( group.getParentTimer() );
00580         if( group.getHeartbeatTimer() ) cancelAndDelete( group.getHeartbeatTimer() );
00581         groupList.erase( group.getGroupId() );
00582     }
00583 }
00584 
00585 void Scribe::refreshChildTimer( NodeHandle& child, OverlayKey& groupId )
00586 {
00587     // find timer
00588     pair<ChildTimeoutList::iterator, ChildTimeoutList::iterator> ret =
00589         childTimeoutList.equal_range( child );
00590     // no timer yet?
00591     if( ret.first == childTimeoutList.end() ) return;
00592 
00593     // restart timer
00594     for( ChildTimeoutList::iterator it = ret.first; it!=ret.second; ++it) {
00595         if( it->first == child && it->second->getGroup() == groupId ) {
00596             startTimer( it->second );
00597         }
00598     }
00599 }
00600 
00601 void Scribe::startTimer( ScribeTimer* timer )
00602 {
00603     if( timer->isScheduled() ) {
00604         cancelEvent( timer );
00605     }
00606 
00607     int duration = 0;
00608     switch( timer->getTimerType() ) {
00609         case SCRIBE_HEARTBEAT:
00610             duration = parentTimeout/2;
00611             break;
00612         case SCRIBE_SUBSCRIPTION_REFRESH:
00613             duration = childTimeout/2;
00614             break;
00615         case SCRIBE_PARENT_TIMEOUT:
00616             duration = parentTimeout;
00617             break;
00618         case SCRIBE_CHILD_TIMEOUT:
00619             duration = childTimeout;
00620             break;
00621     }
00622     scheduleAt(simTime() + duration, timer );
00623 }
00624 
00625 void Scribe::deliverALMDataToRoot( ALMMulticastMessage* mcastMsg )
00626 {
00627     // find group
00628     pair<GroupList::iterator, bool> groupInserter;
00629     groupInserter = groupList.insert( make_pair(mcastMsg->getGroupId(), ScribeGroup(mcastMsg->getGroupId())) );
00630 
00631     // Group is not known yet
00632     if( groupInserter.second ) {
00633         groupInserter.first->second.setAmISource( true );
00634         // TODO: Start/Restart timer to clean up cached groups
00635         // If the timer expires, the flag should be cleared and checkGroupEmpty should be called
00636         //
00637         // FIXME: amISource should be set allways if app publishes messages to the group
00638         // As the timer is not implemented yet, we only set the flag in "sender, but not receiver" mode
00639         // to reduce the amount of unneccessary cached groups
00640     }
00641 
00642     ScribeDataMessage* dataMsg = new ScribeDataMessage( mcastMsg->getName() );
00643     dataMsg->setGroupId( mcastMsg->getGroupId() );
00644     dataMsg->setBitLength( SCRIBE_DATA_L( dataMsg ));
00645     dataMsg->encapsulate( mcastMsg->decapsulate() );
00646 
00647     // Send publish ...
00648     ScribePublishCall* msg = new ScribePublishCall( "ScribePublish" );
00649     msg->setGroupId( dataMsg->getGroupId() );
00650     msg->setBitLength( SCRIBE_PUBLISHCALL_L(msg) );
00651     msg->encapsulate( dataMsg );
00652 
00653     if( !groupInserter.first->second.getRendezvousPoint().isUnspecified() ) {
00654         // ... directly to the rendevouz point, if known ...
00655         sendRouteRpcCall(TIER1_COMP, groupInserter.first->second.getRendezvousPoint(), msg);
00656     } else {
00657         // ... else route it via KBR
00658         sendRouteRpcCall(TIER1_COMP, msg->getGroupId(), msg);
00659     }
00660 
00661     delete mcastMsg;
00662 }
00663 
00664 
00665 void Scribe::deliverALMDataToGroup( ScribeDataMessage* dataMsg )
00666 {
00667     // find group
00668     GroupList::iterator it = groupList.find( dataMsg->getGroupId() );
00669     if( it == groupList.end() ) {
00670         EV << "[Scribe::deliverALMDataToGroup() @ " << overlay->getThisNode().getAddress()
00671             << "Getting ALM data message response for an unknown group!\n";
00672         delete dataMsg;
00673         return;
00674     }
00675     // FIXME: ignore message if not from designated parent to avoid duplicates
00676 
00677     // reset parent heartbeat Timer
00678     ScribeTimer *timer = it->second.getParentTimer();
00679     if( timer ) startTimer( timer );
00680 
00681     // Only empty heartbeat?
00682     if( dataMsg->getEmpty() ) {
00683         delete dataMsg;
00684         return;
00685     }
00686 
00687     // deliver data to children
00688     for( set<NodeHandle>::iterator cit = it->second.getChildrenBegin();
00689             cit != it->second.getChildrenEnd(); ++cit ) {
00690         ScribeDataMessage* newMsg = new ScribeDataMessage( *dataMsg );
00691         RECORD_STATS(++numForward; forwardBytes += newMsg->getByteLength());
00692         callRoute( OverlayKey::UNSPECIFIED_KEY, newMsg, *cit );
00693     }
00694 
00695     // deliver to myself if I'm subscribed to that group
00696     if( it->second.getSubscription() ) {
00697         ALMMulticastMessage* mcastMsg = new ALMMulticastMessage( dataMsg->getName() );
00698         mcastMsg->setGroupId( dataMsg->getGroupId() );
00699         mcastMsg->encapsulate( dataMsg->decapsulate() );
00700         RECORD_STATS(++numReceived; receivedBytes += dataMsg->getByteLength());
00701         send( mcastMsg, "to_upperTier" );
00702     }
00703 
00704     delete dataMsg;
00705 }
00706 

Generated on Tue Sep 8 17:26:54 2009 for OverSim by  doxygen 1.5.8