Example #1
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \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);
    }
}
Example #2
0
////////////////////////////////////////////////////////////////////////////////////
///
///   \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);
    }
}