Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

132 lines
3.8KB

  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. * FileMutex implements mutex "lock" mechanism via local file system files.
  13. * This component relies on PHP `flock()` function.
  14. *
  15. * Application configuration example:
  16. *
  17. * ```
  18. * [
  19. * 'components' => [
  20. * 'mutex'=> [
  21. * 'class' => 'yii\mutex\FileMutex'
  22. * ],
  23. * ],
  24. * ]
  25. * ```
  26. *
  27. * Note: this component can maintain the locks only for the single web server,
  28. * it probably will not suffice to your in case you are using cloud server solution.
  29. *
  30. * Warning: due to `flock()` function nature this component is unreliable when
  31. * using a multithreaded server API like ISAPI.
  32. *
  33. * @see Mutex
  34. *
  35. * @author resurtm <resurtm@gmail.com>
  36. * @since 2.0
  37. */
  38. class FileMutex extends Mutex
  39. {
  40. /**
  41. * @var string the directory to store mutex files. You may use path alias here.
  42. * Defaults to the "mutex" subdirectory under the application runtime path.
  43. */
  44. public $mutexPath = '@runtime/mutex';
  45. /**
  46. * @var integer the permission to be set for newly created mutex files.
  47. * This value will be used by PHP chmod() function. No umask will be applied.
  48. * If not set, the permission will be determined by the current environment.
  49. */
  50. public $fileMode;
  51. /**
  52. * @var integer the permission to be set for newly created directories.
  53. * This value will be used by PHP chmod() function. No umask will be applied.
  54. * Defaults to 0775, meaning the directory is read-writable by owner and group,
  55. * but read-only for other users.
  56. */
  57. public $dirMode = 0775;
  58. /**
  59. * @var resource[] stores all opened lock files. Keys are lock names and values are file handles.
  60. */
  61. private $_files = [];
  62. /**
  63. * Initializes mutex component implementation dedicated for UNIX, GNU/Linux, Mac OS X, and other UNIX-like
  64. * operating systems.
  65. * @throws InvalidConfigException
  66. */
  67. public function init()
  68. {
  69. if (DIRECTORY_SEPARATOR === '\\') {
  70. throw new InvalidConfigException('FileMutex does not have MS Windows operating system support.');
  71. }
  72. $this->mutexPath = Yii::getAlias($this->mutexPath);
  73. if (!is_dir($this->mutexPath)) {
  74. FileHelper::createDirectory($this->mutexPath, $this->dirMode, true);
  75. }
  76. }
  77. /**
  78. * Acquires lock by given name.
  79. * @param string $name of the lock to be acquired.
  80. * @param integer $timeout to wait for lock to become released.
  81. * @return boolean acquiring result.
  82. */
  83. protected function acquireLock($name, $timeout = 0)
  84. {
  85. $fileName = $this->mutexPath . '/' . md5($name) . '.lock';
  86. $file = fopen($fileName, 'w+');
  87. if ($file === false) {
  88. return false;
  89. }
  90. if ($this->fileMode !== null) {
  91. @chmod($fileName, $this->fileMode);
  92. }
  93. $waitTime = 0;
  94. while (!flock($file, LOCK_EX | LOCK_NB)) {
  95. $waitTime++;
  96. if ($waitTime > $timeout) {
  97. fclose($file);
  98. return false;
  99. }
  100. sleep(1);
  101. }
  102. $this->_files[$name] = $file;
  103. return true;
  104. }
  105. /**
  106. * Releases lock by given name.
  107. * @param string $name of the lock to be released.
  108. * @return boolean release result.
  109. */
  110. protected function releaseLock($name)
  111. {
  112. if (!isset($this->_files[$name]) || !flock($this->_files[$name], LOCK_UN)) {
  113. return false;
  114. } else {
  115. fclose($this->_files[$name]);
  116. unset($this->_files[$name]);
  117. return true;
  118. }
  119. }
  120. }