Esempio n. 1
0
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);
    }
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
    }
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
    }
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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++;
    }
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
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);
}
Esempio n. 13
0
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);
}