Esempio n. 1
0
void
d_nameSpacesListenerAction(
    d_listener listener,
    d_message message)
{
    d_durability durability;
    d_admin admin;
    d_publisher publisher;
    d_fellow fellow;
    c_bool allowed;
    d_nameSpace nameSpace, localNameSpace, oldFellowNameSpace;
    c_ulong count;
    d_configuration config;
    d_nameSpacesRequest nsRequest;
    d_networkAddress sender;
    d_subscriber subscriber;
    d_sampleChainListener sampleChainListener;
    struct compatibilityHelper helper;
    d_adminStatisticsInfo info;
    c_bool added;
    os_time srcTime , curTime, difTime, maxDifTime;
    struct checkFellowMasterHelper fellowMasterHelper;
    d_name role;
    c_iter fellowNameSpaces;
    d_nameSpace ns;

    assert(d_listenerIsValid(d_listener(listener), D_NAMESPACES_LISTENER));

    admin               = d_listenerGetAdmin(listener);
    publisher           = d_adminGetPublisher(admin);
    durability          = d_adminGetDurability(admin);
    config              = d_durabilityGetConfiguration(durability);
    fellowNameSpaces    = NULL;

    d_printTimedEvent         (durability, D_LEVEL_FINE,
                               D_THREAD_NAMESPACES_LISTENER,
                               "Received nameSpace from fellow %d (his master: %d, confirmed: %d, mergeState: %s, %d).\n",
                               message->senderAddress.systemId,
                               d_nameSpaces(message)->master.systemId,
                               d_nameSpaces(message)->masterConfirmed,
                               d_nameSpaces(message)->state.role,
                               d_nameSpaces(message)->state.value);

    sender = d_networkAddressNew(message->senderAddress.systemId,
                               message->senderAddress.localId,
                               message->senderAddress.lifecycleId);

    fellow = d_adminGetFellow(admin, sender);

    if(!fellow){
        d_printTimedEvent (durability, D_LEVEL_FINE,
                           D_THREAD_NAMESPACES_LISTENER,
                           "Fellow %d unknown, administrating it.\n",
                           message->senderAddress.systemId);
        fellow = d_fellowNew(sender, message->senderState);
        d_fellowUpdateStatus(fellow, message->senderState, v_timeGet());
        added = d_adminAddFellow(admin, fellow);

        if(added == FALSE){
            d_fellowFree(fellow);
            fellow = d_adminGetFellow(admin, sender);
            assert(fellow);
        } else {
            fellow = d_adminGetFellow(admin, sender); /*Do this to allow fellowFree at the end*/
            nsRequest = d_nameSpacesRequestNew(admin);
            d_messageSetAddressee(d_message(nsRequest), sender);
            d_publisherNameSpacesRequestWrite(publisher, nsRequest, sender);
            d_nameSpacesRequestFree(nsRequest);
        }
    }
    d_fellowUpdateStatus(fellow, message->senderState, v_timeGet());

    nameSpace = d_nameSpaceFromNameSpaces(config, d_nameSpaces(message));

    if(d_fellowGetCommunicationState(fellow) == D_COMMUNICATION_STATE_APPROVED){

        /* Get old namespace of fellow */
        oldFellowNameSpace = d_nameSpaceCopy (d_fellowGetNameSpace (fellow, nameSpace));

        /* Update master of fellow nameSpace */
        added = d_fellowAddNameSpace(fellow, nameSpace);

        /* Create namespace with local policy (if a match exists) */
        localNameSpace = d_nameSpaceNew (config, d_nameSpaceGetName(nameSpace));

        /* If namespace is created, add to administration */
        if (localNameSpace) {
            /* Copy partitions to local nameSpace */
            d_nameSpaceCopyPartitions (localNameSpace, nameSpace);
            d_adminAddNameSpace (admin, localNameSpace);
            d_nameSpaceFree (localNameSpace);
        }

        /* If fellow is master for a namespace, report it to admin */
        fellowMasterHelper.admin = admin;
        fellowMasterHelper.fellow = d_fellowGetAddress(fellow);
        fellowMasterHelper.oldNameSpace = oldFellowNameSpace;
        checkFellowMasterWalk (nameSpace, &fellowMasterHelper);
        d_free (fellowMasterHelper.fellow);

        /* If the namespace was not added to the fellow (because it already existed there), free it */
        if(!added){
            d_nameSpaceFree(nameSpace);
        }

        d_nameSpaceFree (oldFellowNameSpace);

    } else {
        info = d_adminStatisticsInfoNew();
        d_fellowSetExpectedNameSpaces(fellow, d_nameSpaces(message)->total);
        d_fellowAddNameSpace(fellow, nameSpace);
        count = d_fellowNameSpaceCount(fellow);

        if(count == d_nameSpaces(message)->total){
            allowed = isFellowStateCompatible(durability, fellow);

            if(allowed == TRUE){
                config = d_durabilityGetConfiguration(durability);
                helper.fellow = fellow;
                helper.compatible = TRUE;

                d_adminNameSpaceWalk (admin, areFellowNameSpacesCompatible, &helper);

                if(helper.compatible == TRUE){

                    if(config->timeAlignment == TRUE){
                        curTime.tv_sec     = d_readerListener(listener)->lastInsertTime.seconds;
                        curTime.tv_nsec    = d_readerListener(listener)->lastInsertTime.nanoseconds;
                        srcTime.tv_sec     = d_readerListener(listener)->lastSourceTime.seconds;
                        srcTime.tv_nsec    = d_readerListener(listener)->lastSourceTime.nanoseconds;
                        maxDifTime.tv_sec  = 1; /*1s*/
                        maxDifTime.tv_nsec = 0;
                        difTime            = os_timeAbs(os_timeSub(curTime, srcTime));

                        if(os_timeCompare(difTime, maxDifTime) == OS_MORE){
                            d_printTimedEvent (durability, D_LEVEL_WARNING,
                               D_THREAD_NAMESPACES_LISTENER,
                               "Estimated time difference including latency with " \
                               "fellow %d is %f seconds, which is larger then " \
                               "expected.\n",
                               message->senderAddress.systemId,
                               os_timeToReal(difTime));
                            OS_REPORT_2(OS_WARNING, D_CONTEXT, 0,
                                "Estimated time difference including latency " \
                                "with fellow '%d' is larger then expected " \
                                "(%f seconds). Durability alignment might not be " \
                                "reliable. Please align time between these nodes " \
                                "and restart.",
                                message->senderAddress.systemId,
                                os_timeToReal(difTime));
                        } else {
                            d_printTimedEvent (durability, D_LEVEL_FINER,
                               D_THREAD_NAMESPACES_LISTENER,
                               "Estimated time difference including latency with " \
                               "fellow %d is %f seconds.\n",
                               message->senderAddress.systemId,
                               os_timeToReal(difTime));
                        }
                    }

                    /* Set role of fellow (take native role from namespace) */
                    role = d_nameSpaceGetRole(nameSpace);
                    d_fellowSetRole (fellow, role);
                    os_free (role);

                    d_fellowSetCommunicationState(fellow, D_COMMUNICATION_STATE_APPROVED);
                    info->fellowsApprovedDif += 1;
                    subscriber = d_adminGetSubscriber(admin);
                    sampleChainListener = d_subscriberGetSampleChainListener(subscriber);

                    if(sampleChainListener){
                        d_sampleChainListenerTryFulfillChains(sampleChainListener, NULL);
                    }

                    /* Check if the fellow is master for one or more namespaces and report this to admin */
                    fellowNameSpaces = c_iterNew(NULL);

                    /* Collect fellow namespaces */
                    d_fellowNameSpaceWalk (fellow, collectFellowNsWalk, fellowNameSpaces);

                    fellowMasterHelper.admin = admin;
                    fellowMasterHelper.fellow = d_fellowGetAddress(fellow);
                    fellowMasterHelper.oldNameSpace = NULL;
                    c_iterWalk (fellowNameSpaces, checkFellowMasterWalk, &fellowMasterHelper);

                    while ((ns = c_iterTakeFirst(fellowNameSpaces))) {
                        d_nameSpaceFree(ns);
                    }
                    c_iterFree(fellowNameSpaces);

                    d_free (fellowMasterHelper.fellow);

                } else {
                    info->fellowsIncompatibleDataModelDif += 1;

                    d_printTimedEvent (durability, D_LEVEL_WARNING,
                                   D_THREAD_NAMESPACES_LISTENER,
                                   "Communication with fellow %d NOT approved, because data model is not compatible\n",
                                   message->senderAddress.systemId);
                    d_fellowSetCommunicationState(fellow, D_COMMUNICATION_STATE_INCOMPATIBLE_DATA_MODEL);
                }
            } else {
                info->fellowsIncompatibleStateDif += 1;
                d_printTimedEvent (durability, D_LEVEL_WARNING,
                                   D_THREAD_NAMESPACES_LISTENER,
                                   "Communication with fellow %d NOT approved, because state is not compatible my state: %d, fellow state: %d\n",
                                   message->senderAddress.systemId,
                                   d_durabilityGetState(durability),
                                   message->senderState);
                d_fellowSetCommunicationState(fellow, D_COMMUNICATION_STATE_INCOMPATIBLE_STATE);
            }
        } else {
            d_printTimedEvent (durability, D_LEVEL_WARNING,
                               D_THREAD_NAMESPACES_LISTENER,
                               "Received %u of %u nameSpaces from fellow %u.\n",
                               count, d_nameSpaces(message)->total,
                               message->senderAddress.systemId);
        }
        d_adminUpdateStatistics(admin, info);
        d_adminStatisticsInfoFree(info);
    }
    d_fellowFree(fellow);
    d_networkAddressFree(sender);

    return;
}
Esempio n. 2
0
d_subscriber
d_subscriberNew(
    d_admin admin)
{
    d_subscriber    subscriber;
    d_durability    durability;
    d_configuration config;
    v_subscriberQos subscriberQos, psubscriberQos;
    c_char*         partitionExpr;
    struct initialQualityWalkData walkData;
    d_storeResult       result;
    d_nameSpace         nameSpace;
    c_iter              nameSpaces;
    c_bool              nsComplete;
    d_durabilityKind    dkind;

    subscriber = NULL;

    if(admin){
        subscriber        = d_subscriber(os_malloc(C_SIZEOF(d_subscriber)));
        d_objectInit(d_object(subscriber), D_SUBSCRIBER, d_subscriberDeinit);

        subscriber->admin = admin;
        durability        = d_adminGetDurability(admin);
        config            = d_durabilityGetConfiguration(durability);
        subscriberQos     = d_subscriberQosNew(config->partitionName);
        partitionExpr     = getPersistentPartitionExpression(admin, durability);
        psubscriberQos    = d_subscriberQosNew(partitionExpr);

        os_free(partitionExpr);

        subscriber->subscriber = u_subscriberNew (u_participant(d_durabilityGetService(durability)),
                                                  config->subscriberName,
                                                  subscriberQos,
                                                  TRUE);

        subscriber->waitset         = d_waitsetNew(subscriber, FALSE, FALSE);
        subscriber->persistentStore = d_storeOpen(durability, config->persistentStoreMode);

        if(subscriber->persistentStore) {
            if(psubscriberQos->partition){

                /* Collect nameSpaces from admin. */
                nameSpaces = d_adminNameSpaceCollect(admin);

                /* Loop nameSpaces */
                while((nameSpace = c_iterTakeFirst(nameSpaces))) {
                    dkind = d_nameSpaceGetDurabilityKind(nameSpace);

                    /* Walk only over persistent nameSpaces */
                    if((dkind == D_DURABILITY_PERSISTENT) || (dkind == D_DURABILITY_ALL)){

                        /* If persistent nameSpace is not complete, restore backup */
                        result = d_storeNsIsComplete (subscriber->persistentStore, nameSpace, &nsComplete);
                        if ( (result == D_STORE_RESULT_OK) && !nsComplete)
                        {
                            /* Incomplete namespace, restore backup. */
                            d_printTimedEvent(durability, D_LEVEL_WARNING,
                                D_THREAD_GROUP_LOCAL_LISTENER,
                                "Namespace '%s' is incomplete, trying to restore backup.\n",
                                d_nameSpaceGetName(nameSpace));

                            if (d_storeRestoreBackup (subscriber->persistentStore, nameSpace) != D_STORE_RESULT_OK)
                            {
                                d_printTimedEvent(durability, D_LEVEL_WARNING,
                                    D_THREAD_GROUP_LOCAL_LISTENER,
                                    "Backup for namespace '%s' could not be restored as no complete backup did exist on disk. Marking namespace as incomplete and continuing.\n",
                                    d_nameSpaceGetName(nameSpace));

                                OS_REPORT_1(OS_WARNING, D_CONTEXT_DURABILITY, 0,
                                    "Backup for namespace '%s' could not be restored as no complete backup did exist on disk. Marking namespace as incomplete and continuing.\n",
                                    d_nameSpaceGetName (nameSpace));

                                /* If backup fails, mark master state for nameSpace !D_STATE_COMPLETE */
                                d_nameSpaceSetMasterState (nameSpace, D_STATE_INIT);
                            }
                        }
                    }
                    d_nameSpaceFree(nameSpace);
                }

                /* Free nameSpaces iterator */
                assert(c_iterLength(nameSpaces) == 0);
                c_iterFree(nameSpaces);

                subscriber->persistentSubscriber = u_subscriberNew(u_participant(d_durabilityGetService(durability)),
                                                                   config->subscriberName,
                                                                   psubscriberQos,
                                                                   TRUE);

                assert(subscriber->persistentSubscriber);
            } else {
                subscriber->persistentSubscriber = NULL;
            }

            walkData.subscriber = subscriber;
            walkData.i = 0;
            d_adminNameSpaceWalk(admin, nsInitialQualityWalk, &walkData);

        } else {
            subscriber->persistentSubscriber = NULL;
        }
        assert(subscriber->subscriber);

        if(subscriber->subscriber){
            subscriber->statusListener            = NULL;
            subscriber->groupLocalListener        = NULL;
            subscriber->groupRemoteListener       = NULL;
            subscriber->groupsRequestListener     = NULL;
            subscriber->sampleRequestListener     = NULL;
            subscriber->sampleChainListener       = NULL;
            subscriber->nameSpacesRequestListener = NULL;
            subscriber->nameSpacesListener        = NULL;
            subscriber->persistentDataListener    = NULL;
            subscriber->deleteDataListener        = NULL;
        } else {
            d_subscriberFree(subscriber);
            subscriber = NULL;
        }
        d_subscriberQosFree(subscriberQos);
        d_subscriberQosFree(psubscriberQos);
    }
    return subscriber;
}