/* * File: Dispatcher.cc * Author: jgaebler * * Created on September 20, 2010, 1:30 PM */ #include "Dispatcher.h" #include "Moversight.h" #include "app/Application.h" #include "common/container/PeerIDList.h" #include "common/container/PeerIDSet.h" #include "common/container/SubscriberSet.h" #include "common/transport/MoversightMessageTypes.h" #include "common/transport/msg/ExteriorMessage.h" #include "common/validator/MessageValidator.h" #include "common/validator/MessageValidatorType.h" #include "common/validator/StandardValidator.h" #include "common/validator/SemanticSplitValidator.h" #include "common/validator/NVBValidator.h" #include "event/DeliverableObject.h" #include "event/ObjectListener.h" #include "event/events/ConnectionLostEvent.h" #include "event/events/ConnectionReEstablishedEvent.h" #include "event/events/FlushDoneEvent.h" #include "fd/NetworkFailureDetector.h" #include "mrs/sync/NextViewBuffer.h" #include "ms/Peer.h" #include "ms/Invitation.h" #include "ms/MemberRegister.h" #include "ms/Roster.h" #include "ms/events/GroupClosedEvent.h" #include "ms/events/JoinAbortedEvent.h" #include "ms/events/LocalPeerUpdatedEvent.h" #include "mt/msg/MulticastMessage.h" #include "st/msg/StreamMessage.h" #if UBEEME #include "app/events/GroupCreatedEvent.h" #include "app/events/GroupClosedEvent.h" #include "app/events/JoinGroupDoneEvent.h" #include "app/events/LocalPeerUpdateEvent.h" #include "app/events/PeerIsPendingEvent.h" #include "app/events/PeerJoinedEvent.h" #include "app/events/PeerLeftEvent.h" #include "app/events/PeerReconnectedEvent.h" #include "app/events/SplitNotifyEvent.h" #include "app/events/SplitDoneEvent.h" #include "app/events/MergeNotifyEvent.h" #include "app/events/MergeDoneEvent.h" #include "debug.h" #endif namespace ubeeme { namespace moversight { #undef DEBUG #define DEBUG(msg) if (module.isPrintDebugDIS()) MOV_DEBUG << "DIS@" << ms.getLocalAddress() << " "<(this); subscribe(this); ms.initialise(); ct.initialise(); st.initialise(); ut.initialise(); mt.initialise(); fd.initialise(); mob.initialise(); merge.initialise(); split.initialise(); ts.initialise(); uc.initialise(); nvb.initialise(); mrs.initialise(); rvd.initialise(); setStandardMessageValidator(); int modulID =module.getLocalAddress().getHostAddress().get4().getDByte(3); std::stringstream stringBufffer; stringBufffer << "memberRegisterDump-" << modulID << "-" << GenericTime::currentTime().toString() << ".json"; logMemberRegister.setTargetFileName(stringBufffer.str().c_str()); logMemberRegister.initialise(); } /** * @brief Assignment operator. * @param other The instance to assign. * @return A reference of the current object. */ Dispatcher & Dispatcher::operator=(Dispatcher const & other) { if (this != &other) { app = other.app; module = other.module; ms = other.ms; es = other.es; ct = other.ct; st = other.st; ut = other.ut; mt = other.mt; fd = other.fd; mob = other.mob; merge = other.merge; split = other.split; ts = other.ts; mrs = other.mrs; nvb = other.nvb; rvd = other.rvd; uc = other.uc; messageValidator = other.messageValidator; logMemberRegister = other.logMemberRegister; }//End if return *this; } /** * @brief Finalize the current moversight session and set it ready to reinitialize. */ void Dispatcher::finalise() { es.finalise(); ms.finalise(); ct.finalise(); st.finalise(); ut.finalise(); mt.finalise(); fd.finalise(); mob.finalise(); merge.finalise(); split.finalise(); ts.finalise(); uc.finalise(); mrs.finalise(); nvb.finalise(); rvd.finalise(); if (messageValidator != NULL) { delete messageValidator; messageValidator = NULL; }//End if logMemberRegister.finalise(); } /** * @brief Destructor */ Dispatcher::~Dispatcher() { finalise(); } /** * @brief Application Interface, which distributes a message reliable and totaly ordered within the peer group. * @param msg the message to send */ void Dispatcher::sendMessage(MulticastMessage & msg) { // if (getLocalSubState() == WAITING_FOR_REJOIN || // getLocalSubState() == REJOIN_IN_PROGRESS) { // switch (msg.getType()) { // case LT: // LTMessage // case GT: // GTMessage // case LA: // LeaveAnnounce // case RA: // RejoinAnnounce // case RRO: // RejoinRoster // case RCA: // ReconnectAnnounce // case RJRO: // RejoinRoster // case RJRC: // RejoinRosterConfirm // case ROA: // RejoinRosterAnnounce // case RD: // RejoinDone // case RF: // RejoinFailed // mt.send(msg); // break; // // default: // DEBUG("Sorry you are either a secondary group or a rejoin is going on. Messages are not allowed to be sent.") // break; // } // } // else { if (nvb.isLockedSendMsgSemaphoreActivated()) { nvb.pushSendMsg(&msg); } else { if (nvb.isViewChangeAbleMessageType(msg.getType())) { nvb.setLockedSendMsgSemaphoreAndStartFlush(); } mt.send(msg); } // } } /** * @brief Application Interface, which distributes a stream message within the peer group. * @param msg the message to send */ void Dispatcher::sendMessage(StreamMessage& msg) { st.send(msg); } /** * @brief This method handles all incoming messages from the network and distribute these to the submodules * @param msg the received message to distribute to the submodules * * @NOTE In future we will define a generic IOHandler that is responsible for handling messages * when they arrive. Such an IOHandler will be the UnicastTransfer service. */ void Dispatcher::handleMessage(MoversightMessage * msg) { // if (getLocalSubState() == FLUSHING) { // // switch (msg->getType()) { // case LT: // case GT: // case CM: // case CMC: // case SMDT: // case UM: // case UMC: msg->handleReceive(*this); // break; // // default: // //std::cerr<getFullName()<<"\n"; // //tempMessageQueue.add(new MoversightMessage(*msg)); // if(dynamic_cast(msg) != NULL){ // getMaintenanceRoleService().getNextViewBuffer().pushReceiveMsg(dynamic_cast(msg)); // } // break; // } // }//End if // else { // // because of the stateOperation "LOCK" a further differentiation is needed. // if (getLocalStateOperation() != LOCKED) { // msg->handleReceive(*this); // } // else { // switch (msg->getType()) { // //case RRO: // case RJRO: // case RJRC: // case RCA: // case RRO: // case ROA: // case RD: // case RF: // case LT: // case GT: // msg->handleReceive(*this); // break; // // case NDC: // break; // // default: // // //std::cerr<<"add message to temp queue - locked "<getFullName()<<"\n";; // //tempMessageQueue.add(new MoversightMessage(*msg)); // should save the belated data-transmission on both sides of the partition // if(dynamic_cast(msg) != NULL){ // getMaintenanceRoleService().getNextViewBuffer().pushReceiveMsg(dynamic_cast(msg)); // } // DEBUG("Peer is locked at the moment because of an ongoing rejoin - sending messages not belonging to rejoin forbidden!"); // break; // } // } // }//End else // start processing pending events, signaled during message handling. es.process(); } /** * @brief Handle temporary saved messages during flush operations. */ void Dispatcher::handleSavedMessages() { // for (size_t i = 0; i < tempMessageQueue.size(); i++) { // DEBUG("handle stored: " << tempMessageQueue.get(i)->getType()); //std::cerr<getFullName()<<"\n"; // MoversightMessage * pdu = tempMessageQueue.get(i); // handleMessage(pdu); // delete pdu; // }//End for // // //clear saved messages, because all send again // tempMessageQueue.clear(); } /** * @brief Invites a peer to a group. * * This method invites a peer to a group. The invitation is only executed, * if the destination transport address diverse from the local peer address. * @param destTa The transport address of the peer to invite. * @note API method * @throw FlushModeException If while a flush a new member want join */ void Dispatcher::invitePeer(TransportAddress & destTa, PeerDescription & pDesc) { if (getLocalSubState() == FLUSHING) { throw FlushModeException("flush in progress - please try later"); } else if (getLocalSubState() == WAITING_FOR_REJOIN) { DEBUG("Peer does NOT belong to the primary group - it's not allowed to invite a new peer!"); return; } if (getLocalPeer().getLocalAddress() != destTa) { ms.invitePeer(destTa, pDesc); }//End if else { std::string reason("peer already member of the current group"); signal(new JoinAbortedEvent(destTa, reason)); } } /** * @brief Cancel the current inviting process. * Calling this method performs a JoinAbort operation from the user to moversight. * @note API method * @param ta The transport address of the peer to invite. * @param reason The cancel reason. */ void Dispatcher::cancelInvitation(TransportAddress & ta, std::string reason) { ms.cancelInvitation(ta, reason); } /** * @brief Accepts a invitation to joining a group. * * This method accepts a invitation for joining the current group. * @note API method * @param inv The invitation instance, used to response to the correct inviter. * @param comment A short message from the application to the group (e.g. "hello message"). * @param pDesc A short description of the joining peer, provided by the application. * @param resource A generic representation of the resources available at the local peer. */ void Dispatcher::acceptInvitation(const Invitation & inv, const std::string & comment, const PeerDescription & pDesc, const PeerResources & resource) { ms.responseInvitation(inv, true, comment, pDesc, resource); } /** * @brief Rejects a invitation to joining a group. * * This method rejectes a invitation for joining the current group. * @note API method * @param inv The invitation instance, used to response to the correct inviter. * @param reason A short message from the application, why the invitation is rejected. */ void Dispatcher::rejectInvitation(const Invitation & inv, const std::string & reason) { PeerDescription pDesc("not available"); PeerResources resource; ms.responseInvitation(inv, false, reason, pDesc, resource); } /** * @brief Leaves the current group. * * This method is called, if the local peer aims to leave the group. * A leave announce message is disseminated within the group. The group have to closed afterwards. * @note API method * @throw FlushModeException If while a flush an peer want to leave */ void Dispatcher::leaveGroup() { if (getLocalSubState() == FLUSHING) { throw FlushModeException("flush in progress - please try later"); }//End if ms.leaveGroup(); } /** * @brief Starts the SPLIT service at the topology control module * @param options Contents the Flags for synchronising the message queues and SPLIT behaviour * @param splitPeers Contents the PeerIDs of the splitting peers * @note API method * @throw FlushModeException If while a flush an other split occurs */ void Dispatcher::splitGroup(unsigned char options, PeerIDList splitPeers) { split.splitGroup(options, splitPeers); } /** * @brief Try to start a merge with second group. * @param destTa The transport address of the peer to lead the merge in second group. * @note API method. * @throw FlushModeException If a merge will request while a flush */ void Dispatcher::mergeGroup(TransportAddress & destTa) { merge.mergeGroup(destTa); } /** * @brief The App accept the requesting merge. * @note API method. * */ void Dispatcher::acceptGroupMerge() { merge.responseMerge(); } /** * @brief The App reject the requesting merge. * @param reason The reason of the rejection. * @note API method. * */ void Dispatcher::rejectGroupMerge(std::string & reason) { merge.cancelMerge(reason); } /** * @brief Returns the local peer. * @return A reference to the local peer instance. */ Peer & Dispatcher::getLocalPeer() { return ms.getLocalPeer(); } /** * @brief Returns the current view ID. * @return The desired view ID. */ ViewID Dispatcher::getViewID() const { return getMembershipService().getViewID(); } /** * @brief Permits access to the moversight call back * @return The moversight call back. */ Application & Dispatcher::getMoversightCallback() { return app; } /** * @brief Permits access to the moversight call back * @return The moversight call back. */ const Application & Dispatcher::getMoversightCallback() const { return app; } /** * @brief Permits access to the moversight * @return the moversight */ Moversight & Dispatcher::getMoversight() { return module; } /** * @brief Permits access to the moversight * @return the moversight */ const Moversight & Dispatcher::getMoversight() const { return module; } /** * @brief Permits access to the moversight membership service. * @return The current membership service instance. */ MembershipService & Dispatcher::getMembershipService() { return ms; } /** * @brief Permits access to the moversight membership service. * @return The current membership service instance. */ const MembershipService & Dispatcher::getMembershipService() const { return ms; } /** * @brief Permits access to the moversight event service. * @return The current event service instance. */ EventService & Dispatcher::getEventService() { return es; } /** * @brief Permits access to the moversight event service. * @return The current event service instance. */ const EventService & Dispatcher::getEventService() const { return es; } /** * @brief Permits access to the moversight message transfer. * @return The current message transfer instance. */ MessageTransfer & Dispatcher::getMessageTransfer() { return mt; } /** * @brief Permits access to the moversight message transfer. * @return The current message transfer instance. */ const MessageTransfer & Dispatcher::getMessageTransfer() const { return mt; } /** * @brief Permits access to the moversight causal transfer service. * @return The current causal transfer service instance. */ CausalTransfer & Dispatcher::getCausalTransfer() { return ct; } /** * @brief Permits access to the moversight causal transfer service. * @return The current causal transfer service instance. */ const CausalTransfer & Dispatcher::getCausalTransfer() const { return ct; } /** * @brief Permits access to the moversight stream transfer service. * @return The current stream transfer service instance. */ StreamTransfer & Dispatcher::getStreamTransfer() { return st; } /** * @brief Permits access to the moversight stream transfer service. * @return The current stream transfer service instance. */ const StreamTransfer & Dispatcher::getStreamTransfer() const { return st; } /** * @brief Permits access to the moversight unicast transfer service. * @return The current unciast transfer service instance. */ UnicastTransfer & Dispatcher::getUnicastTransfer() { return ut; } /** * @brief Permits access to the moversight unicast transfer service. * @return The current uncast transfer service instance. */ const UnicastTransfer & Dispatcher::getUnicastTransfer() const { return ut; } /** * @brief Permits access to the moversight failure detector. * @return The current failure detector instance. */ FailureDetector & Dispatcher::getFailureDetector() { return fd; } /** * @brief Permits access to the moversight failure detector. * @return The current failure detector instance. */ const FailureDetector & Dispatcher::getFailureDetector() const { return fd; } /** * @brief Permits access to the moversight network failure detector. * @return The current network failure detector instance. */ NetworkFailureDetector & Dispatcher::getNetworkFailureDetector() { return fd.getNetworkFailureDetector(); } /** * @brief Permits access to the moversight network failure detector. * @return The current network failure detector instance. */ const NetworkFailureDetector & Dispatcher::getNetworkFailureDetector() const { return fd.getNetworkFailureDetector(); } /** * @brief Permits access to the moversight time service. * @return The current time service. */ TimeService & Dispatcher::getTimeService() { return ts; } /** * @brief Permits access to the moversight time service. * @return The current time service. */ const TimeService & Dispatcher::getTimeService() const { return ts; } /** * @brief Permits access to the moversight merge service. * @return The current merge service. */ MergeService & Dispatcher::getMergeService() { return merge; } /** * @brief Permits access to the moversight merge service. * @return The current merge service. */ const MergeService & Dispatcher::getMergeService() const { return merge; } /** * @brief Permits access to the moversight split service. * @return The current split service instance. */ SplitService & Dispatcher::getSplitService() { return split; } /** * @brief Permits access to the moversight split service. * @return The current split service instance. */ const SplitService & Dispatcher::getSplitService() const { return split; } /** * @brief Permits access to the moversight mobility support service. * @return The current mobility support service instance. */ MobilitySupport & Dispatcher::getMobilitySupport() { return mob; } /** * @brief Permits access to the moversight mobility support service. * @return The current mobility support service instance. */ const MobilitySupport & Dispatcher::getMobilitySupport() const { return mob; } /** * @brief Permits access to the local peer state. * @return The state of the local peer. */ const State & Dispatcher::getLocalState() const { return getMembershipService().getLocalState(); } /** * @brief Permits access to the local peer state. * @return The state of the local peer. */ const SubState & Dispatcher::getLocalSubState() const { return getMembershipService().getLocalPeer().getSubState(); } /** * @brief Permits access to the local peer state operation. * @return The state operation of the local peer. */ const StateOperation & Dispatcher::getLocalStateOperation() const { return getMembershipService().getLocalPeer().getStateOperation(); } // ----------------------------------------------------------------- // Event service interface // ----------------------------------------------------------------- /** * @brief Signal the object . * @param o Type of the event * @param recipient (optional) Mark this object as to be delivered only to * * This will forward to the event service. */ void Dispatcher::signal(DeliverableObject* o, ObjectListener* recipient) { es.signal(o, recipient); } /** * @brief Unsubscribe all subscriptions at the event service for the * given object listener. * @param ol The object listener to unsubscribe. */ void Dispatcher::unsubscribeAll(ObjectListener * ol) { es.unsubscribeAll(ol); } /** * @brief Handle an incoming GroupClosedEvent. * @param e The event. */ void Dispatcher::handleEvent(const GroupClosedEvent & e) { finalise(); initialise(); } /** * @brief Handle an incoming FlushDoneEvent. * @param e The event. */ void Dispatcher::handleEvent(const FlushDoneEvent & e) { // if (getLocalSubState() == FLUSHING) { // handleSavedMessages(); // } } /** * @brief Signals the loss of the network connection. At ubeeme, the signal is emitted by the ubeeme mobility manager. * If Moversight runs without the base ubeeme framework, the signal receiver has be connected to the local network manager of thrown elsewhere. * @see connectionReEstablished */ void Dispatcher::signalConnectionLost() { signal(new ConnectionLostEvent()); } /** * @brief Signals that a network connection is re-established after a connection lost. At ubeeme, the signal is emitted by the ubeeme mobility manager. * If Moversight runs without the base ubeeme framework, the signal receiver has be connected to the local network manager of thrown elsewhere. * @see connectionLost */ void Dispatcher::signalConnectionReEstablished() { signal(new ConnectionReEstablishedEvent()); } /** * @brief Returns the peer address of the peer, identified by the given PeerID. * @param pId The ID of the peer to retrieve its local address. * @throw PeerNotFoundException Is the desired peer not member of the group. * @return The desired address, if the peer found. */ TransportAddress Dispatcher::getLocalAddressFromPeer(PeerID pId) { return ms.getPeer(pId).getLocalAddress(); } /** * @brief Returns the user selected peer placing strategy type. * @see PeerPlacingStrategy.h * @return The selected strategy type. */ const PeerPlacingStrategyType & Dispatcher::getPeerPlacingStrategyType() const { return module.getPeerPlacingStrategyType(); } /** * @brief Setups the group from a given roster. * * This method re-initialise moversight and installs a dedicated view, according the given roster. * Some minor plausibility will be run before, but note: In general the view is installed without any warranty of correctness or synchrony. * These properties have to be assured by the calling user. * @param roster Describes the group to setup. * @param localPeerID The peer ID of the local peer to setup. * @note This method is only for debug and testing purposes. * @throws LogicException Thrown, if the given parameter not setup properly. */ void Dispatcher::setupGroupFromRoster(Roster & roster, PeerID localPeerID) { //setup all modules DEBUG("setupGroupFromRoster - re-initialise moversight"); initialise(); //setup the group ms.setupGroupFromRoster(roster, localPeerID); } /** * @brief The method sets the standard message validator as active validator. */ void Dispatcher::setStandardMessageValidator() { //setMessageValidator(STANDARD_VALIDATOR); setMessageValidator(NVB_VALIDATOR); } /** * @brief Sets the message validator to the given type. A parameter * exception is thrown when the given type is not supported or unknown. * @param type The type of the message validator to set. */ void Dispatcher::setMessageValidator(MessageValidatorType type) { switch (type) { case STANDARD_VALIDATOR: { if (messageValidator != NULL) { delete messageValidator; }// end if messageValidator = new StandardValidator(*this); break; } case SEMANTIC_SPLIT_VALIDATOR: { if (messageValidator != NULL) { delete messageValidator; }// end if messageValidator = new SemanticSplitValidator(*this); break; } case NVB_VALIDATOR: { if (messageValidator != NULL) { delete messageValidator; }// end if messageValidator = new NVBValidator(*this); break; } default: { DEBUG("setMessageValidator - the given type parameter value " << type << " is not supported by the method"); throw ParameterException("setMessageValidator - the given type parameter value is not supported by the method"); } }//End switch } /** * @brief This method permits access to the currently used message validator. */ const MessageValidator * Dispatcher::getMessageValidator() const { return messageValidator; } /** * @brief Returns the number of peers within the group. * @return The size of the group. */ size_t Dispatcher::getGroupSize() const { return ms.getNumberOfPeers(); } /** * @brief Permits access to the maintenance role service. * @return A instance of the maintenance role service. */ MaintenanceRoleService & Dispatcher::getMaintenanceRoleService() { return mrs; } /** * @brief Permits access to the maintenance role service. * @return A instance of the maintenance role service. */ const MaintenanceRoleService & Dispatcher::getMaintenanceRoleService() const { return mrs; } /** * @brief method returns a const reference of the PeerPlacingStrategyMetricType * @return const reference of the PeerPlacingStrategyMetricType */ const PeerPlacingStrategyMetricType & Dispatcher::getPeerPlacingStrategyMetricType() const { return module.getPeerPlacingStrategyMetricType(); } /** * @brief method returns a const reference of the MaintanceMomentMetricType * @return const reference of the MaintanceMomentMetricType */ const MaintanceMomentMetricType & Dispatcher::getMaintanceMomentMetricType() const { return module.getMaintanceMomentMetricType(); } /** * @brief method returns a const reference of the ResourceValueDistributor * @return const reference of the ResourceValueDistributor */ ResourceValueDistributor & Dispatcher::getResourceValueDistributor() { return rvd; } /** * @brief method returns a const reference of the ResourceValueDistributor * @return const reference of the ResourceValueDistributor */ const ResourceValueDistributor & Dispatcher::getResourceValueDistributor() const { return rvd; } /** * @brief method returns a const reference of the NextViewBuffer * @return const reference of the NextViewBuffer */ NextViewBuffer & Dispatcher::getNextViewBuffer() { return nvb; } /** * @brief method returns a const reference of the NextViewBuffer * @return const reference of the NextViewBufferr */ const NextViewBuffer & Dispatcher::getNextViewBuffer() const { return nvb; } /** * @brief Sets the local peer resources object. * @param pres The peer resources object to set. */ void Dispatcher::setLocalPeerResources(const PeerResources & pres) { ms.setLocalPeerResources(pres); } /** * @brief Permits access to the local peer resources object. * @return The local peer resources object. */ const PeerResources & Dispatcher::getLocalPeerResources() const { return ms.getLocalPeerResources(); } } }