static void nw_entryHashFree( nw_entryHash entryHash) { os_uint32 index; nw_entryHashItem *itemPtr; NW_CONFIDENCE(entryHash != NULL); if (entryHash != NULL) { for (index=0; index< entryHash->hashSize; index++) { itemPtr = &(entryHash->hashItems[index]); while (*itemPtr != NULL) { nw_entryHashItemRemove(*itemPtr, itemPtr); } } os_free(entryHash); } }
nw_bool nw_plugInterChannelProcessDataReceivedMessage( nw_plugInterChannel plugInterChannel, nw_seqNr *sendingNodeId, nw_partitionId *sendingPartitionId, os_sockaddr_storage *sendingNodeAddress, nw_seqNr *packetNr, nw_length *currentRecvBuffer) { nw_bool result; NW_CONFIDENCE(plugInterChannel != NULL); result = nw_ringBufferProcessDataEntry(plugInterChannel->ringBufferDataReceived, sendingNodeId, sendingPartitionId, sendingNodeAddress, packetNr,currentRecvBuffer); DPRINT_DATA_PROCESS(result, *packetNr); return result; }
c_ulong nw_sendChannelWrite( nw_sendChannel sendChannel, v_networkReaderEntry entry, v_message message, nw_signedLength *maxBytes, plugSendStatistics pss) { c_ulong result = 0; nw_channel channel = (nw_channel)sendChannel; NW_CONFIDENCE(channel); result = nw_bridgeWrite(channel->owningBridge, channel->channelId, entry->networkPartitionId, message, entry->hashValue, v_partitionName(v_groupPartition(entry->group)), v_topicName(v_groupTopic(entry->group)),maxBytes, pss); return result; }
nw_bool nw_plugDataBufferIsLastMessageHolder( nw_plugDataBuffer buffer, nw_messageHolder messageHolder) { nw_bool result = FALSE; nw_seqNr fragmentLength; nw_seqNr msgLength; nw_seqNr offset; NW_CONFIDENCE(buffer != NULL); if (messageHolder != NULL) { fragmentLength = nw_plugBufferGetLength(nw_plugBuffer(buffer)); msgLength = nw_messageHolderGetLength(messageHolder); offset = UI(messageHolder) - UI(buffer) + sizeof(messageHolder->length); result = ((offset + NW_ALIGN(NW_PLUGDATABUFFER_DATA_ALIGNMENT, msgLength)) == fragmentLength); } return result; }
nw_bool nw_plugInterChannelProcessAckReceivedMessage( nw_plugInterChannel plugInterChannel, nw_seqNr *sendingNodeId, nw_partitionId *sendingPartitionId, os_sockaddr_storage *sendingNodeAddress, nw_seqNr *startingNr, nw_seqNr *closingNr, nw_length *remoteRecvBuffer) { nw_bool result; NW_CONFIDENCE(plugInterChannel != NULL); result = nw_ringBufferProcessAckEntry(plugInterChannel->ringBufferAckReceived, sendingNodeId, sendingPartitionId, sendingNodeAddress, startingNr, closingNr, remoteRecvBuffer); DPRINT_ACK_PROCESS(result, *startingNr, *closingNr); return result; }
static void nw_entryHashItemInsert( v_networkHashValue hashValue, const c_char *partitionName, const c_char *topicName, v_networkReaderEntry entry, nw_entryHashItem *prevNextPtr) { nw_entryHashItem newItem; NW_CONFIDENCE(prevNextPtr != NULL); newItem = (nw_entryHashItem)os_malloc(sizeof(*newItem)); if (newItem != NULL) { newItem->hashValue = hashValue; newItem->partitionName = (const char *)nw_stringDup(partitionName); newItem->topicName = (const char *)nw_stringDup(topicName); newItem->entry = entry; newItem->next = *prevNextPtr; *prevNextPtr = newItem; } }
static nw_bool nw_ringBufferProcessRequestEntry( nw_ringBuffer ringBuffer, nw_seqNr *servingNodeId, os_sockaddr_storage *servingNodeAddress, nw_seqNr *diedNodeId, nw_partitionId *partitionId, nw_seqNr *firstNr, nw_seqNr *lastNr) { nw_plugInterCommRequestMessage message; nw_bool result; NW_CONFIDENCE(ringBuffer != NULL); NW_CONFIDENCE(ringBuffer->kind == NW_PLUGREL_DATA_REQ); NW_CONFIDENCE(NW_RINGBUFFER_INDEX_IS_VALID(ringBuffer, ringBuffer->tail)); NW_CONFIDENCE(servingNodeId != NULL); NW_CONFIDENCE(servingNodeAddress != NULL); NW_CONFIDENCE(diedNodeId != NULL); NW_CONFIDENCE(firstNr != NULL); NW_CONFIDENCE(lastNr != NULL); if (!NW_RINGBUFFER_IS_EMPTY(ringBuffer)) { message = NW_RINGBUFFER_ENTRY_BY_INDEX(ringBuffer, ringBuffer->tail); *servingNodeId = message->servingNodeId; *servingNodeAddress = message->servingNodeAddress; *diedNodeId = message->diedNodeId; *partitionId = message->partitionId; *firstNr = message->firstNr; *lastNr = message->lastNr; NW_RINGBUFFER_INDEX_INC(ringBuffer, ringBuffer->tail); result = TRUE; } else { result = FALSE; } return result; }
static void nw_splicedaemonListener( v_serviceStateKind spliceDaemonState, c_voidp usrData) { nw_termination *terminate = (nw_termination *)usrData; switch (spliceDaemonState) { case STATE_TERMINATING: case STATE_TERMINATED: case STATE_DIED: os_mutexLock( &terminate->mtx ); terminate->terminate = TRUE; os_condBroadcast( &terminate->cv ); os_mutexUnlock( &terminate->mtx ); break; default: NW_CONFIDENCE(FALSE); break; } }
static c_type onTypeLookup( v_networkHashValue hashValue, const c_char *partitionName, const c_char *topicName, nw_typeLookupArg arg) { c_type result = NULL; nw_lookupArg lookupArg = (nw_lookupArg)arg; nw_receiveChannel receiveChannel = lookupArg->receiveChannel; v_networkReaderEntry entry; NW_CONFIDENCE(receiveChannel != NULL); #ifdef NW_LOOPBACK if (nw_configurationUseComplementPartitions()) { entry = nw_entryHashLookupByNamesOnly(receiveChannel->hash, partitionName, topicName); } else { entry = nw_entryHashLookup(receiveChannel->hash, hashValue, partitionName, topicName); } #else entry = nw_entryHashLookup(receiveChannel->hash, hashValue, partitionName, topicName); #endif if ((entry == NULL) && (lookupArg->entryLookupAction != NULL)) { entry = lookupArg->entryLookupAction(hashValue, partitionName, topicName, lookupArg->entryLookupArg); } lookupArg->entryFound = entry; if (entry != NULL) { result = v_topicMessageType(v_group(entry->group)->topic); } return result; }
void nw_plugInterChannelIncarnate( nw_plugInterChannel *interChannel, const char *pathName) { c_ulong ringbufferSize; NW_CONFIDENCE(interChannel != NULL); if (*interChannel == NULL) { ringbufferSize = NWCF_SIMPLE_PARAM(ULong, pathName, AdminQueueSize); if (ringbufferSize < NWCF_MIN(AdminQueueSize)) { NW_REPORT_WARNING_3("initializing network", "Reliable channel \"%s\": requested value %u for admin queuesize is too small, " "using %u instead", pathName, ringbufferSize, NWCF_MIN(AdminQueueSize)); ringbufferSize = NWCF_MIN(AdminQueueSize); } *interChannel = nw_plugInterChannelNew(ringbufferSize); } else { (*interChannel)->refCount++; } }
static nw_bool nw_ringBufferProcessAckEntry( nw_ringBuffer ringBuffer, nw_seqNr *sendingNodeId, nw_partitionId *sendingPartitionId, os_sockaddr_storage *sendingNodeAddress, nw_seqNr *startingNr, nw_seqNr *closingNr, nw_length *remoteRecvBuffer) { nw_plugInterCommAckMessage message; nw_bool result; NW_CONFIDENCE(ringBuffer != NULL); NW_CONFIDENCE(ringBuffer->kind == NW_PLUGREL_ACK_RECEIVED); NW_CONFIDENCE(NW_RINGBUFFER_INDEX_IS_VALID(ringBuffer, ringBuffer->tail)); NW_CONFIDENCE(sendingNodeId != NULL); NW_CONFIDENCE(startingNr != NULL); NW_CONFIDENCE(closingNr != NULL); NW_CONFIDENCE(remoteRecvBuffer != NULL); if (!NW_RINGBUFFER_IS_EMPTY(ringBuffer)) { message = NW_RINGBUFFER_ENTRY_BY_INDEX(ringBuffer, ringBuffer->tail); *sendingNodeId = message->sendingNodeId; *sendingPartitionId = message->sendingPartitionId; *sendingNodeAddress = message->sendingNodeAddress; *startingNr = message->startingNr; *closingNr = message->closingNr; *remoteRecvBuffer = message->remoteRecvBuffer; NW_RINGBUFFER_INDEX_INC(ringBuffer, ringBuffer->tail); result = TRUE; } else { 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); }
void nw_plugChannelInitialize( nw_plugChannel channel, nw_seqNr seqNr, nw_networkId nodeId, nw_communicationKind communication, nw_plugPartitions partitions, nw_userData *userDataPtr, const char *pathName, nw_onFatalCallBack onFatal, c_voidp onFatalUsrData) { nw_size fragmentLength; nw_bool reliable; nw_bool controlNeeded; static sk_portNr sendingPortNr = NWCF_DEF(PortNr); static sk_portNr receivingPortNr = NWCF_DEF(PortNr); sk_portNr newPortNr; nw_plugInterChannel *interChannelPtr = (nw_plugInterChannel *)userDataPtr; char *defaultPartitionAddress; /* Simple attributes */ channel->name = nw_stringDup(pathName); channel->Id = seqNr; channel->nodeId = nodeId; channel->communication = communication; channel->partitions = partitions; /* Attributes to be read from config */ /* QoS-es*/ reliable = NWCF_SIMPLE_ATTRIB(Bool, pathName, reliable); if (reliable) { channel->reliabilityOffered = NW_REL_RELIABLE; controlNeeded = TRUE; /* Create object for inter-channel communication */ nw_plugInterChannelIncarnate(interChannelPtr, pathName); channel->interChannelComm = *interChannelPtr; } else { channel->reliabilityOffered = NW_REL_BEST_EFFORT; controlNeeded = FALSE; /* NO object needed for inter-channel communication */ channel->interChannelComm = NULL; } /* Default, to be implemented */ channel->priorityOffered = NW_PRIORITY_UNDEFINED; channel->latencyBudgetOffered = NW_LATENCYBUDGET_UNDEFINED; /* Network fragment length */ fragmentLength = (nw_size)NWCF_SIMPLE_PARAM(Size, pathName, FragmentSize); /* CHECKME, NWCF_MIN(FragmentSize) must be larger dealing with encryption */ if (fragmentLength < NWCF_MIN(FragmentSize)) { NW_REPORT_WARNING_3("initializing network", "Channel \"%s\": requested value %u for fragment size is too small, " "using %u instead", pathName, fragmentLength, NWCF_MIN(FragmentSize)); fragmentLength = NWCF_MIN(FragmentSize); } else if(fragmentLength > NWCF_MAX(FragmentSize)) { NW_REPORT_WARNING_3("initializing network", "Channel \"%s\": requested value " PA_SIZEFMT " for fragment size is too big, " "using %u instead", pathName, fragmentLength, NWCF_MAX(FragmentSize)); fragmentLength = NWCF_MAX(FragmentSize); } /* FIXME, this rounds up to multiple of 4, but it should round down to * meet network constraints (??) */ /* round to lowest NW_FRAG_BOUNDARY multiplication higher than * fragmentLength */ channel->fragmentLength = NW_ALIGN(NW_PLUGDATABUFFER_ALIGNMENT, (nw_length)fragmentLength); /* What is the base adress of the socket wee need ? */ nw_plugPartitionsGetDefaultPartition(partitions, &defaultPartitionAddress, NULL /* SecurityProfile not of interest */ ); switch (communication) { case NW_COMM_SEND: newPortNr = NWCF_DEFAULTED_PARAM(ULong, pathName, PortNr, sendingPortNr); if (newPortNr == sendingPortNr) { sendingPortNr+=2; } channel->socket = nw_socketSendNew(defaultPartitionAddress, newPortNr, controlNeeded, pathName); break; case NW_COMM_RECEIVE: newPortNr = NWCF_DEFAULTED_PARAM( ULong, pathName, PortNr, receivingPortNr); if (newPortNr == receivingPortNr) { receivingPortNr+=2; } channel->socket = nw_socketReceiveNew(defaultPartitionAddress, newPortNr, controlNeeded, pathName); break; default: NW_CONFIDENCE(FALSE); break; } channel->messageBox = nw_messageBoxNew(); channel->onFatal = onFatal; channel->onFatalUsrData = onFatalUsrData; channel->reconnectAllowed = NWCF_SIMPLE_ATTRIB(Bool,NWCF_ROOT(General) NWCF_SEP NWCF_NAME(Reconnection),allowed); channel->crc = ut_crcNew(UT_CRC_KEY); }