Example #1
0
void
v_leaseManagerDeinit(
    v_leaseManager _this)
{
    v_leaseAction lease;

    assert(C_TYPECHECK(_this, v_leaseManager));

    c_mutexLock(&_this->mutex);
    c_free(_this->firstLeaseToExpire);
    _this->firstLeaseToExpire = NULL;
    lease = v_leaseAction(c_take(_this->leases));
    while (lease != NULL)
    {
        c_free(lease);
        lease = v_leaseAction(c_take(_this->leases));
    }
    c_free(_this->leases);
    _this->leases = NULL;

    _this->quit = TRUE;
    c_condBroadcast(&_this->cond);
    c_mutexUnlock(&_this->mutex);

    /* Note the condition _this->cond is deinitalised via c_free */
}
Example #2
0
c_bool
v_leaseManagerNotify(
    v_leaseManager _this,
    v_lease lease,
    v_eventKind event)
{
    struct findLeaseActionArg arg;

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

    c_mutexLock(&_this->mutex);
    if (event & V_EVENT_LEASE_RENEWED) {
        if (_this->firstLeaseToExpire) {
            if (_this->firstLeaseToExpire->lease == lease) {
                /* If the lease is the head we are forced to wake-up the
                   thread, since we do not know the remaining sleeptime of the
                   thread.
                */
                c_condBroadcast(&_this->cond);
            } else {
                arg.lease = lease;
                arg.action = NULL;
                c_setWalk(_this->leases, findLeaseAction, &arg);
                if (arg.action) {
                    /* determine if this is the new head */
                    if (c_timeCompare(v_leaseExpiryTime(_this->firstLeaseToExpire->lease),
                                      v_leaseExpiryTime(lease)) == C_GT) {
                        c_free(_this->firstLeaseToExpire);
                        _this->firstLeaseToExpire = c_keep(arg.action);
                        c_condBroadcast(&_this->cond);
                    }
                    c_free(arg.action);
                } /* else lease is not registered, so no interest in this update! */
            }
        }
    } else {
        if (event & V_EVENT_TERMINATE) {
            _this->quit = TRUE;
            c_condBroadcast(&_this->cond);
        }
    }
    c_mutexUnlock(&_this->mutex);

    return TRUE;
}
Example #3
0
void
v_networkQueueTrigger(
    v_networkQueue queue)
{
    c_mutexLock(&queue->mutex);
    queue->triggered = 1;
    if (queue->threadWaiting) {
        c_condBroadcast(&queue->cv);
    }
    c_mutexUnlock(&queue->mutex);
}
Example #4
0
void
v_participantResendManagerQuit(
    v_participant p)
{
    assert(C_TYPECHECK(p,v_participant));

    c_mutexLock(&p->resendMutex);
    p->resendQuit = TRUE;
    c_condBroadcast(&p->resendCond);
    c_mutexUnlock(&p->resendMutex);
}
Example #5
0
void
v_observerFree(
    v_observer o)
{
    assert(C_TYPECHECK(o,v_observer));

    c_mutexLock(&o->mutex);
    o->eventFlags |= V_EVENT_OBJECT_DESTROYED;
    c_condBroadcast(&o->cv);
    c_mutexUnlock(&o->mutex);

    v_observableFree(v_observable(o));
}
Example #6
0
void
v_readerNotifyHistoricalDataAvailable(
    v_reader _this)
{
    assert(C_TYPECHECK(_this, v_reader));

    if(_this){
        V_READER_LOCK(_this);
        _this->historicalDataComplete = TRUE;
        c_condBroadcast(&_this->historicalDataCondition);
        V_READER_UNLOCK(_this);
    }
    return;
}
Example #7
0
void
v_participantResendManagerAddWriter(
    v_participant p,
    v_writer w)
{
    v_proxy wp, found;
    assert(C_TYPECHECK(p,v_participant));

    wp = v_proxyNew(v_objectKernel(w), v_publicHandle(v_public(w)), NULL);

    c_mutexLock(&p->resendMutex);
    found = c_insert(p->resendWriters, wp);
    assert((found->source.index == wp->source.index) &&
            (found->source.serial == wp->source.serial));
    c_condBroadcast(&p->resendCond);
    c_mutexUnlock(&p->resendMutex);

    c_free(wp);
}
Example #8
0
void
v_listenerFree(
   v_listener _this)
{
    v_participant p;
    v_listenerEvent event;
    os_duration delay;

    assert(_this != NULL);
    assert(C_TYPECHECK(_this,v_listener));
    p = v_participant(_this->participant);
    assert(p != NULL);

    c_mutexLock(&_this->mutex);

    /* wakeup blocking threads to evaluate new condition. */
    /* remove all events */
    while (_this->eventList != NULL) {
        event = _this->eventList;
        _this->eventList = event->next;
        v_listenerEventDeinit(event);
        c_free(event);
    }
    _this->eventList = NULL;
    c_free(_this->lastEvent);
    _this->lastEvent = NULL;
    _this->terminate = TRUE;
    c_condBroadcast(&_this->cv);
    c_mutexUnlock(&_this->mutex);

    delay = OS_DURATION_INIT(0, 1000);
    while (_this->waitCount > 0 && !p->processIsZombie) {
        ospl_os_sleep(delay);
    }

    v_participantRemove(p, v_object(_this));
    _this->participant = NULL;
    v_publicFree(v_public(_this));
}
Example #9
0
void
v_listenerFlush(
    v_listener _this,
    v_eventMask events,
    c_voidp userData)
{
    v_listenerEvent event, *prev;

    if (_this == NULL) {
        return;
    }
    assert(C_TYPECHECK(_this,v_listener));
    c_mutexLock(&_this->mutex);
    /* wakeup blocking threads to evaluate new condition. */
    /* remove all events */
    prev = &_this->eventList;
    event = _this->eventList;
    while (event != NULL) {
        if (event->userData == userData) {
            event->kind &= ~events;
        }
        if (event->kind == 0) {
            if (event == _this->lastEvent) {
                _this->lastEvent = c_keep(_this->lastEvent->next);
                v_listenerEventDeinit(event);
                c_free(event);
            }
            *prev = event->next;
            v_listenerEventDeinit(event);
            c_free(event);
            event = *prev;
        } else {
            prev = &event->next;
            event = event->next;
        }
    }
    c_condBroadcast(&_this->cv);
    c_mutexUnlock(&_this->mutex);
}
Example #10
0
void
v_listenerNotify(
    v_listener _this,
    v_event e,
    v_entity listener)
{
   /* The userData argument is typical the user layer entity to which
    * this listener is attached.
    * The userData is passed to the v_listenerWait operation.
    * The eventData is optional for passing additional data,
    * typically status information is passed.
    */
    v_listenerEvent event,found;
    v_status status;

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

    c_mutexLock(&_this->mutex);
    if (e != NULL) {
        found = NULL;
        event = NULL;
        if (_this->combine &&
            ((e->kind & V_EVENT_DATA_AVAILABLE) || (e->kind & V_EVENT_ON_DATA_ON_READERS)) )
        {
            /* Optimization for data availability: look for pending event and combine
             * to avoid triggering after data is already read on behalf of the first
             * trigger.
             */
            c_voidp source = v_publicGetUserData(v_public(e->source));
            found = _this->eventList;
            while (found != NULL) {
                if ((found->source == source) &&
                    (found->kind == e->kind)) {
                    break;
                } else {
                    found = found->next;
                }
            }
        }
        if (found == NULL) {
            event = c_new(v_kernelType(v_objectKernel(_this),K_LISTENEREVENT));
            event->next = NULL;
            event->kind = e->kind;
            event->source = v_publicGetUserData(v_public(e->source));
            /* For all events except for data availability
             * copy the entity status to keep the actual value until the
             * data is processed. The aforementioned events do not affect
             * status, so there is no need to copy the value nor reset any
             * counters.
             */
            if (event->kind == V_EVENT_DATA_AVAILABLE) {
                c_free(event->eventData);
                event->eventData = c_keep(e->data);
            } else {
                status = v_entityStatus(v_entity(e->source));
                c_free(event->eventData);
                event->eventData = v_statusCopyOut(status);
                v_statusResetCounters(status, e->kind);
                c_free(status);
            }
        }
    } else {
        event = c_new(v_kernelType(v_objectKernel(_this),K_LISTENEREVENT));
        event->next = NULL;
        event->kind = V_EVENT_TRIGGER;
        event->source = NULL;
        event->eventData = NULL;
    }
    if (event) {
        /* insert constructed listener event in the listeners event list. */
        if (_this->lastEvent) {
            _this->lastEvent->next = c_keep(event);
            c_free(_this->lastEvent);
        } else {
            assert(_this->eventList == NULL);
            _this->eventList = c_keep(event);
        }
        _this->lastEvent = event /* transfer ref */;
        if (listener) {
            event->listenerData = listener->listenerData;
            event->userData = v_publicGetUserData(v_public(listener)); /* Typical the language binding entity */
        } else {
            event->listenerData = NULL;
            event->userData = NULL; /* Typical the language binding entity */
        }
    }
    _TRACE_EVENTS_("v_listenerNotify: listener 0x%x, events 0x%x\n", _this, (e?e->kind:V_EVENT_TRIGGER));
    c_condBroadcast(&_this->cv);
    c_mutexUnlock(&_this->mutex);
}
Example #11
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;
}
Example #12
0
/**
 * PRE: v_observerLock has been called.
 *
 * When the text 'intentionally no break' is set after a case label
 * the class specified by the label has not implemented the notify
 * method.
 */
