AbstractLockingProvider.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Robin Appelman <robin@icewind.nl>
  6. *
  7. * @license AGPL-3.0
  8. *
  9. * This code is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License, version 3,
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License, version 3,
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>
  20. *
  21. */
  22. namespace OC\Lock;
  23. use OCP\Lock\ILockingProvider;
  24. /**
  25. * Base locking provider that keeps track of locks acquired during the current request
  26. * to release any left over locks at the end of the request
  27. */
  28. abstract class AbstractLockingProvider implements ILockingProvider {
  29. protected $ttl; // how long until we clear stray locks in seconds
  30. protected $acquiredLocks = [
  31. 'shared' => [],
  32. 'exclusive' => []
  33. ];
  34. /**
  35. * Check if we've locally acquired a lock
  36. *
  37. * @param string $path
  38. * @param int $type
  39. * @return bool
  40. */
  41. protected function hasAcquiredLock($path, $type) {
  42. if ($type === self::LOCK_SHARED) {
  43. return isset($this->acquiredLocks['shared'][$path]) && $this->acquiredLocks['shared'][$path] > 0;
  44. } else {
  45. return isset($this->acquiredLocks['exclusive'][$path]) && $this->acquiredLocks['exclusive'][$path] === true;
  46. }
  47. }
  48. /**
  49. * Mark a locally acquired lock
  50. *
  51. * @param string $path
  52. * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
  53. */
  54. protected function markAcquire($path, $type) {
  55. if ($type === self::LOCK_SHARED) {
  56. if (!isset($this->acquiredLocks['shared'][$path])) {
  57. $this->acquiredLocks['shared'][$path] = 0;
  58. }
  59. $this->acquiredLocks['shared'][$path]++;
  60. } else {
  61. $this->acquiredLocks['exclusive'][$path] = true;
  62. }
  63. }
  64. /**
  65. * Mark a release of a locally acquired lock
  66. *
  67. * @param string $path
  68. * @param int $type self::LOCK_SHARED or self::LOCK_EXCLUSIVE
  69. */
  70. protected function markRelease($path, $type) {
  71. if ($type === self::LOCK_SHARED) {
  72. if (isset($this->acquiredLocks['shared'][$path]) and $this->acquiredLocks['shared'][$path] > 0) {
  73. $this->acquiredLocks['shared'][$path]--;
  74. if ($this->acquiredLocks['shared'][$path] === 0) {
  75. unset($this->acquiredLocks['shared'][$path]);
  76. }
  77. }
  78. } else if ($type === self::LOCK_EXCLUSIVE) {
  79. unset($this->acquiredLocks['exclusive'][$path]);
  80. }
  81. }
  82. /**
  83. * Change the type of an existing tracked lock
  84. *
  85. * @param string $path
  86. * @param int $targetType self::LOCK_SHARED or self::LOCK_EXCLUSIVE
  87. */
  88. protected function markChange($path, $targetType) {
  89. if ($targetType === self::LOCK_SHARED) {
  90. unset($this->acquiredLocks['exclusive'][$path]);
  91. if (!isset($this->acquiredLocks['shared'][$path])) {
  92. $this->acquiredLocks['shared'][$path] = 0;
  93. }
  94. $this->acquiredLocks['shared'][$path]++;
  95. } else if ($targetType === self::LOCK_EXCLUSIVE) {
  96. $this->acquiredLocks['exclusive'][$path] = true;
  97. $this->acquiredLocks['shared'][$path]--;
  98. }
  99. }
  100. /**
  101. * release all lock acquired by this instance which were marked using the mark* methods
  102. */
  103. public function releaseAll() {
  104. foreach ($this->acquiredLocks['shared'] as $path => $count) {
  105. for ($i = 0; $i < $count; $i++) {
  106. $this->releaseLock($path, self::LOCK_SHARED);
  107. }
  108. }
  109. foreach ($this->acquiredLocks['exclusive'] as $path => $hasLock) {
  110. $this->releaseLock($path, self::LOCK_EXCLUSIVE);
  111. }
  112. }
  113. protected function getOwnSharedLockCount($path) {
  114. return isset($this->acquiredLocks['shared'][$path]) ? $this->acquiredLocks['shared'][$path] : 0;
  115. }
  116. }