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
ScribeTimer * subscriptionTimer
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 490 of file Scribe.cc.

Referenced by handleJoinMessage().

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 }

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

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

Definition at line 565 of file Scribe.cc.

Referenced by leaveGroup(), and removeChildFromGroup().

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 }

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 664 of file Scribe.cc.

Referenced by deliver(), and handlePublishCall().

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 }

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 624 of file Scribe.cc.

Referenced by handleUpperMessage().

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 }

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 324 of file Scribe.cc.

Referenced by handleRpcCall().

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

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

Handles join requests from other nodes.

Definition at line 329 of file Scribe.cc.

Referenced by forward(), and handleJoinCall().

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 }

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

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

Definition at line 410 of file Scribe.cc.

Referenced by handleRpcResponse().

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 }

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

Handles leave requests from other nodes.

Definition at line 450 of file Scribe.cc.

Referenced by deliver().

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 }

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 375 of file Scribe.cc.

Referenced by handleRpcCall().

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 }

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 433 of file Scribe.cc.

Referenced by handleRpcResponse().

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 }

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) && 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 }

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 244 of file Scribe.cc.

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 }

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 481 of file Scribe.cc.

Referenced by handleUpperMessage().

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

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 584 of file Scribe.cc.

Referenced by deliver().

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 }

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 538 of file Scribe.cc.

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 }

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

Removes a child from a multicast group.

Definition at line 515 of file Scribe.cc.

Referenced by handleLeaveMessage(), and handleTimerEvent().

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 }

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 600 of file Scribe.cc.

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

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 }

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 459 of file Scribe.cc.

Referenced by handleUpperMessage().

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 }

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().

ScribeTimer* Scribe::subscriptionTimer [private]

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 Wed May 26 16:21:19 2010 for OverSim by  doxygen 1.6.3