public function add($key, $value, $exptime = 0)
 {
     $this->debugLog("add({$key})");
     return $this->checkResult($key, parent::add($key, $value, $exptime));
 }
Example #2
0
 /**
  * @param MemcachedBagOStuff $memc
  * @param array $keys List of keys to acquire
  * @return bool
  */
 protected function acquireMutexes(MemcachedBagOStuff $memc, array $keys)
 {
     $lockedKeys = [];
     // Acquire the keys in lexicographical order, to avoid deadlock problems.
     // If P1 is waiting to acquire a key P2 has, P2 can't also be waiting for a key P1 has.
     sort($keys);
     // Try to quickly loop to acquire the keys, but back off after a few rounds.
     // This reduces memcached spam, especially in the rare case where a server acquires
     // some lock keys and dies without releasing them. Lock keys expire after a few minutes.
     $rounds = 0;
     $start = microtime(true);
     do {
         if (++$rounds % 4 == 0) {
             usleep(1000 * 50);
             // 50 ms
         }
         foreach (array_diff($keys, $lockedKeys) as $key) {
             if ($memc->add("{$key}:mutex", 1, 180)) {
                 // lock record
                 $lockedKeys[] = $key;
             } else {
                 continue;
                 // acquire in order
             }
         }
     } while (count($lockedKeys) < count($keys) && microtime(true) - $start <= 3);
     if (count($lockedKeys) != count($keys)) {
         $this->releaseMutexes($memc, $lockedKeys);
         // failed; release what was locked
         return false;
     }
     return true;
 }
Example #3
0
 /**
  * @param MemcachedBagOStuff $memc
  * @param array $keys List of keys to acquire
  * @return bool
  */
 protected function acquireMutexes(MemcachedBagOStuff $memc, array $keys)
 {
     $lockedKeys = [];
     // Acquire the keys in lexicographical order, to avoid deadlock problems.
     // If P1 is waiting to acquire a key P2 has, P2 can't also be waiting for a key P1 has.
     sort($keys);
     // Try to quickly loop to acquire the keys, but back off after a few rounds.
     // This reduces memcached spam, especially in the rare case where a server acquires
     // some lock keys and dies without releasing them. Lock keys expire after a few minutes.
     $loop = new WaitConditionLoop(function () use($memc, $keys, &$lockedKeys) {
         foreach (array_diff($keys, $lockedKeys) as $key) {
             if ($memc->add("{$key}:mutex", 1, 180)) {
                 // lock record
                 $lockedKeys[] = $key;
             }
         }
         return array_diff($keys, $lockedKeys) ? WaitConditionLoop::CONDITION_CONTINUE : true;
     }, 3.0);
     $loop->invoke();
     if (count($lockedKeys) != count($keys)) {
         $this->releaseMutexes($memc, $lockedKeys);
         // failed; release what was locked
         return false;
     }
     return true;
 }