• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ConsistentHash.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   @section license License
00004 
00005   Licensed to the Apache Software Foundation (ASF) under one
00006   or more contributor license agreements.  See the NOTICE file
00007   distributed with this work for additional information
00008   regarding copyright ownership.  The ASF licenses this file
00009   to you under the Apache License, Version 2.0 (the
00010   "License"); you may not use this file except in compliance
00011   with the License.  You may obtain a copy of the License at
00012 
00013       http://www.apache.org/licenses/LICENSE-2.0
00014 
00015   Unless required by applicable law or agreed to in writing, software
00016   distributed under the License is distributed on an "AS IS" BASIS,
00017   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018   See the License for the specific language governing permissions and
00019   limitations under the License.
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 }

Generated by  doxygen 1.7.1