Exemple #1
0
c_bool
v_readerWaitForHistoricalData(
    v_reader r,
    c_time timeout)
{
    struct historicalWaitArg arg;
    c_iter entries;
    c_object e;

    v_readerEntrySetLock(r);
    entries = c_select(r->entrySet.entries, 0);
    v_readerEntrySetUnlock(r);

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

    e = c_iterTakeFirst(entries);
    while (e != NULL) {
        if (arg._status == TRUE) {
            if (r->qos->durability.kind == V_DURABILITY_VOLATILE) {
                getHistoricalData(e, NULL);
            }
            waitForHistoricalData(e, &arg);
        }
        c_free(e);
        e = c_iterTakeFirst(entries);
    }
    c_iterFree(entries);

    return(arg._status);
}
Exemple #2
0
static void
v_networkQueueUpdateNextWakeup(
    v_networkQueue queue,
    c_bool *hasChanged)
{
    c_time now;
    c_time soon;
    c_time newWakeup;
    c_ulonglong msecsTime;
    c_ulonglong msecsResult;
    c_ulonglong msecsLeftOver;
    static c_time minSleepTime = MIN_SLEEPTIME;
    
    *hasChanged = FALSE;
    if (queue->periodic) {
        now = v_timeGet();
        soon = c_timeAdd(now, minSleepTime);
        TIME_TO_MSEC(soon, msecsTime);
        /* Do a ++ because we are doing a ceil and TIME_TO_MSEC is doing a trunc.
         * Only if time was an exact multiple of milliseconds, this approach is
         * not completely correct. But it saves us the hassle and this works fine */
        msecsTime++;
        msecsLeftOver = (msecsTime - queue->phaseMilliSeconds) % queue->msecsResolution;
        msecsResult = msecsTime - msecsLeftOver + queue->msecsResolution;
        MSEC_TO_TIME(msecsResult, newWakeup);
        if (c_timeCompare(newWakeup,queue->nextWakeup) == C_GT) {
            queue->nextWakeup = newWakeup;
            *hasChanged = TRUE;
        }
    }
}
Exemple #3
0
void
v_leaseUpdate(
    v_lease lease)
{
    if (lease != NULL) {
        assert(C_TYPECHECK(lease, v_lease));

        v_leaseLock(lease);
        lease->expiryTime = c_timeAdd(v_timeGet(), lease->duration);
        v_leaseUnlock(lease);
    }
}
c_iter
v_deadLineInstanceListCheckDeadlineMissed(
    v_deadLineInstanceList list,
    v_duration deadlineTime,
    c_time now)
{
    c_time expiryTime;
    v_instance listItem;
    c_iter missed;

    assert(C_TYPECHECK(list,v_deadLineInstanceList));

    missed = NULL;
    if (v_instanceAlone(v_instance(list))) { /* list is empty */
        assert (list->deadlineLease != NULL);
        v_leaseManagerDeregister(list->leaseManager, list->deadlineLease);
        c_free(list->deadlineLease);
        list->deadlineLease = NULL;
    } else {
        listItem = v_instance(list)->prev;
        expiryTime = c_timeSub(now, deadlineTime);
        while ((listItem != NULL) &&
                (v_objectKind(listItem) != K_DEADLINEINSTANCE)  &&
                (c_timeCompare(expiryTime, listItem->lastCheckTime) != C_LT)) {
            missed = c_iterInsert(missed, listItem);
            listItem->lastCheckTime = now;
            listItem = listItem->prev;
        }
        /* determine next wake-up time */
        if (v_objectKind(listItem) == K_DEADLINEINSTANCE) {
            /* listItem is the deadline list itself, so if there
             * were instances all instances have been missed. Just
             * set the new check to be in 'deadlineTime'.
             */
            expiryTime = deadlineTime;
        } else {
            /*
             * The new lease duration can be calculated:
             * lastCheckTime + deadlineTime = next expiry time
             * next expiry time - now = lease duration
             */
            expiryTime = c_timeAdd(listItem->lastCheckTime, deadlineTime);
            expiryTime = c_timeSub(expiryTime, now);
            v_leaseRenew(list->deadlineLease, expiryTime);
        }
    }
    return missed;
}
Exemple #5
0
void
v_leaseInit(
    v_lease _this,
    v_kernel k,
    v_duration leaseDuration)
{
    if (_this != NULL)
    {
        assert(C_TYPECHECK(_this, v_lease));

        c_mutexInit(&_this->mutex,SHARED_MUTEX);
        _this->expiryTime = c_timeAdd(v_timeGet(), leaseDuration);
        _this->duration = leaseDuration;
        _this->observers = c_setNew(v_kernelType(k, K_LEASEMANAGER));
    }
}
Exemple #6
0
v_networkReaderWaitResult
v_networkReaderWaitDelayed(
    v_networkReader reader,
    c_ulong queueId,
    v_networkQueue *queue)
{
    c_time sleep = {0,1000000};
    /* Simply sleeping here for resolution time, is not correct.
    We should wakeup on, or just after the next wakeuptime.*/
    sleep = c_timeAdd(sleep,v_networkQueue(reader->queues[queueId-1])->nextWakeup);
    sleep = c_timeSub(v_networkQueue(reader->queues[queueId-1])->nextWakeup, v_timeGet());
    c_timeNanoSleep(sleep);


    return V_WAITRESULT_TIMEOUT | v_networkReaderWait(reader, queueId, queue);
}
Exemple #7
0
void
v_leaseRenew(
    v_lease lease,
    v_duration leaseDuration)
{
    c_iter observers = NULL;
    v_leaseManager observer;

    if (lease != NULL) {
        assert(C_TYPECHECK(lease, v_lease));

        v_leaseLock(lease);
        lease->expiryTime = c_timeAdd(v_timeGet(), leaseDuration);
        lease->duration = leaseDuration;
        /* Collect all observers, so they can be notified of the lease change
         * Must do a seperate collect as the lease mutex is 'lower' then the
         * leaseManager mutex. So to prevent deadlock we can not directly notify
         * the lease manager as we walk the collection
         */
        if(lease->observers)
        {
            c_walk(lease->observers, v_leaseCollectObservers, &observers);
        }
        v_leaseUnlock(lease);
        if(observers)
        {
            observer = v_leaseManager(c_iterTakeFirst(observers));
            while (observer != NULL)
            {
                v_leaseManagerNotify(
                    observer,
                    lease,
                    V_EVENT_LEASE_RENEWED);
                c_free(observer);
                observer = v_leaseManager(c_iterTakeFirst(observers));
            }
            c_iterFree(observers);
        }
    }
}
v_dataReaderSample
v_dataReaderSampleNew(
    v_dataReaderInstance instance,
    v_message message)
{
    v_dataReader dataReader;
    v_dataReaderSample sample;
    v_readerQos readerQos;
    v_index index;

    assert(instance != NULL);
    assert(C_TYPECHECK(message,v_message));

    index = v_index(instance->index);
    dataReader = v_dataReader(index->reader);
    readerQos = v_reader(dataReader)->qos;
    if (dataReader->cachedSample != NULL) {
        sample = dataReader->cachedSample;

/* Unfinished proto for cache size control
 * #define _SL_
 */
#ifdef _SL_
        dataReader->cachedSample = sample->prev;
        sample->prev = NULL;
        dataReader->cachedSampleCount--;
#else
        dataReader->cachedSample = NULL;
#endif
    } else {
        sample = v_dataReaderSample(c_extentCreate(dataReader->sampleExtent));
    }
    v_readerSample(sample)->instance = (c_voidp)instance;
    v_readerSample(sample)->viewSamples = NULL;
    if ((message->transactionId != 0) &&
        (v_reader(dataReader)->subQos->presentation.coherent_access))
    {
        v_readerSample(sample)->sampleState = L_TRANSACTION;
    } else {
        v_readerSample(sample)->sampleState = 0;
    }
#ifdef _NAT_
    sample->insertTime = v_timeGet();
#else
#define _INCORRECT_BUT_LOW_INSERT_LATENCY_
#ifdef _INCORRECT_BUT_LOW_INSERT_LATENCY_
    if (v_timeIsZero(v_reader(dataReader)->qos->latency.duration)) {
        sample->insertTime = v_timeGet();
    } else {
        sample->insertTime = message->allocTime;
    }
#else
    sample->insertTime = v_timeGet();
#endif
#endif
    if (readerQos->lifespan.used) { 
        v_lifespanSample(sample)->expiryTime = 
            c_timeAdd(sample->insertTime, readerQos->lifespan.duration);
    } else {
        v_lifespanSample(sample)->expiryTime = 
            c_timeAdd(sample->insertTime,
                      v_messageQos_getLifespanPeriod(message->qos));
    }
    sample->disposeCount = instance->disposeCount;
    sample->noWritersCount = instance->noWritersCount;
    sample->publicationHandle = message->writerGID;
    sample->readId = 0;
    sample->prev = NULL;
    assert(message);
    v_dataReaderSampleTemplate(sample)->message = c_keep(message);
    v_lifespanAdminInsert(v_dataReaderEntry(index->entry)->lifespanAdmin,
                          v_lifespanSample(sample));

    dataReader->notReadCount++;

    return sample;
}
Exemple #9
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;
}    
Exemple #10
0
c_bool
v_networkQueueWrite(
    v_networkQueue queue,
    v_message msg,
    v_networkReaderEntry entry,
    c_long sequenceNumber,
    v_gid sender,
    c_bool sendTo, /* for p2p writing */
    v_gid receiver)
{
    c_bool result = TRUE;
    c_bool wasEmpty;
    c_bool found;
    v_networkStatusMarker *currentMarkerPtr;
    v_networkStatusMarker currentMarker;
    v_networkStatusMarker marker;
    v_networkQueueSample newHolder;
    c_ulonglong msecsTime;
    c_ulonglong msecsResult;
    c_ulonglong msecsLeftOver;
    c_time sendBeforeNoTrunc;
    c_time sendBefore;
    c_time now;
    c_ulong priorityLookingFor;
    c_equality eq;
    c_bool newMarkerCreated = FALSE;
    c_bool sendNow = FALSE;
   
    V_MESSAGE_STAMP(msg,readerInsertTime); 

    c_mutexLock(&queue->mutex);

    /* numberOfSamplesArrived statistics */
    v_networkQueueStatisticsAdd(numberOfSamplesArrived,queue->statistics);

    if (queue->currentMsgCount == queue->maxMsgCount) {
        c_mutexUnlock(&queue->mutex);
        /* numberOfSamplesRejected stat */
        v_networkQueueStatisticsAdd(numberOfSamplesRejected,queue->statistics);
        return FALSE;
    }

    currentMarkerPtr = &(queue->firstStatusMarker);
    currentMarker = *currentMarkerPtr;

    if (queue->threadWaiting) {
        wasEmpty = !v_networkQueueHasExpiringData(queue);
    } else {
        wasEmpty = FALSE;
    }

    marker = NULL;
    found = FALSE;

    priorityLookingFor = v_messageQos_getTransportPriority(msg->qos);
    if (queue->periodic) {
        if (v_messageQos_isZeroLatency(msg->qos)) {
            sendBefore = C_TIME_ZERO;
            sendNow = TRUE;
        } else {
#ifdef _NAT_
            now = v_timeGet();
#else
            now = msg->allocTime;
#endif
            sendBeforeNoTrunc = c_timeAdd(now,
                                          v_messageQos_getLatencyPeriod(msg->qos));
            TIME_TO_MSEC(sendBeforeNoTrunc, msecsTime);
            msecsLeftOver = (c_ulonglong)((msecsTime - queue->phaseMilliSeconds) %
                                         queue->msecsResolution);
            msecsResult = (c_ulonglong)(msecsTime - msecsLeftOver);
            MSEC_TO_TIME(msecsResult, sendBefore);
        }
        while ((currentMarker != NULL) && (!found)) {
            eq = c_timeCompare(sendBefore, currentMarker->sendBefore);
            switch (eq) {
            case C_GT:
                currentMarkerPtr = &currentMarker->next;
                currentMarker = *currentMarkerPtr;
            break;
            case C_EQ:
                if (priorityLookingFor < currentMarker->priority) {
                    currentMarkerPtr = &currentMarker->next;
                    currentMarker = *currentMarkerPtr;
                } else {
                    found = TRUE;
                    if (priorityLookingFor == currentMarker->priority) {
                        marker = currentMarker;
                    }
                }
            break;
            case C_LT:
                found = TRUE;
            break;
            default:
                assert(FALSE);
            break;
            }
        }
    } else {
        if (currentMarker) {
        sendBefore = C_TIME_ZERO;
            if (c_timeIsZero(currentMarker->sendBefore)) {
                marker = currentMarker;
            }
        }
    }
    /* Insert after end of list */
    if (marker == NULL) {
        newMarkerCreated = TRUE;
        if (queue->freeStatusMarkers == NULL) {
            marker = v_networkStatusMarker(c_new(queue->statusMarkerType));
        } else {
            marker = queue->freeStatusMarkers;
            queue->freeStatusMarkers = marker->next;
        }

        if (marker != NULL) {
            marker->sendBefore = sendBefore;
            marker->priority = priorityLookingFor;
            marker->firstSample = NULL;
            marker->lastSample = NULL;
            marker->next = *currentMarkerPtr; /* no keep, transfer refCount */
            if (marker->next == NULL) {
                queue->lastStatusMarker = marker; /* no keep, not reference counted */
            }
            *currentMarkerPtr = marker; /* no keep, transfer refCount */
        } else {
            OS_REPORT(OS_ERROR,
                  "v_networkQueueWrite",0,
                  "Failed to send message.");
            c_mutexUnlock(&queue->mutex);
            return FALSE;
        }
    }
    V_MESSAGE_STAMP(msg,readerLookupTime); 
    assert(marker != NULL);
    if (queue->freeSamples == NULL) {
        newHolder = c_new(queue->sampleType);
    } else {
        newHolder = queue->freeSamples;
        queue->freeSamples = newHolder->next;
    }

    if (newHolder) {
        queue->currentMsgCount++;

        /* numberOfSamplesInserted & numberOfSamplesWaiting + stats*/
        v_networkQueueStatisticsAdd(numberOfSamplesInserted,queue->statistics);
        v_networkQueueStatisticsCounterInc(numberOfSamplesWaiting,queue->statistics);

        newHolder->message = c_keep(msg);
        newHolder->entry = c_keep(entry);
        newHolder->sequenceNumber = sequenceNumber;
        newHolder->sender = sender;
        newHolder->sendTo = sendTo;
        newHolder->receiver = receiver;

        if (marker->lastSample != NULL) {
            newHolder->next = v_networkQueueSample(marker->lastSample)->next; /* no keep, transfer refCount */
            v_networkQueueSample(marker->lastSample)->next = newHolder; /* no keep, transfer refCount */
        } else {
            newHolder->next = marker->firstSample; /* no keep, transfer refCount */
            marker->firstSample = newHolder; /* no keep, transfer refCount */
        }
        marker->lastSample = newHolder;


        /* Write done, wake up waiters if needed */
        if (wasEmpty && queue->threadWaiting) {
            if (sendNow || v_networkQueueHasExpiringData(queue)) {
                c_condBroadcast(&queue->cv);
            }
        }
    } else {
        OS_REPORT(OS_ERROR,
              "v_networkQueueWrite",0,
              "Failed to send message.");
        result = FALSE;
    }

    c_mutexUnlock(&queue->mutex);
    
    return result;
}
Exemple #11
0
void
v_leaseRenew(
    v_lease lease,
    v_duration* leaseDuration /* may be NULL */)
{
    c_iter observers = NULL;
    v_leaseManager observer;
    c_time newExpiryTime;
    c_equality cmp;

    if (lease != NULL) {
        assert(C_TYPECHECK(lease, v_lease));

        v_leaseLock(lease);
        /* Is a new lease duration provided, if so replace the current lease
         * duration with the new one
         */
        if(leaseDuration != NULL)
        {
            lease->duration = *leaseDuration;
        } /* else do nothing */
        /* Calculate the new expiry time */
        newExpiryTime = c_timeAdd(v_timeGet(), lease->duration);
        /* Is the new expiryTime earlier then the current expiryTime? */
        cmp = c_timeCompare(newExpiryTime, lease->expiryTime);
        /* Always replace the current expiry time with the new expiryTime */
        lease->expiryTime = newExpiryTime;
        /* If the new expiryTime is earlier then the previous expiryTime. Then
         * this means the observers must be notified so they can take the
         * earlier expiryTime into account
         */
        if (cmp == C_LT)
        {

            /* Collect all observers, so they can be notified of the lease change
             * Must do a seperate collect as the lease mutex is 'lower' then the
             * leaseManager mutex. So to prevent deadlock we can not directly notify
             * the lease manager as we walk the collection
             */
            if(lease->observers)
            {
                c_walk(lease->observers, v_leaseCollectObservers, &observers);
            }
            v_leaseUnlock(lease);
            if(observers)
            {
                observer = v_leaseManager(c_iterTakeFirst(observers));
                while (observer != NULL)
                {
                    v_leaseManagerNotify(
                        observer,
                        lease,
                        V_EVENT_LEASE_RENEWED);
                    c_free(observer);
                    observer = v_leaseManager(c_iterTakeFirst(observers));
                }
                c_iterFree(observers);
            }
        } else
        {
            /* No need to notify observers, the new expiryTime is not earlier
             * then what it was before.
             */
            v_leaseUnlock(lease);
        }
    }
}
Exemple #12
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;
}