Scribe Class Reference

#include <Scribe.h>

Inheritance diagram for Scribe:

BaseApp BaseRpc RpcListener

List of all members.

Public Member Functions

 Scribe ()
 ~Scribe ()
virtual void initializeApp (int stage)
 initializes derived class-attributes
virtual void handleUpperMessage (cMessage *msg)
 handleUpperMessage gets called of handleMessage(cMessage* msg) if msg arrivedOn from_upperTier (currently msg gets deleted in this function)
virtual void handleReadyMessage (CompReadyMessage *msg)
 method to handle ready messages from the overlay
virtual void handleTimerEvent (cMessage *msg)
virtual bool handleRpcCall (BaseCallMessage *msg)
 Processes Remote-Procedure-Call invocation messages.
virtual void handleRpcResponse (BaseResponseMessage *msg, cPolymorphic *context, int rpcId, simtime_t rtt)
 This method is called if an RPC response has been received.
virtual void forward (OverlayKey *key, cPacket **msg, NodeHandle *nextHopNode)
 Common API function: handles messages from overlay to be forwarded.
virtual void deliver (OverlayKey &key, cMessage *msg)
 Common API function: handles delivered messages from overlay.
virtual void update (const NodeHandle &node, bool joined)
 Common API function: informs application about neighbors and own nodeID.
virtual void finishApp ()
 collects statistical data of derived app

Protected Member Functions

void handleJoinResponse (ScribeJoinResponse *joinResponse)
 Handles a response to a join call send by this node.
void handleJoinCall (ScribeJoinCall *joinMsg)
 Handles a join request from another node.
void handlePublishCall (ScribePublishCall *publishCall)
 Handles a publish call from another node.
void handlePublishResponse (ScribePublishResponse *publishResponse)
 Handles a response to a publish call send b this node.
void handleJoinMessage (ScribeJoinCall *joinMsg, bool amIRoot)
 Handles join requests from other nodes.
void handleLeaveMessage (ScribeLeaveMessage *leaveMsg)
 Handles leave requests from other nodes.
void subscribeToGroup (const OverlayKey &groupId)
 Gets called if the local node wants to subscribe to a multicast group.
void leaveGroup (const OverlayKey &group)
 Gets called if the local node wants to leave a multicast group.
void startTimer (ScribeTimer *timer)
 Starts a local timer.
void addChildToGroup (const NodeHandle &child, ScribeGroup &group)
 Adds a child to a multicast group.
void removeChildFromGroup (const NodeHandle &child, ScribeGroup &group)
 Removes a child from a multicast group.
void removeChildFromGroup (ScribeTimer *timer)
 Removes a child from a multicast group.
void checkGroupEmpty (ScribeGroup &group)
 Chechs wheter there are any subscibers left to a given root.
void refreshChildTimer (NodeHandle &child, OverlayKey &groupId)
 Refreshes a child timer.
void deliverALMDataToGroup (ScribeDataMessage *dataMsg)
 Delivers a multicast message to all children in the multicast group.
void deliverALMDataToRoot (ALMMulticastMessage *mcastMsg)
 Delivers a multicast message to the tree's root.

Private Types

typedef std::map< OverlayKey,
ScribeGroup
GroupList
typedef std::multimap
< NodeHandle, ScribeTimer * > 
ChildTimeoutList

Private Attributes

GroupList groupList
ChildTimeoutList childTimeoutList
int childTimeout
int parentTimeout
ScribeTimersubscriptionTimer
int numJoins
int numChildTimeout
int numParentTimeout
int numForward
int forwardBytes
int numReceived
int receivedBytes
int numHeartbeat
int heartbeatBytes
int numSubscriptionRefresh
int subscriptionRefreshBytes


Detailed Description

Definition at line 57 of file Scribe.h.


Member Typedef Documentation

typedef std::multimap<NodeHandle, ScribeTimer*> Scribe::ChildTimeoutList [private]

Definition at line 62 of file Scribe.h.

typedef std::map<OverlayKey, ScribeGroup> Scribe::GroupList [private]

Definition at line 60 of file Scribe.h.


Constructor & Destructor Documentation

Scribe::Scribe (  ) 

Definition at line 36 of file Scribe.cc.

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 }

Scribe::~Scribe (  ) 

Definition at line 53 of file Scribe.cc.

00054 {
00055     groupList.clear();
00056     cancelAndDelete(subscriptionTimer);
00057     // TODO: clear childTimeoutList
00058 }


Member Function Documentation

void Scribe::addChildToGroup ( const NodeHandle child,
ScribeGroup group 
) [protected]

Adds a child to a multicast group.

Definition at line 491 of file Scribe.cc.

Referenced by handleJoinMessage().

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 }

void Scribe::checkGroupEmpty ( ScribeGroup group  )  [protected]

Chechs wheter there are any subscibers left to a given root.

Definition at line 566 of file Scribe.cc.

Referenced by leaveGroup(), and removeChildFromGroup().

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 }

