3 function getBucketMemcache()
7 if (!CONST_ConnectionBucket_MemcacheServerAddress) return null;
11 $m->addServer(CONST_ConnectionBucket_MemcacheServerAddress, CONST_ConnectionBucket_MemcacheServerPort);
16 function doBucket($asKey, $iRequestCost, $iLeakPerSecond, $iThreshold)
18 $m = getBucketMemcache();
24 foreach($asKey as $sKey)
26 $aCurrentBlock = $m->get($sKey);
29 $aCurrentBlock = array($iRequestCost, $t, false);
34 // remove leak * the time since the last request
35 $aCurrentBlock[0] += $iRequestCost - ($t - $aCurrentBlock[1])*$iLeakPerSecond;
36 $aCurrentBlock[1] = $t;
39 if ($aCurrentBlock[0] <= 0)
45 // If we have hit the threshold stop and record this to the block list
46 if ($aCurrentBlock[0] >= $iThreshold)
48 $aCurrentBlock[0] = $iThreshold;
50 // Make up to 10 attempts to record this to memcache (with locking to prevent conflicts)
52 for($i = 0; $i < 10; $i++)
54 $aBlockedList = $m->get('blockedList', null, $hCasToken);
57 $aBlockedList = array();
58 $m->add('blockedList', $aBlockedList);
59 $aBlockedList = $m->get('blockedList', null, $hCasToken);
61 if (!isset($aBlockedList[$sKey]))
63 $aBlockedList[$sKey] = array(1, $t);
67 $aBlockedList[$sKey][0]++;
68 $aBlockedList[$sKey][1] = $t;
70 if (sizeof($aBlockedList) > CONST_ConnectionBucket_MaxBlockList)
72 uasort($aBlockedList, 'byValue1');
73 $aBlockedList = array_slice($aBlockedList, 0, CONST_ConnectionBucket_MaxBlockList);
75 $x = $m->cas($hCasToken, 'blockedList', $aBlockedList);
79 // Only keep in memcache until the time it would have expired (to avoid clutering memcache)
80 $m->set($sKey, $aCurrentBlock, $t + 1 + $aCurrentBlock[0]/$iLeakPerSecond);
83 // Bucket result in the largest bucket we find
84 $iMaxVal = max($iMaxVal, $aCurrentBlock[0]);
90 function isBucketSleeping($asKey)
92 $m = getBucketMemcache();
93 if (!$m) return false;
95 foreach($asKey as $sKey)
97 $aCurrentBlock = $m->get($sKey);
98 if ($aCurrentBlock[2]) return true;
103 function setBucketSleeping($asKey, $bVal)
105 $m = getBucketMemcache();
106 if (!$m) return false;
111 foreach($asKey as $sKey)
113 $aCurrentBlock = $m->get($sKey);
114 $aCurrentBlock[2] = $bVal;
115 $m->set($sKey, $aCurrentBlock, $t + 1 + $aCurrentBlock[0]/CONST_ConnectionBucket_LeakRate);
120 function byValue1($a, $b)
126 return ($a[1] > $b[1]) ? -1 : 1;
129 function byLastBlockTime($a, $b)
131 if ($a['lastBlockTimestamp'] == $b['lastBlockTimestamp'])
135 return ($a['lastBlockTimestamp'] > $b['lastBlockTimestamp']) ? -1 : 1;
138 function getBucketBlocks()
140 $m = getBucketMemcache();
141 if (!$m) return null;
143 $aBlockedList = $m->get('blockedList', null, $hCasToken);
144 if (!$aBlockedList) $aBlockedList = array();
145 foreach($aBlockedList as $sKey => $aDetails)
147 $aCurrentBlock = $m->get($sKey);
148 if (!$aCurrentBlock) $aCurrentBlock = array(0, $t);
149 $iCurrentBucketSize = max(0, $aCurrentBlock[0] - ($t - $aCurrentBlock[1])*CONST_ConnectionBucket_LeakRate);
150 $aBlockedList[$sKey] = array(
151 'totalBlocks' => $aDetails[0],
152 'lastBlockTimestamp' => $aDetails[1],
153 'isSleeping' => (isset($aCurrentBlock[2])?$aCurrentBlock[2]:false),
154 'currentBucketSize' => $iCurrentBucketSize,
155 'currentlyBlocked' => $iCurrentBucketSize + (CONST_ConnectionBucket_Cost_Reverse) >= CONST_ConnectionBucket_BlockLimit,
158 uasort($aBlockedList, 'byLastBlockTime');
159 return $aBlockedList;
162 function clearBucketBlocks()
164 $m = getBucketMemcache();
165 if (!$m) return false;
166 $m->delete('blockedList');