PageRenderTime 24ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/src/peer_sourcehash.cc

https://github.com/dkurochkin/squid
C++ | 233 lines | 138 code | 44 blank | 51 comment | 27 complexity | 63513ac88b1abfabe3c551c0a2d36bb0 MD5 | raw file
  1. /*
  2. * $Id$
  3. *
  4. * DEBUG: section 39 Peer source hash based selection
  5. * AUTHOR: Henrik Nordstrom
  6. * BASED ON: carp.cc
  7. *
  8. * SQUID Web Proxy Cache http://www.squid-cache.org/
  9. * ----------------------------------------------------------
  10. *
  11. * Squid is the result of efforts by numerous individuals from
  12. * the Internet community; see the CONTRIBUTORS file for full
  13. * details. Many organizations have provided support for Squid's
  14. * development; see the SPONSORS file for full details. Squid is
  15. * Copyrighted (C) 2001 by the Regents of the University of
  16. * California; see the COPYRIGHT file for full details. Squid
  17. * incorporates software developed and/or copyrighted by other
  18. * sources; see the CREDITS file for full details.
  19. *
  20. * This program is free software; you can redistribute it and/or modify
  21. * it under the terms of the GNU General Public License as published by
  22. * the Free Software Foundation; either version 2 of the License, or
  23. * (at your option) any later version.
  24. *
  25. * This program is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. * GNU General Public License for more details.
  29. *
  30. * You should have received a copy of the GNU General Public License
  31. * along with this program; if not, write to the Free Software
  32. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  33. *
  34. */
  35. #include "squid.h"
  36. #include "Store.h"
  37. #include "HttpRequest.h"
  38. #include "mgr/Registration.h"
  39. #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  40. static int n_sourcehash_peers = 0;
  41. static peer **sourcehash_peers = NULL;
  42. static OBJH peerSourceHashCachemgr;
  43. static void peerSourceHashRegisterWithCacheManager(void);
  44. static int
  45. peerSortWeight(const void *a, const void *b)
  46. {
  47. const peer *const *p1 = (const peer *const *)a;
  48. const peer *const *p2 = (const peer *const *)b;
  49. return (*p1)->weight - (*p2)->weight;
  50. }
  51. void
  52. peerSourceHashInit(void)
  53. {
  54. int W = 0;
  55. int K;
  56. int k;
  57. double P_last, X_last, Xn;
  58. peer *p;
  59. peer **P;
  60. char *t;
  61. /* Clean up */
  62. for (k = 0; k < n_sourcehash_peers; k++) {
  63. cbdataReferenceDone(sourcehash_peers[k]);
  64. }
  65. safe_free(sourcehash_peers);
  66. n_sourcehash_peers = 0;
  67. /* find out which peers we have */
  68. for (p = Config.peers; p; p = p->next) {
  69. if (!p->options.sourcehash)
  70. continue;
  71. assert(p->type == PEER_PARENT);
  72. if (p->weight == 0)
  73. continue;
  74. n_sourcehash_peers++;
  75. W += p->weight;
  76. }
  77. peerSourceHashRegisterWithCacheManager();
  78. if (n_sourcehash_peers == 0)
  79. return;
  80. sourcehash_peers = (peer **)xcalloc(n_sourcehash_peers, sizeof(*sourcehash_peers));
  81. /* Build a list of the found peers and calculate hashes and load factors */
  82. for (P = sourcehash_peers, p = Config.peers; p; p = p->next) {
  83. if (!p->options.sourcehash)
  84. continue;
  85. if (p->weight == 0)
  86. continue;
  87. /* calculate this peers hash */
  88. p->sourcehash.hash = 0;
  89. for (t = p->name; *t != 0; t++)
  90. p->sourcehash.hash += ROTATE_LEFT(p->sourcehash.hash, 19) + (unsigned int) *t;
  91. p->sourcehash.hash += p->sourcehash.hash * 0x62531965;
  92. p->sourcehash.hash = ROTATE_LEFT(p->sourcehash.hash, 21);
  93. /* and load factor */
  94. p->sourcehash.load_factor = ((double) p->weight) / (double) W;
  95. if (floor(p->sourcehash.load_factor * 1000.0) == 0.0)
  96. p->sourcehash.load_factor = 0.0;
  97. /* add it to our list of peers */
  98. *P++ = cbdataReference(p);
  99. }
  100. /* Sort our list on weight */
  101. qsort(sourcehash_peers, n_sourcehash_peers, sizeof(*sourcehash_peers), peerSortWeight);
  102. /* Calculate the load factor multipliers X_k
  103. *
  104. * X_1 = pow ((K*p_1), (1/K))
  105. * X_k = ([K-k+1] * [P_k - P_{k-1}])/(X_1 * X_2 * ... * X_{k-1})
  106. * X_k += pow ((X_{k-1}, {K-k+1})
  107. * X_k = pow (X_k, {1/(K-k+1)})
  108. * simplified to have X_1 part of the loop
  109. */
  110. K = n_sourcehash_peers;
  111. P_last = 0.0; /* Empty P_0 */
  112. Xn = 1.0; /* Empty starting point of X_1 * X_2 * ... * X_{x-1} */
  113. X_last = 0.0; /* Empty X_0, nullifies the first pow statement */
  114. for (k = 1; k <= K; k++) {
  115. double Kk1 = (double) (K - k + 1);
  116. p = sourcehash_peers[k - 1];
  117. p->sourcehash.load_multiplier = (Kk1 * (p->sourcehash.load_factor - P_last)) / Xn;
  118. p->sourcehash.load_multiplier += pow(X_last, Kk1);
  119. p->sourcehash.load_multiplier = pow(p->sourcehash.load_multiplier, 1.0 / Kk1);
  120. Xn *= p->sourcehash.load_multiplier;
  121. X_last = p->sourcehash.load_multiplier;
  122. P_last = p->sourcehash.load_factor;
  123. }
  124. }
  125. static void
  126. peerSourceHashRegisterWithCacheManager(void)
  127. {
  128. Mgr::RegisterAction("sourcehash", "peer sourcehash information",
  129. peerSourceHashCachemgr, 0, 1);
  130. }
  131. peer *
  132. peerSourceHashSelectParent(HttpRequest * request)
  133. {
  134. int k;
  135. const char *c;
  136. peer *p = NULL;
  137. peer *tp;
  138. unsigned int user_hash = 0;
  139. unsigned int combined_hash;
  140. double score;
  141. double high_score = 0;
  142. const char *key = NULL;
  143. char ntoabuf[MAX_IPSTRLEN];
  144. if (n_sourcehash_peers == 0)
  145. return NULL;
  146. key = request->client_addr.NtoA(ntoabuf, sizeof(ntoabuf));
  147. /* calculate hash key */
  148. debugs(39, 2, "peerSourceHashSelectParent: Calculating hash for " << key);
  149. for (c = key; *c != 0; c++)
  150. user_hash += ROTATE_LEFT(user_hash, 19) + *c;
  151. /* select peer */
  152. for (k = 0; k < n_sourcehash_peers; k++) {
  153. tp = sourcehash_peers[k];
  154. combined_hash = (user_hash ^ tp->sourcehash.hash);
  155. combined_hash += combined_hash * 0x62531965;
  156. combined_hash = ROTATE_LEFT(combined_hash, 21);
  157. score = combined_hash * tp->sourcehash.load_multiplier;
  158. debugs(39, 3, "peerSourceHashSelectParent: " << tp->name << " combined_hash " << combined_hash <<
  159. " score " << std::setprecision(0) << score);
  160. if ((score > high_score) && peerHTTPOkay(tp, request)) {
  161. p = tp;
  162. high_score = score;
  163. }
  164. }
  165. if (p)
  166. debugs(39, 2, "peerSourceHashSelectParent: selected " << p->name);
  167. return p;
  168. }
  169. static void
  170. peerSourceHashCachemgr(StoreEntry * sentry)
  171. {
  172. peer *p;
  173. int sumfetches = 0;
  174. storeAppendPrintf(sentry, "%24s %10s %10s %10s %10s\n",
  175. "Hostname",
  176. "Hash",
  177. "Multiplier",
  178. "Factor",
  179. "Actual");
  180. for (p = Config.peers; p; p = p->next)
  181. sumfetches += p->stats.fetches;
  182. for (p = Config.peers; p; p = p->next) {
  183. storeAppendPrintf(sentry, "%24s %10x %10f %10f %10f\n",
  184. p->name, p->sourcehash.hash,
  185. p->sourcehash.load_multiplier,
  186. p->sourcehash.load_factor,
  187. sumfetches ? (double) p->stats.fetches / sumfetches : -1.0);
  188. }
  189. }