c_bool v_readerWaitForHistoricalData( v_reader r, c_time timeout) { struct historicalWaitArg arg; c_iter entries; c_object e; v_readerEntrySetLock(r); entries = c_select(r->entrySet.entries, 0); v_readerEntrySetUnlock(r); arg._expire_time = c_timeAdd(v_timeGet(), timeout); arg._status = TRUE; e = c_iterTakeFirst(entries); while (e != NULL) { if (arg._status == TRUE) { if (r->qos->durability.kind == V_DURABILITY_VOLATILE) { getHistoricalData(e, NULL); } waitForHistoricalData(e, &arg); } c_free(e); e = c_iterTakeFirst(entries); } c_iterFree(entries); return(arg._status); }
static void v_networkQueueUpdateNextWakeup( v_networkQueue queue, c_bool *hasChanged) { c_time now; c_time soon; c_time newWakeup; c_ulonglong msecsTime; c_ulonglong msecsResult; c_ulonglong msecsLeftOver; static c_time minSleepTime = MIN_SLEEPTIME; *hasChanged = FALSE; if (queue->periodic) { now = v_timeGet(); soon = c_timeAdd(now, minSleepTime); TIME_TO_MSEC(soon, msecsTime); /* Do a ++ because we are doing a ceil and TIME_TO_MSEC is doing a trunc. * Only if time was an exact multiple of milliseconds, this approach is * not completely correct. But it saves us the hassle and this works fine */ msecsTime++; msecsLeftOver = (msecsTime - queue->phaseMilliSeconds) % queue->msecsResolution; msecsResult = msecsTime - msecsLeftOver + queue->msecsResolution; MSEC_TO_TIME(msecsResult, newWakeup); if (c_timeCompare(newWakeup,queue->nextWakeup) == C_GT) { queue->nextWakeup = newWakeup; *hasChanged = TRUE; } } }
void v_messageSetAllocTime( v_message _this) { if (_this) { _this->allocTime = v_timeGet(); } }
void v_instanceUpdate( v_instance instance) { assert(C_TYPECHECK(instance, v_instance)); instance->lastCheckTime = v_timeGet(); }
void v_instanceUpdate( v_instance instance) { assert(C_TYPECHECK(instance, v_instance)); instance->lastDeadlineResetTime = v_timeGet(); }
void v_timedValueSetValue( v_timedValue *_this, c_ulong value) { assert(_this != NULL); _this->value = value; _this->lastUpdate = v_timeGet(); }
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)); }
void v_messageSetAllocTime( v_message _this) { #ifndef _NAT_ if (_this) { _this->allocTime = v_timeGet(); } #endif }
void v_leaseUpdate( v_lease lease) { if (lease != NULL) { assert(C_TYPECHECK(lease, v_lease)); v_leaseLock(lease); lease->expiryTime = c_timeAdd(v_timeGet(), lease->duration); v_leaseUnlock(lease); } }
void v_lifespanAdminTakeExpired( v_lifespanAdmin admin, v_lifespanSampleAction action, c_voidp arg) { c_bool proceed; v_lifespanSample removed; c_time now; c_equality eq; assert(C_TYPECHECK(admin,v_lifespanAdmin)); CHECK_ADMIN(admin, NULL); if (admin->head != NULL) { now = v_timeGet(); eq = c_timeCompare(now, admin->head->expiryTime); proceed = TRUE; while ((proceed) && (eq != C_LT /* >= */) && (admin->head != NULL)) { removed = admin->head; if (action) { proceed = action(removed, arg); } else { proceed = TRUE; } if ((proceed) && (removed == admin->head)) { /* The action routine might have already removed the sample, so * we check if the head of the list has not changed! */ admin->head = removed->next; /* transfer refcount */ removed->next = NULL; if (admin->head == NULL) { assert(removed == admin->tail); c_free(admin->tail); admin->tail = NULL; proceed = FALSE; } else { admin->head->prev = NULL; } assert(admin->sampleCount > 0); admin->sampleCount--; CHECK_ADMIN(admin, removed); c_free(removed); } if (admin->head != NULL) { eq = c_timeCompare(now, admin->head->expiryTime); } } } CHECK_ADMIN(admin, NULL); }
v_networkReaderWaitResult v_networkReaderWaitDelayed( v_networkReader reader, c_ulong queueId, v_networkQueue *queue) { c_time sleep; /* Simply sleeping here for resolution time, is not correct. We should wakeup on, or just after the next wakeuptime.*/ sleep = c_timeSub(v_networkQueue(reader->queues[queueId-1])->nextWakeup, v_timeGet()); c_timeNanoSleep(sleep); return V_WAITRESULT_TIMEOUT | v_networkReaderWait(reader, queueId, queue); }
void v_participantDeleteHistoricalData( v_participant participant, const c_char* partitionExpr, const c_char* topicExpr) { c_iter matchingGroups; v_group group; c_time t; c_value params[2]; C_STRUCT(v_event) event; C_STRUCT(v_historyDeleteEventData) hde; assert(participant != NULL); assert(C_TYPECHECK(participant, v_participant)); assert(partitionExpr); assert(topicExpr); if(partitionExpr && topicExpr){ params[0] = c_stringValue((c_string)partitionExpr); params[1] = c_stringValue((c_string)topicExpr); c_lockRead(&participant->lock); t = v_timeGet(); matchingGroups = v_groupSetSelect( v_objectKernel(participant)->groupSet, "partition.name like %0 AND topic.name like %1", params); c_lockUnlock(&participant->lock); group = v_group(c_iterTakeFirst(matchingGroups)); while(group){ v_groupDeleteHistoricalData(group, t); c_free(group); group = v_group(c_iterTakeFirst(matchingGroups)); } c_iterFree(matchingGroups); hde.partitionExpression = (c_char *)partitionExpr; hde.topicExpression = (c_char *)topicExpr; hde.deleteTime = t; event.kind = V_EVENT_HISTORY_DELETE; event.source = v_publicHandle(v_public(participant)); event.userData = &hde; v_observableNotify(v_observable(v_objectKernel(participant)),&event); } return; }
void v_leaseInit( v_lease _this, v_kernel k, v_duration leaseDuration) { if (_this != NULL) { assert(C_TYPECHECK(_this, v_lease)); c_mutexInit(&_this->mutex,SHARED_MUTEX); _this->expiryTime = c_timeAdd(v_timeGet(), leaseDuration); _this->duration = leaseDuration; _this->observers = c_setNew(v_kernelType(k, K_LEASEMANAGER)); } }
void v_unregisterBuiltinTopic( v_kernel k, enum v_infoId id, v_message msg) { v_writer writer; if (msg != NULL) { writer = v_builtinWriterLookup(k->builtin,id); if (writer != NULL) { /* No need to fill writerGID, this is done by the writer */ v_writerUnregister(writer,msg,v_timeGet(),NULL); } } }
v_result v_participantWriteCandMCommand(v_participant participant, v_message msg) { v_writeResult wres; v_writer builtinWriter; assert(participant != NULL); assert(C_TYPECHECK(participant,v_participant)); assert(msg != NULL); assert(C_TYPECHECK(msg,v_message)); builtinWriter = v_builtinWriterLookup(v_objectKernel(participant)->builtin, V_C_AND_M_COMMAND_ID); wres = v_writerWrite(builtinWriter, msg, v_timeGet(), NULL); return ( wres == V_WRITE_SUCCESS ? V_RESULT_OK : V_RESULT_INTERNAL_ERROR ); }
static v_message createUnregisterMessage( v_group group, v_message message) { c_array messageKeyList; c_long i, nrOfKeys; v_message unregisterMessage; assert(!v_stateTest(v_nodeState(message), L_UNREGISTER)); /* Create new message objec */ unregisterMessage = v_topicMessageNew (group->topic); /* Copy keyvalues to unregistermessage */ messageKeyList = v_topicMessageKeyList(v_groupTopic(group)); nrOfKeys = c_arraySize(messageKeyList); for (i=0;i<nrOfKeys;i++) { c_fieldAssign (messageKeyList[i], unregisterMessage, c_fieldValue(messageKeyList[i],message)); } /* Set instance & writer GID */ unregisterMessage->writerGID = message->writerGID; unregisterMessage->writerInstanceGID = message->writerInstanceGID; /* Copy messageQos */ c_keep (message->qos); unregisterMessage->qos = message->qos; /* Set nodestate to unregister */ v_nodeState(unregisterMessage) = L_UNREGISTER; unregisterMessage->writeTime = v_timeGet(); #ifndef _NAT_ unregisterMessage->allocTime = unregisterMessage->writeTime; #endif return unregisterMessage; }
void cmx_writerUnregisterCopy( v_entity entity, c_voidp args) { v_writer kw; v_message message; void *to; sd_serializer ser; sd_serializedData data; sd_validationResult valResult; struct cmx_writerArg *arg; arg = (struct cmx_writerArg *)args; kw = v_writer(entity); message = v_topicMessageNew(kw->topic); to = C_DISPLACE(message,v_topicDataOffset(kw->topic)); ser = sd_serializerXMLNewTyped(v_topicDataType(kw->topic)); data = sd_serializerFromString(ser, arg->result); sd_serializerDeserializeIntoValidated(ser, data, to); valResult = sd_serializerLastValidationResult(ser); if(valResult != SD_VAL_SUCCESS){ OS_REPORT_2(OS_ERROR, CM_XML_CONTEXT, 0, "Unregister of userdata failed.\nReason: %s\nError: %s\n", sd_serializerLastValidationMessage(ser), sd_serializerLastValidationLocation(ser)); arg->success = CMX_RESULT_FAILED; } else { arg->success = CMX_RESULT_OK; } sd_serializedDataFree(data); sd_serializerFree(ser); /* Note that the last param of v_writerWriteDispose is NULL, performance can be improved if the instance is provided. */ v_writerUnregister(kw,message,v_timeGet(),NULL); c_free(message); }
static c_bool d_statusListenerRemoveDeadFellows( d_action action, c_bool terminate) { d_admin admin; d_configuration config; d_timestamp removeTime; d_durability durability; c_bool result = FALSE; admin = d_admin(d_actionGetArgs(action)); if(d_objectIsValid(d_object(admin), D_ADMIN) == TRUE){ if(terminate == FALSE){ config = d_durabilityGetConfiguration(d_adminGetDurability(admin)); removeTime.seconds = config->heartbeatExpiryTime.tv_sec; removeTime.nanoseconds = config->heartbeatExpiryTime.tv_nsec; while (removeTime.nanoseconds >= 1000000000) { removeTime.seconds += 1; removeTime.nanoseconds -= 1000000000; } /* * Remove the fellow if it didn't report since current time minus * the heartbeat period times the maximum nomber of heartbeat * misses. */ durability = d_adminGetDurability(admin); if(d_durabilityMustTerminate(durability) == FALSE){ removeTime = c_timeSub(v_timeGet(), removeTime); d_adminCleanupFellows(admin, removeTime); } result = TRUE; } } return result; }
void v_leaseRenew( v_lease lease, v_duration leaseDuration) { c_iter observers = NULL; v_leaseManager observer; if (lease != NULL) { assert(C_TYPECHECK(lease, v_lease)); v_leaseLock(lease); lease->expiryTime = c_timeAdd(v_timeGet(), leaseDuration); lease->duration = leaseDuration; /* Collect all observers, so they can be notified of the lease change * Must do a seperate collect as the lease mutex is 'lower' then the * leaseManager mutex. So to prevent deadlock we can not directly notify * the lease manager as we walk the collection */ if(lease->observers) { c_walk(lease->observers, v_leaseCollectObservers, &observers); } v_leaseUnlock(lease); if(observers) { observer = v_leaseManager(c_iterTakeFirst(observers)); while (observer != NULL) { v_leaseManagerNotify( observer, lease, V_EVENT_LEASE_RENEWED); c_free(observer); observer = v_leaseManager(c_iterTakeFirst(observers)); } c_iterFree(observers); } } }
static c_bool waitForHistoricalData( c_object o, c_voidp arg) { v_entry entry; c_iter proxies; v_proxy proxy; v_group group; c_time waitTime; struct historicalWaitArg *parms = (struct historicalWaitArg *)arg; assert(o != NULL); assert(arg != NULL); entry = v_entry(o); assert(entry != NULL); assert(C_TYPECHECK(entry,v_entry)); proxies = c_select(entry->groups, 0); proxy = c_iterTakeFirst(proxies); while ((proxy != NULL) && (parms->_status == TRUE)) { group = v_group(v_proxyClaim(proxy)); if (group) { if (group->complete == FALSE) { waitTime = c_timeSub(parms->_expire_time, v_timeGet()); if (c_timeCompare(waitTime, C_TIME_ZERO) == C_GT) { parms->_status = v_groupWaitForComplete(group, waitTime); } else { parms->_status = FALSE; /* time out */ } } v_proxyRelease(proxy); } c_free(proxy); proxy = c_iterTakeFirst(proxies); } c_iterFree(proxies); return parms->_status; }
v_networkQueue v_networkQueueNew( c_base base, c_ulong queueSize, c_ulong priority, c_bool reliable, c_bool P2P, c_time resolution, v_networkQueueStatistics statistics) { v_networkQueue result = NULL; c_type type; c_equality equality; c_bool hasChanged; c_time now; type = c_resolve(base, "kernelModule::v_networkQueue"); assert(type); result = v_networkQueue(c_new(type)); c_free(type); if (result) { /* Queue properties */ result->maxMsgCount = queueSize; result->currentMsgCount = 0; /* Cached type */ result->statusMarkerType = c_resolve(base, "kernelModule::v_networkStatusMarker"); assert(result->statusMarkerType != NULL); result->sampleType = c_resolve(base, "kernelModule::v_networkQueueSample"); assert(result->sampleType != NULL); /* Linked list of in-use marker items */ result->firstStatusMarker = NULL; result->lastStatusMarker = NULL; /* Linked list of free marker and message items */ result->freeStatusMarkers = NULL; result->freeSamples = NULL; /* Init cv stuff */ c_mutexInit(&result->mutex, SHARED_MUTEX); c_condInit(&result->cv, &result->mutex, SHARED_COND); /* Currently no differentiation wrt qos */ result->priority = priority; result->reliable = reliable; result->P2P = P2P; result->statistics = statistics; equality = c_timeCompare(C_TIME_ZERO, resolution); if (equality == C_EQ) { result->periodic = FALSE; result->resolution = C_TIME_INFINITE; result->msecsResolution = 0xFFFFFFFF; result->phaseMilliSeconds = 0; result->nextWakeup = C_TIME_INFINITE; } else { assert(equality == C_LT); result->periodic = TRUE; result->resolution = resolution; TIME_TO_MSEC(resolution, result->msecsResolution); /* A semi-random phase to avoid wake-ups at the same time */ now = v_timeGet(); result->phaseMilliSeconds = ((c_ulong)(now.nanoseconds/1000000 * 1.618)) % result->msecsResolution; v_networkQueueUpdateNextWakeup(result, &hasChanged); assert(hasChanged); } result->threadWaiting = FALSE; } else { OS_REPORT(OS_ERROR, "v_networkQueueNew",0, "Failed to allocate network queue."); } return result; }
/************************************************************** * Public functions **************************************************************/ c_time u_timeGet() { return v_timeGet(); }
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 v_leaseRenew( v_lease lease, v_duration* leaseDuration /* may be NULL */) { c_iter observers = NULL; v_leaseManager observer; c_time newExpiryTime; c_equality cmp; if (lease != NULL) { assert(C_TYPECHECK(lease, v_lease)); v_leaseLock(lease); /* Is a new lease duration provided, if so replace the current lease * duration with the new one */ if(leaseDuration != NULL) { lease->duration = *leaseDuration; } /* else do nothing */ /* Calculate the new expiry time */ newExpiryTime = c_timeAdd(v_timeGet(), lease->duration); /* Is the new expiryTime earlier then the current expiryTime? */ cmp = c_timeCompare(newExpiryTime, lease->expiryTime); /* Always replace the current expiry time with the new expiryTime */ lease->expiryTime = newExpiryTime; /* If the new expiryTime is earlier then the previous expiryTime. Then * this means the observers must be notified so they can take the * earlier expiryTime into account */ if (cmp == C_LT) { /* Collect all observers, so they can be notified of the lease change * Must do a seperate collect as the lease mutex is 'lower' then the * leaseManager mutex. So to prevent deadlock we can not directly notify * the lease manager as we walk the collection */ if(lease->observers) { c_walk(lease->observers, v_leaseCollectObservers, &observers); } v_leaseUnlock(lease); if(observers) { observer = v_leaseManager(c_iterTakeFirst(observers)); while (observer != NULL) { v_leaseManagerNotify( observer, lease, V_EVENT_LEASE_RENEWED); c_free(observer); observer = v_leaseManager(c_iterTakeFirst(observers)); } c_iterFree(observers); } } else { /* No need to notify observers, the new expiryTime is not earlier * then what it was before. */ v_leaseUnlock(lease); } } }
void d_nameSpacesRequestListenerAction( d_listener listener, d_message message) { d_durability durability; d_admin admin; d_fellow fellow; d_publisher publisher; c_ulong i, count; d_nameSpaces ns; d_networkAddress addr; d_nameSpacesRequest request; c_bool added; c_iter nameSpaces; assert(d_listenerIsValid(d_listener(listener), D_NAMESPACES_REQ_LISTENER)); admin = d_listenerGetAdmin(listener); durability = d_adminGetDurability(admin); addr = d_networkAddressNew(message->senderAddress.systemId, message->senderAddress.localId, message->senderAddress.lifecycleId); fellow = d_adminGetFellow(admin, addr); publisher = d_adminGetPublisher(admin); d_printTimedEvent(durability, D_LEVEL_FINE, D_THREAD_NAMESPACES_REQUEST_LISTENER, "Received nameSpacesRequest from fellow %d.\n", message->senderAddress.systemId); /* Update nameSpaces list for listener */ nameSpaces = updateNameSpaces(d_nameSpacesRequestListener(listener)); if(!fellow){ fellow = d_fellowNew(addr, message->senderState); d_fellowUpdateStatus(fellow, message->senderState, v_timeGet()); added = d_adminAddFellow(admin, fellow); if(added == FALSE){ d_fellowFree(fellow); fellow = d_adminGetFellow(admin, addr); assert(fellow); } else { fellow = d_adminGetFellow(admin, addr); d_printTimedEvent(durability, D_LEVEL_FINE, D_THREAD_NAMESPACES_REQUEST_LISTENER, "Fellow %d unknown, added to administration and requesting nameSpaces.\n", message->senderAddress.systemId); request = d_nameSpacesRequestNew(admin); d_messageSetAddressee(d_message(request), addr); d_publisherNameSpacesRequestWrite(publisher, request, addr); d_nameSpacesRequestFree(request); } } d_fellowUpdateStatus(fellow, message->senderState, v_timeGet()); count = c_iterLength(nameSpaces); for(i=0; i<count; i++){ ns = d_nameSpaces(c_iterObject(nameSpaces, i)); d_messageInit(d_message(ns), admin); d_messageSetAddressee(d_message(ns), addr); d_publisherNameSpacesWrite(publisher, ns, addr); } cleanNameSpaces (nameSpaces); d_fellowFree(fellow); d_networkAddressFree(addr); return; }
v_dataReaderSample v_dataReaderSampleNew( v_dataReaderInstance instance, v_message message) { v_dataReader dataReader; v_dataReaderSample sample; v_readerQos readerQos; v_index index; assert(instance != NULL); assert(C_TYPECHECK(message,v_message)); index = v_index(instance->index); dataReader = v_dataReader(index->reader); readerQos = v_reader(dataReader)->qos; if (dataReader->cachedSample != NULL) { sample = dataReader->cachedSample; /* Unfinished proto for cache size control * #define _SL_ */ #ifdef _SL_ dataReader->cachedSample = sample->prev; sample->prev = NULL; dataReader->cachedSampleCount--; #else dataReader->cachedSample = NULL; #endif } else { sample = v_dataReaderSample(c_extentCreate(dataReader->sampleExtent)); } v_readerSample(sample)->instance = (c_voidp)instance; v_readerSample(sample)->viewSamples = NULL; if ((message->transactionId != 0) && (v_reader(dataReader)->subQos->presentation.coherent_access)) { v_readerSample(sample)->sampleState = L_TRANSACTION; } else { v_readerSample(sample)->sampleState = 0; } #ifdef _NAT_ sample->insertTime = v_timeGet(); #else #define _INCORRECT_BUT_LOW_INSERT_LATENCY_ #ifdef _INCORRECT_BUT_LOW_INSERT_LATENCY_ if (v_timeIsZero(v_reader(dataReader)->qos->latency.duration)) { sample->insertTime = v_timeGet(); } else { sample->insertTime = message->allocTime; } #else sample->insertTime = v_timeGet(); #endif #endif if (readerQos->lifespan.used) { v_lifespanSample(sample)->expiryTime = c_timeAdd(sample->insertTime, readerQos->lifespan.duration); } else { v_lifespanSample(sample)->expiryTime = c_timeAdd(sample->insertTime, v_messageQos_getLifespanPeriod(message->qos)); } sample->disposeCount = instance->disposeCount; sample->noWritersCount = instance->noWritersCount; sample->publicationHandle = message->writerGID; sample->readId = 0; sample->prev = NULL; assert(message); v_dataReaderSampleTemplate(sample)->message = c_keep(message); v_lifespanAdminInsert(v_dataReaderEntry(index->entry)->lifespanAdmin, v_lifespanSample(sample)); dataReader->notReadCount++; return sample; }
c_bool d_publisherDeleteDataWrite( d_publisher publisher, d_deleteData message, d_networkAddress addressee) { c_bool result; u_result ur; int resendCount; c_bool terminate; d_durability durability; OS_UNUSED_ARG(addressee); result = FALSE; assert(d_objectIsValid(d_object(publisher), D_PUBLISHER) == TRUE); if(publisher){ if(publisher->enabled == TRUE){ terminate = FALSE; resendCount = 0; durability = d_adminGetDurability(publisher->admin); d_publisherInitMessage(publisher, d_message(message)); d_message(message)->sequenceNumber = publisher->deleteDataNumber++; while((!result) && (!terminate)){ ur = u_writerWrite(publisher->deleteDataWriter, message, v_timeGet(), U_INSTANCEHANDLE_NIL); if(ur == U_RESULT_OK){ result = TRUE; } else if(ur == U_RESULT_TIMEOUT) { terminate = d_durabilityMustTerminate(durability); resendCount++; if(terminate){ d_printTimedEvent(durability, D_LEVEL_SEVERE, D_THREAD_UNSPECIFIED, "Failed to resend d_deleteData message, because durability is terminating.\n"); OS_REPORT(OS_WARNING, D_CONTEXT_DURABILITY, 0, "Failed to send d_deleteData message, because durability is terminating."); } else if((resendCount == 1) || ((resendCount % 5) == 0)){ d_printTimedEvent(durability, D_LEVEL_WARNING, D_THREAD_UNSPECIFIED, "Already tried to resend d_deleteData message '%d' times.\n", resendCount); if(resendCount != 1){ OS_REPORT_1(OS_WARNING, D_CONTEXT_DURABILITY, 0, "Already tried to resend d_deleteData message '%d' times.", resendCount); } } } else { d_printTimedEvent(durability, D_LEVEL_SEVERE, D_THREAD_UNSPECIFIED, "Write of d_deleteData message FAILED with result %d.\n", ur); OS_REPORT_1(OS_ERROR, D_CONTEXT_DURABILITY, 0, "Write of d_deleteData message FAILED with result %d.", ur); d_durabilityTerminate(durability, TRUE); terminate = d_durabilityMustTerminate(durability); } } } } return result; }
c_bool d_publisherStatusWrite( d_publisher publisher, d_status message, d_networkAddress addressee) { c_bool result; u_result ur; int resendCount; c_bool terminate; d_durability durability; OS_UNUSED_ARG(addressee); result = FALSE; assert(d_objectIsValid(d_object(publisher), D_PUBLISHER) == TRUE); if(publisher){ if(publisher->enabled == TRUE){ terminate = FALSE; resendCount = 0; durability = d_adminGetDurability(publisher->admin); d_publisherInitMessage(publisher, d_message(message)); d_message(message)->sequenceNumber = publisher->statusNumber++; while((!result) && (!terminate)){ ur = u_writerWrite(publisher->statusWriter, message, v_timeGet(), U_INSTANCEHANDLE_NIL); if(ur == U_RESULT_OK){ result = TRUE; } else if(ur == U_RESULT_TIMEOUT) { terminate = d_durabilityMustTerminate(durability); if(!terminate && d_message(message)->senderState == D_STATE_TERMINATING){ /* ES 21 - okt - 2011: * if durability is not yet terminating, but the message being written * does indicate that termination of durability is imminent, then we have * to prevent durability from constantly retrying in the case of a TIMEOUT * of the datawriter. The standard timeout provided to the write will ensure * the write is tried during the period of the timeout. But once that timeout is * exceeded then it is fruitless to continue try to write the terminating message * Without this specific code, durability will hang when terminating is caused * by splice daemon terminating. */ terminate = TRUE; } resendCount++; if(terminate){ d_printTimedEvent(durability, D_LEVEL_SEVERE, D_THREAD_UNSPECIFIED, "Failed to resend d_status message, because durability is terminating.\n"); OS_REPORT(OS_WARNING, D_CONTEXT_DURABILITY, 0, "Failed to send d_status message, because durability is terminating."); } else if((resendCount == 1) || ((resendCount % 5) == 0)){ d_printTimedEvent(durability, D_LEVEL_WARNING, D_THREAD_UNSPECIFIED, "Already tried to resend d_status message '%d' times.\n", resendCount); if(resendCount != 1){ OS_REPORT_1(OS_WARNING, D_CONTEXT_DURABILITY, 0, "Already tried to resend d_status message '%d' times.", resendCount); } } } else { d_printTimedEvent(durability, D_LEVEL_SEVERE, D_THREAD_UNSPECIFIED, "Write of d_status message FAILED with result %d.\n", ur); OS_REPORT_1(OS_ERROR, D_CONTEXT_DURABILITY, 0, "Write of d_status message FAILED with result %d.", ur); d_durabilityTerminate(durability, TRUE); terminate = d_durabilityMustTerminate(durability); } } } } return result; }
c_bool v_networkQueueWrite( v_networkQueue queue, v_message msg, v_networkReaderEntry entry, c_long sequenceNumber, v_gid sender, c_bool sendTo, /* for p2p writing */ v_gid receiver) { c_bool result = TRUE; c_bool wasEmpty; c_bool found; v_networkStatusMarker *currentMarkerPtr; v_networkStatusMarker currentMarker; v_networkStatusMarker marker; v_networkQueueSample newHolder; c_ulonglong msecsTime; c_ulonglong msecsResult; c_ulonglong msecsLeftOver; c_time sendBeforeNoTrunc; c_time sendBefore; c_time now; c_ulong priorityLookingFor; c_equality eq; c_bool newMarkerCreated = FALSE; c_bool sendNow = FALSE; V_MESSAGE_STAMP(msg,readerInsertTime); c_mutexLock(&queue->mutex); /* numberOfSamplesArrived statistics */ v_networkQueueStatisticsAdd(numberOfSamplesArrived,queue->statistics); if (queue->currentMsgCount == queue->maxMsgCount) { c_mutexUnlock(&queue->mutex); /* numberOfSamplesRejected stat */ v_networkQueueStatisticsAdd(numberOfSamplesRejected,queue->statistics); return FALSE; } currentMarkerPtr = &(queue->firstStatusMarker); currentMarker = *currentMarkerPtr; if (queue->threadWaiting) { wasEmpty = !v_networkQueueHasExpiringData(queue); } else { wasEmpty = FALSE; } marker = NULL; found = FALSE; priorityLookingFor = v_messageQos_getTransportPriority(msg->qos); if (queue->periodic) { if (v_messageQos_isZeroLatency(msg->qos)) { sendBefore = C_TIME_ZERO; sendNow = TRUE; } else { #ifdef _NAT_ now = v_timeGet(); #else now = msg->allocTime; #endif sendBeforeNoTrunc = c_timeAdd(now, v_messageQos_getLatencyPeriod(msg->qos)); TIME_TO_MSEC(sendBeforeNoTrunc, msecsTime); msecsLeftOver = (c_ulonglong)((msecsTime - queue->phaseMilliSeconds) % queue->msecsResolution); msecsResult = (c_ulonglong)(msecsTime - msecsLeftOver); MSEC_TO_TIME(msecsResult, sendBefore); } while ((currentMarker != NULL) && (!found)) { eq = c_timeCompare(sendBefore, currentMarker->sendBefore); switch (eq) { case C_GT: currentMarkerPtr = ¤tMarker->next; currentMarker = *currentMarkerPtr; break; case C_EQ: if (priorityLookingFor < currentMarker->priority) { currentMarkerPtr = ¤tMarker->next; currentMarker = *currentMarkerPtr; } else { found = TRUE; if (priorityLookingFor == currentMarker->priority) { marker = currentMarker; } } break; case C_LT: found = TRUE; break; default: assert(FALSE); break; } } } else { if (currentMarker) { sendBefore = C_TIME_ZERO; if (c_timeIsZero(currentMarker->sendBefore)) { marker = currentMarker; } } } /* Insert after end of list */ if (marker == NULL) { newMarkerCreated = TRUE; if (queue->freeStatusMarkers == NULL) { marker = v_networkStatusMarker(c_new(queue->statusMarkerType)); } else { marker = queue->freeStatusMarkers; queue->freeStatusMarkers = marker->next; } if (marker != NULL) { marker->sendBefore = sendBefore; marker->priority = priorityLookingFor; marker->firstSample = NULL; marker->lastSample = NULL; marker->next = *currentMarkerPtr; /* no keep, transfer refCount */ if (marker->next == NULL) { queue->lastStatusMarker = marker; /* no keep, not reference counted */ } *currentMarkerPtr = marker; /* no keep, transfer refCount */ } else { OS_REPORT(OS_ERROR, "v_networkQueueWrite",0, "Failed to send message."); c_mutexUnlock(&queue->mutex); return FALSE; } } V_MESSAGE_STAMP(msg,readerLookupTime); assert(marker != NULL); if (queue->freeSamples == NULL) { newHolder = c_new(queue->sampleType); } else { newHolder = queue->freeSamples; queue->freeSamples = newHolder->next; } if (newHolder) { queue->currentMsgCount++; /* numberOfSamplesInserted & numberOfSamplesWaiting + stats*/ v_networkQueueStatisticsAdd(numberOfSamplesInserted,queue->statistics); v_networkQueueStatisticsCounterInc(numberOfSamplesWaiting,queue->statistics); newHolder->message = c_keep(msg); newHolder->entry = c_keep(entry); newHolder->sequenceNumber = sequenceNumber; newHolder->sender = sender; newHolder->sendTo = sendTo; newHolder->receiver = receiver; if (marker->lastSample != NULL) { newHolder->next = v_networkQueueSample(marker->lastSample)->next; /* no keep, transfer refCount */ v_networkQueueSample(marker->lastSample)->next = newHolder; /* no keep, transfer refCount */ } else { newHolder->next = marker->firstSample; /* no keep, transfer refCount */ marker->firstSample = newHolder; /* no keep, transfer refCount */ } marker->lastSample = newHolder; /* Write done, wake up waiters if needed */ if (wasEmpty && queue->threadWaiting) { if (sendNow || v_networkQueueHasExpiringData(queue)) { c_condBroadcast(&queue->cv); } } } else { OS_REPORT(OS_ERROR, "v_networkQueueWrite",0, "Failed to send message."); result = FALSE; } c_mutexUnlock(&queue->mutex); return result; }
v_networkReaderWaitResult v_networkQueueWait( v_networkQueue queue) { v_networkReaderWaitResult result = V_WAITRESULT_NONE; c_syncResult syncResult; c_bool hasChanged; c_time interval; c_time minSleepTime = MIN_SLEEPTIME; c_equality eq; c_mutexLock(&queue->mutex); /* First update nextWakeup */ v_networkQueueUpdateNextWakeup(queue, &hasChanged); if (hasChanged) { result |= V_WAITRESULT_TIMEOUT; } /* With the new nextWakeup, check if any data is expiring */ if ((int)v_networkQueueHasExpiringData(queue)) { result |= V_WAITRESULT_MSGWAITING; } /* Also check if no request has been issued lately */ if ((int)queue->triggered) { result |= V_WAITRESULT_TRIGGERED; } /* Now go to sleep if needed */ while (result == V_WAITRESULT_NONE) { if (queue->periodic) { c_time org = v_timeGet(); interval = c_timeSub(queue->nextWakeup,org); eq = c_timeCompare(minSleepTime, interval); if (eq == C_LT) { queue->threadWaiting = TRUE; syncResult = c_condTimedWait(&queue->cv, &queue->mutex, interval); queue->threadWaiting = FALSE; } else { syncResult = SYNC_RESULT_TIMEOUT; } if (syncResult == SYNC_RESULT_TIMEOUT) { result |= V_WAITRESULT_TIMEOUT; queue->nextWakeup = c_timeAdd(queue->nextWakeup, queue->resolution); } } else { /* Wait infinitely if the queue is not periodic */ queue->threadWaiting = TRUE; syncResult = c_condWait(&queue->cv, &queue->mutex); queue->threadWaiting = FALSE; } /* Test current status of queue */ if ((int)queue->triggered) { result |= V_WAITRESULT_TRIGGERED; } if (v_networkQueueHasExpiringData(queue)) { result |= V_WAITRESULT_MSGWAITING; } } queue->triggered = 0; c_mutexUnlock(&queue->mutex); return result; }