#include <Scribe.h>

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 |
Definition at line 57 of file Scribe.h.
typedef std::multimap<NodeHandle, ScribeTimer*> Scribe::ChildTimeoutList [private] |
typedef std::map<OverlayKey, ScribeGroup> Scribe::GroupList [private] |
| 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 }
| 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
| 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
| 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
| 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.
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.
| 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)
| 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
| 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.
| 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.
| 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.
| 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 }
int Scribe::childTimeout [private] |
ChildTimeoutList Scribe::childTimeoutList [private] |
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().
GroupList Scribe::groupList [private] |
Definition at line 61 of file Scribe.h.
Referenced by checkGroupEmpty(), deliverALMDataToGroup(), deliverALMDataToRoot(), handleJoinMessage(), handleJoinResponse(), handleLeaveMessage(), handlePublishCall(), handlePublishResponse(), handleTimerEvent(), initializeApp(), leaveGroup(), removeChildFromGroup(), subscribeToGroup(), update(), 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().
int Scribe::numSubscriptionRefresh [private] |
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().
int Scribe::subscriptionRefreshBytes [private] |
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().
1.5.8