Пример #1
0
static v_networkQueue
v_networkReaderSelectBestQueueByReliability(
    v_networkReader reader,
    v_messageQos qos,
    c_bool requiresP2P,
    const char *partitionName,
    const char *topicName)
{
    unsigned int n;
    v_networkQueue currentQueue;
    v_networkQueue bestQueue = NULL;
    v_networkQueue possiblyBestQueue = NULL;
    v_networkQueue bestAlternativeQueue = NULL;
    c_bool reliabilityMatches = FALSE;
    c_bool P2PMatches = FALSE;
    c_bool reliable;
    c_ulong prio,queuePrio;

    assert(reader != NULL);
    assert(C_TYPECHECK(reader, v_networkReader));
    assert(qos != NULL);
    assert(partitionName != NULL);
    assert(topicName != NULL);

    /* Transform kernel prio to networking prio */
    prio = v_messageQos_getTransportPriority(qos);
    reliable = v_messageQos_isReliable(qos);
    /* First select the best queue */
    if (prio < NW_MAX_QUEUE_CACHE_PRIO) {
        if (reliable) {
            bestQueue = reader->queueCache[prio+NW_MAX_QUEUE_CACHE_PRIO];
        } else {
            bestQueue = reader->queueCache[prio];
        }
    }
    if (!bestQueue) {
        for (n=0; (n<reader->nofQueues) && (bestQueue == NULL); n++) {
            currentQueue = reader->queues[n];
            /* Check on reliability */
            if (reliable) {
                reliabilityMatches = v_networkQueueReliable(currentQueue);
            } else {
                reliabilityMatches = !v_networkQueueReliable(currentQueue);
            }
            P2PMatches = (requiresP2P == v_networkQueueP2P(currentQueue));
            if (reliabilityMatches && P2PMatches) {
                queuePrio = v_networkQueuePriority(currentQueue);
                if (prio == queuePrio) {
                    /* An exact match! Stop here */
                    bestQueue = currentQueue;
                } else {
                    if (prio < queuePrio) {
                        /* This queue might be the best fit, it offers higher prio
                         * than requested */
                        if (possiblyBestQueue != NULL) {
                            if (queuePrio < possiblyBestQueue->priority) {
                                possiblyBestQueue = currentQueue;
                            }
                        } else {
                            possiblyBestQueue = currentQueue;
                        }
                    }
                    if (possiblyBestQueue == NULL) {
                        /* No queue fits until now, but this queue
                         * might be the best alternative if no queue
                         * offers the requested prio at all */
                        if (bestAlternativeQueue != NULL) {
                            if (queuePrio > bestAlternativeQueue->priority) {
                                bestAlternativeQueue  = currentQueue;
                            }
                        } else {
                            bestAlternativeQueue = currentQueue;
                        }
                    }
                }
            }
        }
        if (bestQueue == NULL) {
            bestQueue = possiblyBestQueue;
        }
        if (bestQueue == NULL) {
            bestQueue = bestAlternativeQueue;
        }
        if (bestQueue == NULL) {
            OS_REPORT_2(OS_WARNING, "v_networkReaderSelectBestQueue", 0,
                "Unable to select best fitting queue for partition \"%s\", "
                "topic \"%s\". Switching to default", partitionName, topicName);
            bestQueue = reader->defaultQueue;
        }
        if (prio < NW_MAX_QUEUE_CACHE_PRIO) {
            /* Store found bestQueue in the cache, while maintaining
             * correct reference counts on the Queues
             */
            if (reliable) {
                c_free(reader->queueCache[prio+NW_MAX_QUEUE_CACHE_PRIO]);
                reader->queueCache[prio+NW_MAX_QUEUE_CACHE_PRIO] = c_keep(bestQueue);
            } else {
                c_free(reader->queueCache[prio]);
                reader->queueCache[prio] = c_keep(bestQueue);
            }
        }
    }

    return bestQueue;
}
Пример #2
0
static v_networkQueue
v_networkReaderSelectBestQueueIgnoreReliability(
    v_networkReader reader,
    v_messageQos qos,
    c_bool requiresP2P,
    const char *partitionName,
    const char *topicName)
{
    unsigned int n;
    v_networkQueue currentQueue;
    v_networkQueue bestQueue = NULL;
    v_networkQueue possiblyBestQueue = NULL;
    v_networkQueue bestAlternativeQueue = NULL;
    c_bool P2PMatches = FALSE;
    c_ulong prio,queuePrio;

    assert(reader != NULL);
    assert(C_TYPECHECK(reader, v_networkReader));
    assert(qos != NULL);
    assert(partitionName != NULL);
    assert(topicName != NULL);

    /* Transform kernel prio to networking prio */
    if (v_messageQos_getTransportPriority(qos) >= 0) {
        prio = (c_ulong)v_messageQos_getTransportPriority(qos);
    } else {
        prio = 0;
    }

    /* First select the best queue */
    for (n=0; (n<reader->nofQueues) && (bestQueue == NULL); ++n) {
        currentQueue = reader->queues[n];
        P2PMatches = (requiresP2P == v_networkQueueP2P(currentQueue));
        if (P2PMatches) {
            queuePrio = v_networkQueuePriority(currentQueue);
            if (prio == queuePrio) {
                /* An exact match! Stop here */
                bestQueue = currentQueue;
            } else {
                if (prio < queuePrio) {
                    /* This queue might be the best fit, it offers higher prio
                     * than requested */
                    if (possiblyBestQueue != NULL) {
                        if (queuePrio < possiblyBestQueue->priority) {
                            possiblyBestQueue = currentQueue;
                        }
                    } else {
                        possiblyBestQueue = currentQueue;
                    }
                }
                if (possiblyBestQueue == NULL) {
                    /* No queue fits until now, but this queue
                     * might be the best alternative if no queue
                     * offers the requested prio at all */
                    if (bestAlternativeQueue != NULL) {
                        if (queuePrio > bestAlternativeQueue->priority) {
                            bestAlternativeQueue  = currentQueue;
                        }
                    } else {
                        bestAlternativeQueue = currentQueue;
                    }
                }
            }
        }
    }
    if (bestQueue == NULL) {
        bestQueue = possiblyBestQueue;
    }
    if (bestQueue == NULL) {
        bestQueue = bestAlternativeQueue;
    }
    if (bestQueue == NULL) {
        OS_REPORT_2(OS_WARNING, "v_networkReaderSelectBestQueue", 0,
            "Unable to select best fitting queue for partition \"%s\", "
            "topic \"%s\". Switching to default", partitionName, topicName);
        bestQueue = reader->defaultQueue;
    }

    return bestQueue;
}
Пример #3
0
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 = &currentMarker->next;
                currentMarker = *currentMarkerPtr;
            break;
            case C_EQ:
                if (priorityLookingFor < currentMarker->priority) {
                    currentMarkerPtr = &currentMarker->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;
}