void TransactionAcquire::onTimer (bool progress, ScopedLockType& psl)
{
    bool aggressive = false;

    if (getTimeouts () > 10)
    {
        WriteLog (lsWARNING, TransactionAcquire) << "Ten timeouts on TX set " << getHash ();
        psl.unlock();
        {
            Application::ScopedLockType lock (getApp().getMasterLock (), __FILE__, __LINE__);

            if (getApp().getOPs ().stillNeedTXSet (mHash))
            {
                WriteLog (lsWARNING, TransactionAcquire) << "Still need it";
                mTimeouts = 0;
                aggressive = true;
	    }
        }
        psl.lock(__FILE__, __LINE__);

        if (!aggressive)
        {
            mFailed = true;
            done ();
            return;
        }
    }

    if (aggressive || !getPeerCount ())
    {
        // out of peers
        WriteLog (lsWARNING, TransactionAcquire) << "Out of peers for TX set " << getHash ();

        bool found = false;
        std::vector<Peer::pointer> peerList = getApp().getPeers ().getPeerVector ();
        BOOST_FOREACH (Peer::ref peer, peerList)
        {
            if (peer->hasTxSet (getHash ()))
            {
                found = true;
                peerHas (peer);
            }
        }

        if (!found)
        {
            BOOST_FOREACH (Peer::ref peer, peerList)
            peerHas (peer);
        }
    }
Beispiel #2
0
//
// MFUNCTION: CPlayer::waitPdu
// 
// PURPOSE: Wait for an incoming pdu for the
// specified timeout.
// If the incoming pdu has a sequence number different
// from what is expected, the pdu is ignored.
//
// RETURN:
// If a pdu arrives in time, return 0, otherwise
// return Pdu_Wait_Timeout.
//
int CPlayer::waitPdu(Cpdu** ppPdu, DWORD timeOut, u_int16_t sequenceNumber)
{
    int rc = 0;

    if (disconnected_)
        return CPlayer::Pdu_Wait_Timeout;

    long start = 0, elapsed = 0;
    time(&start);    

    // note: timeOut is in milliseconds while
    // elapsed is in seconds

    while (timeOut > (1000 * elapsed))
    {
        if (pduEvent_.lock(timeOut - (1000 * elapsed)))
        {   // When we get here we have an incoming PDU
            pduEvent_.resetEvent();

            // Get all pdus from queue, consider the one
            // with correct sequence number
            while (Cpdu* pdu = getFromQueue())
            {
                // if sequence numbers don't match, ignore
                // the pdu and wait for next one to arrive
                if (checkSequenceNumber(pdu, sequenceNumber))
                {
                    // XXX Tournament: pdu received, reset timeouts
                    setTimeouts(0);
                    *ppPdu = pdu;
                    return 0; // OK!
                }
                else
                {
                    // pdu had wrong sequence number - it is
                    // and old pdu and is ignored
                    delete pdu;

                    // The loop will check for more pdus and
                    // will resume waiting if necessary
                }
            }

            long now = 0;
            time(&now);
            elapsed += (now - start);
        }
        else
        {
            // Wait timed out, will exit loop
            elapsed = (1000 * timeOut);
        }
    }

    // this is ok, player did not respond within timeout
    printf("CPlayer::waitPdu: timed out (%s)\n", getUsername());
    rc = CPlayer::Pdu_Wait_Timeout;

    // XXX Tournament
    if (CTournament::Inst()->isTournament())
    {
        CpduPing p;
        if (p.sendPing(this) == -1)
        {
          char buf[200];
          sprintf(buf, "Player %s sendPing==-1\n", getUsername());
          Sys_LogError(buf);
          setSendError(true);
        }

        setTimeouts(getTimeouts() + 1);
        if (getTimeouts() >= MAX_TIMEOUTS)
        {
            // Player is not responding - set network error flag
            char buf[200];
            sprintf(buf, "Player %s (%d) times out\n",
                    getUsername(), getConnfd());
            Sys_LogError(buf);

            setSendError(true);
        }
    }

    return rc;
}