]> git.mxchange.org Git - friendica.git/blob - src/Core/Lock/SemaphoreLock.php
Merge pull request #7519 from nupplaphil/task/add_page
[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                                 if (file_exists(self::keyToFile($key)) && $success) {
73                                         $success = unlink(self::keyToFile($key));
74                                 }
75                                 unset(self::$semaphore[$key]);
76                                 $this->markRelease($key);
77                         } catch (\Exception $exception) {
78                                 $success = false;
79                         }
80                 } else if ($override) {
81                         if ($this->acquireLock($key)) {
82                                 $success = $this->releaseLock($key, true);
83                         }
84                 }
85
86                 return $success;
87         }
88
89         /**
90          * (@inheritdoc)
91          */
92         public function isLocked($key)
93         {
94                 return isset(self::$semaphore[$key]);
95         }
96
97         /**
98          * {@inheritDoc}
99          */
100         public function getName()
101         {
102                 return self::TYPE_SEMAPHORE;
103         }
104
105         /**
106          * {@inheritDoc}
107          */
108         public function getLocks(string $prefix = '')
109         {
110                 $temp = get_temppath();
111                 $locks = [];
112                 foreach (glob(sprintf('%s/%s*.sem', $temp, $prefix)) as $lock) {
113                         $lock = pathinfo($lock, PATHINFO_FILENAME);
114                         if(sem_get(self::semaphoreKey($lock))) {
115                                 $locks[] = $lock;
116                         }
117                 }
118
119                 return $locks;
120         }
121
122         /**
123          * {@inheritDoc}
124          */
125         public function releaseAll($override = false)
126         {
127                 $success = parent::releaseAll($override);
128
129                 $temp = get_temppath();
130                 foreach (glob(sprintf('%s/*.sem', $temp)) as $lock) {
131                         $lock = pathinfo($lock, PATHINFO_FILENAME);
132                         if (!$this->releaseLock($lock, true)) {
133                                 $success = false;
134                         }
135                 }
136
137                 return $success;
138         }
139 }