void Scribe::deliver ( OverlayKey key,
cMessage *  msg 
) [virtual]

Common API function: handles delivered messages from overlay.

method to handle decapsulated KBRdeliver messages from overlay module, should be overwritten in derived application

Parameters:
key destination key
msg delivered message

Reimplemented from BaseApp.

Definition at line 178 of file Scribe.cc.

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 }

void Scribe::deliverALMDataToGroup ( ScribeDataMessage dataMsg  )  [protected]

Delivers a multicast message to all children in the multicast group.

Definition at line 665 of file Scribe.cc.

Referenced by deliver(), and handlePublishCall().

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 }

void Scribe::deliverALMDataToRoot ( ALMMulticastMessage mcastMsg  )  [protected]

Delivers a multicast message to the tree's root.

This method gets called when the local app wants to publish some data to the multiacst group.

Definition at line 625 of file Scribe.cc.

Referenced by handleUpperMessage().

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 }

void Scribe::finishApp (  )  [virtual]

collects statistical data of derived app

Reimplemented from BaseApp.

Definition at line 84 of file Scribe.cc.

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 }

void Scribe::forward ( OverlayKey key,
cPacket **  msg,
NodeHandle nextHopNode 
) [virtual]

Common API function: handles messages from overlay to be forwarded.

method to handle decapsulated KBRdeliver messages from overlay module, should be overwritten in derived application if needed

Parameters:
key destination key
msg message to forward
nextHopNode next hop

Reimplemented from BaseApp.

Definition at line 113 of file Scribe.cc.

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 }

void Scribe::handleJoinCall ( ScribeJoinCall joinMsg  )  [protected]

Handles a join request from another node.

This method only gets called if the local node is the root of the multicast group. It only calls handlePublishCall with amIRoot parameter set to "true"

Definition at line 325 of file Scribe.cc.

Referenced by handleRpcCall().

00326 {
00327     handleJoinMessage( joinMsg, true );
00328 }

void Scribe::handleJoinMessage ( ScribeJoinCall joinMsg,
bool  amIRoot 
) [protected]

Handles join requests from other nodes.

Definition at line 330 of file Scribe.cc.

Referenced by forward(), and handleJoinCall().

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 }

void Scribe::handleJoinResponse ( ScribeJoinResponse joinResponse  )  [protected]

Handles a response to a join call send by this node.

Definition at line 411 of file Scribe.cc.

Referenced by handleRpcResponse().

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 }

void Scribe::handleLeaveMessage ( ScribeLeaveMessage leaveMsg  )  [protected]

Handles leave requests from other nodes.

Definition at line 451 of file Scribe.cc.

Referenced by deliver().

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 }

void Scribe::handlePublishCall ( ScribePublishCall publishCall  )  [protected]

Handles a publish call from another node.

Publish calls are used to send multicast messages to the root of the multicast tree.

Definition at line 376 of file Scribe.cc.

Referenced by handleRpcCall().

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 }

void Scribe::handlePublishResponse ( ScribePublishResponse publishResponse  )  [protected]

Handles a response to a publish call send b this node.

Publish calls are used to send multicast messages to the root of the multicast tree.

Definition at line 434 of file Scribe.cc.

Referenced by handleRpcResponse().

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 }

void Scribe::handleReadyMessage ( CompReadyMessage msg  )  [virtual]

method to handle ready messages from the overlay

Parameters:
msg message to handle

Reimplemented from BaseApp.

Definition at line 227 of file Scribe.cc.

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 }

bool Scribe::handleRpcCall ( BaseCallMessage msg  )  [virtual]

Processes Remote-Procedure-Call invocation messages.


This method should be overloaded when the overlay provides RPC functionality.

Returns:
true, if rpc has been handled

Reimplemented from BaseRpc.

Definition at line 149 of file Scribe.cc.

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 }

void Scribe::handleRpcResponse ( BaseResponseMessage msg,
cPolymorphic *  context,
int  rpcId,
simtime_t  rtt 
) [virtual]

This method is called if an RPC response has been received.

Parameters:
msg The response message.
context Pointer to an optional state object. The object has to be handled/deleted by the handleRpcResponse() code
rpcId The RPC id.
rtt The Round-Trip-Time of this RPC

Reimplemented from RpcListener.

Definition at line 158 of file Scribe.cc.

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 }

void Scribe::handleTimerEvent ( cMessage *  msg  )  [virtual]

Reimplemented from BaseRpc.

Definition at line 245 of file Scribe.cc.

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 }

void Scribe::handleUpperMessage ( cMessage *  msg  )  [virtual]

handleUpperMessage gets called of handleMessage(cMessage* msg) if msg arrivedOn from_upperTier (currently msg gets deleted in this function)

Parameters:
msg the message to handle

Reimplemented from BaseApp.

Definition at line 192 of file Scribe.cc.

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 }

void Scribe::initializeApp ( int  stage  )  [virtual]

initializes derived class-attributes

Parameters:
stage the init stage

Reimplemented from BaseApp.

Definition at line 60 of file Scribe.cc.

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 }

