Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 #include "ConsistentHash.h"
00023 #include <cstring>
00024 #include <string>
00025 #include <sstream>
00026 #include <cmath>
00027 #include <climits>
00028 #include <cstdio>
00029 
00030 std::ostream &
00031 operator << (std::ostream & os, ATSConsistentHashNode & thing)
00032 {
00033   return os << thing.name;
00034 }
00035 
00036 ATSConsistentHash::ATSConsistentHash(int r, ATSHash64 *h) : replicas(r), hash(h)
00037 {
00038 }
00039 
00040 void
00041 ATSConsistentHash::insert(ATSConsistentHashNode * node, float weight, ATSHash64 *h)
00042 {
00043   int i;
00044   char numstr[256];
00045   ATSHash64 *thash;
00046   std::ostringstream string_stream;
00047   std::string std_string;
00048 
00049   if (h) {
00050     thash = h;
00051   } else if (hash) {
00052     thash = hash;
00053   } else {
00054     return;
00055   }
00056 
00057   string_stream << *node;
00058   std_string = string_stream.str();
00059 
00060   for (i = 0; i < (int) roundf(replicas * weight); i++) {
00061     snprintf(numstr, 256, "%d-", i);
00062     thash->update(numstr, strlen(numstr));
00063     thash->update(std_string.c_str(), strlen(std_string.c_str()));
00064     thash->final();
00065     NodeMap.insert(std::pair<uint64_t, ATSConsistentHashNode *>(thash->get(), node));
00066     thash->clear();
00067   }
00068 }
00069 
00070 ATSConsistentHashNode *
00071 ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
00072 {
00073   uint64_t url_hash;
00074   ATSConsistentHashIter NodeMapIterUp, *iter;
00075   ATSHash64 *thash;
00076   bool *wptr, wrapped = false;
00077 
00078   if (h) {
00079     thash = h;
00080   } else if (hash) {
00081     thash = hash;
00082   } else {
00083     return NULL;
00084   }
00085 
00086   if (w) {
00087     wptr = w;
00088   } else {
00089     wptr = &wrapped;
00090   }
00091 
00092   if (i) {
00093     iter = i;
00094   } else {
00095     iter = &NodeMapIterUp;
00096   }
00097 
00098   if (url) {
00099     thash->update(url, strlen(url));
00100     thash->final();
00101     url_hash = thash->get();
00102     thash->clear();
00103 
00104     *iter = NodeMap.lower_bound(url_hash);
00105 
00106     if (*iter == NodeMap.end()) {
00107       *wptr = true;
00108       *iter = NodeMap.begin();
00109     }
00110 
00111   } else {
00112     (*iter)++;
00113   }
00114 
00115   if (!(*wptr) && *iter == NodeMap.end()) {
00116     *wptr = true;
00117     *iter = NodeMap.begin();
00118   }
00119 
00120   if (*wptr && *iter == NodeMap.end()) {
00121     return NULL;
00122   }
00123 
00124   return (*iter)->second;
00125 }
00126 
00127 ATSConsistentHashNode *
00128 ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, bool *w, ATSHash64 *h)
00129 {
00130   uint64_t url_hash;
00131   ATSConsistentHashIter NodeMapIterUp, *iter;
00132   ATSHash64 *thash;
00133   bool *wptr, wrapped = false;
00134 
00135   if (h) {
00136     thash = h;
00137   } else if (hash) {
00138     thash = hash;
00139   } else {
00140     return NULL;
00141   }
00142 
00143   if (w) {
00144     wptr = w;
00145   } else {
00146     wptr = &wrapped;
00147   }
00148 
00149   if (i) {
00150     iter = i;
00151   } else {
00152     iter = &NodeMapIterUp;
00153   }
00154 
00155   if (url) {
00156     thash->update(url, strlen(url));
00157     thash->final();
00158     url_hash = thash->get();
00159     thash->clear();
00160 
00161     *iter = NodeMap.lower_bound(url_hash);
00162   }
00163 
00164   if (*iter == NodeMap.end()) {
00165     *wptr = true;
00166     *iter = NodeMap.begin();
00167   }
00168 
00169   while (!(*iter)->second->available) {
00170     (*iter)++;
00171 
00172     if (!(*wptr) && *iter == NodeMap.end()) {
00173       *wptr = true;
00174       *iter = NodeMap.begin();
00175     } else if (*wptr && *iter == NodeMap.end()) {
00176       return NULL;
00177     }
00178   }
00179 
00180   return (*iter)->second;
00181 }
00182 
00183 ATSConsistentHash::~ATSConsistentHash()
00184 {
00185   if (hash) {
00186     delete hash;
00187   }
00188 }