static void v_networkReaderEntryInit( v_networkReaderEntry entry, v_networkReader reader, v_group group, v_networkId networkId, c_ulong channelsToConnect, v_networkPartitionId networkPartitionId, c_bool isRouting) { v_networkReaderEntry found; v_entryInit(v_entry(entry),v_reader(reader)); entry->group = c_keep(group); entry->networkId = networkId; entry->channelCountdown = channelsToConnect; c_mutexInit(&entry->channelCountdownMutex, SHARED_MUTEX); entry->networkPartitionId = networkPartitionId; entry->hashValue = v_networkReaderEntryCalculateHashValue(entry); entry->isRouting = isRouting; found = v_networkReaderEntry(v_readerAddEntry(v_reader(reader), v_entry(entry))); assert(found == entry); c_free(found); }
v_result v_deliveryServiceEnable( v_deliveryService _this) { #if 0 v_kernel kernel; v_message builtinMsg; #endif v_subscriber subscriber; v_result result; if (_this) { result = V_RESULT_OK; subscriber = v_subscriber(v_reader(_this)->subscriber); v_subscriberAddReader(subscriber,v_reader(_this)); #if 0 kernel = v_objectKernel(_this); builtinMsg = v_builtinCreateSubscriptionInfo(kernel->builtin, _this); v_writeBuiltinTopic(kernel, V_SUBSCRIPTIONINFO_ID, builtinMsg); c_free(builtinMsg); #endif } else { result = V_RESULT_ILL_PARAM; } return result; }
v_networkReader v_networkReaderNew( v_subscriber subscriber, const c_char *name, v_readerQos qos, c_bool ignoreReliabilityQoS) { /* Note: currently, no qos-es are supported. Everything is redirected * to the defaultQueue */ v_kernel kernel; v_networkReader reader; v_readerQos q; v_statistics s; c_type queueType; c_long i; assert(C_TYPECHECK(subscriber,v_subscriber)); /* Creation */ kernel = v_objectKernel(subscriber); q = v_readerQosNew(kernel,qos); if (q != NULL) { reader = v_networkReader(v_objectNew(kernel,K_NETWORKREADER)); s = v_statistics(v_networkReaderStatisticsNew(kernel)); /* Initialization of parent */ v_readerInit(v_reader(reader), name, subscriber, q, s, TRUE); c_free(q); /* ref now in v_reader(queue)->qos */ /* This function only ever called once per network instance so no * need to store queueType as static variable. Look up as needed (once) */ queueType = c_resolve(c_getBase(subscriber),"kernelModule::v_networkQueue"); /* Initialization of self */ reader->queues = NULL; reader->queues = c_arrayNew(queueType, NW_MAX_NOF_QUEUES); reader->nofQueues = 0; reader->defaultQueue = NULL; reader->remoteActivity = FALSE; reader->ignoreReliabilityQoS = ignoreReliabilityQoS; reader->queueCache = c_arrayNew(queueType, 2*NW_MAX_QUEUE_CACHE_PRIO); for( i= 0; i < 2*NW_MAX_QUEUE_CACHE_PRIO; i++) { reader->queueCache[i] = NULL; } c_free(queueType); /* Add to subscriber */ v_subscriberAddReader(subscriber,v_reader(reader)); } else { OS_REPORT(OS_ERROR, "v_networkReaderNew", 0, "NetworkReader not created: inconsistent qos"); reader = NULL; } return reader; }
void v_networkReaderFree( v_networkReader reader) { c_bool sendTo, more; v_message message; c_ulong sequenceNumber, priority; v_gid sender, receiver; os_timeE sendBefore; v_networkReaderEntry entry; c_ulong i; c_keep(reader); /* call inherited free, * which will remove the entry from the associated groups */ v_readerFree(v_reader(reader)); /* remove the messages still pressent in the network queues */ for (i = 0; i < reader->nofQueues; i++) { while (v_networkQueueTakeFirst ( v_networkQueue(reader->queues[i]), &message, &entry, &sequenceNumber, &sender, &sendTo, &receiver, &sendBefore, &priority, &more)) { c_free(message); c_free(entry); } } c_free(reader); }
void v_networkReaderFree( v_networkReader reader) { /* call inherited free */ v_readerFree(v_reader(reader)); }
void v_deliveryServiceFree ( v_deliveryService _this) { #if 0 v_message builtinMsg; v_message unregisterMsg; #endif assert(_this != NULL); assert(C_TYPECHECK(_this,v_deliveryService)); v_readerFree(v_reader(_this)); #if 0 /* First create message, only at the end dispose. Applications expect * the disposed sample to be the last! */ kernel = v_objectKernel(_this); builtinMsg = v_builtinCreateSubscriptionInfo(kernel->builtin,_this); unregisterMsg = v_builtinCreateSubscriptionInfo(kernel->builtin,_this); v_writeDisposeBuiltinTopic(kernel, V_SUBSCRIPTIONINFO_ID, builtinMsg); v_unregisterBuiltinTopic(kernel, V_SUBSCRIPTIONINFO_ID, unregisterMsg); c_free(builtinMsg); c_free(unregisterMsg); #endif }
c_bool v_groupStreamSubscribeGroup( v_groupStream stream, v_group group) { c_bool inserted; assert(C_TYPECHECK(stream, v_groupStream)); assert(C_TYPECHECK(group, v_group)); if (v_reader(stream)->qos->durability.kind == v_topicQosRef(group->topic)->durability.kind) { struct groupMatched data; /* * OSPL-1073: Check if the new group matches with the group-expression list. This * is a collection of partition.topic strings that allows users to connect to specific * topics rather than connecting to all topics within a partition. */ if(stream->expr) { data.matched = FALSE; data.group = group; c_walk(stream->expr, (c_action)isGroupMatched, &data); }else { data.matched = TRUE; } if(data.matched) { inserted = v_groupAddStream(group, stream); if(inserted == TRUE){ c_insert(stream->groups, group); } } } return TRUE; }
void v_publicDispose( v_public o) { assert(C_TYPECHECK(o,v_public)); if (o == NULL) { return; } switch(v_objectKind(o)) { case K_PARTICIPANT: v_participantDeinit(v_participant(o)); break; case K_PUBLISHER: v_publisherDeinit(v_publisher(o)); break; case K_SUBSCRIBER: v_subscriberDeinit(v_subscriber(o)); break; case K_WRITER: v_writerDeinit(v_writer(o)); break; case K_DATAREADER: v_dataReaderDeinit(v_dataReader(o)); break; case K_DELIVERYSERVICE:v_deliveryServiceDeinit(v_deliveryService(o)); break; case K_NETWORKREADER: v_networkReaderDeinit(v_networkReader(o)); break; case K_READER: v_readerDeinit(v_reader(o)); break; case K_GROUPQUEUE: v_groupQueueDeinit(v_groupQueue(o)); break; case K_TOPIC: v_topicDeinit(v_topic(o)); break; case K_ENTITY: break; case K_DOMAIN: v_partitionDeinit(v_partition(o)); break; case K_GROUP: v_groupDeinit(v_group(o)); break; case K_SERVICEMANAGER: /* Is never freed! */ break; case K_SPLICED: v_splicedDeinit(v_spliced(o)); break; case K_NETWORKING: case K_DURABILITY: case K_CMSOAP: case K_SERVICE: v_serviceDeinit(v_service(o)); break; case K_SERVICESTATE: /* Is never freed! */ break; case K_CONFIGURATION: break; case K_QUERY: OS_REPORT(OS_ERROR, "v_publicDispose failure", 0, "deinit of abstract class K_QUERY"); break; case K_DATAREADERQUERY: v_dataReaderQueryDeinit(v_dataReaderQuery(o)); break; case K_DATAVIEWQUERY: v_dataViewQueryDeinit(v_dataViewQuery(o)); break; case K_DATAVIEW: v_dataViewDeinit(v_dataView(o)); break; case K_WAITSET: v_waitsetDeinit(v_waitset(o)); break; case K_WRITERINSTANCE: v_writerInstanceDeinit(v_writerInstance(o)); break; case K_DATAREADERINSTANCE: v_dataReaderInstanceDeinit(v_dataReaderInstance(o)); break; case K_DATAVIEWINSTANCE: v_dataViewInstanceDeinit(v_dataViewInstance(o)); break; default: OS_REPORT_1(OS_ERROR,"v_publicDispose failed",0, "illegal entity kind (%d) specified",v_objectKind(o)); assert(FALSE); break; } c_free(o); }
void v_networkReaderDeinit( v_networkReader reader) { assert(reader != NULL); assert(C_TYPECHECK(reader,v_networkReader)); v_readerDeinit(v_reader(reader)); }
void v_groupStreamFree( v_groupStream stream) { assert(C_TYPECHECK(stream, v_groupStream)); v_readerFree(v_reader(stream)); }
void v_deliveryServiceDeinit ( v_deliveryService _this) { assert(_this != NULL); assert(C_TYPECHECK(_this,v_deliveryService)); v_readerDeinit(v_reader(_this)); }
c_bool v_deliveryServiceUnSubscribe( v_deliveryService _this, v_partition d) { assert(C_TYPECHECK(_this,v_deliveryService)); return v_readerWalkEntries(v_reader(_this), unsubscribe, d); }
void v_groupStreamInit( v_groupStream stream, const c_char *name, v_subscriber subscriber, v_readerQos qos) { v_kernel kernel; assert(C_TYPECHECK(stream, v_groupStream)); assert(C_TYPECHECK(subscriber, v_subscriber)); kernel = v_objectKernel(subscriber); stream->groups = c_setNew(v_kernelType(kernel,K_GROUP)); v_readerInit(v_reader(stream),name,subscriber,qos,NULL,TRUE); v_subscriberAddReader(subscriber,v_reader(stream)); }
c_bool v_networkReaderUnSubscribe( v_networkReader reader, v_partition partition) { assert(C_TYPECHECK(reader, v_networkReader)); assert(C_TYPECHECK(partition, v_partition)); return v_readerWalkEntries(v_reader(reader), (c_action)v_networkReaderEntryUnSubscribe, partition); }
c_bool v_networkReaderUnSubscribeGroup( v_networkReader reader, v_group group) { assert(C_TYPECHECK(reader, v_networkReader)); assert(C_TYPECHECK(group, v_group)); return v_readerWalkEntries(v_reader(reader), (c_action)v_networkReaderEntryUnSubscribeGroup, group); }
void v_groupStreamInit( v_groupStream stream, const c_char *name, v_subscriber subscriber, v_readerQos qos, v_statistics rs, c_iter expr) { v_kernel kernel; assert(C_TYPECHECK(stream, v_groupStream)); assert(C_TYPECHECK(subscriber, v_subscriber)); kernel = v_objectKernel(subscriber); stream->groups = c_setNew(v_kernelType(kernel,K_GROUP)); stream->expr = c_listNew(c_resolve(c_getBase(stream), "::c_string")); c_iterWalk(expr, fillExprList, stream->expr); v_readerInit(v_reader(stream),name,subscriber,qos,rs,TRUE); v_subscriberAddReader(subscriber,v_reader(stream)); }
c_bool v_indexWalk( v_index _this, c_action action, c_voidp arg) { v_reader reader; c_bool result; assert(C_TYPECHECK(_this,v_index)); reader = v_reader(_this->reader); if (reader->qos->userKey.v.enable) { result = c_tableWalk(_this->notEmptyList, action, arg); } else { result = c_tableWalk(_this->objects, action, arg); } return result; }
v_deliveryServiceEntry v_deliveryServiceEntryNew( v_deliveryService deliveryService, v_topic topic) { v_kernel kernel; v_deliveryServiceEntry e; assert(C_TYPECHECK(deliveryService,v_deliveryService)); assert(C_TYPECHECK(topic,v_topic)); kernel = v_objectKernel(deliveryService); e = v_deliveryServiceEntry(v_objectNew(kernel,K_DELIVERYSERVICEENTRY)); v_entryInit(v_entry(e), v_reader(deliveryService)); e->topic = c_keep(topic); return e; }
c_bool v_groupStreamSubscribeGroup( v_groupStream stream, v_group group) { c_bool inserted; assert(C_TYPECHECK(stream, v_groupStream)); assert(C_TYPECHECK(group, v_group)); if (v_reader(stream)->qos->durability.kind == v_topicQosRef(group->topic)->durability.kind) { inserted = v_groupAddStream(group, stream); if(inserted == TRUE){ c_insert(stream->groups, group); } } return TRUE; }
void checkInstance( v_dataViewInstance instance, c_bool isNotEmpty) { int i = 0; v_dataViewSample current; v_dataViewSample next; if (instance) { if (!isNotEmpty) { REL_ASSERT(instance->sampleCount == 0); } if (!v_reader(v_dataViewReader(instance->dataView))->qos->userKey.enable && isNotEmpty) { REL_ASSERT(instance->sampleCount == 1); } REL_ASSERT(c_refCount(instance) > 0); REL_ASSERT(C_TYPECHECK(instance, v_dataViewInstance)); next = NULL; current = v_dataViewInstanceTemplate(instance)->sample; while (current != NULL) { if (!isNotEmpty) { checkSample(current); } REL_ASSERT(current->next == next); if (next != NULL) { REL_ASSERT(next->prev == current); } next = current; current = current->prev; i++; } if (next != NULL) { REL_ASSERT(next->prev == current); } if (isNotEmpty) { REL_ASSERT(i == instance->sampleCount); } else { REL_ASSERT(i == 1); } } }
v_networkReaderEntry v_networkReaderLookupEntry( v_networkReader reader, v_group group) { struct v_findEntryArg findEntryArg; assert(v_networkReader(reader) == reader); assert(v_group(group) == group); findEntryArg.group = c_keep(group); findEntryArg.found = NULL; v_readerWalkEntries(v_reader(reader), (c_action)v_networkReaderFindEntry, &findEntryArg); c_free(group); /* Note that the keep has been done in the walk (if any entry was found) */ return findEntryArg.found; }
void v_groupStreamDeinit( v_groupStream stream) { c_iter groups; v_group group; assert(C_TYPECHECK(stream, v_groupStream)); v_readerDeinit(v_reader(stream)); groups = ospl_c_select(stream->groups, 0); group = v_group(c_iterTakeFirst(groups)); while(group){ v_groupRemoveStream(group, stream); c_free(group); group = v_group(c_iterTakeFirst(groups)); } c_iterFree(groups); c_free(stream->groups); stream->groups = NULL; }
static void nw_channelWriterMain( v_entity e, c_voidp arg) { v_networkReader reader; nw_channelWriter channelWriter; c_bool newGroupAvailable; v_networkQueue qosQueue; v_networkReaderWaitResult waitResult; c_long bytesWritten; /* Total number of messages sent to the network */ c_ulong writtenCountMessages; /* Total number of bytes sent to the network */ c_ulong writtenCountBytes; /* Total number of bytes sent to the network during one burst */ c_ulong writtenCountBytesThisBurst; /* Number of message sent to the network after last report */ c_ulong writtenCountMessagesReport; v_message message; v_networkReaderEntry entry; c_ulong sequenceNumber; v_gid sender; c_bool sendTo; v_gid receiver; c_time sendBefore; c_ulong priority; c_bool more = TRUE; c_bool slowingDown; c_ulong timeoutCount; nw_signedLength credits; v_networking n; NW_STRUCT(plugSendStatistics) pss = {0,0,0,0,0,0,0,0,0,0, {0, {{0,0}, 0}, {{0,0}, 0}, {0.0,0}}, {0, {{0,0}, 0}, {{0,0}, 0}, {0.0,0}}, 0,0,0}; v_fullCounterInit(&(pss.adminQueueAcks)); v_fullCounterInit(&(pss.adminQueueData)); reader = v_networkReader(e); channelWriter = (nw_channelWriter)arg; /* This line is needed as long as the discovery channel is not yet implemented */ writtenCountBytesThisBurst = 0; writtenCountMessages = 0; writtenCountBytes = 0; writtenCountMessagesReport = 0; slowingDown = FALSE; timeoutCount = 0; credits = 0; while (!(int)nw_runnableTerminationRequested((nw_runnable)channelWriter)) { /* Wait for data on the reader */ if (!slowingDown) { waitResult = v_networkReaderWait(reader, channelWriter->queueId, &qosQueue); } else { waitResult = v_networkReaderWaitDelayed(reader, channelWriter->queueId, &qosQueue); NW_CONFIDENCE(waitResult & (V_WAITRESULT_TIMEOUT | V_WAITRESULT_TRIGGERED)); } if ((waitResult & V_WAITRESULT_TRIGGERED) && (!nw_runnableTerminationRequested((nw_runnable)channelWriter))) { /* If necessary, check if any new groups need to be added */ newGroupAvailable = nw_channelUserRetrieveNewGroup( (nw_channelUser)channelWriter, &entry); while (newGroupAvailable) { /* Create a new channel on the network */ /* No, do not call any function. With the new design, * a channelWriter does not need to know anything about this * new group. Maybe at a later stage. */ /* nw_channelAddGroup((nw_channel)channelWriter->sendChannel, entry); */ /* And notify we are connected */ v_networkReaderEntryNotifyConnected(entry,channelWriter->serviceName); newGroupAvailable = nw_channelUserRetrieveNewGroup( (nw_channelUser)channelWriter, &entry); } } /* Resend data should also obey max_burst_size * Each clocktick, the remaining credits of the last period and a * third of the new max_burst_size budget may be used for resend data. * The rest of the budget is assigned after that, and can be used to * flush stored buffers of send fresh data. */ if (waitResult & V_WAITRESULT_TIMEOUT) { /* * The periodic action is needed for every clocktick. * This will also update the credits, for the amount of bandwidth * available in the coming period. */ /*stat update routine */ n = v_networking(v_subscriber(v_reader(reader)->subscriber)->participant); /* update statistics */ if (v_entity(n)->statistics) { if (!pss.enabled) { pss.enabled =1; } /* sync plug stats */ nw_updatePlugSendStatistics(&pss,channelWriter); nw_SendChannelUpdate(v_networkingStatistics(v_entity(n)->statistics)->channels[channelWriter->stat_channel_id],channelWriter->scs); } nw_sendChannelPeriodicAction(channelWriter->sendChannel,&credits,&pss); /*struc call*/ /* A flush is needed if we are slowing down. */ if (slowingDown) { /* The return value is true is all data has been sent. * Afterwards, credits will contain the new amount of allowed * bytes. * We are using a special flush function here that flushes full * buffers only */ slowingDown = !nw_sendChannelFlush(channelWriter->sendChannel, FALSE, &credits, &pss); } } if ((waitResult & V_WAITRESULT_MSGWAITING) && !slowingDown) { /* Messages are waiting... */ writtenCountBytesThisBurst = 0; more= TRUE; while (more && ((nw_signedLength)writtenCountBytesThisBurst <= credits)) { /* Take any new messages */ v_networkQueueTakeFirst(qosQueue, &message, &entry, &sequenceNumber, &sender, &sendTo, &receiver, &sendBefore, &priority, &more); NW_CONFIDENCE(message != NULL); NW_CONFIDENCE(entry != NULL); if (!(NW_SECURITY_CHECK_FOR_PUBLISH_PERMISSION_OF_SENDER_ON_SENDER_SIDE(entry))) { bytesWritten = 0; /* indicates that nothing has been written */ NW_REPORT_WARNING_2( "nw_channelWriterMain", "Channel \"%s\" could not deliver message 0x%x : message dropped!", ((nw_runnable)channelWriter)->name, message); } else { bytesWritten = nw_sendChannelWrite(channelWriter->sendChannel, entry, message, &credits ,&pss); /* stat struc plug vars */ if (bytesWritten == 0) { NW_REPORT_WARNING_2( "nw_channelWriterMain", "Channel \"%s\" could not deliver message 0x%x : message dropped!", ((nw_runnable)channelWriter)->name, message); } /*numberOfMessagesSent stats*/ if (pss.enabled) { channelWriter->scs->numberOfMessagesSent++; } assert( bytesWritten > 0); /* if permission grantedm the value must be greater 0 */ } writtenCountBytesThisBurst += bytesWritten; #define NW_IS_BUILTIN_DOMAINNAME(name) ((int)(name)[0] == (int)'_') /* Do not trace for internal partitions */ if (bytesWritten>0 && /* might be 0 if access control refuses write permission */ !NW_IS_BUILTIN_DOMAINNAME( v_partitionName(v_groupPartition(entry->group)))) { #undef NW_IS_BUILTIN_DOMAINNAME writtenCountBytes += bytesWritten; writtenCountMessages++; writtenCountMessagesReport++; if (writtenCountMessagesReport == channelWriter->reportInterval) { NW_TRACE_3(Send, 3, "Channel %s: %u messages (%u bytes) " "taken from queue and written to network", ((nw_runnable)channelWriter)->name, writtenCountMessages, writtenCountBytes); writtenCountMessagesReport = 0; } NW_TRACE_3(Send, 4, "Channel %s: data message taken from queue, " "and written to network (partition = %s, topic = %s)", ((nw_runnable)channelWriter)->name, v_partitionName(v_groupPartition(entry->group)), v_topicName(v_groupTopic(entry->group))); } c_free(message); c_free(entry); } slowingDown = !nw_sendChannelFlush(channelWriter->sendChannel, TRUE, &credits, &pss); } } NW_TRACE_3(Send, 2, "Channel %s: %u messages (%u bytes) taken from queue and " "written to network", ((nw_runnable)channelWriter)->name, writtenCountMessages, writtenCountBytes); }
v_dataReaderSample v_dataReaderSampleNew( v_dataReaderInstance instance, v_message message) { v_dataReader dataReader; v_dataReaderSample sample; v_readerQos readerQos; v_index index; os_timeE msgEpoch; assert(instance != NULL); assert(C_TYPECHECK(message,v_message)); index = v_index(instance->index); dataReader = v_dataReader(index->reader); readerQos = v_reader(dataReader)->qos; assert(readerQos); sample = v_dataReaderSample(c_new(dataReader->sampleType)); if (sample != NULL) { v_readerSample(sample)->instance = (c_voidp)instance; v_readerSample(sample)->viewSamples = NULL; v_readerSample(sample)->sampleState = 0; sample->insertTime = os_timeWGet(); /* The expiry time calculation is dependent on the DestinationOrderQos(readerQos->orderby.v.kind): * In case of the by_reception_timestamp kind the expiry time is determined based on insertion time(sample->insertTime). * In case of the by_source_timestamp kind the expiry time is determined based on source time (message->writeTime). */ msgEpoch = os_timeEGet(); if (readerQos->orderby.v.kind == V_ORDERBY_SOURCETIME) { /* assuming wall clocks of source and destination are aligned! * calculate the age of the message and then correct the message epoch. */ os_duration message_age = os_timeWDiff(os_timeWGet(), message->writeTime); msgEpoch = os_timeESub(msgEpoch, message_age); } v_dataReaderSampleTemplate(sample)->message = c_keep(message); sample->disposeCount = instance->disposeCount; sample->noWritersCount = instance->noWritersCount; sample->publicationHandle = message->writerGID; sample->readId = 0; sample->newer = NULL; /* When both ReaderLifespanQos(readerQos->lifespan.used) and the inline LifespanQos (v_messageQos_getLifespanPeriod(message->qos)) * are set the expiryTime will be set to the earliest time among them. */ if (message->qos) { os_duration lifespan = v_messageQos_getLifespanPeriod(message->qos); if (readerQos->lifespan.v.used) { if (os_durationCompare(readerQos->lifespan.v.duration, lifespan) == OS_LESS) { v_lifespanSample(sample)->expiryTime = os_timeEAdd(msgEpoch, readerQos->lifespan.v.duration); } else { v_lifespanSample(sample)->expiryTime = os_timeEAdd(msgEpoch, lifespan); } v_lifespanAdminInsert(v_dataReaderEntry(index->entry)->lifespanAdmin, v_lifespanSample(sample)); } else { if (OS_DURATION_ISINFINITE(lifespan)) { v_lifespanSample(sample)->expiryTime = OS_TIMEE_INFINITE; } else { v_lifespanSample(sample)->expiryTime = os_timeEAdd(msgEpoch, lifespan); v_lifespanAdminInsert(v_dataReaderEntry(index->entry)->lifespanAdmin, v_lifespanSample(sample)); } } } else { if (readerQos->lifespan.v.used) { v_lifespanSample(sample)->expiryTime = os_timeEAdd(msgEpoch,readerQos->lifespan.v.duration); v_lifespanAdminInsert(v_dataReaderEntry(index->entry)->lifespanAdmin, v_lifespanSample(sample)); } else { v_lifespanSample(sample)->expiryTime = OS_TIMEE_INFINITE; } } } else { OS_REPORT(OS_FATAL, OS_FUNCTION, V_RESULT_INTERNAL_ERROR, "Failed to allocate v_dataReaderSample."); } return sample; }
void v_groupStreamNotify( v_groupStream stream, v_event e, c_voidp userData) { struct groupConnected data; c_iter partitions; c_bool interested; v_partition partition, found; OS_UNUSED_ARG(userData); assert(stream != NULL); assert(C_TYPECHECK(stream,v_groupStream)); if (e) { if (e->kind == V_EVENT_NEW_GROUP) { v_observerLock(v_observer(stream)); /* * Check if group fits interest. This extra steps are needed because * the groupActionStream does not create the groups that match the * subscriber qos partition expression on creation. It only needs to * connect to new groups once they are created. This is a different * approach then for a data reader. */ partition = v_group(e->userData)->partition; /* * Because already existing partitions are created and added to the * subscriber of the groupActionStream at creation time, these * partitions can be resolved from the subscriber. This is necessary to * determine whether the groupActionStream should connect to the new * group or if it is already connected. */ partitions = v_subscriberLookupPartitions(v_reader(stream)->subscriber, v_partitionName(partition)); interested = FALSE; found = v_partition(c_iterTakeFirst(partitions)); while(found){ if(interested == FALSE){ if(strcmp(v_partitionName(partition), v_partitionName(found)) == 0){ interested = TRUE; } } c_free(found); found = v_partition(c_iterTakeFirst(partitions)); } c_iterFree(partitions); if(interested == TRUE){ /* * This means the group is interesting for this * groupActionStream. Now I have to check if the stream is already * connected to this group, because we wouldn't want to connect * multiple times to one single group. */ data.connected = FALSE; data.group = v_group(e->userData); c_walk(stream->groups, (c_action)isGroupConnected, &data); if(data.connected == FALSE){ /* * The stream is not connected to the group yet, so connect now. */ v_groupStreamSubscribeGroup(stream, v_group(e->userData)); } } v_observerUnlock(v_observer(stream)); } } return; }
v_index v__indexNew( v_dataReader reader, q_expr _from, c_iter indexList, v_indexNewAction action, c_voidp arg) { v_kernel kernel; v_index index; v_topic topic; c_type instanceType; c_iter list; c_char *keyExpr; c_array keyList; c_ulong nrOfTopics; assert(C_TYPECHECK(reader,v_dataReader)); kernel = v_objectKernel(reader); if (q_isId(_from)) { list = v_resolveTopics(kernel,q_getId(_from)); nrOfTopics = c_iterLength(list); if (nrOfTopics == 0) { OS_REPORT(OS_ERROR, "v__indexNew", V_RESULT_ILL_PARAM, "Unknown topic %s", q_getId(_from)); c_iterFree(list); return NULL; } if (nrOfTopics > 1) { OS_REPORT(OS_ERROR, "v__indexNew", V_RESULT_ILL_PARAM, "Multiple topic definitions of: %s", q_getId(_from)); topic = v_topic(c_iterTakeFirst(list)); while (topic != NULL) { c_free(topic); topic = v_topic(c_iterTakeFirst(list)); } c_iterFree(list); return NULL; } topic = c_iterTakeFirst(list); c_iterFree(list); index = v_index(c_iterReadAction(indexList, indexCompare, topic)); if (index == NULL) { /* If the userKey is enabled then the instance type key field type * will be determined from the user key expression and topic. * Otherwise when no user key is specified the default Topic key * type will be used. */ if (v_reader(reader)->qos->userKey.v.enable) { keyExpr = v_reader(reader)->qos->userKey.v.expression; } else { keyExpr = NULL; } instanceType = createInstanceType(topic,keyExpr,&keyList); if (instanceType) { index = v_index(v_objectNew(kernel,K_INDEX)); v_indexInit(index, instanceType, keyList, v_reader(reader)); } c_free(keyList); c_free(instanceType); if (index != NULL) { if (action != NULL && !action(index, topic, arg)) { OS_REPORT(OS_ERROR, "v_indexNew", V_RESULT_INTERNAL_ERROR, "v_indexNewAction failed!"); c_free(index); index = NULL; } else { (void)c_iterAppend(indexList, index); } } } } else { OS_REPORT(OS_ERROR, "v_indexNew failed",V_RESULT_ILL_PARAM, "illegal from clause specified"); assert(FALSE); index = NULL; } return index; }
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_ulong v_networkReaderCreateQueue( v_networkReader reader, c_ulong queueSize, c_ulong priority, c_bool reliable, c_bool P2P, c_time resolution, c_bool useAsDefault, const c_char *name) { c_ulong result = 0; v_networkQueue queue; v_networkReaderStatistics s; v_networkQueueStatistics nqs; v_networkingStatistics nws; v_networkChannelStatistics ncs; v_kernel kernel; v_networking n; v_participant p; kernel = v_objectKernel(reader); if (reader->nofQueues < NW_MAX_NOF_QUEUES) { p = v_participant(v_subscriber(v_reader(reader)->subscriber)->participant); if ((v_objectKind(p) == K_NETWORKING) && (v_isEnabledStatistics(kernel, V_STATCAT_NETWORKING))) { nqs = v_networkQueueStatisticsNew(kernel,name); ncs = v_networkChannelStatisticsNew(kernel,name); } else { nqs = NULL; ncs = NULL; } queue = v_networkQueueNew(c_getBase((c_object)reader), queueSize, priority, reliable, P2P, resolution, nqs); if (queue != NULL) { reader->queues[reader->nofQueues] = queue; reader->nofQueues++; result = reader->nofQueues; /* insert statistics */ if (nqs != NULL) { s = v_networkReaderStatistics(v_entityStatistics(v_entity(reader))); if (s != NULL) { s->queues[s->queuesCount]=nqs; s->queuesCount++; } } if ((useAsDefault) || (reader->defaultQueue == NULL)){ c_free(reader->defaultQueue); reader->defaultQueue = c_keep(queue); } if (ncs != NULL) { /* add channel to the networking statistics also */ n = v_networking(p); nws = (v_networkingStatistics)v_entity(n)->statistics; nws->channels[nws->channelsCount]=ncs; nws->channelsCount++; } } } else { OS_REPORT_1(OS_ERROR, "v_networkReaderCreateQueue", 0, "Maximum number of network queues (%d) exceeded, " "new queue not created", NW_MAX_NOF_QUEUES); } return result; }
v_deliveryService v_deliveryServiceNew ( v_subscriber subscriber, const c_char *name) { v_kernel kernel; v_deliveryService _this; v_readerQos q; v_topic topic; c_base base; c_type type; v_entry entry, found; assert(C_TYPECHECK(subscriber,v_subscriber)); base = c_getBase(subscriber); kernel = v_objectKernel(subscriber); topic = v_lookupTopic (kernel, V_DELIVERYINFO_NAME); /* ES, dds1576: Before creating the ackreader we have to verify that read * access to the topic is allowed. We can accomplish this by checking the * access mode of the topic. */ if(!topic) { OS_REPORT(OS_ERROR, "v_deliveryServiceNew",0, "DeliveryService not created: " "Could not locate topic with name DCPS_Delivery."); return NULL; } if(v_topicAccessMode(topic) == V_ACCESS_MODE_READ || v_topicAccessMode(topic) == V_ACCESS_MODE_READ_WRITE) { q = v_readerQosNew(kernel,NULL); if (q == NULL) { OS_REPORT(OS_ERROR, "v_deliveryServiceNew", 0, "DeliveryService not created: inconsistent qos"); return NULL; } _this = v_deliveryService(v_objectNew(kernel,K_DELIVERYSERVICE)); type = c_resolve(base, "kernelModule::v_deliveryGuard"); _this->guards = c_tableNew(type, "writerGID.localId"); c_free(type); type = c_resolve(base, "kernelModule::v_subscriptionInfoTemplate"); _this->subscriptions = c_tableNew(type, "userData.key.systemId,userData.key.localId"); c_free(type); q->userKey.enable = TRUE; q->userKey.expression = NULL; v_readerInit(v_reader(_this),name, subscriber,q, NULL, TRUE); c_free(q); entry = v_entry(v_deliveryServiceEntryNew(_this,topic)); found = v_readerAddEntry(v_reader(_this),v_entry(entry)); c_free(entry); c_free(found); v_deliveryServiceEnable(_this); } else { OS_REPORT_1(OS_ERROR, "v_deliveryServiceNew", 0, "Creation of DeliveryService <%s> failed. Topic DCPS_Delivery." "does not have read access rights.", name); _this = NULL; } return _this; }
v_networkReader v_networkReaderNew( v_subscriber subscriber, const c_char *name, v_readerQos qos, c_bool ignoreReliabilityQoS) { /* Note: currently, no qos-es are supported. Everything is redirected * to the defaultQueue */ v_kernel kernel; v_networkReader reader = NULL; v_result r; v_readerQos q; c_type queueType; c_long i; assert(C_TYPECHECK(subscriber,v_subscriber)); /* Creation */ kernel = v_objectKernel(subscriber); if (v_readerQosCheck(qos) == V_RESULT_OK) { q = v_readerQosNew(kernel,qos); if (q != NULL) { reader = v_networkReader(v_objectNew(kernel,K_NETWORKREADER)); reader->statistics = v_networkReaderStatisticsNew(kernel); /* Initialization of parent */ v_readerInit(v_reader(reader), name, subscriber, q); (void)v_entityEnable(v_entity(reader)); c_free(q); /* ref now in v_reader(queue)->qos */ /* This function only ever called once per network instance so no * need to store queueType as static variable. Look up as needed (once) */ queueType = c_resolve(c_getBase(subscriber),"kernelModuleI::v_networkQueue"); /* Initialization of self */ reader->queues = NULL; reader->queues = c_arrayNew_s(queueType, NW_MAX_NOF_QUEUES); if (!reader->queues) { OS_REPORT(OS_ERROR, "v_networkReaderNew", V_RESULT_OUT_OF_MEMORY, "Creation of NetworkReader <%s> failed: cannot create queues", name); goto err_alloc_queues; } reader->nofQueues = 0; reader->defaultQueue = NULL; reader->remoteActivity = FALSE; reader->ignoreReliabilityQoS = ignoreReliabilityQoS; reader->queueCache = c_arrayNew_s(queueType, 2*NW_MAX_QUEUE_CACHE_PRIO); if (!reader->queueCache) { OS_REPORT(OS_ERROR, "v_networkReaderNew", V_RESULT_OUT_OF_MEMORY, "Creation of NetworkReader <%s> failed: cannot create queue cache", name); goto err_alloc_cache; } for( i= 0; i < 2*NW_MAX_QUEUE_CACHE_PRIO; i++) { reader->queueCache[i] = NULL; } c_free(queueType); /* Add to subscriber */ r = v_subscriberAddReader(subscriber,v_reader(reader)); if (r != V_RESULT_OK) { OS_REPORT(OS_ERROR, "v_networkReaderNew", r, "Creation of NetworkReader <%s> failed: cannot add reader to subscriber", name); goto err_add_reader; } } else { OS_REPORT(OS_ERROR, "v_networkReaderNew", V_RESULT_OUT_OF_MEMORY, "Creation of NetworkReader <%s> failed: cannot create reader QoS", name); reader = NULL; } } return reader; err_add_reader: err_alloc_cache: err_alloc_queues: c_free(queueType); c_free(reader); return NULL; }