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; }
v_networkReaderWaitResult v_networkReaderWaitDelayed( v_networkReader reader, c_ulong queueId, v_networkQueue *queue) { c_time sleep; /* Simply sleeping here for resolution time, is not correct. We should wakeup on, or just after the next wakeuptime.*/ sleep = c_timeSub(v_networkQueue(reader->queues[queueId-1])->nextWakeup, v_timeGet()); c_timeNanoSleep(sleep); return V_WAITRESULT_TIMEOUT | v_networkReaderWait(reader, queueId, queue); }
static c_bool waitForHistoricalData( c_object o, c_voidp arg) { v_entry entry; c_iter proxies; v_proxy proxy; v_group group; c_time waitTime; struct historicalWaitArg *parms = (struct historicalWaitArg *)arg; assert(o != NULL); assert(arg != NULL); entry = v_entry(o); assert(entry != NULL); assert(C_TYPECHECK(entry,v_entry)); proxies = c_select(entry->groups, 0); proxy = c_iterTakeFirst(proxies); while ((proxy != NULL) && (parms->_status == TRUE)) { group = v_group(v_proxyClaim(proxy)); if (group) { if (group->complete == FALSE) { waitTime = c_timeSub(parms->_expire_time, v_timeGet()); if (c_timeCompare(waitTime, C_TIME_ZERO) == C_GT) { parms->_status = v_groupWaitForComplete(group, waitTime); } else { parms->_status = FALSE; /* time out */ } } v_proxyRelease(proxy); } c_free(proxy); proxy = c_iterTakeFirst(proxies); } c_iterFree(proxies); return parms->_status; }
static c_bool d_statusListenerRemoveDeadFellows( d_action action, c_bool terminate) { d_admin admin; d_configuration config; d_timestamp removeTime; d_durability durability; c_bool result = FALSE; admin = d_admin(d_actionGetArgs(action)); if(d_objectIsValid(d_object(admin), D_ADMIN) == TRUE){ if(terminate == FALSE){ config = d_durabilityGetConfiguration(d_adminGetDurability(admin)); removeTime.seconds = config->heartbeatExpiryTime.tv_sec; removeTime.nanoseconds = config->heartbeatExpiryTime.tv_nsec; while (removeTime.nanoseconds >= 1000000000) { removeTime.seconds += 1; removeTime.nanoseconds -= 1000000000; } /* * Remove the fellow if it didn't report since current time minus * the heartbeat period times the maximum nomber of heartbeat * misses. */ durability = d_adminGetDurability(admin); if(d_durabilityMustTerminate(durability) == FALSE){ removeTime = c_timeSub(v_timeGet(), removeTime); d_adminCleanupFellows(admin, removeTime); } result = TRUE; } } return result; }
v_networkReaderWaitResult v_networkQueueWait( v_networkQueue queue) { v_networkReaderWaitResult result = V_WAITRESULT_NONE; c_syncResult syncResult; c_bool hasChanged; c_time interval; c_time minSleepTime = MIN_SLEEPTIME; c_equality eq; c_mutexLock(&queue->mutex); /* First update nextWakeup */ v_networkQueueUpdateNextWakeup(queue, &hasChanged); if (hasChanged) { result |= V_WAITRESULT_TIMEOUT; } /* With the new nextWakeup, check if any data is expiring */ if ((int)v_networkQueueHasExpiringData(queue)) { result |= V_WAITRESULT_MSGWAITING; } /* Also check if no request has been issued lately */ if ((int)queue->triggered) { result |= V_WAITRESULT_TRIGGERED; } /* Now go to sleep if needed */ while (result == V_WAITRESULT_NONE) { if (queue->periodic) { c_time org = v_timeGet(); interval = c_timeSub(queue->nextWakeup,org); eq = c_timeCompare(minSleepTime, interval); if (eq == C_LT) { queue->threadWaiting = TRUE; syncResult = c_condTimedWait(&queue->cv, &queue->mutex, interval); queue->threadWaiting = FALSE; } else { syncResult = SYNC_RESULT_TIMEOUT; } if (syncResult == SYNC_RESULT_TIMEOUT) { result |= V_WAITRESULT_TIMEOUT; queue->nextWakeup = c_timeAdd(queue->nextWakeup, queue->resolution); } } else { /* Wait infinitely if the queue is not periodic */ queue->threadWaiting = TRUE; syncResult = c_condWait(&queue->cv, &queue->mutex); queue->threadWaiting = FALSE; } /* Test current status of queue */ if ((int)queue->triggered) { result |= V_WAITRESULT_TRIGGERED; } if (v_networkQueueHasExpiringData(queue)) { result |= V_WAITRESULT_MSGWAITING; } } queue->triggered = 0; c_mutexUnlock(&queue->mutex); return result; }
/************************************************************** * 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); }