Exemplo n.º 1
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);
    }
}
Exemplo n.º 2
0
c_time
v_leaseExpiryTime(
    v_lease lease)
{
    c_time expTime;

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

    v_leaseLock(lease);
    expTime = v_leaseExpiryTimeNoLock(lease);
    v_leaseUnlock(lease);

    return expTime;
}
Exemplo n.º 3
0
void
v_leaseGetExpiryAndDuration(
    v_lease lease,
    c_time *expiryTime,
    v_duration *duration)
{
    assert(lease != NULL);
    assert(C_TYPECHECK(lease, v_lease));

    if(expiryTime || duration){
        v_leaseLock(lease);
        if(expiryTime){
            *expiryTime = lease->expiryTime;
        }
        if(duration){
            *duration = lease->duration;
        }
        v_leaseUnlock(lease);
    }
}
Exemplo n.º 4
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);
        }
    }
}
Exemplo n.º 5
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);
        }
    }
}
Exemplo n.º 6
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);
    }
}
Exemplo n.º 7
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;
}