예제 #1
0
MemCacheClient::Server *
MemCacheClient::FindServer(
    const string_t & a_sKey
    )
{
    // probably need some servers for this
    if (m_rgServerHash.empty()) {
        return NULL;
    }

    // find the next largest consistent hash value above this key hash
    ConsistentHash hash(CreateKeyHash(a_sKey.data()), NULL);
    std::vector<ConsistentHash>::iterator iServer = 
        std::lower_bound(m_rgServerHash.begin(), m_rgServerHash.end(), hash);
    if (iServer == m_rgServerHash.end()) {
        iServer = m_rgServerHash.begin();
    }

    // ensure that this server is connected 
    Server * pServer = iServer->mServer;
    if (!pServer->Connect(m_nTimeoutMs)) {
        return NULL;
    }
    return pServer;
}
예제 #2
0
MemCacheClient::Server *
MemCacheClient::FindServer(
    const string_t & aKey,
    unsigned         aService
    )
{
#ifdef CROSSBASE_API
    // in our private usage of this, the service must never be 0
    if (aService == 0) {
        mTrace.Trace(CLERROR, "FindServer: no service requested, supplied cache server may not be appropriate!!!");
        CR_ASSERT(!"FindServer: no service requested, supplied cache server may not be appropriate!!!");
    }
#endif

    // probably need some servers for this
    if (mServerHash.empty()) {
        //mTrace.Trace(CLDEBUG, "FindServer: server hash is empty");
        return NULL;
    }

    // find the next largest consistent hash value above this key hash
    ConsistentHash hash(CreateKeyHash(aKey.data()), NULL, 0, 0);
    std::vector<ConsistentHash>::iterator iBegin = mServerHash.begin();
    std::vector<ConsistentHash>::iterator iEnd = mServerHash.end();
    std::vector<ConsistentHash>::iterator iCurr = std::lower_bound(iBegin, iEnd, hash);
    if (iCurr == iEnd) iCurr = iBegin;

    // now find the next server that handles this service
    if (aService != 0) {
        //int nSkipped = 0;
        std::vector<ConsistentHash>::iterator iStart = iCurr;
        while (!iCurr->services(aService)) {
            //++nSkipped;
            ++iCurr; 
            if (iCurr == iEnd) iCurr = iBegin;
            if (iCurr == iStart) {
                mTrace.Trace(CLDEBUG, "FindServer: no server for required service: %u", aService);
                return NULL;
            }
        }
        //if (nSkipped > 0) mTrace.Trace(CLDEBUG, "skipped %d servers for service: %u", nSkipped, aService);
    }

    // ensure that this server is connected 
    Server * pServer = iCurr->mServer;
    Server::ConnectResult rc = pServer->Connect(mTimeoutMs, mRetryMs);
    switch (rc) {
    case Server::CONNECT_SUCCESS:
        //mTrace.Trace(CLDEBUG, "FindServer: using server %s", pServer->GetAddress());
        return pServer;
    case Server::CONNECT_WAITING:
        return NULL;
    default:
    case Server::CONNECT_FAILED:
        //mTrace.Trace(CLDEBUG, "FindServer: failed to connect to server %s", pServer->GetAddress());
        return NULL;
    }
}
예제 #3
0
bool 
MemCacheClient::AddServer(
    const char *    aServerAddress,
    const char *    aServerName,
    unsigned        aServices
    )
{
    if (!aServerName) {
        aServerName = aServerAddress;
    }

    // if we the server address is valid then we allow the server 
    // to be added. All servers being added are assumed to be available
    // or to be soon made available. 
    Server * pServer = new Server(mTrace);
    if (!pServer->Set(aServerAddress)) {
        mTrace.Trace(CLERROR, "Ignoring invalid server: %s (%s)", 
            aServerAddress, aServerName);
        delete pServer;
        return false;
    }
    for (size_t n = 0; n < mServer.size(); ++n) {
        if (*pServer == *mServer[n]) {
            mTrace.Trace(CLERROR, "Ignoring duplicate server: %s (%s)", 
                aServerAddress, aServerName);
            return true; // already have it
        }
    }
    mServer.push_back(pServer);

    // for each salt we generate a string hash for the consistent hash 
    // table. To ensure stability of the hashing for multiple servers, 
    // we want to have a number of entries for each server. 
    static const char * rgpSalt[] = {
        "{DEA60AAB-CFF9-4a20-A799-4E5E93369656}",
        "{C05167CC-57DA-40f2-9EB8-18F65E56FD21}",
        "{57939537-0966-49e7-B675-ACE63246BFA5}",
        "{F0C8BE5C-A0F1-478f-BC45-28D42AF0CA1E}"
    };

    string_t sKey;
    ConsistentHash entry(0, pServer, aServices, 0);
    for (size_t n = 0; n < sizeof(rgpSalt)/sizeof(rgpSalt[0]); ++n) {
        sKey  = pServer->GetAddress();
        sKey += rgpSalt[n];
        entry.mEntry++;
        entry.mHash = CreateKeyHash(sKey.data());
        mServerHash.push_back(entry);
    }

    // sort the vector so that we can binary search it
    std::sort(mServerHash.begin(), mServerHash.end());

    mTrace.Trace(CLINFO, "Adding server: %s (%s:%u), services: 0x%x",
        aServerAddress, aServerName, pServer->GetPort(), aServices);
    return true;
}
예제 #4
0
bool 
MemCacheClient::AddServer(
    const char * a_pszServer
    )
{
    // if we the server address is valid then we allow the server 
    // to be added. All servers being added are assumed to be available
    // or to be soon made available. Uncontactable servers will cause
    // extra load on the database because the caching will not be available.
    Server * pServer = new Server;
    if (!pServer->Set(a_pszServer)) {
        delete pServer;
        return false;
    }

    for (size_t n = 0; n < m_rgpServer.size(); ++n) {
        if (*pServer == *m_rgpServer[n]) return true; // already have it
    }
    m_rgpServer.push_back(pServer);

    // for each salt we generate a string hash for the consistent hash 
    // table. To ensure stability of the hashing for multiple servers, 
    // we want to have a number of entries for each server. 
    static const char * rgpSalt[] = {
        "{DD4C855D-7548-4804-8F1A-166CDBACEFE7}",
        "{9BF02198-1D29-4aa3-9466-A4AF4372D5B1}",
        "{0F20CD2F-ACF2-44bc-8CE3-54529D7B738D}",
        "{DEA60AAB-CFF9-4a20-A799-4E5E93369656}",
        "{C05167CC-57DA-40f2-9EB8-18F65E56FD21}",
        "{57939537-0966-49e7-B675-ACE63246BFA5}",
        "{F0C8BE5C-A0F1-478f-BC45-28D42AF0CA1E}"
    };

    string_t sKey;
    ConsistentHash entry(0, pServer);
    for (size_t n = 0; n < sizeof(rgpSalt)/sizeof(rgpSalt[0]); ++n) {
        sKey  = pServer->GetAddress();
        sKey += rgpSalt[n];
        entry.mHash = CreateKeyHash(sKey.data());
        m_rgServerHash.push_back(entry);
    }

    // sort the vector so that we can binary search it
    std::sort(m_rgServerHash.begin(), m_rgServerHash.end());

#if 0
    printf("\nSERVER RING (%d servers):\n", m_rgpServer.size());
    for (size_t n = 0; n < m_rgServerHash.size(); ++n) {
        printf("%08x = %s\n", m_rgServerHash[n].mHash,
            m_rgServerHash[n].mServer->GetAddress());
    }
#endif

    return true;
}
예제 #5
0
void
MemCacheClient::DumpTables()
{
    // we need this information to ensure that different servers are
    // using the same consistent hashing tables.
    if (!mTrace.IsThisModuleTracing(CLDEBUG)) {
        return;
    }

    std::string verify;
    char buf[200];
    mTrace.Trace(CLDEBUG, "Consistent Hash Server Ring (%u entries):", mServerHash.size());
    for (size_t n = 0; n < mServerHash.size(); ++n) {
        const ConsistentHash & server = mServerHash[n];
        mTrace.Trace(CLDEBUG, "%2u: %08lx = %s (services: 0x%x, entry: %d)", 
            n, server.mHash, server.mServer->GetAddress(), server.mServices, server.mEntry);
        snprintf(buf, sizeof(buf), "%s>%d>%x>%lx>", server.mServer->GetAddress(), 
            server.mEntry, server.mServices, server.mHash);
        verify += buf;
    }

    mTrace.Trace(CLDEBUG, "Data verification code: %lx", CreateKeyHash(verify.c_str()));
}