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 }