//////////////////////////////////////////////////////////////////////////////////// /// /// \brief Processes message received by the Service. If not supported, then /// message is passed to inheriting services depending on what /// type of control has been established for the component. /// /// This Service supports AccessControl related messages only. /// /// \param[in] message Message data to process. /// //////////////////////////////////////////////////////////////////////////////////// void AccessControl::Receive(const Message* message) { if(AcceptCommandMessage(message) == false) { return; } if(mControllerID == message->GetSourceID()) { mControllerUpdateTime.SetCurrentTime(); } switch(message->GetMessageCode()) { case CONFIRM_CONTROL: { const ConfirmControl* command = dynamic_cast<const ConfirmControl*>(message); if(command == NULL) return; if(command->GetResponseCode() == ConfirmControl::ControlAccepted) { bool firstTime = true; // Lock data. mControlMutex.Lock(); // See if we already had control, and if not, then // we re-acquired control of this component and must // signal via callbacks, etc. of this event. Address::Set::iterator controlledComponent = mControlledComponents.find(message->GetSourceID()); if(controlledComponent != mControlledComponents.end()) { // If we get here, we have been trying to control this // component. Check the control status flag. std::map<Address, bool>::iterator flag = mControlFlags.find(message->GetSourceID()); if(flag->second == true) { // We already had control, nothing new here. // So don't trigger events. firstTime = false; } } mControlledComponents.insert(message->GetSourceID()); mControlConfirmTimes[message->GetSourceID()].SetCurrentTime(); mControlFlags[message->GetSourceID()] = true; // Unlock data. mControlMutex.Unlock(); if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); if(firstTime) { std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Acquired Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } else { std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Maintained Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } } // Trigger callbacks if needed. if(firstTime) { Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlChild->ProcessAcquisitionOfControl(message->GetSourceID()); } } Mutex::ScopedLock cbLock(&mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessAcquisitionfControl(message->GetSourceID()); } } } else { Address::Set::iterator component; // Lock data. mControlMutex.Lock(); component = mControlledComponents.find(message->GetSourceID()); if(component != mControlledComponents.end()) { std::map<Address, bool>::iterator flag; flag = mMaintainFlags.find(message->GetSourceID()); if(flag != mMaintainFlags.end()) { // If we didn't get control, and we are not // trying to maintain control, remove the component // from our lists. If we don't have high enough authority // then don't bother trying to re-acquire control. if(flag->second == false || command->GetMessageCode() == ConfirmControl::InsufficientAuthority) { EraseComponentControlInfo(message->GetSourceID()); } else // Update control status { mControlFlags[message->GetSourceID()] = false; } } // Delete junk data. else { EraseComponentControlInfo(message->GetSourceID()); } } // Unlock data. mControlMutex.Unlock(); } } break; case QUERY_AUTHORITY: { if(mShutdownServiceFlag) { break; } Mutex::ScopedLock lock(&mControlMutex); ReportAuthority report(message->GetSourceID(), GetComponentID()); report.SetAuthorityCode(mAuthorityCode); Send(&report); } break; case QUERY_CONTROL: { Mutex::ScopedLock lock(&mControlMutex); ReportControl report(message->GetSourceID(), GetComponentID()); report.SetAuthorityCode(mControllerAuthorityCode); report.SetControllingComponent(mControllerID); Send(&report); } break; case QUERY_TIMEOUT: { Mutex::ScopedLock lock(&mControlMutex); ReportTimeout report(message->GetSourceID(), GetComponentID()); report.SetTimeoutSeconds(mTimeoutPeriod); Send(&report); } break; case REJECT_CONTROL: { const RejectControl* command = dynamic_cast<const RejectControl*>(message); if(mShutdownServiceFlag || command == NULL) return; Mutex::ScopedLock lock(&mControlMutex); Address::Set::iterator component; component = mControlledComponents.find(message->GetSourceID()); if(component != mControlledComponents.end()) { std::map<Address, bool>::iterator flag; flag = mMaintainFlags.find(message->GetSourceID()); if(flag != mMaintainFlags.end()) { // If we lost control, and we are not // trying to maintain control, remove the component // from our lists. if(flag->second == false) { mMaintainFlags.erase(flag); mControlFlags.erase(mControlFlags.find(message->GetSourceID())); mControlConfirmTimes.erase(mControlConfirmTimes.find(message->GetSourceID())); mControlledComponents.erase(component); } else // Update control status { mControlFlags[message->GetSourceID()] = false; } // Generate events and callbacks. Mutex::ScopedLock clock(&mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessLossOfControl(message->GetSourceID()); } } // Delete junk data. else { if(mControlFlags.find(*component) != mControlFlags.end()) { mControlFlags.erase(*component); } mControlledComponents.erase(*component); } } if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Lost Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } } break; case RELEASE_CONTROL: { const ReleaseControl* command = dynamic_cast<const ReleaseControl*>(message); if(mShutdownServiceFlag || command == NULL) return; Mutex::ScopedLock lock(&mControlMutex); if(command->GetSourceID() == mControllerID) { RejectControl response(mControllerID, GetComponentID()); bool controlReleased = true; Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { if(controlChild->ReleaseControl()) { controlReleased; } } } if(controlReleased) { response.SetResponseCode(RejectControl::ControlReleased); Send(&response); mControllerID = Address(); mControllerAuthorityCode = 0; mControllerUpdateTime.Clear(); mControllerCheckTime.Clear(); if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Released from " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } // Generate events and callbacks. Mutex::ScopedLock clock(&mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessReleaseOfControl(message->GetSourceID()); } SignalEvent(REPORT_CONTROL); } else { response.SetResponseCode(RejectControl::NotAvailable); Send(&response); } } } break; case REPORT_AUTHORITY: { const JAUS::ReportAuthority* report = dynamic_cast<const JAUS::ReportAuthority*>(message); if(report) { // Update Discovery Contents. try { Discovery* discovery = GetComponent()->DiscoveryService(); if(discovery) { discovery->GetSubsystem(report->GetSourceID().mSubsystem)->GetComponent(report->GetSourceID())->mAuthorityLevel = (int)report->GetAuthorityCode(); if( discovery->GetVehicle(report->GetSourceID().mSubsystem).IsValid() && discovery->GetVehicle(report->GetSourceID().mSubsystem)->mAuthority < (int)report->GetAuthorityCode()) { discovery->GetVehicle(report->GetSourceID().mSubsystem)->mAuthority = (int)report->GetAuthorityCode(); } } } catch(Exception& e) { e.Print(); } } } break; case REPORT_CONTROL: // Not used. break; case REPORT_TIMEOUT: { const ReportTimeout* report = dynamic_cast<const ReportTimeout*>(message); if(report == NULL) return; Mutex::ScopedLock lock(&mControlMutex); mTimeoutPeriods[message->GetSourceID()] = report->GetTimeoutSeconds(); if(mTimeoutPeriods[message->GetSourceID()] == 0) { // We always want to check for control. mTimeoutPeriods[message->GetSourceID()] = 2; } } break; case REQUEST_CONTROL: { const RequestControl* command = dynamic_cast<const RequestControl*>(message); if(mShutdownServiceFlag || command == NULL) return; ConfirmControl response(message->GetSourceID(), GetComponentID()); Mutex::ScopedLock lock(&mControlMutex); // If they have minimum authority and we are // not under control or component has greater authority than // the current controller, accept. if(mControllableFlag && command->GetAuthorityCode() >= mAuthorityCode && (mControllerID == command->GetSourceID() || mControllerID.IsValid() == false || command->GetAuthorityCode() > mControllerAuthorityCode)) { bool controlAccepted = true; Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlAccepted = controlChild->RequestControl(); if(controlAccepted) { break; } } } // This check is needed in case any child // service (Management) is in an Emergency state // and cannot transition. if(controlAccepted == false) { response.SetResponseCode(ConfirmControl::NotAvailable); } else { response.SetResponseCode(ConfirmControl::ControlAccepted); if(mControllerID != command->GetSourceID() && mControllerID.IsValid()) { // Notify controller that they have lost control. RejectControl reject(mControllerID, GetComponentID()); reject.SetResponseCode(RejectControl::ControlReleased); Send(&reject); } mControllerID = message->GetSourceID(); mControllerAuthorityCode = command->GetAuthorityCode(); mControllerCheckTime.SetCurrentTime(); mControllerUpdateTime.SetCurrentTime(); if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Granted to " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } } } else { if(mControllableFlag == false) { response.SetResponseCode(ConfirmControl::NotAvailable); } else { response.SetResponseCode(ConfirmControl::InsufficientAuthority); } if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Rejected from " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } } Send(&response); } break; case SET_AUTHORITY: { const SetAuthority* command = dynamic_cast<const SetAuthority*>(message); if(command == NULL) return; Mutex::ScopedLock lock(&mControlMutex); mAuthorityCode = command->GetAuthorityCode(); SignalEvent(REPORT_AUTHORITY); // Update Discovery Contents. try { Discovery* discovery = GetComponent()->DiscoveryService(); if(discovery) { discovery->GetSubsystem(command->GetDestinationID().mSubsystem)->GetComponent(command->GetDestinationID())->mAuthorityLevel = (int)command->GetAuthorityCode(); if(discovery->GetVehicle(command->GetDestinationID().mSubsystem)->mAuthority < (int)command->GetAuthorityCode()) { discovery->GetVehicle(command->GetDestinationID().mSubsystem)->mAuthority = (int)command->GetAuthorityCode(); } } } catch(Exception& e) { e.Print(); } } break; default: break; }; }
//////////////////////////////////////////////////////////////////////////////////// /// /// \brief Method to request exclusive control of a component. /// /// \param[in] id The ID of the component to request control of. /// \param[in] reacquire If true, and control is lost for any reason, then /// we will try to re-acquire control. If false, and /// control is lost, we forget about the component. /// \param[in] waitTimeMs How long to wait for a response in milliseconds /// from the component being requested. /// /// \return True if control is established, otherwise false. /// //////////////////////////////////////////////////////////////////////////////////// bool AccessControl::RequestComponentControl(const Address& id, const bool reacquire, const unsigned int waitTimeMs) { RequestControl request(id, GetComponentID()); request.SetAuthorityCode(mAuthorityCode); Message::List responses; ConfirmControl confirm; RejectControl reject; responses.push_back(&confirm); responses.push_back(&reject); if(Send(&request, responses, waitTimeMs) && responses.size() == 1) { // See if control was acquired. if(responses.front()->GetMessageCode() == CONFIRM_CONTROL) { if(confirm.GetResponseCode() == ConfirmControl::ControlAccepted) { // Don't use a scoped lock because we // dont' want the callback mutex run within it. mControlMutex.Lock(); mControlledComponents.insert(id); mMaintainFlags[id] = reacquire; mControlFlags[id] = true; // Set the time we verified we have control. mControlCheckTimes[id].SetCurrentTime(); // Set the time we confirmed control. mControlConfirmTimes[id].SetCurrentTime(); // Set a default value for timeout. mTimeoutPeriods[id] = mTimeoutPeriod; // Unlock mControlMutex.Unlock(); // Query the timout period for the component. QueryTimeout query(id, GetComponentID()); Send(&query); // Trigger acquisition of control events! Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlChild->ProcessAcquisitionOfControl(id); } } Mutex::ScopedLock cbLock(&mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessAcquisitionfControl(id); } return true; } } else { return false; } } return false; }
//////////////////////////////////////////////////////////////////////////////////// /// /// \brief Processes message received by the Service. If not supported, then /// message is passed to inheriting services depending on what /// type of control has been established for the component. /// /// This Service supports AccessControl related messages only. /// /// \param[in] message Message data to process. /// //////////////////////////////////////////////////////////////////////////////////// void AccessControl::Receive(const Message* message) { if(AcceptCommandMessage(message) == false) { return; } if(mControllerID == message->GetSourceID()) { mControllerUpdateTime.SetCurrentTime(); } switch(message->GetMessageCode()) { case CONFIRM_CONTROL: { const ConfirmControl* command = static_cast<const ConfirmControl*>(message); if(command == NULL) return; if(command->GetResponseCode() == ConfirmControl::ControlAccepted) { bool firstTime = true; // Lock data. { WriteLock wLock(mControlMutex); // See if we already had control, and if not, then // we re-acquired control of this component and must // signal via callbacks, etc. of this event. Address::Set::iterator controlledComponent = mControlledComponents.find(message->GetSourceID()); if(controlledComponent != mControlledComponents.end()) { // If we get here, we have been trying to control this // component. Check the control status flag. std::map<Address, bool>::iterator flag = mControlFlags.find(message->GetSourceID()); if(flag->second == true) { // We already had control, nothing new here. // So don't trigger events. firstTime = false; } } mControlledComponents.insert(message->GetSourceID()); mControlConfirmTimes[message->GetSourceID()].SetCurrentTime(); mControlFlags[message->GetSourceID()] = true; } if(DebugMessagesEnabled()) { if(firstTime) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Acquired Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } else { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Maintained Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } } // Trigger callbacks if needed. if(firstTime) { Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlChild->ProcessAcquisitionOfControl(message->GetSourceID()); } } { ReadLock cbrLock(mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessAcquisitionfControl(message->GetSourceID()); } } } } else { Address::Set::iterator component; // Lock data. WriteLock wLock(mControlMutex); component = mControlledComponents.find(message->GetSourceID()); if(component != mControlledComponents.end()) { std::map<Address, bool>::iterator flag; flag = mMaintainFlags.find(message->GetSourceID()); if(flag != mMaintainFlags.end()) { // If we didn't get control, and we are not // trying to maintain control, remove the component // from our lists. If we don't have high enough authority // then don't bother trying to re-acquire control. if(flag->second == false || command->GetMessageCode() == ConfirmControl::InsufficientAuthority) { EraseComponentControlInfo(message->GetSourceID()); } else // Update control status { mControlFlags[message->GetSourceID()] = false; } } // Delete junk data. else { EraseComponentControlInfo(message->GetSourceID()); } } } } break; case QUERY_AUTHORITY: { if(mShutdownServiceFlag) { break; } ReportAuthority report(message->GetSourceID(), GetComponentID()); { ReadLock rLock(mControlMutex); report.SetAuthorityCode(mAuthorityCode); } Send(&report); } break; case QUERY_CONTROL: { ReportControl report(message->GetSourceID(), GetComponentID()); { ReadLock rLock(mControlMutex); report.SetAuthorityCode(mAuthorityCode); report.SetControllingComponent(mControllerID); } Send(&report); } break; case QUERY_TIMEOUT: { ReportTimeout report(message->GetSourceID(), GetComponentID()); { ReadLock rLock(mControlMutex); report.SetTimeoutSeconds(mTimeoutPeriod); } Send(&report); } break; case REJECT_CONTROL: { const RejectControl* command = static_cast<const RejectControl*>(message); if(mShutdownServiceFlag || command == NULL) return; bool signalCallbacks = false; { WriteLock wLock(mControlMutex); // Update state of controlled components. Address::Set::iterator component; component = mControlledComponents.find(message->GetSourceID()); if(component != mControlledComponents.end()) { std::map<Address, bool>::iterator flag; flag = mMaintainFlags.find(message->GetSourceID()); if(flag != mMaintainFlags.end()) { // If we lost control, and we are not // trying to maintain control, remove the component // from our lists. if(flag->second == false) { mMaintainFlags.erase(flag); mControlFlags.erase(mControlFlags.find(message->GetSourceID())); mControlConfirmTimes.erase(mControlConfirmTimes.find(message->GetSourceID())); mControlledComponents.erase(component); } else // Update control status { mControlFlags[message->GetSourceID()] = false; } signalCallbacks = true; } // Delete junk data. else { if(mControlFlags.find(*component) != mControlFlags.end()) { mControlFlags.erase(*component); } mControlledComponents.erase(*component); } } } if(signalCallbacks) { // Generate events and callbacks. ReadLock cbrLock(mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessLossOfControl(message->GetSourceID()); } } if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Lost Control of " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } } break; case RELEASE_CONTROL: { const ReleaseControl* command = static_cast<const ReleaseControl*>(message); if(mShutdownServiceFlag || command == NULL) return; if(command->GetSourceID() == mControllerID) { RejectControl response(mControllerID, GetComponentID()); bool controlReleased = true; Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { if(controlChild->ReleaseControl()) { controlReleased; } } } if(controlReleased) { response.SetResponseCode(RejectControl::ControlReleased); Send(&response); // Update data members of who was in control to nobody! { WriteLock wLock(mControlMutex); mControllerID = Address(); mControllerAuthorityCode = 0; mControllerUpdateTime.Clear(); mControllerCheckTime.Clear(); } if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Released from " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } // Signal a change in control event SignalEvent(REPORT_CONTROL); // Notify children of control release. { // Generate events and callbacks. ReadLock cbrLock(mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessReleaseOfControl(message->GetSourceID()); } } } else { response.SetResponseCode(RejectControl::NotAvailable); Send(&response); } } } break; case REPORT_AUTHORITY: { const JAUS::ReportAuthority* report = static_cast<const JAUS::ReportAuthority*>(message); if(report) { // Used by Discovery service to keep track of information // about components on the netework } } break; case REPORT_CONTROL: // Not used. break; case REPORT_TIMEOUT: { const ReportTimeout* report = static_cast<const ReportTimeout*>(message); if(report == NULL) return; WriteLock wLock(mControlMutex); mTimeoutPeriods[message->GetSourceID()] = report->GetTimeoutSeconds(); if(mTimeoutPeriods[message->GetSourceID()] == 0) { // We always want to check for control. mTimeoutPeriods[message->GetSourceID()] = 2; } } break; case REQUEST_CONTROL: { const RequestControl* command = static_cast<const RequestControl*>(message); if(mShutdownServiceFlag || command == NULL) return; ConfirmControl response(message->GetSourceID(), GetComponentID()); #ifdef JAUS_USE_UPGRADE_LOCKS UpgradeLock upLock(mControlMutex); #else WriteLock wLock(mControlMutex); #endif // If they have minimum authority and we are // not under control or component has greater authority than // the current controller, accept. if(mControllableFlag && command->GetAuthorityCode() >= mAuthorityCode && (mControllerID == command->GetSourceID() || mControllerID.IsValid() == false || command->GetAuthorityCode() > mControllerAuthorityCode)) { bool controlAccepted = true; Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlAccepted = controlChild->RequestControl(); if(controlAccepted) { break; } } } // This check is needed in case any child // service (Management) is in an Emergency state // and cannot transition. if(controlAccepted == false) { response.SetResponseCode(ConfirmControl::NotAvailable); } else { response.SetResponseCode(ConfirmControl::ControlAccepted); if(mControllerID != command->GetSourceID() && mControllerID.IsValid()) { // Notify controller that they have lost control. RejectControl reject(mControllerID, GetComponentID()); reject.SetResponseCode(RejectControl::ControlReleased); Send(&reject); } { #ifdef JAUS_USE_UPGRADE_LOCKS UpgradeToUniqueLock uniqueLock(upLock); #endif mControllerID = message->GetSourceID(); mControllerAuthorityCode = command->GetAuthorityCode(); mControllerCheckTime.SetCurrentTime(); mControllerUpdateTime.SetCurrentTime(); } if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Granted to " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } } } else { if(mControllableFlag == false) { response.SetResponseCode(ConfirmControl::NotAvailable); } else { response.SetResponseCode(ConfirmControl::InsufficientAuthority); } if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Rejected from " << message->GetSourceID().ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } } Send(&response); } break; case SET_AUTHORITY: { const SetAuthority* command = static_cast<const SetAuthority*>(message); if(command == NULL) return; SetAuthorityCode(command->GetAuthorityCode()); } break; default: break; }; }
//////////////////////////////////////////////////////////////////////////////////// /// /// \brief Method called periodically by external classes and is used to /// verify control of components. /// /// \param[in] timeSinceLastCheckMs Number of milliseconds since the last time /// this method was called. /// //////////////////////////////////////////////////////////////////////////////////// void AccessControl::CheckServiceStatus(const unsigned int timeSinceLastCheckMs) { RequestControl request; mControlMutex.Lock(); request.SetSourceID(GetComponentID()); request.SetAuthorityCode(mAuthorityCode); Address::Set::iterator component; Time currentTime; currentTime.SetCurrentTime(); for(component = mControlledComponents.begin(); component != mControlledComponents.end(); component++) { // If we are releasing control, do not check. if(mToReleaseControl.find(*component) != mToReleaseControl.end()) { continue; } // If we have not checked within timeout - .x seconds, then re-acquire control to // maintain constant control of component. double thresh = mTimeoutPeriods[*component]*mTimeoutThreshold/100.0; double checkTimeDiff = currentTime.ToSeconds() - mControlCheckTimes[*component].ToSeconds(); double timeThresh = (mTimeoutPeriods[*component] - thresh); bool checkConfirmation = true; if(mTimeoutPeriods[*component] > 0 && checkTimeDiff >= thresh) { request.SetDestinationID(*component); if(Send(&request)) { // Update the check time. mControlCheckTimes[*component].SetCurrentTime(); checkConfirmation = false; } } double confirmTimeDiff = currentTime.ToSeconds() - mControlConfirmTimes[*component].ToSeconds(); timeThresh = (mTimeoutPeriods[*component] + thresh); // If we haven't been confirmed in this time, then we have lost control. if(checkConfirmation && confirmTimeDiff > timeThresh) { mControlFlags[*component] = false; // Generate events and callbacks. Mutex::ScopedLock clock(&mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessLossOfControl(*component); } } } mControlMutex.Unlock(); // Allow control check time to update. mControlMutex.Lock(); Address controller = mControllerID; bool timeout = false; currentTime.SetCurrentTime(); double timeSinceRequest = currentTime - mControllerCheckTime; if(mTimeoutPeriod > 0 && controller.IsValid() && timeSinceRequest >= (double)mTimeoutPeriod + mTimeoutPeriod*mTimeoutThreshold/100.0) { timeout = true; // Release control due to timeout. RejectControl reject(controller, GetComponentID()); reject.SetResponseCode(RejectControl::ControlReleased); Send(&reject); if(mDebugMessagesFlag) { Mutex::ScopedLock plock(&mDebugMessagesMutex); std::cout << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Time Out From " << controller.ToString() << " at " << Time::GetUtcTime().ToString() << "\n"; } // Clear values. mControllerID.Clear(); mControllerAuthorityCode = 0; mControllerCheckTime.Clear(); mControllerUpdateTime.Clear(); } mControlMutex.Unlock(); if(timeout) { Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessReleaseOfControl(controller); } Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlChild->ReleaseControl(); } } SignalEvent(REPORT_CONTROL); } }
//////////////////////////////////////////////////////////////////////////////////// /// /// \brief Method called periodically by external classes and is used to /// verify control of components. /// /// \param[in] timeSinceLastCheckMs Number of milliseconds since the last time /// this method was called. /// //////////////////////////////////////////////////////////////////////////////////// void AccessControl::CheckServiceStatus(const unsigned int timeSinceLastCheckMs) { RequestControl request; Address::Set lostComponents; Time currentTime; // Upgrade/Read lock { #ifdef JAUS_USE_UPGRADE_LOCKS UpgradeLock uLock(mControlMutex); #else WriteLock wLock(mControlMutex); #endif request.SetSourceID(GetComponentID()); request.SetAuthorityCode(mAuthorityCode); Address::Set::iterator component; currentTime.SetCurrentTime(); for(component = mControlledComponents.begin(); component != mControlledComponents.end(); component++) { // If we are releasing control, do not check. if(mToReleaseControl.find(*component) != mToReleaseControl.end()) { continue; } // If we have not checked within timeout - .x seconds, then re-acquire control to // maintain constant control of component. double thresh = mTimeoutPeriods[*component]*mTimeoutThreshold/100.0; double checkTimeDiff = currentTime.ToSeconds() - mControlCheckTimes[*component].ToSeconds(); double timeThresh = (mTimeoutPeriods[*component] - thresh); bool checkConfirmation = true; if(mTimeoutPeriods[*component] > 0 && checkTimeDiff >= thresh) { request.SetDestinationID(*component); if(Send(&request)) { // Update the check time. #ifdef JAUS_USE_UPGRADE_LOCKS UpgradeToUniqueLock upLock(uLock); #endif mControlCheckTimes[*component].SetCurrentTime(); checkConfirmation = false; } } double confirmTimeDiff = currentTime.ToSeconds() - mControlConfirmTimes[*component].ToSeconds(); timeThresh = (mTimeoutPeriods[*component] + thresh); // If we haven't been confirmed in this time, then we have lost control. if(checkConfirmation && confirmTimeDiff > timeThresh) { mControlFlags[*component] = false; lostComponents.insert(*component); } } } // Notify subscribers of any lost control events. { Address::Set::iterator lost; for(lost = lostComponents.begin(); lost != lostComponents.end(); lost++) { // Generate events and callbacks. ReadLock cbrLock(mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessLossOfControl(*lost); } } } Address controller; // Current controlling component. bool timeout = false; { #ifdef JAUS_USE_UPGRADE_LOCKS UpgradeLock uLock(mControlMutex); #else WriteLock wLock(mControlMutex); #endif controller = mControllerID; currentTime.SetCurrentTime(); double timeSinceRequest = currentTime - mControllerCheckTime; if(mTimeoutPeriod > 0 && controller.IsValid() && timeSinceRequest >= (double)mTimeoutPeriod + mTimeoutPeriod*mTimeoutThreshold/100.0) { timeout = true; // Release control due to timeout. RejectControl reject(controller, GetComponentID()); reject.SetResponseCode(RejectControl::ControlReleased); Send(&reject); if(DebugMessagesEnabled()) { std::stringstream dMessage; dMessage << "[" << GetServiceID().ToString() << "-" << mComponentID.ToString() << "] - Control Time from " << controller.ToString() << " at " << Time::GetUtcTime().ToString(); PrintDebugMessage(dMessage.str()); } { #ifdef JAUS_USE_UPGRADE_LOCKS UpgradeToUniqueLock upLock(uLock); #endif // Clear values. mControllerID.Clear(); mControllerAuthorityCode = 0; mControllerCheckTime.Clear(); mControllerUpdateTime.Clear(); } } } if(timeout) { { ReadLock cbrLock(mCallbacksMutex); Callback::Set::iterator cb; for(cb = mCallbacks.begin(); cb != mCallbacks.end(); cb++) { (*cb)->ProcessReleaseOfControl(controller); } } Service::Map children = GetChildServices(); Service::Map::iterator child; for(child = children.begin(); child != children.end(); child++) { Child* controlChild = dynamic_cast<Child *>(child->second); if(controlChild) { controlChild->ReleaseControl(); } } SignalEvent(REPORT_CONTROL); } }