]> git.mxchange.org Git - friendica.git/blob - src/Core/Lock/SemaphoreLock.php
Merge pull request #7515 from nupplaphil/task/console_lock
[friendica.git] / src / Core / Lock / SemaphoreLock.php
1 <?php
2
3 namespace Friendica\Core\Lock;
4
5 use Friendica\Core\Cache;
6
7 class SemaphoreLock extends Lock
8 {
9         private static $semaphore = [];
10
11         public function __construct()
12         {
13                 if (!function_exists('sem_get')) {
14                         throw new \Exception('Semaphore lock not supported');
15                 }
16         }
17
18         /**
19          * (@inheritdoc)
20          */
21         private static function semaphoreKey($key)
22         {
23                 $file = self::keyToFile($key);
24
25                 if (!file_exists($file)) {
26                         file_put_contents($file, $key);
27                 }
28
29                 return ftok($file, 'f');
30         }
31
32         /**
33          * Returns the full path to the semaphore file
34          *
35          * @param string $key The key of the semaphore
36          *
37          * @return string The full path
38          */
39         private static function keyToFile($key)
40         {
41                 $temp = get_temppath();
42
43                 return $temp . '/' . $key . '.sem';
44         }
45
46         /**
47          * (@inheritdoc)
48          */
49         public function acquireLock($key, $timeout = 120, $ttl = Cache\Cache::FIVE_MINUTES)
50         {
51                 self::$semaphore[$key] = sem_get(self::semaphoreKey($key));
52                 if (self::$semaphore[$key]) {
53                         if (sem_acquire(self::$semaphore[$key], ($timeout == 0))) {
54                                 $this->markAcquire($key);
55                                 return true;
56                         }
57                 }
58
59                 return false;
60         }
61
62         /**
63          * (@inheritdoc)
64          */
65         public function releaseLock($key, $override = false)
66         {
67                 $success = false;
68
69                 if (!empty(self::$semaphore[$key])) {
70                         try {
71                                 $success = @sem_release(self::$semaphore[$key]) &&
72                                            unlink(self::keyToFile($key));
73                                 unset(self::$semaphore[$key]);
74                                 $this->markRelease($key);
75                         } catch (\Exception $exception) {
76                                 $success = false;
77                         }
78                 } else if ($override) {
79                         if ($this->acquireLock($key)) {
80                                 $success = $this->releaseLock($key, true);
81                         }
82                 }
83
84                 return $success;
85         }
86
87         /**
88          * (@inheritdoc)
89          */
90         public function isLocked($key)
91         {
92                 return isset(self::$semaphore[$key]);
93         }
94
95         /**
96          * {@inheritDoc}
97          */
98         public function getName()
99         {
100                 return self::TYPE_SEMAPHORE;
101         }
102
103         /**
104          * {@inheritDoc}
105          */
106         public function getLocks(string $prefix = '')
107         {
108                 $temp = get_temppath();
109                 $locks = [];
110                 foreach (glob(sprintf('%s/%s*.sem', $temp, $prefix)) as $lock) {
111                         $lock = pathinfo($lock, PATHINFO_FILENAME);
112                         if(sem_get(self::semaphoreKey($lock))) {
113                                 $locks[] = $lock;
114                         }
115                 }
116
117                 return $locks;
118         }
119
120         /**
121          * {@inheritDoc}
122          */
123         public function releaseAll($override = false)
124         {
125                 $success = parent::releaseAll($override);
126
127                 $temp = get_temppath();
128                 foreach (glob(sprintf('%s/*.sem', $temp)) as $lock) {
129                         $lock = pathinfo($lock, PATHINFO_FILENAME);
130                         if (!$this->releaseLock($lock, true)) {
131                                 $success = false;
132                         }
133                 }
134
135                 return $success;
136         }
137 }