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); }
c_bool v_readerUnSubscribe( v_reader r, v_partition d) { assert(C_TYPECHECK(r,v_reader)); switch(v_objectKind(r)) { case K_DATAREADER: return v_dataReaderUnSubscribe(v_dataReader(r),d); case K_DELIVERYSERVICE: return v_deliveryServiceUnSubscribe(v_deliveryService(r),d); case K_GROUPQUEUE: return v_groupStreamUnSubscribe(v_groupStream(r),d); case K_NETWORKREADER: return v_networkReaderUnSubscribe(v_networkReader(r),d); default: OS_REPORT_1(OS_ERROR,"v_readerUnSubscribe failed",0, "illegal reader kind (%d) specified", v_objectKind(r)); assert(FALSE); } return TRUE; }
/************************************************************** * Public functions **************************************************************/ c_bool v_readerSubscribe( v_reader r, v_partition d) { c_bool result; assert(C_TYPECHECK(r,v_reader)); switch(v_objectKind(r)) { case K_DATAREADER: result = v_dataReaderSubscribe(v_dataReader(r),d); break; case K_DELIVERYSERVICE: result = v_deliveryServiceSubscribe(v_deliveryService(r),d); break; case K_GROUPQUEUE: result = v_groupStreamSubscribe(v_groupStream(r),d); break; case K_NETWORKREADER: result = v_networkReaderSubscribe(v_networkReader(r),d); break; default: OS_REPORT_1(OS_ERROR,"v_readerSubscribe failed",0, "illegal reader kind (%d) specified", v_objectKind(r)); assert(FALSE); result = FALSE; break; } readerGetHistoricalData(r); return result; }
c_bool v_readerUnSubscribeGroup( v_reader reader, v_group group) { c_bool result; assert(C_TYPECHECK(reader, v_reader)); switch(v_objectKind(reader)) { case K_DATAREADER: result = v_dataReaderUnSubscribeGroup(v_dataReader(reader), group); break; case K_GROUPQUEUE: result = v_groupStreamUnSubscribeGroup(v_groupStream(reader), group); break; case K_NETWORKREADER: result = v_networkReaderUnSubscribeGroup(v_networkReader(reader), group); break; default: OS_REPORT_1(OS_ERROR,"v_readerUnSubscribeGroup failed",0, "illegal reader kind (%d) specified", v_objectKind(reader)); assert(FALSE); result = FALSE; } return result; }
void v_subscriberFree( v_subscriber s) { v_kernel kernel; v_participant p; v_reader o; v_entity found; c_long sc; kernel = v_objectKernel(s); sc = (c_long)pa_decrement(&(s->shareCount)); if (sc > 0) return; if(sc == 0){ v_observableRemoveObserver(v_observable(kernel->groupSet),v_observer(s), NULL); if (s->qos->share.enable) { found = v_removeShare(kernel,v_entity(s)); assert(found == v_entity(s)); c_free(found); } while ((o = c_take(s->readers)) != NULL) { switch (v_objectKind(o)) { case K_DATAREADER: v_dataReaderFree(v_dataReader(o)); break; case K_DELIVERYSERVICE: v_deliveryServiceFree(v_deliveryService(o)); break; case K_GROUPQUEUE: v_groupQueueFree(v_groupQueue(o)); break; case K_NETWORKREADER: v_networkReaderFree(v_networkReader(o)); break; default: OS_REPORT_1(OS_ERROR, "v_subscriber", 0, "Unknown reader %d", v_objectKind(o)); assert(FALSE); break; } c_free(o); } p = v_participant(s->participant); if (p != NULL) { v_participantRemove(p,v_entity(s)); s->participant = NULL; } v_publicFree(v_public(s)); } else { OS_REPORT_1(OS_ERROR, "v_subscriberFree", 0, "subscriber already freed (shareCount is now %d).", sc); assert(sc == 0); } }
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; }
c_char* cmx_networkReaderInit( v_networkReader entity) { char buf[512]; v_networkReader reader; reader = v_networkReader(entity); os_sprintf(buf, "<kind>NETWORKREADER</kind>"); return (c_char*)(os_strdup(buf)); }
v_writeResult v_networkReaderEntryWrite( v_networkReaderEntry entry, v_message message, v_networkId writingNetworkId) { v_writeResult result = V_WRITE_SUCCESS; c_bool writeSucceeded; static v_gid zeroAddressee = {0,0,0}; assert(C_TYPECHECK(entry, v_networkReaderEntry)); assert(message != NULL); /* First check if there is any remote interest at all */ if (v_networkReader(v_entry(entry)->reader)->remoteActivity) { /* Only forward messages that come from this kernel */ if (writingNetworkId == V_NETWORKID_LOCAL || entry->isRouting) { /* OK, message is from this kernel or this is a routing entry. Now * attach the correct fields if needed */ /* TODO: For networking services that support routing perhaps * messages shouldn't be forwarded to 'self' (e.g., echo cancellation * may be needed). For R&R this modus is fine. */ writeSucceeded = v_networkReaderWrite( v_networkReader(v_entry(entry)->reader), message, entry, 0, message->writerGID, FALSE /* no p2p */, zeroAddressee); if (writeSucceeded) { result = V_WRITE_SUCCESS; } else { result = V_WRITE_REJECTED; } } } return result; }
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; }
/************************************************************** * Protected functions **************************************************************/ c_bool v_readerSubscribeGroup( v_reader _this, v_group group) { c_bool result; assert(C_TYPECHECK(_this, v_reader)); switch(v_objectKind(_this)) { case K_DATAREADER: /* ES, dds1576: For the K_DATAREADER object we need to verify if * the access rights are correct. No subscriptions may be made onto * groups which have a v_accessMode of write only. */ if(v_groupPartitionAccessMode(group) == V_ACCESS_MODE_READ_WRITE || v_groupPartitionAccessMode(group) == V_ACCESS_MODE_READ) { result = v_dataReaderSubscribeGroup(v_dataReader(_this), group); readerGetHistoricalData(_this); } else { result = FALSE; } break; case K_GROUPQUEUE: result = v_groupStreamSubscribeGroup(v_groupStream(_this), group); break; case K_NETWORKREADER: result = v_networkReaderSubscribeGroup(v_networkReader(_this), group); readerGetHistoricalData(_this); break; default: OS_REPORT_1(OS_ERROR,"v_readerSubscribeGroup failed",0, "illegal reader kind (%d) specified", v_objectKind(_this)); assert(FALSE); result = FALSE; } return result; }
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_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; }