void v_deadLineInstanceListRemoveInstance( v_deadLineInstanceList list, v_instance instance) { assert(C_TYPECHECK(list,v_deadLineInstanceList)); assert((instance->prev != NULL) && (instance->next != NULL)); assert(c_refCount(list) > 0); assert(c_refCount(instance) > 0); /* As the instance is removed, there is no need to update the lease. * Updating the lease might trigger the leasemanager thread to determine * the next expiry time. The next expiry time can also be determined on * the next deadline check, which is more efficient as the administration * might already have changed many times. */ v_instanceRemove(instance); if (v_instanceAlone(v_instance(list))) { /* list has become empty */ if (list->deadlineLease != NULL) { v_leaseManagerDeregister(list->leaseManager, list->deadlineLease); c_free(list->deadlineLease); list->deadlineLease = NULL; } } }
void v_deadLineInstanceListFree( v_deadLineInstanceList list) { assert(C_TYPECHECK(list,v_deadLineInstanceList)); v_leaseManagerDeregister(list->leaseManager, list->deadlineLease); c_free(list->leaseManager); list->leaseManager = NULL; c_free(list->deadlineLease); list->deadlineLease = NULL; }
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; }
void v_participantDeinit( v_participant p) { v_kernel kernel; assert(C_TYPECHECK(p,v_participant)); kernel = v_objectKernel(p); v_leaseManagerDeregister(kernel->livelinessLM, p->lease); c_free(p->lease); p->lease = NULL; v_leaseManagerFree(p->leaseManager); p->leaseManager = NULL; v_observerDeinit(v_observer(p)); }
void v_serviceDeinit( v_service service) { v_kernel kernel; assert(service != NULL); assert(C_TYPECHECK(service, v_service)); c_free(service->state); service->state = NULL; c_free((c_object)v_observer(service)->eventData); kernel = v_objectKernel(service); v_leaseManagerDeregister(kernel->livelinessLM, service->lease); c_free(service->lease); service->lease = NULL; v_participantDeinit(v_participant(service)); }
void v_deadLineInstanceListSetDuration( v_deadLineInstanceList list, v_duration duration) { v_kernel k; v_result result; assert(C_TYPECHECK(list,v_deadLineInstanceList)); list->leaseDuration = duration; if (list->deadlineLease != NULL) { if (c_timeCompare(duration, C_TIME_INFINITE) != C_EQ) { v_leaseRenew(list->deadlineLease,duration); } else { v_leaseManagerDeregister(list->leaseManager, list->deadlineLease); c_free(list->deadlineLease); list->deadlineLease = NULL; } } else { if ((v_objectKind(v_instance(list)->prev) != K_DEADLINEINSTANCE) && /* not in list */ (c_timeCompare(duration, C_TIME_INFINITE) != C_EQ)) { /* new instance */ k = v_objectKernel(list->leaseManager); list->deadlineLease = v_leaseNew(k, duration); if(list->deadlineLease) { result = v_leaseManagerRegister( list->leaseManager, list->deadlineLease, list->actionId, v_public(list->actionObject), TRUE /* repeat lease if expired */); if(result != V_RESULT_OK) { c_free(list->deadlineLease); list->deadlineLease = NULL; OS_REPORT_1(OS_ERROR, "v_deadLineInstanceList", 0, "A fatal error was detected when trying to register the deadline lease." "The result code was %d.", result); } } } } }
void v_leaseManagerProcessLeaseAction( v_leaseManager _this, v_leaseAction leaseAction, c_time now) { assert(_this != NULL); assert(C_TYPECHECK(_this, v_leaseManager)); assert(leaseAction != NULL); assert(C_TYPECHECK(leaseAction, v_leaseAction)); switch (leaseAction->actionId) { case V_LEASEACTION_SERVICESTATE_EXPIRED: serviceStateExpired(leaseAction); break; case V_LEASEACTION_READER_DEADLINE_MISSED: readerDeadlineMissed(leaseAction, now); break; case V_LEASEACTION_WRITER_DEADLINE_MISSED: writerDeadlineMissed(leaseAction, now); break; case V_LEASEACTION_LIVELINESS_CHECK: livelinessCheck(_this, leaseAction); break; case V_LEASEACTION_HEARTBEAT_SEND: heartbeatSend(leaseAction); break; case V_LEASEACTION_HEARTBEAT_CHECK: heartbeatCheck(leaseAction); break; case V_LEASEACTION_SPLICED_DEATH_DETECTED: splicedDeathDetected(leaseAction); break; default: OS_REPORT_3(OS_WARNING, "v_leaseManager", 0, "Unknown lease action %d for lease %p within leaseManager %p", leaseAction->actionId, leaseAction->lease, _this); /* lets remove lease from lease manager to prevent future wakeups of lease manager. */ v_leaseManagerDeregister(_this, leaseAction->lease); break; } }
void livelinessCheck( v_leaseManager _this, v_leaseAction leaseAction) { v_object o; v_handleResult r; assert(leaseAction != NULL); assert(C_TYPECHECK(leaseAction, v_leaseAction)); /* Liveliness lease expired, so the reader/writer must be notified! */ r = v_handleClaim(leaseAction->actionObject, &o); if (r == V_HANDLE_OK) { v_writerNotifyLivelinessLost(v_writer(o)); if (v_objectKind(o) != K_WRITER) { OS_REPORT_1(OS_WARNING, "v_lease", 0, "entity %d has no liveliness policy", v_objectKind(o)); } r = v_handleRelease(leaseAction->actionObject); if(r != V_HANDLE_OK) { OS_REPORT_1(OS_WARNING, "v_leaseManager", 0, "Handle release failed with result code %d ", r); } } else { /* Corresponding reader/writer is already gone, so remove this lease * from its leasemanager. */ v_leaseManagerDeregister(_this, leaseAction->lease); } }
/************************************************************** * 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); }