void
v_observerNotify(
    v_observer _this,
    v_event event,
    c_voidp userData)
{
    /* This Notify method is part of the observer-observable pattern.
     * It is designed to be invoked when _this object as observer receives
     * an event from an observable object.
     * It must be possible to pass the event to the subclass of itself by
     * calling <subclass>Notify(_this, event, userData).
     * This implies that _this cannot be locked within any Notify method
     * to avoid deadlocks.
     * For consistency _this must be locked by v_observerLock(_this) before
     * calling this method.
     */

    c_ulong trigger;

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

    /* The observer will be made insensitive to event as soon as the
     * observer is deinitialized. However it may be that destruction
     * of the observer has started before the deinit of the observer
     * is called. In that case the V_EVENT_OBJECT_DESTROYED flag will
     * be set to avoid processing of incomming events.
     */
    if ((_this->eventFlags & V_EVENT_OBJECT_DESTROYED) == 0) {
        /* The observer is valid so the event can be processed.
          */
        if (event != NULL ) {
            trigger = event->kind & _this->eventMask;
        } else {
            /* NULL-event always notifies observers */
            trigger = V_EVENT_TRIGGER;
        }

        /* The following code invokes the observers subclass specific
         * notification method.
         * This is a bit strange that the observer has knowledge about
         * the subclass notification methods, a better model is that
         * subclasses register the notification method to the observer
         * instead. The reason for this model is that registering a
         * function pointer is only valid in the process scope and this
         * method will typically be called from another process.
         */
        if (trigger != 0) {
            switch (v_objectKind(_this)) {
            case K_DATAREADER:
                v_dataReaderNotify(v_dataReader(_this), event, userData);
            break;
            case K_WAITSET:
                v_waitsetNotify(v_waitset(_this), event, userData);
            break;
            case K_PARTICIPANT:
                v_participantNotify(v_participant(_this), event, userData);
            break;
            case K_TOPIC:
                v_topicNotify(v_topic(_this), event, userData);
            break;
            case K_QUERY:
                /* v_queryNotify(v_query(_this), event, userData); */
            break;
            case K_SPLICED: /* intentionally no break */
            case K_SERVICE:
            case K_NETWORKING:
            case K_DURABILITY:
            case K_CMSOAP:
                v_serviceNotify(v_service(_this), event, userData);
            break;
            case K_SERVICEMANAGER:
                v_serviceManagerNotify(v_serviceManager(_this), event, userData);
            break;
            case K_WRITER: /* no action for the following observers */
            case K_PUBLISHER:
            case K_SUBSCRIBER:
            case K_GROUPQUEUE:
            break;
            default:
                OS_REPORT_1(OS_INFO,"Kernel Observer",0,
                            "Notify an unknown observer type: %d",
                            v_objectKind(_this));
            break;
            }

            /*
             * Only trigger condition variable if at least
             * one thread is waiting AND the event is seen for the first time.
             */
            if ((_this->waitCount > 0) &&
                ((trigger == V_EVENT_TRIGGER) || (~_this->eventFlags & trigger)))
            {
                _this->eventFlags |= trigger; /* store event */
                c_condBroadcast(&_this->cv);
            } else {
                _this->eventFlags |= trigger; /* store event */
            }
        }
    } /* else observer object destroyed, skip notification */
}
Example #13
0
/**************************************************************
 * register/deregister of leases
 **************************************************************/
