Esempio n. 1
0
 public function lockAcquire($name, $timeout = 30.0)
 {
     $client = Redis_Client::getClient();
     $key = $this->getKey($name);
     $id = $this->getLockId();
     // Insure that the timeout is at least 1 second, we cannot do otherwise with
     // Redis, this is a minor change to the function signature, but in real life
     // nobody will notice with so short duration.
     $timeout = ceil(max($timeout, 1));
     // If we already have the lock, check for his owner and attempt a new EXPIRE
     // command on it.
     if (isset($this->_locks[$name])) {
         // Create a new transaction, for atomicity.
         $client->watch($key);
         // Global tells us we are the owner, but in real life it could have expired
         // and another process could have taken it, check that.
         if ($client->get($key) != $id) {
             $client->unwatch($key);
             unset($this->_locks[$name]);
             return FALSE;
         }
         switch (Redis_Client_Predis::getPredisVersionMajor()) {
             case 0:
                 $replies = $client->pipeline(function ($pipe) use($key, $timeout, $id) {
                     $pipe->multi();
                     $pipe->setex($key, $timeout, $id);
                     $pipe->exec();
                 });
                 break;
             default:
                 $replies = $client->transaction(function ($pipe) use($key, $timeout, $id) {
                     $pipe->setex($key, $timeout, $id);
                 });
                 break;
         }
         $execReply = array_pop($replies);
         if (FALSE === $execReply[0]) {
             unset($this->_locks[$name]);
             return FALSE;
         }
         return TRUE;
     } else {
         $client->watch($key);
         $owner = $client->get($key);
         if (!empty($owner) && $owner != $id) {
             $client->unwatch();
             unset($this->_locks[$name]);
             return FALSE;
         }
         $replies = $client->pipeline(function ($pipe) use($key, $timeout, $id) {
             $pipe->multi();
             $pipe->setex($key, $timeout, $id);
             $pipe->exec();
         });
         $execReply = array_pop($replies);
         // If another client modified the $key value, transaction will be discarded
         // $result will be set to FALSE. This means atomicity have been broken and
         // the other client took the lock instead of us.
         // EXPIRE and SETEX won't return something here, EXEC return is index 0
         // This was determined debugging, seems to be Predis specific.
         if (FALSE === $execReply[0]) {
             return FALSE;
         }
         // Register the lock and return.
         return $this->_locks[$name] = TRUE;
     }
     return FALSE;
 }