Example #1
0
int 
MemCacheClient::Store(
    const char *    aType,
    MemRequest *    aItem, 
    int             aCount
    )
{
    if (aCount < 1) {
        mTrace.Trace(CLDEBUG, "Store: ignoring request for %d items", aCount);
        return 0;
    }

    // initialize and find all of the servers for these items
    int nItemCount = 0;
    for (int n = 0; n < aCount; ++n) {
        // ensure that the key doesn't have a space in it
        CR_ASSERT(NULL == strchr(aItem[n].mKey.data(), ' '));
        aItem[n].mServer = FindServer(aItem[n].mKey, aItem[n].mService);
        if (aItem[n].mServer) {
            ++nItemCount;
        }
        else {
            aItem[n].mResult = MCERR_NOSERVER;
        }
    }
    if (nItemCount == 0) {
        mTrace.Trace(CLDEBUG, "Store: ignoring request for all %d items (no servers available)", 
            aCount);
        return 0;
    }

    char szBuf[50];
    int nResponses = 0;
    string_t sRequest;
    for (int n = 0; n < aCount; ++n) {
        if (!aItem[n].mServer) continue;

        // <command name> <key> <flags> <exptime> <bytes> [noreply]\r\n
        sRequest  = aType;
        sRequest += ' ';
        sRequest += aItem[n].mKey;
        snprintf(szBuf, sizeof(szBuf), " %u %ld %u", 
            aItem[n].mFlags, (long) aItem[n].mExpiry, 
            (unsigned)aItem[n].mData.GetReadSize());
        sRequest += szBuf;
        if (*aType == 'c') { // cas
            snprintf(szBuf, sizeof(szBuf), " %" PRIu64, aItem[n].mCas);
            sRequest += szBuf;
        }
        if (aItem[n].mResult == MCERR_NOREPLY) {
            sRequest += " noreply";
        }
        sRequest += "\r\n";

        // send the request. any socket error causes the server connection 
        // to be dropped, so we return errors for all requests using that server.
        try {
            aItem[n].mServer->SendBytes(
                sRequest.data(), sRequest.length());
            aItem[n].mServer->SendBytes(
                aItem[n].mData.GetReadBuffer(), 
                aItem[n].mData.GetReadSize());
            aItem[n].mServer->SendBytes("\r\n", 2);

            // done with these read bytes
            aItem[n].mData.CommitReadBytes(
                aItem[n].mData.GetReadSize());

            // if no reply is required then move on to the next request
            if (aItem[n].mResult == MCERR_NOREPLY) {
                continue;
            }

            // handle this response
            HandleStoreResponse(aItem[n].mServer, aItem[n]);
            ++nResponses;
        }
        catch (const Socket::Exception & e) {
            mTrace.Trace(CLINFO, "Store: error '%s' at %s, marking requests as NOSERVER",
                e.mDetail, aItem[n].mServer->GetAddress());
            for (int i = aCount - 1; i >= n; --i) {
                if (aItem[n].mServer != aItem[i].mServer) continue;
                aItem[i].mServer = NULL;
                aItem[i].mResult = MCERR_NOSERVER;
            }
            continue;
        }
    }

    return nResponses;
}
Example #2
0
int 
MemCacheClient::Store(
    const char *    a_pszType,
    MemRequest *    a_rgItem, 
    int             a_nCount
    )
{
    if (a_nCount < 1) return 0;

    // initialize and find all of the servers for these items
    for (int n = 0; n < a_nCount; ++n) {
        // ensure that the key doesn't have a space in it
        assert(NULL == strchr(a_rgItem[n].mKey.data(), ' '));
        a_rgItem[n].mServer = FindServer(a_rgItem[n].mKey);
        if (!a_rgItem[n].mServer) {
            a_rgItem[n].mResult = MCERR_NOSERVER;
        }
    }

    char szBuf[50];
    int nResponses = 0;
    string_t sRequest;
    for (int n = 0; n < a_nCount; ++n) {
        if (!a_rgItem[n].mServer) continue;

        // <command name> <key> <flags> <exptime> <bytes> [noreply]\r\n
        sRequest  = a_pszType;
        sRequest += ' ';
        sRequest += a_rgItem[n].mKey;
        snprintf(szBuf, sizeof(szBuf), " %u %ld %u", 
            a_rgItem[n].mFlags, (long) a_rgItem[n].mExpiry, 
            a_rgItem[n].mData.GetReadSize());
        sRequest += szBuf;
        if (*a_pszType == 'c') { // cas
            snprintf(szBuf, sizeof(szBuf), " " SPRINTF_UINT64, a_rgItem[n].mCas);
            sRequest += szBuf;
        }
        if (a_rgItem[n].mResult == MCERR_NOREPLY) {
            sRequest += " noreply";
        }
        sRequest += "\r\n";

        // send the request. any socket error causes the server connection 
        // to be dropped, so we return errors for all requests using that server.
        try {
            a_rgItem[n].mServer->SendBytes(
                sRequest.data(), sRequest.length());
            a_rgItem[n].mServer->SendBytes(
                a_rgItem[n].mData.GetReadBuffer(), 
                a_rgItem[n].mData.GetReadSize());
            a_rgItem[n].mServer->SendBytes("\r\n", 2);

            // done with these read bytes
            a_rgItem[n].mData.CommitReadBytes(
                a_rgItem[n].mData.GetReadSize());

            // if no reply is required then move on to the next request
            if (a_rgItem[n].mResult == MCERR_NOREPLY) {
                continue;
            }

            // handle this response
            HandleStoreResponse(a_rgItem[n].mServer, a_rgItem[n]);
            ++nResponses;
        }
        catch (const ServerSocket::Exception &) {
            for (int i = a_nCount - 1; i >= n; --i) {
                if (a_rgItem[n].mServer != a_rgItem[i].mServer) continue;
                a_rgItem[i].mServer = NULL;
                a_rgItem[i].mResult = MCERR_NOSERVER;
            }
            continue;
        }
    }

    return nResponses;
}