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_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; }
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); } }
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); } } }
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); } } }
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); } }
/************************************************************** * 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; }