vendor/zf1/zend-search-lucene/library/Zend/Search/Lucene/LockManager.php line 134

Open in your IDE?
  1. <?php
  2. /**
  3.  * Zend Framework
  4.  *
  5.  * LICENSE
  6.  *
  7.  * This source file is subject to the new BSD license that is bundled
  8.  * with this package in the file LICENSE.txt.
  9.  * It is also available through the world-wide-web at this URL:
  10.  * http://framework.zend.com/license/new-bsd
  11.  * If you did not receive a copy of the license and are unable to
  12.  * obtain it through the world-wide-web, please send an email
  13.  * to license@zend.com so we can send you a copy immediately.
  14.  *
  15.  * @category   Zend
  16.  * @package    Zend_Search_Lucene
  17.  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  18.  * @license    http://framework.zend.com/license/new-bsd     New BSD License
  19.  * @version    $Id$
  20.  */
  21. /** Zend_Search_Lucene_Storage_Directory */
  22. // require_once 'Zend/Search/Lucene/Storage/Directory.php';
  23. /** Zend_Search_Lucene_Storage_File */
  24. // require_once 'Zend/Search/Lucene/Storage/File.php';
  25. /**
  26.  * This is an utility class which provides index locks processing functionality
  27.  *
  28.  * @category   Zend
  29.  * @package    Zend_Search_Lucene
  30.  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  31.  * @license    http://framework.zend.com/license/new-bsd     New BSD License
  32.  */
  33. class Zend_Search_Lucene_LockManager
  34. {
  35.     /**
  36.      * consts for name of file to show lock status
  37.      */
  38.     const WRITE_LOCK_FILE                'write.lock.file';
  39.     const READ_LOCK_FILE                 'read.lock.file';
  40.     const READ_LOCK_PROCESSING_LOCK_FILE 'read-lock-processing.lock.file';
  41.     const OPTIMIZATION_LOCK_FILE         'optimization.lock.file';
  42.     /**
  43.      * Obtain exclusive write lock on the index
  44.      *
  45.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  46.      * @return Zend_Search_Lucene_Storage_File
  47.      * @throws Zend_Search_Lucene_Exception
  48.      */
  49.     public static function obtainWriteLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  50.     {
  51.         $lock $lockDirectory->createFile(self::WRITE_LOCK_FILE);
  52.         if (!$lock->lock(LOCK_EX)) {
  53.             // require_once 'Zend/Search/Lucene/Exception.php';
  54.             throw new Zend_Search_Lucene_Exception('Can\'t obtain exclusive index lock');
  55.         }
  56.         return $lock;
  57.     }
  58.     /**
  59.      * Release exclusive write lock
  60.      *
  61.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  62.      */
  63.     public static function releaseWriteLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  64.     {
  65.         $lock $lockDirectory->getFileObject(self::WRITE_LOCK_FILE);
  66.         $lock->unlock();
  67.     }
  68.     /**
  69.      * Obtain the exclusive "read escalation/de-escalation" lock
  70.      *
  71.      * Required to protect the escalate/de-escalate read lock process
  72.      * on GFS (and potentially other) mounted filesystems.
  73.      *
  74.      * Why we need this:
  75.      *  While GFS supports cluster-wide locking via flock(), it's
  76.      *  implementation isn't quite what it should be.  The locking
  77.      *  semantics that work consistently on a local filesystem tend to
  78.      *  fail on GFS mounted filesystems.  This appears to be a design defect
  79.      *  in the implementation of GFS.  How this manifests itself is that
  80.      *  conditional promotion of a shared lock to exclusive will always
  81.      *  fail, lock release requests are honored but not immediately
  82.      *  processed (causing erratic failures of subsequent conditional
  83.      *  requests) and the releasing of the exclusive lock before the
  84.      *  shared lock is set when a lock is demoted (which can open a window
  85.      *  of opportunity for another process to gain an exclusive lock when
  86.      *  it shoudln't be allowed to).
  87.      *
  88.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  89.      * @return Zend_Search_Lucene_Storage_File
  90.      * @throws Zend_Search_Lucene_Exception
  91.      */
  92.     private static function _startReadLockProcessing(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  93.     {
  94.         $lock $lockDirectory->createFile(self::READ_LOCK_PROCESSING_LOCK_FILE);
  95.         if (!$lock->lock(LOCK_EX)) {
  96.             // require_once 'Zend/Search/Lucene/Exception.php';
  97.             throw new Zend_Search_Lucene_Exception('Can\'t obtain exclusive lock for the read lock processing file');
  98.         }
  99.         return $lock;
  100.     }
  101.     /**
  102.      * Release the exclusive "read escalation/de-escalation" lock
  103.      *
  104.      * Required to protect the escalate/de-escalate read lock process
  105.      * on GFS (and potentially other) mounted filesystems.
  106.      *
  107.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  108.      */
  109.     private static function _stopReadLockProcessing(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  110.     {
  111.         $lock $lockDirectory->getFileObject(self::READ_LOCK_PROCESSING_LOCK_FILE);
  112.         $lock->unlock();
  113.     }
  114.     /**
  115.      * Obtain shared read lock on the index
  116.      *
  117.      * It doesn't block other read or update processes, but prevent index from the premature cleaning-up
  118.      *
  119.      * @param Zend_Search_Lucene_Storage_Directory $defaultLockDirectory
  120.      * @return Zend_Search_Lucene_Storage_File
  121.      * @throws Zend_Search_Lucene_Exception
  122.      */
  123.     public static function obtainReadLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  124.     {
  125.         $lock $lockDirectory->createFile(self::READ_LOCK_FILE);
  126.         if (!$lock->lock(LOCK_SH)) {
  127.             // require_once 'Zend/Search/Lucene/Exception.php';
  128.             throw new Zend_Search_Lucene_Exception('Can\'t obtain shared reading index lock');
  129.         }
  130.         return $lock;
  131.     }
  132.     /**
  133.      * Release shared read lock
  134.      *
  135.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  136.      */
  137.     public static function releaseReadLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  138.     {
  139.         $lock $lockDirectory->getFileObject(self::READ_LOCK_FILE);
  140.         $lock->unlock();
  141.     }
  142.     /**
  143.      * Escalate Read lock to exclusive level
  144.      *
  145.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  146.      * @return boolean
  147.      */
  148.     public static function escalateReadLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  149.     {
  150.         self::_startReadLockProcessing($lockDirectory);
  151.         $lock $lockDirectory->getFileObject(self::READ_LOCK_FILE);
  152.         // First, release the shared lock for the benefit of GFS since
  153.         // it will fail the conditional request to promote the lock to
  154.         // "exclusive" while the shared lock is held (even when we are
  155.         // the only holder).
  156.         $lock->unlock();
  157.         // GFS is really poor.  While the above "unlock" returns, GFS
  158.         // doesn't clean up it's tables right away (which will potentially
  159.         // cause the conditional locking for the "exclusive" lock to fail.
  160.         // We will retry the conditional lock request several times on a
  161.         // failure to get past this.  The performance hit is negligible
  162.         // in the grand scheme of things and only will occur with GFS
  163.         // filesystems or if another local process has the shared lock
  164.         // on local filesystems.
  165.         for ($retries 0$retries 10$retries++) {
  166.             if ($lock->lock(LOCK_EXtrue)) {
  167.                 // Exclusive lock is obtained!
  168.                 self::_stopReadLockProcessing($lockDirectory);
  169.                 return true;
  170.             }
  171.             // wait 1 microsecond
  172.             usleep(1);
  173.         }
  174.         // Restore lock state
  175.         $lock->lock(LOCK_SH);
  176.         self::_stopReadLockProcessing($lockDirectory);
  177.         return false;
  178.     }
  179.     /**
  180.      * De-escalate Read lock to shared level
  181.      *
  182.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  183.      */
  184.     public static function deEscalateReadLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  185.     {
  186.         $lock $lockDirectory->getFileObject(self::READ_LOCK_FILE);
  187.         $lock->lock(LOCK_SH);
  188.     }
  189.     /**
  190.      * Obtain exclusive optimization lock on the index
  191.      *
  192.      * Returns lock object on success and false otherwise (doesn't block execution)
  193.      *
  194.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  195.      * @return mixed
  196.      */
  197.     public static function obtainOptimizationLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  198.     {
  199.         $lock $lockDirectory->createFile(self::OPTIMIZATION_LOCK_FILE);
  200.         if (!$lock->lock(LOCK_EXtrue)) {
  201.             return false;
  202.         }
  203.         return $lock;
  204.     }
  205.     /**
  206.      * Release exclusive optimization lock
  207.      *
  208.      * @param Zend_Search_Lucene_Storage_Directory $lockDirectory
  209.      */
  210.     public static function releaseOptimizationLock(Zend_Search_Lucene_Storage_Directory $lockDirectory)
  211.     {
  212.         $lock $lockDirectory->getFileObject(self::OPTIMIZATION_LOCK_FILE);
  213.         $lock->unlock();
  214.     }
  215. }