FileMutex.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\mutex;
  8. use Yii;
  9. use yii\base\InvalidConfigException;
  10. use yii\helpers\FileHelper;
  11. /**
  12. * @author resurtm <[email protected]>
  13. * @since 2.0
  14. */
  15. class FileMutex extends Mutex
  16. {
  17. /**
  18. * @var string the directory to store mutex files. You may use path alias here.
  19. * Defaults to the "mutex" subdirectory under the application runtime path.
  20. */
  21. public $mutexPath = '@runtime/mutex';
  22. /**
  23. * @var integer the permission to be set for newly created mutex files.
  24. * This value will be used by PHP chmod() function. No umask will be applied.
  25. * If not set, the permission will be determined by the current environment.
  26. */
  27. public $fileMode;
  28. /**
  29. * @var integer the permission to be set for newly created directories.
  30. * This value will be used by PHP chmod() function. No umask will be applied.
  31. * Defaults to 0775, meaning the directory is read-writable by owner and group,
  32. * but read-only for other users.
  33. */
  34. public $dirMode = 0775;
  35. /**
  36. * @var resource[] stores all opened lock files. Keys are lock names and values are file handles.
  37. */
  38. private $_files = [];
  39. /**
  40. * Initializes mutex component implementation dedicated for UNIX, GNU/Linux, Mac OS X, and other UNIX-like
  41. * operating systems.
  42. * @throws InvalidConfigException
  43. */
  44. public function init()
  45. {
  46. if (stripos(php_uname('s'), 'win') === 0) {
  47. throw new InvalidConfigException('FileMutex does not have MS Windows operating system support.');
  48. }
  49. $this->mutexPath = Yii::getAlias($this->mutexPath);
  50. if (!is_dir($this->mutexPath)) {
  51. FileHelper::createDirectory($this->mutexPath, $this->dirMode, true);
  52. }
  53. }
  54. /**
  55. * Acquires lock by given name.
  56. * @param string $name of the lock to be acquired.
  57. * @param integer $timeout to wait for lock to become released.
  58. * @return boolean acquiring result.
  59. */
  60. protected function acquireLock($name, $timeout = 0)
  61. {
  62. $fileName = $this->mutexPath . '/' . md5($name) . '.lock';
  63. $file = fopen($fileName, 'w+');
  64. if ($file === false) {
  65. return false;
  66. }
  67. if ($this->fileMode !== null) {
  68. @chmod($fileName, $this->fileMode);
  69. }
  70. $waitTime = 0;
  71. while (!flock($file, LOCK_EX | LOCK_NB)) {
  72. $waitTime++;
  73. if ($waitTime > $timeout) {
  74. fclose($file);
  75. return false;
  76. }
  77. sleep(1);
  78. }
  79. $this->_files[$name] = $file;
  80. return true;
  81. }
  82. /**
  83. * Releases lock by given name.
  84. * @param string $name of the lock to be released.
  85. * @return boolean release result.
  86. */
  87. protected function releaseLock($name)
  88. {
  89. if (!isset($this->_files[$name]) || !flock($this->_files[$name], LOCK_UN)) {
  90. return false;
  91. } else {
  92. fclose($this->_files[$name]);
  93. unset($this->_files[$name]);
  94. return true;
  95. }
  96. }
  97. }