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; }
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; } }
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; }
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; }
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())); }