Esempio n. 1
0
 /**
  * Define Predis base path if not already set, and if we need to set the
  * autoloader by ourself. This will ensure no crash. Best way would have
  * been that Drupal ships a PSR-0 autoloader, in which we could manually
  * add our library path.
  * 
  * We cannot do that in the file header, PHP class_exists() function wont
  * see classes being loaded during the autoloading because this file is
  * loaded by another autoloader: attempting the class_exists() during a
  * pending autoloading would cause PHP to crash and ignore the rest of the
  * file silentely (WTF!?). By delaying this at the getClient() call we
  * ensure we are not in the class loading process anymore.
  */
 public static function setPredisAutoload()
 {
     if (self::$autoloaderRegistered) {
         return;
     } else {
         self::$autoloaderRegistered = true;
     }
     // If you attempt to set Drupal's bin cache_bootstrap using Redis, you
     // will experience an infinite loop (breaking by itself the second time
     // it passes by): the following call will wake up autoloaders (and we
     // want that to work since user may have set its own autoloader) but
     // will wake up Drupal's one too, and because Drupal core caches its
     // file map, this will trigger this method to be called a second time
     // and boom! Adios bye bye. That's why this will be called early in the
     // 'redis.autoload.inc' file instead.
     if (!class_exists('Predis\\Client')) {
         if (!defined('PREDIS_BASE_PATH')) {
             $search = DRUPAL_ROOT . '/sites/all/libraries/predis/lib/';
             if (is_dir($search)) {
                 define('PREDIS_BASE_PATH', $search);
             } else {
                 throw new Exception("PREDIS_BASE_PATH constant must be set, Predis library must live in sites/all/libraries/predis.");
             }
         }
         if (class_exists('AutoloadEarly')) {
             AutoloadEarly::getInstance()->registerNamespace('Predis', PREDIS_BASE_PATH);
         } else {
             // Register a simple autoloader for Predis library. Since the Predis
             // library is PHP 5.3 only, we can afford doing closures safely.
             spl_autoload_register(function ($classname) {
                 if (0 === strpos($classname, 'Predis\\')) {
                     $filename = PREDIS_BASE_PATH . str_replace('\\', '/', $classname) . '.php';
                     return (bool) (require_once $filename);
                 }
                 return false;
             });
         }
     }
 }
Esempio n. 2
0
 /**
  * Define Predis base path if not already set, and if we need to set the
  * autoloader by ourself. This will ensure no crash. Best way would have
  * been that Drupal ships a PSR-0 autoloader, in which we could manually
  * add our library path.
  * 
  * We cannot do that in the file header, PHP class_exists() function wont
  * see classes being loaded during the autoloading because this file is
  * loaded by another autoloader: attempting the class_exists() during a
  * pending autoloading would cause PHP to crash and ignore the rest of the
  * file silentely (WTF!?). By delaying this at the getClient() call we
  * ensure we are not in the class loading process anymore.
  */
 public static function setPredisAutoload()
 {
     if (self::$autoloaderRegistered) {
         return;
     }
     self::$stupidCoreWorkaround++;
     // If you attempt to set Drupal's bin cache_bootstrap using Redis, you
     // will experience an infinite loop (breaking by itself the second time
     // it passes by): the following call will wake up autoloaders (and we
     // want that to work since user may have set its own autoloader) but
     // will wake up Drupal's one too, and because Drupal core caches its
     // file map, this will trigger this method to be called a second time
     // and boom! Adios bye bye. That's why this will be called early in the
     // 'redis.autoload.inc' file instead.
     if (1 < self::$stupidCoreWorkaround || !class_exists('Predis\\Client')) {
         if (!defined('PREDIS_BASE_PATH')) {
             $search = DRUPAL_ROOT . '/sites/all/libraries/predis';
             define('PREDIS_BASE_PATH', $search);
         } else {
             $search = PREDIS_BASE_PATH;
         }
         if (is_dir($search . '/src')) {
             // Predis v1.x
             define('PREDIS_VERSION_MAJOR', 1);
         } else {
             if (is_dir($search . '/lib')) {
                 // Predis v0.x
                 define('PREDIS_VERSION_MAJOR', 0);
             } else {
                 throw new Exception("PREDIS_BASE_PATH constant must be set, Predis library must live in sites/all/libraries/predis.");
             }
         }
         // Register a simple autoloader for Predis library. Since the Predis
         // library is PHP 5.3 only, we can afford doing closures safely.
         switch (PREDIS_VERSION_MAJOR) {
             case 0:
                 $autoload = function ($classname) {
                     // PSR-0 autoloader.
                     if (0 === strpos($classname, 'Predis\\')) {
                         $filename = PREDIS_BASE_PATH . '/lib/' . str_replace('\\', '/', $classname) . '.php';
                         return (bool) (require_once $filename);
                     }
                     return false;
                 };
                 break;
             case 1:
                 // Register a simple autoloader for Predis library. Since the Predis
                 // library is PHP 5.3 only, we can afford doing closures safely.
                 $autoload = function ($classname) {
                     // PSR-4 autoloader
                     if (0 === strpos($classname, 'Predis\\')) {
                         $filename = PREDIS_BASE_PATH . '/src/' . str_replace('\\', '/', substr($classname, 7)) . '.php';
                         return (bool) (require_once $filename);
                     }
                     return false;
                 };
                 break;
         }
         if ($autoload) {
             spl_autoload_register($autoload);
         }
         // Same reason why we have the stupid core workaround, if this happens
         // during a second autoload call, PHP won't call the newly registered
         // autoloader function, so just load the file.
         if (1 < self::$stupidCoreWorkaround) {
             call_user_func($autoload, 'Predis\\Client');
         }
     }
     self::$autoloaderRegistered = true;
 }
Esempio n. 3
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;
 }