Ejemplo n.º 1
0
c_bool
v_waitsetDetach (
    v_waitset _this,
    v_observable o)
{
    c_bool result;
    v_proxy found;
    findProxyArgument arg;
    void* userDataRemoved = NULL;

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

    arg.observable = v_publicHandle(v_public(o));
    arg.proxy = NULL;
    v_waitsetLock(_this);
    c_setWalk(_this->observables,findProxy,&arg);
    if (arg.proxy != NULL) { /* proxy to the observer found */
        found = c_remove(_this->observables,arg.proxy,NULL,NULL);
        assert(found == arg.proxy);
        c_free(found);
    }
    v_waitsetUnlock(_this);

    result = v_observableRemoveObserver(o,v_observer(_this), &userDataRemoved);
    v_waitsetClearRemovedObserverPendingEvents(_this, userDataRemoved);

    /* wakeup blocking threads to evaluate new condition. */
    if (v_observerWaitCount(_this)) {
        v_waitsetTrigger(_this, NULL);
    }
    return result;
}
Ejemplo n.º 2
0
c_bool
v_waitsetAttach (
    v_waitset _this,
    v_observable o,
    c_voidp userData)
{
    c_bool result;
    v_proxy proxy;
    findProxyArgument arg;

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

    arg.observable = v_publicHandle(v_public(o));
    arg.proxy = NULL;

    v_waitsetLock(_this);
    c_setWalk(_this->observables, findProxy,&arg);
    if (arg.proxy == NULL) { /* no proxy to the observer exists */
        proxy = v_proxyNew(v_objectKernel(_this),
                           arg.observable, userData);
        c_insert(_this->observables,proxy);
        c_free(proxy);
    }
    v_waitsetUnlock(_this);
    result = v_observableAddObserver(o,v_observer(_this), userData);
    /* wakeup blocking threads to evaluate new condition. */
    if (v_observerWaitCount(_this)) {
        v_waitsetTrigger(_this, NULL);
    }
    return result;
}
Ejemplo n.º 3
0
void
v_subscriberUnSubscribe(
    v_subscriber s,
    const c_char *partitionExpr)
{
    v_partition d;
    v_dataReaderConnectionChanges arg;
    v_partitionPolicy old;

    assert(s != NULL);
    assert(C_TYPECHECK(s,v_subscriber));

    arg.addedPartitions = NULL;

    c_lockWrite(&s->lock);

    arg.removedPartitions = v_partitionAdminRemove(s->partitions, partitionExpr);
    old = s->qos->partition;
    s->qos->partition = v_partitionPolicyRemove(old, partitionExpr,
                                                c_getBase(c_object(s)));
    c_free(old);
    c_setWalk(s->readers, qosChangedAction, &arg);

    d = v_partition(c_iterTakeFirst(arg.removedPartitions));
    while (d != NULL) {
        c_free(d);
        d = v_partition(c_iterTakeFirst(arg.removedPartitions));
    }
    c_iterFree(arg.removedPartitions);

    c_lockUnlock(&s->lock);
}
Ejemplo n.º 4
0
void
v_subscriberConnectNewGroup(
    v_subscriber s,
    v_group g)
{
    c_bool connect;
    c_iter addedPartitions;
    v_partition d;

    c_lockWrite(&s->lock);
    connect = v_partitionAdminFitsInterest(s->partitions, g->partition);
    if (connect) {
        addedPartitions = v_partitionAdminAdd(s->partitions,
                                        v_partitionName(g->partition));
        d = v_partition(c_iterTakeFirst(addedPartitions));
        while (d != NULL) {
            c_free(d);

            d = v_partition(c_iterTakeFirst(addedPartitions));
        }
        c_iterFree(addedPartitions);
        c_setWalk(s->readers, (c_action)v_readerSubscribeGroup, g);
    } else {
        /*
         * Check if group fits interest. This extra steps are needed because
         * the groupActionStream does not create the groups that match the
         * subscriber qos partition expression on creation. It only needs to
         * connect to new groups once they are created. This is a different
         * approach then for a data reader.
         */
        /*
         * Because already existing partitions are created and added to the
         * subscriber of the groupActionStream at creation time, these
         * partitions can be resolved from the subscriber. This is necessary to
         * determine whether the groupActionStream should connect to the new
         * group or if it is already connected.
         */
        if (v_partitionAdminExists(s->partitions, v_partitionName(g->partition))) {
            c_setWalk(s->readers, (c_action)notifyGroupQueues, g);
        }
    }
    c_lockUnlock(&s->lock);
}
Ejemplo n.º 5
0
c_bool
v_readerWalkEntries(
    v_reader r,
    c_action action,
    c_voidp arg)
{
    c_bool result;

    assert(C_TYPECHECK(r,v_reader));

    v_readerEntrySetLock(r);
    result = c_setWalk(r->entrySet.entries, action, arg);
    v_readerEntrySetUnlock(r);

    return result;
}
Ejemplo n.º 6
0
static void
getStatusMask(
    v_entity e,
    c_voidp arg)
{
    c_long *mask = (c_long *)arg;

    if ( v_objectKind(e) == K_SUBSCRIBER ) {
        if ( !c_setWalk(v_subscriber(e)->readers, (c_action)readerHasDataAvailable, NULL) ) {
            *mask = V_EVENT_DATA_AVAILABLE;
        } else {
            *mask = 0;
        }
    } else {
        *mask = v_statusGetMask(e->status);
    }
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
c_iter
v_subscriberLookupReadersByTopic(
    v_subscriber s,
    const c_char *topicName)
{
    struct lookupReaderByTopicArg arg;

    assert(s != NULL);

    arg.list = NULL;
    arg.topicName = topicName;

    c_lockRead(&s->lock);
    c_setWalk(s->readers, (c_action)lookupReaderByTopic, &arg);
    c_lockUnlock(&s->lock);

    return arg.list;
}
Ejemplo n.º 9
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);
}
Ejemplo n.º 10
0
void
v_leaseManagerDeregister(
    v_leaseManager _this,
    v_lease lease)
{
    struct findLeaseActionArg arg;
    v_leaseAction found;
    c_bool removed;

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

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

        /* Step 1: Locate the leaseAction object based on the lease object */
        c_mutexLock(&_this->mutex);
        arg.lease = lease;
        arg.action = NULL;
        c_setWalk(_this->leases, findLeaseAction, &arg);
        if(arg.action)
        {
            /* step 2a: If we found the action object, then remove it */
            found = c_setRemove(_this->leases, arg.action, NULL, NULL);
            assert(found == arg.action);
            /* Step 2b: Remove the leaseManager from the list of observers of the
             * lease object. Using explicit lock operations, to keep the
             * v_leaseRemoveObserverNoLock operation consistent with the
             * v_leaseAddObserverNoLock operation.
             */
            v_leaseLock(lease);
            removed = v_leaseRemoveObserverNoLock(lease, _this);
            v_leaseUnlock(lease);
            if(removed == FALSE)
            {
                OS_REPORT_2(OS_ERROR,
                    "v_leaseManagerDeregister",0,
                    "Failed to remove leaseManager %p from the list of "
                    "observers of lease %p, while the lease WAS contained in "
                    "the list of leases managed by the leaseManager. This means "
                    "the administration has become inconsistent internally. "
                    "This is not a fatal error in itself, but points towards "
                    "a bug that could affect behaviour of OpenSpliceDDS",
                    _this,
                    lease);
            } /* else everything is ok */
            /* step 3: If the removed action was the 'firstLeaseToExpire' then we need
             * to redetermine the new 'firstLeaseToExpire'. Take note that no broadcast is done
             * on the condition. Because the new 'firstLeaseToExpire' will always have a later
             * expiry time, otherwise the one removed would not have been the first to expire.
             * So as a result of not doing the broadcast the leaseManager will wake up and find no
             * lease to be expired and continue as normal
             */
            if (arg.action == _this->firstLeaseToExpire)
            {
                c_free(_this->firstLeaseToExpire);
                _this->firstLeaseToExpire = NULL;
                c_setWalk(_this->leases, determineFirstLeaseToExpire, _this);
            }
            c_free(found); /* delete local reference */
            c_free(arg.action);
        }/* else the lease was not contained, so do nothing */
        c_mutexUnlock(&_this->mutex);
    }
}
Ejemplo n.º 11
0
v_result
v_subscriberSetQos(
    v_subscriber s,
    v_subscriberQos qos)
{
    v_result result;
    v_qosChangeMask cm;
    v_dataReaderConnectionChanges arg;
    v_partition d;
    v_accessMode access;

    assert(s != NULL);

    arg.addedPartitions = NULL;
    arg.removedPartitions = NULL;

    c_lockWrite(&s->lock);

    /* ES, dds1576: When the QoS is being set we have to verify that the partitions
     * listed in the qos do not have an invalid access mode set. For a subscriber
     * an invalid mode is characterized as 'write' mode. If the partitionAccess
     * check returns ok, then everything continue as normal. If the
     * partitionAccess check returns something else, then the setQos operation
     * is aborted. Please see the partitionAccess check operation to know when
     * a partition expression is not allowed.
     */
    if(qos && qos->partition)
    {
        access = v_kernelPartitionAccessMode(v_objectKernel(s), qos->partition);
    } else
    {
        access = V_ACCESS_MODE_READ_WRITE;/* default */
    }
    if(access == V_ACCESS_MODE_READ_WRITE || access == V_ACCESS_MODE_READ)
    {
        result = v_subscriberQosSet(s->qos, qos, v_entity(s)->enabled, &cm);
        if ((result == V_RESULT_OK) && (cm != 0)) {
            c_lockUnlock(&s->lock); /* since creation builtin topic might lock subscriber again. */
            if (cm & V_POLICY_BIT_PARTITION) { /* partition policy has changed! */
                v_partitionAdminSet(s->partitions, s->qos->partition,
                                 &arg.addedPartitions, &arg.removedPartitions);
            }

            c_setWalk(s->readers, qosChangedAction, &arg);

            d = v_partition(c_iterTakeFirst(arg.addedPartitions));
            while (d != NULL) {
                c_free(d);
                d = v_partition(c_iterTakeFirst(arg.addedPartitions));
            }
            c_iterFree(arg.addedPartitions);
            d = v_partition(c_iterTakeFirst(arg.removedPartitions));
            while (d != NULL) {
                c_free(d);
                d = v_partition(c_iterTakeFirst(arg.removedPartitions));
            }
            c_iterFree(arg.removedPartitions);
        } else {
            c_lockUnlock(&s->lock);
        }
    } else
    {
        result = V_RESULT_PRECONDITION_NOT_MET;
        c_lockUnlock(&s->lock);
    }
    return result;
}