Exemplo n.º 1
0
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;
        }
    }
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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));
}
Exemplo n.º 5
0
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));
}
Exemplo n.º 6
0
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);
                }
            }
        }
    }
}
Exemplo n.º 7
0
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;
    }
}
Exemplo n.º 8
0
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);
    }
}
Exemplo 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);
}