static void* d_waitsetEventHandler( void* userData) { d_subscriber subscriber; d_durability durability; d_admin admin; c_iter events; d_waitsetEntity we; c_time time; d_waitsetHelper helper; u_waitset userWaitset; u_waitsetEvent event; u_result ur; helper = d_waitsetHelper(userData); we = helper->entity; subscriber = d_waitsetGetSubscriber(helper->waitset); admin = d_subscriberGetAdmin(subscriber); durability = d_adminGetDurability(admin); time.seconds = 1; time.nanoseconds = 0; userWaitset = helper->userWaitset; ur = U_RESULT_OK; while((helper->terminate == FALSE) && (ur == U_RESULT_OK)) { events = NULL; if(helper->waitset->timedWait == TRUE){ ur = u_waitsetTimedWaitEvents(userWaitset, time,&events); } else { ur = u_waitsetWaitEvents(userWaitset,&events); } if(events && (ur == U_RESULT_OK)){/* events may be null if waitset was deleted*/ event = u_waitsetEvent(c_iterTakeFirst(events)); while(event){ /* Only dispatch event when durability is not terminating */ if (d_durabilityGetState(durability) != D_STATE_TERMINATING){ we->action(we->dispatcher, event, we->usrData); } u_waitsetEventFree(event); event = u_waitsetEvent(c_iterTakeFirst(events)); } c_iterFree(events); } } if(ur != U_RESULT_OK){ d_printTimedEvent(durability, D_LEVEL_SEVERE, we->name, "Waitset no longer available (result: %d). Fatal error, terminating now...\n", ur); OS_REPORT_1(OS_ERROR, D_CONTEXT_DURABILITY, 0, "Waitset no longer available (result: %d). Fatal error, terminating now...\n", ur); d_durabilityTerminate(durability); } return NULL; }
void d_publisherInitMessage( d_publisher publisher, d_message message) { d_message(message)->productionTimestamp = v_timeGet(); d_message(message)->senderState = d_durabilityGetState( d_adminGetDurability( publisher->admin)); }
static void* d_waitsetEventHandlerRunToCompletion( void* userData) { d_subscriber subscriber; d_durability durability; d_admin admin; d_waitset waitset; c_iter events = NULL; d_waitsetEntity we; c_time time; u_waitsetEvent event; waitset = d_waitset(userData); subscriber = d_waitsetGetSubscriber(waitset); admin = d_subscriberGetAdmin(subscriber); durability = d_adminGetDurability(admin); time.seconds = 1; time.nanoseconds = 0; while(waitset->terminate == FALSE) { if(waitset->timedWait == TRUE){ u_waitsetTimedWaitEvents(waitset->uwaitset, time,&events); } else { u_waitsetWaitEvents(waitset->uwaitset,&events); } if(d_durabilityGetState(durability) != D_STATE_TERMINATING){ if(waitset->terminate == FALSE){ d_lockLock(d_lock(waitset)); event = u_waitsetEvent(c_iterTakeFirst(events)); while(event){ we = c_iterResolve(waitset->entities, d_waitsetEntityFind, event->entity); if(we){ we->action(we->dispatcher, event, we->usrData); } u_waitsetEventFree(event); event = u_waitsetEvent(c_iterTakeFirst(events)); } } d_lockUnlock(d_lock(waitset)); } if(events){/* events may be null if waitset was deleted */ c_iterFree(events); } } return NULL; }
static c_bool isFellowStateCompatible( d_durability durability, d_fellow fellow) { d_serviceState state, fellowState; c_bool allowed; allowed = FALSE; fellowState = d_fellowGetState(fellow); state = d_durabilityGetState(durability); switch(state){ case D_STATE_INIT: case D_STATE_DISCOVER_FELLOWS_GROUPS: switch(fellowState){ case D_STATE_INIT: case D_STATE_DISCOVER_FELLOWS_GROUPS: case D_STATE_INJECT_PERSISTENT: case D_STATE_FETCH_INITIAL: case D_STATE_FETCH: case D_STATE_ALIGN: case D_STATE_FETCH_ALIGN: case D_STATE_COMPLETE: case D_STATE_DISCOVER_LOCAL_GROUPS: allowed = TRUE; break; case D_STATE_DISCOVER_PERSISTENT_SOURCE: case D_STATE_TERMINATING: case D_STATE_TERMINATED: allowed = FALSE; break; default: assert(FALSE); allowed = FALSE; break; } break; case D_STATE_INJECT_PERSISTENT: case D_STATE_DISCOVER_LOCAL_GROUPS: case D_STATE_FETCH_INITIAL: case D_STATE_FETCH: case D_STATE_ALIGN: case D_STATE_FETCH_ALIGN: case D_STATE_COMPLETE: switch(fellowState){ case D_STATE_INIT: case D_STATE_DISCOVER_FELLOWS_GROUPS: case D_STATE_COMPLETE: /* TODO: need to allow other states too? */ allowed = TRUE; break; default: allowed = FALSE; break; } break; case D_STATE_DISCOVER_PERSISTENT_SOURCE: case D_STATE_TERMINATING: case D_STATE_TERMINATED: allowed = FALSE; break; default: assert(FALSE); allowed = FALSE; break; } return TRUE; }
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; }
void d_printState( d_durability durability, d_configuration config, const char* threadName) { os_time time; d_serviceState kind; const c_char* state; if(config->tracingOutputFile){ kind = d_durabilityGetState(durability); switch(kind){ case D_STATE_INIT: state = "INIT"; break; case D_STATE_DISCOVER_FELLOWS_GROUPS: state = "DISCOVER_FELLOWS_GROUPS"; break; case D_STATE_DISCOVER_PERSISTENT_SOURCE: state = "DISCOVER_PERSISTENT_SOURCE"; break; case D_STATE_INJECT_PERSISTENT: state = "INJECT_PERSISTENT"; break; case D_STATE_DISCOVER_LOCAL_GROUPS: state = "DISCOVER_LOCAL_GROUPS"; break; case D_STATE_FETCH_INITIAL: state = "FETCH_INITIAL"; break; case D_STATE_FETCH: state = "FETCH"; break; case D_STATE_ALIGN: state = "ALIGN"; break; case D_STATE_FETCH_ALIGN: state = "FETCH_ALIGN"; break; case D_STATE_COMPLETE: state = "COMPLETE"; break; case D_STATE_TERMINATING: state = "TERMINATING"; break; case D_STATE_TERMINATED: state = "TERMINATED"; break; default: state = "<<UNKNOWN>>"; break; } if(config->tracingTimestamps == TRUE){ time = os_timeGet(); if(config->tracingRelativeTimestamps == TRUE){ time = os_timeSub(time, config->startTime); } fprintf(config->tracingOutputFile, "%d.%9.9d %s (%s) -> ", time.tv_sec, time.tv_nsec, state, threadName); } else { fprintf(config->tracingOutputFile, "%s (%s) -> ", state, threadName); } } }
static void* d_groupCreationQueueRun( void* userData) { d_groupCreationQueue queue; c_iter groupsToCreate, reinsert; d_group group, localGroup; d_durability durability; d_durabilityKind kind; u_participant uservice; c_char *partition, *topic; v_duration duration; u_group ugroup; c_long creationCountVolatile, creationCountTransient, creationCountPersistent; c_ulong maxBurst; os_time sleepTime, maxBurstSleepTime; c_bool update; sleepTime.tv_sec = 1; sleepTime.tv_nsec = 0; duration.seconds = 0; duration.nanoseconds = 5000000; /*5ms*/ creationCountVolatile = 0; creationCountTransient = 0; creationCountPersistent = 0; maxBurstSleepTime.tv_sec = 0; maxBurstSleepTime.tv_nsec = 10000000; /*10ms*/ queue = d_groupCreationQueue(userData); groupsToCreate = c_iterNew(NULL); reinsert = c_iterNew(NULL); durability = d_adminGetDurability(queue->admin); uservice = u_participant(d_durabilityGetService(durability)); d_waitForCompletenessDCPSTopic(queue); while(queue->terminate == FALSE) { d_lockLock(d_lock(queue)); queue->groupsToCreateVolatile -= creationCountVolatile; assert(queue->groupsToCreateVolatile >= 0); queue->groupsToCreateTransient -= creationCountTransient; assert(queue->groupsToCreateTransient >= 0); queue->groupsToCreatePersistent -= creationCountPersistent; assert(queue->groupsToCreatePersistent >= 0); group = d_group(c_iterTakeFirst(queue->groups)); while(group){ groupsToCreate = c_iterInsert(groupsToCreate, group); group = d_group(c_iterTakeFirst(queue->groups)); } assert((queue->groupsToCreateVolatile + queue->groupsToCreateTransient + queue->groupsToCreatePersistent) == c_iterLength(groupsToCreate)); durability = d_adminGetDurability(queue->admin); d_durabilityUpdateStatistics(durability, d_statisticsUpdateGroupsToCreate, queue); d_lockUnlock(d_lock(queue)); creationCountVolatile = 0; creationCountTransient = 0; creationCountPersistent = 0; maxBurst = 10; group = c_iterTakeFirst(groupsToCreate); while(group && (queue->terminate == FALSE)){ partition = d_groupGetPartition(group); topic = d_groupGetTopic(group); kind = d_groupGetKind(group); localGroup = d_adminGetLocalGroup(queue->admin, partition, topic, kind); update = FALSE; if(localGroup) { d_printTimedEvent(durability, D_LEVEL_FINE, D_THREAD_GROUP_CREATION, "Remote group %s.%s has already been created locally.\n", partition, topic); update = TRUE; } else { ugroup = u_groupNew(uservice, partition, topic, duration); if(ugroup){ d_printTimedEvent(durability, D_LEVEL_FINE, D_THREAD_GROUP_CREATION, "Remote group %s.%s created locally.\n", partition, topic); update = TRUE; u_entityFree(u_entity(ugroup)); maxBurst--; if(maxBurst == 0){ os_nanoSleep(maxBurstSleepTime); maxBurst = 10; } } else { maxBurst++; d_printTimedEvent(durability, D_LEVEL_FINE, D_THREAD_GROUP_CREATION, "Remote group %s.%s could not be created locally.\n", partition, topic); if(d_durabilityGetState(durability) == D_STATE_COMPLETE){ d_printTimedEvent(durability, D_LEVEL_FINE, D_THREAD_GROUP_CREATION, "I am complete so it will not be available anymore.\n"); update = TRUE; } else if(d_adminGetFellowCount(queue->admin) == 0){ d_printTimedEvent(durability, D_LEVEL_WARNING, D_THREAD_GROUP_CREATION, "No fellows available to provide me with group information. " \ "Ignoring group.\n", partition, topic); update = TRUE; } else { reinsert = c_iterInsert(reinsert, group); } } } if(update){ switch(d_groupGetKind(group)){ case D_DURABILITY_VOLATILE: creationCountVolatile++; break; case D_DURABILITY_TRANSIENT: case D_DURABILITY_TRANSIENT_LOCAL: creationCountTransient++; break; case D_DURABILITY_PERSISTENT: creationCountPersistent++; break; default: assert(FALSE); break; } d_groupFree(group); } os_free(partition); os_free(topic); group = c_iterTakeFirst(groupsToCreate); } group = d_group(c_iterTakeFirst(reinsert)); while(group){ groupsToCreate = c_iterInsert(groupsToCreate, group); group = d_group(c_iterTakeFirst(reinsert)); } if(queue->terminate == FALSE){ os_nanoSleep(sleepTime); } } group = d_group(c_iterTakeFirst(groupsToCreate)); while(group) { d_groupFree(group); group = d_group(c_iterTakeFirst(groupsToCreate)); } c_iterFree(groupsToCreate); c_iterFree(reinsert); d_lockLock(d_lock(queue)); group = d_group(c_iterTakeFirst(queue->groups)); while(group) { d_groupFree(group); group = d_group(c_iterTakeFirst(queue->groups)); } d_lockUnlock(d_lock(queue)); return NULL; }