Beispiel #1
0
    /* Do not use C_TYPECHECK on qos parameter, since it might be allocated on heap! */

    kernel = v_objectKernel(p);
    c_lockWrite(&p->lock);
    result = v_participantQosSet(p->qos, qos, &cm);

    if ((result == V_RESULT_OK) && (cm != 0)) {
        builtinMsg = v_builtinCreateParticipantInfo(kernel->builtin,p);
        c_lockUnlock(&p->lock);
        v_writeBuiltinTopic(kernel, V_PARTICIPANTINFO_ID, builtinMsg);
        c_free(builtinMsg);
    } else {
        c_lockUnlock(&p->lock);
    }

    return result;
}

v_leaseManager
v_participantGetLeaseManager(
    v_participant p)
{
    assert(C_TYPECHECK(p,v_participant));

    return c_keep(p->leaseManager);
}

#define RESEND_SECS      (0U)
#define RESEND_NANOSECS  (2000000U) /* 2 ms */
void
v_participantResendManagerMain(
    v_participant p)
{
    c_iter writerProxies;
    v_proxy wp;
    v_writer w;
    v_handleResult r;
    c_time waitTime = { RESEND_SECS, RESEND_NANOSECS };

    assert(C_TYPECHECK(p,v_participant));

    c_mutexLock(&p->resendMutex);
    while (!p->resendQuit) {

        if (c_count(p->resendWriters) == 0) {
            c_condWait(&p->resendCond, &p->resendMutex);
        } else {
            c_condTimedWait(&p->resendCond, &p->resendMutex, waitTime);
        }

        if (!p->resendQuit) {
            writerProxies = c_select(p->resendWriters, 0);
            c_mutexUnlock(&p->resendMutex);
            wp = v_proxy(c_iterTakeFirst(writerProxies));
            while (wp != NULL) {
                r = v_handleClaim(wp->source,(v_object *)&w);
                if (r == V_HANDLE_OK) {
                    assert(C_TYPECHECK(w,v_writer));
                    v_writerResend(w);
                    v_handleRelease(wp->source);
                }
                c_free(wp);
                wp = v_proxy(c_iterTakeFirst(writerProxies));
            }
            c_iterFree(writerProxies);

            c_mutexLock(&p->resendMutex);
        } /* already quiting */
    }
    c_mutexUnlock(&p->resendMutex);
}
Beispiel #2
0
v_result
v_deliveryWaitListWait (
    v_deliveryWaitList _this,
    v_duration timeout)
{
    v_result result = V_RESULT_OK;
    c_syncResult r;

    assert(C_TYPECHECK(_this,v_deliveryWaitList));

    if (_this->readerGID != NULL) {
        c_mutexLock(&_this->mutex);
        if(c_timeCompare(timeout, C_TIME_INFINITE) != C_EQ)
        {
            r = c_condTimedWait(&_this->cv,&_this->mutex,timeout);
        }
        else
        {
            r = c_condWait(&_this->cv,&_this->mutex);
        }
        c_mutexUnlock(&_this->mutex);

        switch (r) {
        case SYNC_RESULT_SUCCESS:
           result = V_RESULT_OK;
        break;
        case SYNC_RESULT_TIMEOUT:
           result = V_RESULT_TIMEOUT;
        break;
        case SYNC_RESULT_UNAVAILABLE:
        case SYNC_RESULT_BUSY:
        case SYNC_RESULT_INVALID:
        case SYNC_RESULT_FAIL:
        default:
            result = V_RESULT_PRECONDITION_NOT_MET;
        break;
        }
    }

    return result;
}
Beispiel #3
0
c_ulong
v__observerWait(
    v_observer o)
{
    os_result result = os_resultSuccess;
    c_ulong flags;

    assert(o != NULL);
    assert(C_TYPECHECK(o,v_observer));

    if (o->eventFlags == 0) {
        o->waitCount++;
        result = c_condWait(&o->cv,&o->mutex);
        o->waitCount--;
    }
    flags = o->eventFlags;
    /* Reset events but remember destruction event.
     * To avoid any further use of this observer in case of destruction.
     */
    o->eventFlags &= V_EVENT_OBJECT_DESTROYED;

    return flags;
}
Beispiel #4
0
v_networkReaderWaitResult
v_networkQueueWait(
    v_networkQueue queue)
{
    v_networkReaderWaitResult result = V_WAITRESULT_NONE;
    c_syncResult syncResult;
    c_bool hasChanged;
    c_time interval;
    c_time minSleepTime = MIN_SLEEPTIME;
    c_equality eq;
    
    c_mutexLock(&queue->mutex);

    /* First update nextWakeup */
    v_networkQueueUpdateNextWakeup(queue, &hasChanged);
    if (hasChanged) {
        result |= V_WAITRESULT_TIMEOUT;
    }
    
    /* With the new nextWakeup, check if any data is expiring */
    if ((int)v_networkQueueHasExpiringData(queue)) {
        result |= V_WAITRESULT_MSGWAITING;
    }
    
    /* Also check if no request has been issued lately */
    if ((int)queue->triggered) {
        result |= V_WAITRESULT_TRIGGERED;
    }
    
    /* Now go to sleep if needed */
    while (result == V_WAITRESULT_NONE) {
        if (queue->periodic) {
            c_time org =  v_timeGet();
            interval = c_timeSub(queue->nextWakeup,org);
            eq = c_timeCompare(minSleepTime, interval);
            if (eq == C_LT) {
                queue->threadWaiting = TRUE;
                syncResult = c_condTimedWait(&queue->cv,
                                             &queue->mutex,
                                             interval);
                queue->threadWaiting = FALSE;
            } else {
                syncResult = SYNC_RESULT_TIMEOUT;
            }
            if (syncResult == SYNC_RESULT_TIMEOUT) {
                result |= V_WAITRESULT_TIMEOUT;
                queue->nextWakeup = c_timeAdd(queue->nextWakeup,
                                              queue->resolution);
            }
        } else {
            /* Wait infinitely if the queue is not periodic */
            queue->threadWaiting = TRUE;
            syncResult = c_condWait(&queue->cv, &queue->mutex);
            queue->threadWaiting = FALSE;
        }
        /* Test current status of queue */
        if ((int)queue->triggered) {
            result |= V_WAITRESULT_TRIGGERED;
        }
        if (v_networkQueueHasExpiringData(queue)) {
            result |= V_WAITRESULT_MSGWAITING;
        }
    }
    
    queue->triggered = 0;
    
    c_mutexUnlock(&queue->mutex);
    
    return result;
}    
Beispiel #5
0
v_historyResult
v_readerWaitForHistoricalDataWithCondition(
    v_reader _this,
    c_char* filter,
    c_char* params[],
    c_ulong paramsLength,
    c_time minSourceTime,
    c_time maxSourceTime,
    struct v_resourcePolicy *resourceLimits,
    c_time timeout)
{
    c_iter entries;
    c_object e;
    v_historyResult result;
    v_historicalDataRequest request;
    c_bool doRequest, doWait;
    struct historicalWaitArg arg;
    C_STRUCT(v_event) event;

    arg._expire_time = c_timeAdd(v_timeGet(), timeout);
    arg._status = TRUE;

    request = v_historicalDataRequestNew(v_objectKernel(_this), filter, params,
                paramsLength, minSourceTime, maxSourceTime, resourceLimits);

    if(request){
        V_READER_LOCK(_this);

        if(_this->historicalDataRequest) {
            /* Historical data request already in progress or complete, check
             * whether request is equal to the original one.
             */
            doRequest = FALSE;

            if(v_historicalDataRequestEquals(request, _this->historicalDataRequest)){
                /* Request is equal to original request*/
                result = V_HISTORY_RESULT_OK;

                if(_this->historicalDataComplete){
                    /* Request has already been fulfilled. Consider this call
                     * a no-operation.
                     */
                    doWait = FALSE;
                } else {
                    /* Request is still in progress, wait for data to arrive*/
                    doWait = TRUE;
                }
            } else {
                /* The requested parameters are not equal to the originally
                 * requested set. Return a precondition not met.
                 */
                doWait = FALSE;
                result = V_HISTORY_RESULT_PRE_NOT_MET;
            }
            c_free(request);
        } else {
            /* No active request, so validate it now.*/
            if(v_historicalDataRequestIsValid(request, _this)){
                /* This request is valid, so request data.*/
                doRequest = TRUE;
                doWait    = TRUE;
                result    = V_HISTORY_RESULT_OK;
                _this->historicalDataRequest = request;
            } else {
                /* Request is not valid, so return bad parameter.*/
                doRequest = FALSE;
                doWait    = FALSE;
                result    = V_HISTORY_RESULT_BAD_PARAM;
                c_free(request);
            }
        }
        V_READER_UNLOCK(_this);
    } else {
        doRequest = FALSE;
        doWait    = FALSE;
        result    = V_HISTORY_RESULT_ERROR;
    }

    if(doWait){
        v_readerEntrySetLock(_this);
        entries = c_select(_this->entrySet.entries, 0);
        v_readerEntrySetUnlock(_this);

        if(doRequest){
            /* Historical data must be requested, since this is the first time
             * the operation is called and the request is valid.
             */
            if (_this->qos->durability.kind == V_DURABILITY_VOLATILE) {
                /* If reader is volatile, the historical data from the
                 * group(s) has/have not been retrieved yet, so do it now.
                 */
                e = c_iterTakeFirst(entries);
                while (e != NULL) {
                    getHistoricalData(e, _this->historicalDataRequest);
                    c_free(e);
                    e = c_iterTakeFirst(entries);
                }
                c_iterFree(entries);
            }
            event.kind = V_EVENT_HISTORY_REQUEST;
            event.source = v_publicHandle(v_public(_this));
            event.userData = _this->historicalDataRequest;
            v_observableNotify(v_observable(v_objectKernel(_this)),&event);
        }

        V_READER_LOCK(_this);

        if(!_this->historicalDataComplete){
            if (c_timeCompare(timeout, C_TIME_INFINITE) != C_EQ) {
                if (c_condTimedWait(&_this->historicalDataCondition,
                                    &V_READER_GET_LOCK(_this),
                                    timeout) != SYNC_RESULT_SUCCESS)
                {
                    result = V_HISTORY_RESULT_TIMEOUT;
                }
            } else if (c_condWait(&_this->historicalDataCondition,
                            &V_READER_GET_LOCK(_this)) != SYNC_RESULT_SUCCESS)
            {
                    result = V_HISTORY_RESULT_TIMEOUT;
            }
            assert( (result == V_HISTORY_RESULT_OK) ==
                     _this->historicalDataComplete);
        }
        V_READER_UNLOCK(_this);

    }
    return result;
}
Beispiel #6
0
/**************************************************************
 * Main / notify fnctions
 **************************************************************/
