PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/core/Cache/AggregateCache.class.php

http://github.com/onPHP/onphp-framework
PHP | 130 lines | 77 code | 23 blank | 30 comment | 8 complexity | 85d2036b014aa2242559779cf1fe4602 MD5 | raw file
Possible License(s): LGPL-3.0
  1. <?php
  2. /****************************************************************************
  3. * Copyright (C) 2005-2008 by Anton E. Lebedevich, Konstantin V. Arkhipov *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU Lesser General Public License as *
  7. * published by the Free Software Foundation; either version 3 of the *
  8. * License, or (at your option) any later version. *
  9. * *
  10. ****************************************************************************/
  11. /**
  12. * A wrapper to multiple cache for workload
  13. * distribution using CachePeer childs.
  14. *
  15. * @ingroup Cache
  16. **/
  17. class AggregateCache extends BaseAggregateCache
  18. {
  19. const LEVEL_ULTRAHIGH = 0xFFFF;
  20. const LEVEL_HIGH = 0xC000;
  21. const LEVEL_NORMAL = 0x8000;
  22. const LEVEL_LOW = 0x4000;
  23. const LEVEL_VERYLOW = 0x0001;
  24. private $levels = array();
  25. /**
  26. * @return AggregateCache
  27. **/
  28. public static function create()
  29. {
  30. return new self;
  31. }
  32. /**
  33. * @return AggregateCache
  34. **/
  35. public function addPeer(
  36. $label, CachePeer $peer, $level = self::LEVEL_NORMAL
  37. )
  38. {
  39. $this->doAddPeer($label, $peer);
  40. $this->peers[$label]['level'] = $level;
  41. return $this;
  42. }
  43. /**
  44. * @return AggregateCache
  45. **/
  46. public function setClassLevel($class, $level)
  47. {
  48. $this->levels[$class] = $level;
  49. return $this;
  50. }
  51. /**
  52. * brain
  53. **/
  54. protected function guessLabel($key)
  55. {
  56. $class = $this->getClassName();
  57. if (isset($this->levels[$class]))
  58. $classLevel = $this->levels[$class];
  59. else
  60. $classLevel = self::LEVEL_NORMAL;
  61. // init by $key, randomness will be restored later
  62. mt_srand(hexdec(substr(md5($key), 3, 7)));
  63. $zeroDistances = array();
  64. $weights = array();
  65. foreach ($this->peers as $label => $peer) {
  66. $distance = abs($classLevel - $peer['level']);
  67. if (!$distance)
  68. $zeroDistances[] = $label;
  69. else
  70. $weights[$peer['level']] = 1 / pow($distance, 2); // BOVM
  71. }
  72. if (count($zeroDistances)) {
  73. $selectedLabel =
  74. $zeroDistances[mt_rand(0, count($zeroDistances) - 1)];
  75. } else {
  76. // weighted random level selection
  77. $sum = mt_rand() * array_sum($weights) / mt_getrandmax();
  78. $peerLevel = null;
  79. foreach ($weights as $level => $weight) {
  80. if ($sum <= $weight) {
  81. $peerLevel = $level;
  82. break;
  83. } else
  84. $sum -= $weight;
  85. }
  86. $selectedPeers = array();
  87. foreach ($this->peers as $label => $peer) {
  88. if ($peer['level'] == $peerLevel)
  89. $selectedPeers[] = $label;
  90. }
  91. $selectedLabel = $selectedPeers[mt_rand(0, count($selectedPeers) - 1)];
  92. }
  93. if (isset($this->peers[$selectedLabel]['stat'][$class]))
  94. ++$this->peers[$selectedLabel]['stat'][$class];
  95. else
  96. $this->peers[$selectedLabel]['stat'][$class] = 1;
  97. // restore randomness
  98. mt_srand(
  99. (int) (
  100. (int) (microtime(true) << 2)
  101. * (rand(time() / 2, time()) >> 2)
  102. )
  103. );
  104. return $selectedLabel;
  105. }
  106. }
  107. ?>