bool DomainContentBackupManager::process() {
    if (isStillRunning()) {
        constexpr int64_t MSECS_TO_USECS = 1000;
        constexpr int64_t USECS_TO_SLEEP = 10 * MSECS_TO_USECS;  // every 10ms
        std::this_thread::sleep_for(std::chrono::microseconds(USECS_TO_SLEEP));

        if (_isRecovering) {
            bool isStillRecovering = any_of(begin(_backupHandlers), end(_backupHandlers), [](const BackupHandlerPointer& handler) {
                return handler->getRecoveryStatus().first;
            });

            if (!isStillRecovering) {
                _isRecovering = false;
                _recoveryFilename = "";
                emit recoveryCompleted();
            }
        }

        auto now = p_high_resolution_clock::now();
        auto sinceLastSave = now - _lastCheck;
        if (sinceLastSave > _persistInterval) {
            _lastCheck = now;

            if (!_isRecovering) {
                backup();
            }
        }
    }

    return isStillRunning();
}
Exemplo n.º 2
0
bool OctreeSendThread::process() {
    quint64  start = usecTimestampNow();
    bool gotLock = false;

    // don't do any send processing until the initial load of the octree is complete...
    if (_myServer->isInitialLoadComplete()) {
        SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);

        if (node) {
            // make sure the node list doesn't kill our node while we're using it
            if (node->getMutex().tryLock()) {
                gotLock = true;
                OctreeQueryNode* nodeData = NULL;

                nodeData = (OctreeQueryNode*) node->getLinkedData();

                int packetsSent = 0;

                // Sometimes the node data has not yet been linked, in which case we can't really do anything
                if (nodeData) {
                    bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
                    if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
                        printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged));
                    }
                    packetsSent = packetDistributor(node, nodeData, viewFrustumChanged);
                }

                node->getMutex().unlock(); // we're done with this node for now.
            }
        }
    } else {
        if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
            qDebug("OctreeSendThread::process() waiting for isInitialLoadComplete()");
        }
    }

    // Only sleep if we're still running and we got the lock last time we tried, otherwise try to get the lock asap
    if (isStillRunning() && gotLock) {
        // dynamically sleep until we need to fire off the next set of octree elements
        int elapsed = (usecTimestampNow() - start);
        int usecToSleep =  OCTREE_SEND_INTERVAL_USECS - elapsed;

        if (usecToSleep > 0) {
            PerformanceWarning warn(false,"OctreeSendThread... usleep()",false,&_usleepTime,&_usleepCalls);
            usleep(usecToSleep);
        } else {
            if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) {
                std::cout << "Last send took too much time, not sleeping!\n";
            }
        }
    }

    return isStillRunning();  // keep running till they terminate us
}
bool ReceivedPacketProcessor::process() {
    quint64 now = usecTimestampNow();
    quint64 sinceLastWindow = now - _lastWindowAt;

    if (sinceLastWindow > USECS_PER_SECOND) {
        lock();
        float secondsSinceLastWindow = sinceLastWindow / USECS_PER_SECOND;
        float incomingPacketsPerSecondInWindow = (float)_lastWindowIncomingPackets / secondsSinceLastWindow;
        _incomingPPS.updateAverage(incomingPacketsPerSecondInWindow);

        float processedPacketsPerSecondInWindow = (float)_lastWindowProcessedPackets / secondsSinceLastWindow;
        _processedPPS.updateAverage(processedPacketsPerSecondInWindow);

        _lastWindowAt = now;
        _lastWindowIncomingPackets = 0;
        _lastWindowProcessedPackets = 0;
        unlock();
    }

    if (_packets.size() == 0) {
        _waitingOnPacketsMutex.lock();
        _hasPackets.wait(&_waitingOnPacketsMutex, getMaxWait());
        _waitingOnPacketsMutex.unlock();
    }

    preProcess();
    if (!_packets.size()) {
        return isStillRunning();
    }

    lock();
    std::list<NodeSharedReceivedMessagePair> currentPackets;
    currentPackets.swap(_packets);
    unlock();

    for(auto& packetPair : currentPackets) {
        processPacket(packetPair.second, packetPair.first);
        _lastWindowProcessedPackets++;
        midProcess();
    }

    lock();
    for(auto& packetPair : currentPackets) {
        _nodePacketCounts[packetPair.first->getUUID()]--;
    }
    unlock();

    postProcess();
    return isStillRunning();  // keep running till they terminate us
}
Exemplo n.º 4
0
bool OctreeSendThread::process() {
    if (_isShuttingDown) {
        return false; // exit early if we're shutting down
    }

    // check that our server and assignment is still valid
    if (!_myServer || !_myAssignment) {
        return false; // exit early if it's not, it means the server is shutting down
    }

    OctreeServer::didProcess(this);

    quint64  start = usecTimestampNow();

    // don't do any send processing until the initial load of the octree is complete...
    if (_myServer->isInitialLoadComplete()) {
        if (_node) {
            _nodeMissingCount = 0;
            OctreeQueryNode* nodeData = static_cast<OctreeQueryNode*>(_node->getLinkedData());

            // Sometimes the node data has not yet been linked, in which case we can't really do anything
            if (nodeData && !nodeData->isShuttingDown()) {
                bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
                packetDistributor(nodeData, viewFrustumChanged);
            }
        }
    }

    if (_isShuttingDown) {
        return false; // exit early if we're shutting down
    }

    // Only sleep if we're still running and we got the lock last time we tried, otherwise try to get the lock asap
    if (isStillRunning()) {
        // dynamically sleep until we need to fire off the next set of octree elements
        int elapsed = (usecTimestampNow() - start);
        int usecToSleep =  OCTREE_SEND_INTERVAL_USECS - elapsed;

        if (usecToSleep > 0) {
            PerformanceWarning warn(false,"OctreeSendThread... usleep()",false,&_usleepTime,&_usleepCalls);
            usleep(usecToSleep);
        } else {
            const int MIN_USEC_TO_SLEEP = 1;
            usleep(MIN_USEC_TO_SLEEP);
        }
    }

    return isStillRunning();  // keep running till they terminate us
}
Exemplo n.º 5
0
bool JurisdictionListener::queueJurisdictionRequest() {
    //qDebug() << "JurisdictionListener::queueJurisdictionRequest()\n";

    static unsigned char buffer[MAX_PACKET_SIZE];
    unsigned char* bufferOut = &buffer[0];
    ssize_t sizeOut = populateTypeAndVersion(bufferOut, PACKET_TYPE_JURISDICTION_REQUEST);
    int nodeCount = 0;

    NodeList* nodeList = NodeList::getInstance();
    for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
        if (nodeList->getNodeActiveSocketOrPing(&(*node)) &&
                node->getType() == getNodeType()) {
            const HifiSockAddr* nodeAddress = node->getActiveSocket();
            PacketSender::queuePacketForSending(*nodeAddress, bufferOut, sizeOut);
            nodeCount++;
        }
    }

    if (nodeCount > 0) {
        setPacketsPerSecond(nodeCount);
    } else {
        setPacketsPerSecond(NO_SERVER_CHECK_RATE);
    }

    // keep going if still running
    return isStillRunning();
}
Exemplo n.º 6
0
bool JurisdictionListener::queueJurisdictionRequest() {
    static unsigned char buffer[MAX_PACKET_SIZE];
    unsigned char* bufferOut = &buffer[0];
    ssize_t sizeOut = populateTypeAndVersion(bufferOut, PACKET_TYPE_VOXEL_JURISDICTION_REQUEST);
    int nodeCount = 0;

    NodeList* nodeList = NodeList::getInstance();
    for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {

        // only send to the NodeTypes that are interested in our jurisdiction details
        const int numNodeTypes = 1; 
        const NODE_TYPE nodeTypes[numNodeTypes] = { NODE_TYPE_VOXEL_SERVER };
        if (node->getActiveSocket() != NULL && memchr(nodeTypes, node->getType(), numNodeTypes)) {
            sockaddr* nodeAddress = node->getActiveSocket();
            PacketSender::queuePacketForSending(*nodeAddress, bufferOut, sizeOut);
            nodeCount++;
        }
    }

    // set our packets per second to be the number of nodes
    setPacketsPerSecond(nodeCount);
    
    // keep going if still running
    return isStillRunning();
}
Exemplo n.º 7
0
bool JurisdictionSender::process() {
    bool continueProcessing = isStillRunning();

    // call our ReceivedPacketProcessor base class process so we'll get any pending packets
    if (continueProcessing && (continueProcessing = ReceivedPacketProcessor::process())) {
        int nodeCount = 0;

        lockRequestingNodes();
        while (!_nodesRequestingJurisdictions.empty()) {

            QUuid nodeUUID = _nodesRequestingJurisdictions.front();
            _nodesRequestingJurisdictions.pop();
            SharedNodePointer node = DependencyManager::get<NodeList>()->nodeWithUUID(nodeUUID);

            if (node && node->getActiveSocket()) {
                auto packet = (_jurisdictionMap) ? _jurisdictionMap->packIntoPacket()
                                                 : JurisdictionMap::packEmptyJurisdictionIntoMessage(getNodeType());
                _packetSender.queuePacketForSending(node, std::move(packet));
                nodeCount++;
            }
        }
        unlockRequestingNodes();

        // set our packets per second to be the number of nodes
        _packetSender.setPacketsPerSecond(nodeCount);

        continueProcessing = _packetSender.process();
    }
    return continueProcessing;
}
Exemplo n.º 8
0
bool OctreeSendThread::process() {
    const int MAX_NODE_MISSING_CHECKS = 10;
    if (_nodeMissingCount > MAX_NODE_MISSING_CHECKS) {
        qDebug() << "our target node:" << _nodeUUID << "has been missing the last" << _nodeMissingCount 
                        << "times we checked, we are going to stop attempting to send.";
        return false; // stop processing and shutdown, our node no longer exists
    }

    quint64  start = usecTimestampNow();

    // don't do any send processing until the initial load of the octree is complete...
    if (_myServer->isInitialLoadComplete()) {
        SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID);

        if (node) {
            _nodeMissingCount = 0;
            OctreeQueryNode* nodeData = NULL;

            nodeData = (OctreeQueryNode*) node->getLinkedData();

            // Sometimes the node data has not yet been linked, in which case we can't really do anything
            if (nodeData) {
                bool viewFrustumChanged = nodeData->updateCurrentViewFrustum();
                packetDistributor(node, nodeData, viewFrustumChanged);
            }
        } else {
            _nodeMissingCount++;
        }
    }

    // Only sleep if we're still running and we got the lock last time we tried, otherwise try to get the lock asap
    if (isStillRunning()) {
        // dynamically sleep until we need to fire off the next set of octree elements
        int elapsed = (usecTimestampNow() - start);
        int usecToSleep =  OCTREE_SEND_INTERVAL_USECS - elapsed;

        if (usecToSleep > 0) {
            PerformanceWarning warn(false,"OctreeSendThread... usleep()",false,&_usleepTime,&_usleepCalls);
            usleep(usecToSleep);
        } else {
            const int MIN_USEC_TO_SLEEP = 1;
            usleep(MIN_USEC_TO_SLEEP);
        }
    }

    return isStillRunning();  // keep running till they terminate us
}
Exemplo n.º 9
0
bool PacketSender::threadedProcess() {
    bool hasSlept = false;

    if (_lastSendTime == 0) {
        _lastSendTime = usecTimestampNow();
    }

    // in threaded mode, we keep running and just empty our packet queue sleeping enough to keep our PPS on target
    while (_packets.size() > 0) {
        // Recalculate our SEND_INTERVAL_USECS each time, in case the caller has changed it on us..
        int packetsPerSecondTarget = (_packetsPerSecond > MINIMUM_PACKETS_PER_SECOND)
                                            ? _packetsPerSecond : MINIMUM_PACKETS_PER_SECOND;

        quint64 intervalBetweenSends = USECS_PER_SECOND / packetsPerSecondTarget;
        quint64 sleepInterval = (intervalBetweenSends > SENDING_INTERVAL_ADJUST) ?
                    intervalBetweenSends - SENDING_INTERVAL_ADJUST : intervalBetweenSends;

        // We'll sleep before we send, this way, we can set our last send time to be our ACTUAL last send time
        quint64 now = usecTimestampNow();
        quint64 elapsed = now - _lastSendTime;
        int usecToSleep =  sleepInterval - elapsed;

        // If we've never sent, or it's been a long time since we sent, then our elapsed time will be quite large
        // and therefore usecToSleep will be less than 0 and we won't sleep before sending...
        if (usecToSleep > 0) {
            if (usecToSleep > MAX_SLEEP_INTERVAL) {
                usecToSleep = MAX_SLEEP_INTERVAL;
            }
            usleep(usecToSleep);
            hasSlept = true;
        }

        // call our non-threaded version of ourselves
        bool keepRunning = nonThreadedProcess();

        if (!keepRunning) {
            break;
        }
    }

    // if threaded and we haven't slept? We want to wait for our consumer to signal us with new packets
    if (!hasSlept) {
        // wait till we have packets
        _waitingOnPacketsMutex.lock();
        _hasPackets.wait(&_waitingOnPacketsMutex);
        _waitingOnPacketsMutex.unlock();
    }

    return isStillRunning();
}
Exemplo n.º 10
0
bool JurisdictionListener::process() {
    bool continueProcessing = isStillRunning();

    // If we're still running, and we don't have any requests waiting to be sent, then queue our jurisdiction requests
    if (continueProcessing && !hasPacketsToSend()) {
        queueJurisdictionRequest();
        continueProcessing = PacketSender::process();
    }
    if (continueProcessing) {
        // NOTE: This will sleep if there are no pending packets to process
        continueProcessing = ReceivedPacketProcessor::process();
    }
    return continueProcessing;
}
Exemplo n.º 11
0
bool PacketSender::threadedProcess() {
    bool hasSlept = false;

    if (_lastSendTime == 0) {
        _lastSendTime = usecTimestampNow();
    }

    // in threaded mode, we keep running and just empty our packet queue sleeping enough to keep our PPS on target
    while (_packets.size() > 0) {
        // Recalculate our SEND_INTERVAL_USECS each time, in case the caller has changed it on us..
        int packetsPerSecondTarget = (_packetsPerSecond > MINIMUM_PACKETS_PER_SECOND)
                                            ? _packetsPerSecond : MINIMUM_PACKETS_PER_SECOND;

        quint64 intervalBetweenSends = USECS_PER_SECOND / packetsPerSecondTarget;
        quint64 sleepInterval = (intervalBetweenSends > SENDING_INTERVAL_ADJUST) ?
                    intervalBetweenSends - SENDING_INTERVAL_ADJUST : intervalBetweenSends;

        // We'll sleep before we send, this way, we can set our last send time to be our ACTUAL last send time
        quint64 now = usecTimestampNow();
        quint64 elapsed = now - _lastSendTime;
        int usecToSleep =  sleepInterval - elapsed;

        // If we've never sent, or it's been a long time since we sent, then our elapsed time will be quite large
        // and therefore usecToSleep will be less than 0 and we won't sleep before sending...
        if (usecToSleep > 0) {
            if (usecToSleep > MAX_SLEEP_INTERVAL) {
                usecToSleep = MAX_SLEEP_INTERVAL;
            }
            usleep(usecToSleep);
            hasSlept = true;
        }

        // call our non-threaded version of ourselves
        bool keepRunning = nonThreadedProcess();

        if (!keepRunning) {
            break;
        }
    }

    // if threaded and we haven't slept? We want to sleep a little so we don't hog the CPU, but
    // we don't want to sleep too long because how ever much we sleep will delay any future unsent
    // packets that arrive while we're sleeping. So we sleep 1/2 of our target fps interval
    if (!hasSlept) {
        usleep(MINIMAL_SLEEP_INTERVAL);
    }

    return isStillRunning();
}
Exemplo n.º 12
0
bool ReceivedPacketProcessor::process() {

    if (_packets.size() == 0) {
        _waitingOnPacketsMutex.lock();
        _hasPackets.wait(&_waitingOnPacketsMutex);
        _waitingOnPacketsMutex.unlock();
    }
    while (_packets.size() > 0) {
        lock(); // lock to make sure nothing changes on us
        NetworkPacket& packet = _packets.front(); // get the oldest packet
        NetworkPacket temporary = packet; // make a copy of the packet in case the vector is resized on us
        _packets.erase(_packets.begin()); // remove the oldest packet
        _nodePacketCounts[temporary.getNode()->getUUID()]--;
        unlock(); // let others add to the packets
        processPacket(temporary.getNode(), temporary.getByteArray()); // process our temporary copy
    }
    return isStillRunning();  // keep running till they terminate us
}
Exemplo n.º 13
0
bool ReceivedPacketProcessor::process() {

    // If a derived class handles process sleeping, like the JurisdiciontListener, then it can set
    // this _dontSleep member and we will honor that request.
    if (_packets.size() == 0 && !_dontSleep) {
        const uint64_t RECEIVED_THREAD_SLEEP_INTERVAL = (1000 * 1000)/60; // check at 60fps
        usleep(RECEIVED_THREAD_SLEEP_INTERVAL);
    }
    while (_packets.size() > 0) {

        lock(); // lock to make sure nothing changes on us
        NetworkPacket& packet = _packets.front(); // get the oldest packet
        NetworkPacket temporary = packet; // make a copy of the packet in case the vector is resized on us
        _packets.erase(_packets.begin()); // remove the oldest packet
        unlock(); // let others add to the packets
        processPacket(temporary.getAddress(), temporary.getData(), temporary.getLength()); // process our temporary copy
    }
    return isStillRunning();  // keep running till they terminate us
}
Exemplo n.º 14
0
GenericThread::~GenericThread() {
    // we only need to call terminate() if we're actually threaded and still running
    if (isStillRunning() && isThreaded()) {
        terminate();
    }
}
Exemplo n.º 15
0
// We may be called more frequently than we get packets or need to send packets, we may also get called less frequently.
//
// If we're called more often then out target PPS then we will space out our actual sends to be a single packet for multiple
// calls to process. Those calls to proces in which we do not need to send a packet to keep up with our target PPS we will
// just track our call rate (in order to predict our sends per call) but we won't actually send any packets.
//
// When we are called less frequently than we have packets to send, we will send enough packets per call to keep up with our
// target PPS.
//
// We also keep a running total of packets sent over multiple calls to process() so that we can adjust up or down for
// possible rounding error that would occur if we only considered whole integer packet counts per call to process
bool PacketSender::nonThreadedProcess() {
    quint64 now = usecTimestampNow();

    if (_lastProcessCallTime == 0) {
        _lastProcessCallTime = now - _usecsPerProcessCallHint;
    }

    const quint64 MINIMUM_POSSIBLE_CALL_TIME = 10; // in usecs
    const quint64 USECS_PER_SECOND = 1000 * 1000;
    const float ZERO_RESET_CALLS_PER_SECOND = 1; // used in guard against divide by zero

    // keep track of our process call times, so we have a reliable account of how often our caller calls us
    quint64 elapsedSinceLastCall = now - _lastProcessCallTime;
    _lastProcessCallTime = now;
    _averageProcessCallTime.updateAverage(elapsedSinceLastCall);

    float averageCallTime = 0;
    const int TRUST_AVERAGE_AFTER = AVERAGE_CALL_TIME_SAMPLES * 2;
    if (_usecsPerProcessCallHint == 0 || _averageProcessCallTime.getSampleCount() > TRUST_AVERAGE_AFTER) {
        averageCallTime = _averageProcessCallTime.getAverage();
    } else {
        averageCallTime = _usecsPerProcessCallHint;
    }

    if (_packets.size() == 0) {
        // in non-threaded mode, if there's nothing to do, just return, keep running till they terminate us
        return isStillRunning();
    }

    // This only happens once, the first time we get this far... so we can use it as an accurate initialization
    // point for these important timing variables
    if (_lastPPSCheck == 0) {
        _lastPPSCheck = now;
        // pretend like our lifetime began once call cycle for now, this makes our lifetime PPS start out most accurately
        _started = now - (quint64)averageCallTime;
    }


    float averagePacketsPerCall = 0;  // might be less than 1, if our caller calls us more frequently than the target PPS
    int packetsSentThisCall = 0;
    int packetsToSendThisCall = 0;

    // Since we're in non-threaded mode, we need to determine how many packets to send per call to process
    // based on how often we get called... We do this by keeping a running average of our call times, and we determine
    // how many packets to send per call

    // We assume you can't possibly call us less than MINIMUM_POSSIBLE_CALL_TIME apart
    if (averageCallTime <= 0) {
        averageCallTime = MINIMUM_POSSIBLE_CALL_TIME;
    }

    // we can determine how many packets we need to send per call to achieve our desired
    // packets per second send rate.
    float callsPerSecond = USECS_PER_SECOND / averageCallTime;

    // theoretically we could get called less than 1 time per second... but since we're using floats, it really shouldn't be
    // possible to get 0 calls per second, but we will guard agains that here, just in case.
    if (callsPerSecond == 0) {
        callsPerSecond = ZERO_RESET_CALLS_PER_SECOND;
    }

    // This is the average number of packets per call...
    averagePacketsPerCall = _packetsPerSecond / callsPerSecond;
    packetsToSendThisCall = averagePacketsPerCall;

    // if we get called more than 1 per second, we want to mostly divide the packets evenly across the calls...
    // but we want to track the remainder and make sure over the course of a second, we are sending the target PPS
    // e.g.
    //     200pps called 60 times per second...
    //     200/60 = 3.333... so really...
    //     each call we should send 3
    //     every 3rd call we should send 4...
    //     3,3,4,3,3,4...3,3,4 = 200...

    // if we get called less than 1 per second, then we want to send more than our PPS each time...
    // e.g.
    //     200pps called ever 1332.5ms
    //     200 / (1000/1332.5) = 200/(0.7505) = 266.5 packets per call
    //     so...
    //        every other call we should send 266 packets
    //        then on the next call we should send 267 packets

    // So no mater whether or not we're getting called more or less than once per second, we still need to do some bookkeeping
    // to make sure we send a few extra packets to even out our flow rate.
    quint64 elapsedSinceLastCheck = now - _lastPPSCheck;

    // we might want to tun this in the future and only check after a certain number of call intervals. for now we check
    // each time and adjust accordingly
    const float CALL_INTERVALS_TO_CHECK = 1;
    const float MIN_CALL_INTERVALS_PER_RESET = 5;

    // we will reset our check PPS and time each second (callsPerSecond) or at least 5 calls (if we get called less frequently
    // than 5 times per second) This gives us sufficient smoothing in our packet adjustments
    float callIntervalsPerReset = std::max(callsPerSecond, MIN_CALL_INTERVALS_PER_RESET);

    if  (elapsedSinceLastCheck > (averageCallTime * CALL_INTERVALS_TO_CHECK)) {
        float ppsOverCheckInterval = (float)_packetsOverCheckInterval;
        float ppsExpectedForCheckInterval = (float)_packetsPerSecond * ((float)elapsedSinceLastCheck / (float)USECS_PER_SECOND);

        if (ppsOverCheckInterval < ppsExpectedForCheckInterval) {
            int adjust = ppsExpectedForCheckInterval - ppsOverCheckInterval;
            packetsToSendThisCall += adjust;
        } else if (ppsOverCheckInterval > ppsExpectedForCheckInterval) {
            int adjust = ppsOverCheckInterval - ppsExpectedForCheckInterval;
            packetsToSendThisCall -= adjust;
        }

        // now, do we want to reset the check interval? don't want to completely reset, because we would still have
        // a rounding error. instead, we check to see that we've passed the reset interval (which is much larger than
        // the check interval), and on those reset intervals we take the second half average and keep that for the next
        // interval window...
        if (elapsedSinceLastCheck > (averageCallTime * callIntervalsPerReset)) {
            // Keep average packets and time for "second half" of check interval
            _lastPPSCheck += (elapsedSinceLastCheck / 2);
            _packetsOverCheckInterval = (_packetsOverCheckInterval / 2);

            elapsedSinceLastCheck = now - _lastPPSCheck;
        }
    }

    auto packetsLeft = _packets.size();

    // Now that we know how many packets to send this call to process, just send them.
    while ((packetsSentThisCall < packetsToSendThisCall) && (packetsLeft > 0)) {
        lock();

        NodePacketPair packetPair = std::move(_packets.front());
        _packets.pop_front();
        packetsLeft = _packets.size();

        unlock();

        // send the packet through the NodeList...
        DependencyManager::get<NodeList>()->sendUnreliablePacket(*packetPair.second, *packetPair.first);

        packetsSentThisCall++;
        _packetsOverCheckInterval++;
        _totalPacketsSent++;

        int packetSize = packetPair.second->getDataSize();

        _totalBytesSent += packetSize;
        emit packetSent(packetSize);

        _lastSendTime = now;
    }
    return isStillRunning();
}
Exemplo n.º 16
0
bool PacketSender::process() {
    uint64_t USECS_PER_SECOND = 1000 * 1000;
    uint64_t SEND_INTERVAL_USECS = (_packetsPerSecond == 0) ? USECS_PER_SECOND : (USECS_PER_SECOND / _packetsPerSecond);

    // keep track of our process call times, so we have a reliable account of how often our caller calls us
    uint64_t now = usecTimestampNow();
    uint64_t elapsedSinceLastCall = now - _lastProcessCallTime;
    _lastProcessCallTime = now;
    _averageProcessCallTime.updateAverage(elapsedSinceLastCall);

    if (_packets.size() == 0) {
        if (isThreaded()) {
            usleep(SEND_INTERVAL_USECS);
        } else {
            return isStillRunning();  // in non-threaded mode, if there's nothing to do, just return, keep running till they terminate us
        }
    }

    int packetsPerCall = _packets.size(); // in threaded mode, we just empty this!
    int packetsThisCall = 0;

    // if we're in non-threaded mode, then we actually need to determine how many packets to send per call to process
    // based on how often we get called... We do this by keeping a running average of our call times, and we determine
    // how many packets to send per call
    if (!isThreaded()) {
        int averageCallTime;
        const int TRUST_AVERAGE_AFTER = AVERAGE_CALL_TIME_SAMPLES * 2;
        if (_usecsPerProcessCallHint == 0 || _averageProcessCallTime.getSampleCount() > TRUST_AVERAGE_AFTER) {
            averageCallTime = _averageProcessCallTime.getAverage();
        } else {
            averageCallTime = _usecsPerProcessCallHint;
        }

        // we can determine how many packets we need to send per call to achieve our desired
        // packets per second send rate.
        int callsPerSecond = USECS_PER_SECOND / averageCallTime;
        packetsPerCall = ceil(_packetsPerSecond / callsPerSecond);

        // send at least one packet per call, if we have it
        if (packetsPerCall < 1) {
            packetsPerCall = 1;
        }
    }

    int packetsLeft = _packets.size();
    bool keepGoing = packetsLeft > 0;
    while (keepGoing) {

        NetworkPacket& packet = _packets.front();

        // send the packet through the NodeList...
        UDPSocket* nodeSocket = NodeList::getInstance()->getNodeSocket();

        nodeSocket->send(&packet.getAddress(), packet.getData(), packet.getLength());
        packetsThisCall++;

        if (_notify) {
            _notify->packetSentNotification(packet.getLength());
        }

        lock();
        _packets.erase(_packets.begin());
        unlock();

        packetsLeft = _packets.size();

        // in threaded mode, we go till we're empty
        if (isThreaded()) {
            keepGoing = packetsLeft > 0;

            // dynamically sleep until we need to fire off the next set of voxels we only sleep in threaded mode
            if (keepGoing) {
                uint64_t elapsed = now - _lastSendTime;
                int usecToSleep =  std::max(SEND_INTERVAL_USECS, SEND_INTERVAL_USECS - elapsed);

                // we only sleep in non-threaded mode
                if (usecToSleep > 0) {
                    usleep(usecToSleep);
                }
            }

        } else {
            // in non-threaded mode, we send as many packets as we need per expected call to process()
            keepGoing = (packetsThisCall < packetsPerCall) && (packetsLeft > 0);
        }

        _lastSendTime = now;
    }

    return isStillRunning();  // keep running till they terminate us
}
Exemplo n.º 17
0
bool OctreePersistThread::process() {

    if (!_initialLoadComplete) {
        quint64 loadStarted = usecTimestampNow();
        qDebug() << "loading Octrees from file: " << _filename << "...";

        bool persistantFileRead;

        _tree->lockForWrite();
        {
            PerformanceWarning warn(true, "Loading Octree File", true);
            persistantFileRead = _tree->readFromSVOFile(_filename.toLocal8Bit().constData());
            _tree->pruneTree();
        }
        _tree->unlock();

        quint64 loadDone = usecTimestampNow();
        _loadTimeUSecs = loadDone - loadStarted;

        _tree->clearDirtyBit(); // the tree is clean since we just loaded it
        qDebug("DONE loading Octrees from file... fileRead=%s", debug::valueOf(persistantFileRead));

        unsigned long nodeCount = OctreeElement::getNodeCount();
        unsigned long internalNodeCount = OctreeElement::getInternalNodeCount();
        unsigned long leafNodeCount = OctreeElement::getLeafNodeCount();
        qDebug("Nodes after loading scene %lu nodes %lu internal %lu leaves", nodeCount, internalNodeCount, leafNodeCount);

        bool wantDebug = false;
        if (wantDebug) {
            double usecPerGet = (double)OctreeElement::getGetChildAtIndexTime() 
                                    / (double)OctreeElement::getGetChildAtIndexCalls();
            qDebug() << "getChildAtIndexCalls=" << OctreeElement::getGetChildAtIndexCalls()
                    << " getChildAtIndexTime=" << OctreeElement::getGetChildAtIndexTime() << " perGet=" << usecPerGet;

            double usecPerSet = (double)OctreeElement::getSetChildAtIndexTime() 
                                    / (double)OctreeElement::getSetChildAtIndexCalls();
            qDebug() << "setChildAtIndexCalls=" << OctreeElement::getSetChildAtIndexCalls()
                    << " setChildAtIndexTime=" << OctreeElement::getSetChildAtIndexTime() << " perSet=" << usecPerSet;
        }

        _initialLoadComplete = true;
        _lastBackup = _lastCheck = usecTimestampNow(); // we just loaded, no need to save again
        time(&_lastPersistTime);

        emit loadCompleted();
    }

    if (isStillRunning()) {
        quint64 MSECS_TO_USECS = 1000;
        quint64 USECS_TO_SLEEP = 10 * MSECS_TO_USECS; // every 10ms
        usleep(USECS_TO_SLEEP);

        // do our updates then check to save...
        _tree->update();

        quint64 now = usecTimestampNow();
        quint64 sinceLastSave = now - _lastCheck;
        quint64 intervalToCheck = _persistInterval * MSECS_TO_USECS;

        if (sinceLastSave > intervalToCheck) {
            _lastCheck = now;
            persist();
        }
    }
    
    // if we were asked to debugTimestampNow do that now...
    if (_debugTimestampNow) {
        quint64 now = usecTimestampNow();
        quint64 sinceLastDebug = now - _lastTimeDebug;
        quint64 DEBUG_TIMESTAMP_INTERVAL = 600000000; // every 10 minutes

        if (sinceLastDebug > DEBUG_TIMESTAMP_INTERVAL) {
            _lastTimeDebug = usecTimestampNow(true); // ask for debug output
        }
        
    }
    return isStillRunning();  // keep running till they terminate us
}