void
v_leaseManagerMain(
    v_leaseManager _this)
{
    v_leaseAction leaseAction;
    c_time waitTime = C_TIME_ZERO;
    c_time expTime;
    v_duration duration;
    struct collectExpiredArg arg;
    c_syncResult waitResult = SYNC_RESULT_SUCCESS;

    assert(_this != NULL);
    assert(C_TYPECHECK(_this, v_leaseManager));

    c_mutexLock(&_this->mutex);
    /* initialize the current time once before the loop */
    arg.now = v_timeGet();
    while (_this->quit == FALSE) {
        if (_this->firstLeaseToExpire != NULL) {
            v_leaseGetExpiryAndDuration(_this->firstLeaseToExpire->lease, &expTime, &duration);
            if (c_timeCompare(expTime, C_TIME_INFINITE) != C_EQ) {
                waitTime = c_timeSub(expTime, arg.now);
                if (c_timeCompare(waitTime, C_TIME_ZERO) == C_GT) {
                    waitResult = c_condTimedWait(&_this->cond, &_this->mutex, waitTime);
                } else {
                    /* If the duration specified with the lease is C_TIME_ZERO,
                     * it is expected that the expiryTime lies in the past, so
                     * only warn if an actual duration was specified. */
                    if(c_timeCompare(duration, C_TIME_ZERO) != C_EQ){
                        OS_REPORT(OS_WARNING, "v_leaseManager", 0,
                            "The wait time has become negative! This means "
                            "that the leaseManager could not wake up in time to "
                            "evaluate the lease expiry statusses. This could be "
                            "due to scheduling problems or clock alignment issues on "
                            "multi core machines. The lease manager will continue to "
                            "function normal after this though.");
                    }
                }
            } else {
                /* The shortest expiry time is from a lease with an infinite duration. So
                 * wait indefinately
                 */
                waitResult = c_condWait(&_this->cond, &_this->mutex);
            }
        } else {
            /* no leases registered, so wait until the first one is registered */
            waitResult = c_condWait(&_this->cond, &_this->mutex);
        }

        if (waitResult == SYNC_RESULT_FAIL)
        {
            OS_REPORT(OS_CRITICAL, "v_leaseManagerMain", 0,
                      "c_condTimedWait / c_condWait failed - thread will terminate");
            break;
        }

        /**
         * First walk through the collection of leases and record all
         * expired leases in an iterator. We cannot remove expired leases
         * while walking through the set, since it interferes with the
         * walk.
         * Any lease with a repeat bool to TRUE  will automatically be renewed
         * while collecting all the leases.
         */
        arg.expiredLeases = NULL;
        arg.firstLeaseToExpire = NULL;
        arg.now = v_timeGet();
        c_setWalk(_this->leases, collectExpired, &arg);

        c_free(_this->firstLeaseToExpire);
        _this->firstLeaseToExpire = arg.firstLeaseToExpire;/* takes over ref count from arg object */
        c_mutexUnlock(&_this->mutex);

        leaseAction = v_leaseAction(c_iterTakeFirst(arg.expiredLeases));
        while (leaseAction != NULL) {
            if(!leaseAction->repeat)
            {
                v_leaseManagerDeregister(_this, leaseAction->lease);
            }
            v_leaseManagerProcessLeaseAction(_this, leaseAction, arg.now);
            c_free(leaseAction);
            leaseAction = v_leaseAction(c_iterTakeFirst(arg.expiredLeases));
        }
        c_iterFree(arg.expiredLeases);
        c_mutexLock(&_this->mutex);
    }
    _this->quit = FALSE; /* for a next time */
    c_mutexUnlock(&_this->mutex);
}