void Scribe::leaveGroup ( const OverlayKey group  )  [protected]

Gets called if the local node wants to leave a multicast group.

Parameters:
group the ID of the group to leave

Definition at line 482 of file Scribe.cc.

Referenced by handleUpperMessage().

00483 {
00484     GroupList::iterator it = groupList.find( group );
00485     if( it != groupList.end() ){
00486         it->second.setSubscription( false );
00487         checkGroupEmpty( it->second );
00488     }
00489 }

void Scribe::refreshChildTimer ( NodeHandle child,
OverlayKey groupId 
) [protected]

Refreshes a child timer.

If a child sends a subscribtion refresh, this method gets called. It finds the subscriptionTimeout timer for the group and reschedules it.

Definition at line 585 of file Scribe.cc.

Referenced by deliver().

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 }

void Scribe::removeChildFromGroup ( ScribeTimer timer  )  [protected]

Removes a child from a multicast group.

Both the child and the group are determined from the timer message This method gets calld if a subscription timer of a child expires.

Definition at line 539 of file Scribe.cc.

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 }

void Scribe::removeChildFromGroup ( const NodeHandle child,
ScribeGroup group 
) [protected]

Removes a child from a multicast group.

Definition at line 516 of file Scribe.cc.

Referenced by handleLeaveMessage(), and handleTimerEvent().

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 }

void Scribe::startTimer ( ScribeTimer timer  )  [protected]

Starts a local timer.

This method automaticly determines the type of the timer and schedules it accordingly. If the timer is already scheduled, it gets canceled before getting rescheduled.

Definition at line 601 of file Scribe.cc.

Referenced by addChildToGroup(), deliverALMDataToGroup(), handleJoinMessage(), handleJoinResponse(), handleReadyMessage(), handleTimerEvent(), and refreshChildTimer().

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 }

void Scribe::subscribeToGroup ( const OverlayKey groupId  )  [protected]

Gets called if the local node wants to subscribe to a multicast group.

Parameters:
groupId the ID of the group to join

Definition at line 460 of file Scribe.cc.

Referenced by handleUpperMessage().

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 }

void Scribe::update ( const NodeHandle node,
bool  joined 
) [virtual]

Common API function: informs application about neighbors and own nodeID.

Parameters:
node new or lost neighbor
joined new or lost?

Reimplemented from BaseApp.

Definition at line 129 of file Scribe.cc.

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 }


Member Data Documentation

int Scribe::childTimeout [private]

Definition at line 65 of file Scribe.h.

Referenced by initializeApp(), and startTimer().

Definition at line 63 of file Scribe.h.

Referenced by addChildToGroup(), refreshChildTimer(), and removeChildFromGroup().

int Scribe::forwardBytes [private]

Definition at line 75 of file Scribe.h.

Referenced by deliverALMDataToGroup(), finishApp(), initializeApp(), and Scribe().

int Scribe::heartbeatBytes [private]

Definition at line 79 of file Scribe.h.

Referenced by finishApp(), handleTimerEvent(), initializeApp(), and Scribe().

int Scribe::numChildTimeout [private]

Definition at line 72 of file Scribe.h.

Referenced by finishApp(), handleTimerEvent(), initializeApp(), and Scribe().

int Scribe::numForward [private]

Definition at line 74 of file Scribe.h.

Referenced by deliverALMDataToGroup(), finishApp(), initializeApp(), and Scribe().

int Scribe::numHeartbeat [private]

Definition at line 78 of file Scribe.h.

Referenced by finishApp(), handleTimerEvent(), initializeApp(), and Scribe().

int Scribe::numJoins [private]

Definition at line 71 of file Scribe.h.

Referenced by finishApp(), handleJoinMessage(), initializeApp(), and Scribe().

int Scribe::numParentTimeout [private]

Definition at line 73 of file Scribe.h.

Referenced by finishApp(), handleTimerEvent(), initializeApp(), and Scribe().

int Scribe::numReceived [private]

Definition at line 76 of file Scribe.h.

Referenced by deliverALMDataToGroup(), finishApp(), initializeApp(), and Scribe().

Definition at line 80 of file Scribe.h.

Referenced by finishApp(), handleTimerEvent(), initializeApp(), and Scribe().

int Scribe::parentTimeout [private]

Definition at line 66 of file Scribe.h.

Referenced by handleJoinResponse(), initializeApp(), and startTimer().

int Scribe::receivedBytes [private]

Definition at line 77 of file Scribe.h.

Referenced by deliverALMDataToGroup(), finishApp(), initializeApp(), and Scribe().

Definition at line 81 of file Scribe.h.

Referenced by finishApp(), handleTimerEvent(), initializeApp(), and Scribe().

Definition at line 68 of file Scribe.h.

Referenced by handleReadyMessage(), handleTimerEvent(), Scribe(), and ~Scribe().


The documentation for this class was generated from the following files:

Generated on Tue Sep 8 17:27:02 2009 for OverSim by  doxygen 1.5.8