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; }
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; }