#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 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
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
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
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.
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 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)
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 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.
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.
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] |
Definition at line 65 of file Scribe.h.
Referenced by initializeApp(), and startTimer().
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().