/* Walk admin namespaces */
static void
areFellowNameSpacesCompatible(
    d_nameSpace adminNs,
    c_voidp args)
{
    struct compatibilityHelper* walkData;
    d_networkAddress address;
    char* localPartitions;
    char* remotePartitions;

    walkData    = (struct compatibilityHelper*)args;

    walkData->ns = adminNs;

    if (!d_fellowNameSpaceWalk(walkData->fellow, isFellowNameSpaceCompatible, walkData))
    {
        walkData->compatible = FALSE;
        localPartitions = d_nameSpaceGetPartitionTopics(adminNs);
        remotePartitions = d_nameSpaceGetPartitionTopics(walkData->fellowNs);
        address = d_fellowGetAddress (walkData->fellow);

        OS_REPORT_5(OS_ERROR, D_CONTEXT, 0,
            "NameSpace configuration of remote durability service '%u' for NameSpace "\
            "'%s' is incompatible with local NameSpace '%s'. Partition(-Topic) expressions "\
            "are '%s'(local) and '%s'(remote).",
            address->systemId, d_nameSpaceGetName(walkData->fellowNs),
            d_nameSpaceGetName(adminNs), localPartitions,
            remotePartitions);

        d_networkAddressFree(address);
        os_free (localPartitions);
        os_free (remotePartitions);
    }
}
/* Walk admin namespaces */
static void
areFellowNameSpacesCompatible(
    d_nameSpace adminNs,
    c_voidp args)
{
    struct compatibilityHelper* walkData;
    d_networkAddress address;
    char* localPartitions;
    char* remotePartitions;

    walkData    = (struct compatibilityHelper*)args;

    walkData->ns = adminNs;

    if (!d_fellowNameSpaceWalk(walkData->fellow, isFellowNameSpaceCompatible, walkData))
    {
        walkData->compatible = FALSE;
        localPartitions = d_nameSpaceGetPartitions(adminNs);
        remotePartitions = d_nameSpaceGetPartitions(walkData->fellowNs);
        address = d_fellowGetAddress (walkData->fellow);

        OS_REPORT_2(OS_ERROR, D_CONTEXT, 0,
            "Namespace '%s' from fellow '%d' is incompatible with local namespace.",
            d_nameSpaceGetName(adminNs), address->systemId);

        OS_REPORT_2(OS_ERROR, D_CONTEXT, 0,
            "Partition expressions are '%s'(local) and '%s'(remote).",
            localPartitions, remotePartitions);

        d_networkAddressFree(address);
        os_free (localPartitions);
        os_free (remotePartitions);
    }
}
/* Walk fellow namespaces */
static c_bool
isFellowNameSpaceCompatible(
    d_nameSpace fellowNs,
    c_voidp args)
{
    struct compatibilityHelper* walkData;
    walkData = (struct compatibilityHelper*)args;

    /* If nameSpace name is equal, policy of namespace must be equal too */
    if (!strcmp (d_nameSpaceGetName(fellowNs), d_nameSpaceGetName(walkData->ns))) {
        walkData->fellowNs = fellowNs;
        return (d_nameSpaceCompatibilityCompare(walkData->ns, fellowNs) == 0);
    }

    return TRUE;
}
d_storeResult
d_storeMMFKernelIsNameSpaceComplete(
    d_storeMMFKernel kernel,
    const d_nameSpace nameSpace,
    c_bool* isComplete)
{
    d_nameSpaceInfo nsInfo;
    c_char* name;
    d_storeResult result;
    c_value keyValues[1];

    if(kernel && nameSpace){
        name = d_nameSpaceGetName(nameSpace);
        keyValues[0] = c_stringValue((c_string)name);
        nsInfo = c_tableFind(kernel->nameSpaces, keyValues);

        if(nsInfo){
            *isComplete = nsInfo->complete;
            result = D_STORE_RESULT_OK;
        } else {
            *isComplete = FALSE;
            result = D_STORE_RESULT_OK;
        }
    } else {
        result = D_STORE_RESULT_ILL_PARAM;
    }
    return result;
}
d_storeResult
d_storeMMFKernelMarkNameSpaceComplete(
    d_storeMMFKernel kernel,
    const d_nameSpace nameSpace,
    const c_bool isComplete)
{
    d_nameSpaceInfo nsInfo;
    c_type type;
    c_char* name;
    c_value keyValues[1];
    d_storeResult result;

    if(kernel && nameSpace){
        name = d_nameSpaceGetName(nameSpace);
        keyValues[0] = c_stringValue((c_string)name);
        nsInfo = c_tableFind(kernel->nameSpaces, keyValues);

        if(nsInfo){
            nsInfo->complete = isComplete;
            result = D_STORE_RESULT_OK;
        } else {
            type = c_resolve(c_getBase(kernel),
                    "durabilityModule2::d_nameSpaceInfo");
            nsInfo = (d_nameSpaceInfo)c_new(type);
            c_free(type);

            if (nsInfo) {
                nsInfo->name = c_stringNew(c_getBase(kernel), name);
                nsInfo->complete = isComplete;
                c_tableInsert(kernel->nameSpaces, nsInfo);
                c_free(nsInfo);
                result = D_STORE_RESULT_OK;
            } else {
                OS_REPORT(OS_ERROR,
                      "d_storeMMFKernelMarkNameSpaceComplete",0,
                      "Failed to allocate nameSpaceInfo.");
                result = D_STORE_RESULT_OUT_OF_RESOURCES;
            }
        }
    } else {
        result = D_STORE_RESULT_ILL_PARAM;
    }
    return result;
}
Exemple #6
0
d_nameSpaces
d_nameSpacesNew(
    d_admin admin,
    d_nameSpace nameSpace,
    d_quality initialQuality,
    c_ulong total)
{
    d_nameSpaces ns = NULL;
    d_networkAddress master;
    d_mergeState state;
    c_sequence *mergedStatesPtr;
    struct nsWalkHelper helper;

    if(nameSpace){
        ns = d_nameSpaces(os_malloc(C_SIZEOF(d_nameSpaces)));

        if(ns){
            master     = d_networkAddressUnaddressed();
            d_messageInit(d_message(ns), admin);

            ns->aligner                    = d_nameSpaceIsAligner(nameSpace);
            ns->durabilityKind             = d_nameSpaceGetDurabilityKind(nameSpace);
            ns->alignmentKind              = d_nameSpaceGetAlignmentKind(nameSpace);
            ns->partitions                 = d_nameSpaceGetPartitionTopics(nameSpace);
            ns->total                      = total;
            ns->initialQuality.seconds     = initialQuality.seconds;
            ns->initialQuality.nanoseconds = initialQuality.nanoseconds;
            ns->master.systemId            = master->systemId;
            ns->master.localId             = master->localId;
            ns->master.lifecycleId         = master->lifecycleId;
            ns->isComplete                 = TRUE;
            ns->name                       = os_strdup (d_nameSpaceGetName(nameSpace));
            ns->masterConfirmed            = d_nameSpaceIsMasterConfirmed(nameSpace);

            state = d_nameSpaceGetMergeState(nameSpace, NULL);
            if(state) {
                ns->state.role                 = os_strdup(state->role);
                ns->state.value                = state->value;
                d_mergeStateFree(state);
            } else {
                ns->state.role                 = d_nameSpaceGetRole(nameSpace);
                ns->state.value                = -1;
            }

            ns->mergedStatesCount          = d_tableSize(nameSpace->mergedRoleStates);

            if(ns->mergedStatesCount > 0){
                ns->mergedStates               = os_malloc(C_SIZEOF(d_mergeState)*ns->mergedStatesCount);

                helper.states = (d_mergeState*)(mergedStatesPtr = &(ns->mergedStates));
                helper.index = 0;

                d_tableWalk(nameSpace->mergedRoleStates, addMergeState, &helper);
            } else {
                ns->mergedStates = NULL;
            }
            d_networkAddressFree(master);
        }
    }
    return ns;
}
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;
}
Exemple #8
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;
}