v_result
v_leaseManagerRegister(
    v_leaseManager  _this,
    v_lease         lease,
    v_leaseActionId actionId,
    v_public        actionObject,
    c_bool          repeatLease)
{
    c_bool obsAdded;
    v_leaseAction leaseAction;
    v_leaseAction found;
    v_result result;
    v_kernel k;

    assert(_this != NULL);
    assert(C_TYPECHECK(_this, v_leaseManager));
    assert(lease != NULL);
    assert(C_TYPECHECK(lease, v_lease));
    assert(actionObject != NULL);
    assert(C_TYPECHECK(actionObject, v_public));

    /* Step 1: Create a lease action object. This object will contain the relevant
     * information needed when reacting to an expired lease. This action information
     * can be different depending on which lease manager a lease is being registered
     * to, hence why the leaseAction object resides at leaseManager level and not
     * at lease level as it did in the past
     */
    k = v_objectKernel(_this);
    leaseAction = v_leaseAction(v_objectNew(k, K_LEASEACTION));
    if(!leaseAction)
    {
        OS_REPORT(OS_ERROR, "v_leaseManager", 0,
            "Failed to create a v_leaseManager object. "
            "Most likely not enough shared memory available to "
            "complete the operation.");
        result = V_RESULT_OUT_OF_MEMORY;
    } else
    {
        leaseAction->lease = v_lease(c_keep(lease));
        assert(leaseAction->lease);
        leaseAction->actionId = actionId;
        leaseAction->actionObject = v_publicHandle(actionObject);
        leaseAction->repeat = repeatLease;
        /* Step 2: insert the leaseAction object into the set of leases. */
        c_mutexLock(&_this->mutex);
        found = c_setInsert(_this->leases, leaseAction);
        if(!found)
        {
            /* Because the leaseAction object was just allocated we only have
             * to check if found is a NULL pointer. As it can never find the
             * action already being present in the set.
             */
            OS_REPORT(OS_ERROR, "v_leaseManager", 0,
                "Unable to register the lease to the list of "
                "leases of the leaseManager object! Most likely not enough shared "
                "memory available to complete the operation.");
            result = V_RESULT_OUT_OF_MEMORY;
            c_free(leaseAction);
            leaseAction = NULL;
        } else
        {
            assert(found == leaseAction);
            /* Step 3: Determine if the newly inserted leaseAction will become the
             * 'next lease to expire'. E.G., if the lease contained within the
             * leaseAction object has an expiry time that is the closest to the
             * present time compared to the other leases managed within this lease
             * manager. To prevent the lease time from changing while we evaluate the
             * lease we will lock the lease object.
             */
            v_leaseLock(lease);
            if(!_this->firstLeaseToExpire)
            {
                _this->firstLeaseToExpire = c_keep(leaseAction);
                /* head changed, so signal */
                c_condBroadcast(&_this->cond);
            } else if ((_this->firstLeaseToExpire->lease != lease) &&
                       (c_timeCompare(v_leaseExpiryTime(_this->firstLeaseToExpire->lease),
                                     v_leaseExpiryTimeNoLock(lease)) == C_GT))
            {
                c_free(_this->firstLeaseToExpire);
                _this->firstLeaseToExpire = c_keep(leaseAction);
                /* head changed, so signal */
                c_condBroadcast(&_this->cond);
            }/* else do nothing as the newly added lease expires after the firstLeaseToExpire */
            /* Step 4: Now that the lease was successfully inserted into the lease manager,
             * we need to register the leaseManager as an observer of the lease to ensure that the
             * lease manager is notified if the lease expiry time and/or duration changes.
             */
            obsAdded = v_leaseAddObserverNoLock(lease, _this);
            if(!obsAdded)
            {
                OS_REPORT(OS_ERROR, "v_leaseManager", 0,
                    "Unable to register the lease manager to the list of "
                    "observers of the lease object! Possibly not enough "
                    "shared memory available to complete the operation.");
                result = V_RESULT_INTERNAL_ERROR;
                v_leaseUnlock(lease);
                /* Remove the lease from the leaseManager */
                found = c_setRemove(_this->leases, leaseAction, NULL, NULL);
                if(found != leaseAction)
                {
                    OS_REPORT(OS_ERROR, "v_leaseManager", 0,
                        "Unable to unregister the lease to the list of "
                        "leases of the leaseManager object after previous internal error!");
                }
                c_free(leaseAction);
                leaseAction = NULL;
            } else
            {
                /* Now that the lease manager is in the observer list of the lease, we can unlock the lease
                 * as from now on we will be notified of any changes to the lease expiry time and/or duration
                 */
                v_leaseUnlock(lease);
                result = V_RESULT_OK;
            }

        }
        c_mutexUnlock(&_this->mutex);
    }
    if(leaseAction)
    {
        /* Done with the leaseAction object in this operation. If the object is not a NULL
         * pointer then everything went ok. The leases set of the leaseManager should be
         * the only one maintaining a ref count now (and possibly the 'firstLeaseToExpire'
         * attribute. But we do not need the leaseAction object in this operation anymore
         * and we are not returning it, so we need to lower the ref count for the new operation
         */
        c_free(leaseAction);
    }/* else do nothing */

    return result;
}