]> git.mxchange.org Git - friendica.git/blob - src/Core/Lock/CacheLockDriver.php
13d912c1e2979726fff44e3c511180a5739b8410
[friendica.git] / src / Core / Lock / CacheLockDriver.php
1 <?php
2
3 namespace Friendica\Core\Lock;
4
5 use Friendica\Core\Cache\IMemoryCacheDriver;
6
7 class CacheLockDriver extends AbstractLockDriver
8 {
9         /**
10          * @var \Friendica\Core\Cache\ICacheDriver;
11          */
12         private $cache;
13
14         /**
15          * CacheLockDriver constructor.
16          *
17          * @param IMemoryCacheDriver $cache The CacheDriver for this type of lock
18          */
19         public function __construct(IMemoryCacheDriver $cache)
20         {
21                 $this->cache = $cache;
22         }
23
24         /**
25          *
26          * @brief Sets a lock for a given name
27          *
28          * @param string $key The Name of the lock
29          * @param integer $timeout Seconds until we give up
30          *
31          * @return boolean Was the lock successful?
32          */
33         public function acquireLock($key, $timeout = 120)
34         {
35                 $got_lock = false;
36                 $start = time();
37
38                 $cachekey = self::getCacheKey($key);
39
40                 do {
41                         $lock = $this->cache->get($cachekey);
42                         // When we do want to lock something that was already locked by us.
43                         if ((int)$lock == getmypid()) {
44                                 $got_lock = true;
45                         }
46
47                         // When we do want to lock something new
48                         if (is_null($lock)) {
49                                 // At first initialize it with "0"
50                                 $this->cache->add($cachekey, 0);
51                                 // Now the value has to be "0" because otherwise the key was used by another process meanwhile
52                                 if ($this->cache->compareSet($cachekey, 0, getmypid(), 300)) {
53                                         $got_lock = true;
54                                         $this->markAcquire($key);
55                                 }
56                         }
57
58                         if (!$got_lock && ($timeout > 0)) {
59                                 usleep(rand(10000, 200000));
60                         }
61                 } while (!$got_lock && ((time() - $start) < $timeout));
62
63                 return $got_lock;
64         }
65
66         /**
67          * @brief Removes a lock if it was set by us
68          *
69          * @param string $key Name of the lock
70          */
71         public function releaseLock($key)
72         {
73                 $cachekey = self::getCacheKey($key);
74
75                 $this->cache->compareDelete($cachekey, getmypid());
76                 $this->markRelease($key);
77         }
78
79         /**
80          * @brief Checks, if a key is currently locked to a process
81          *
82          * @param string $key The name of the lock
83          * @return bool
84          */
85         public function isLocked($key)
86         {
87                 $cachekey = self::getCacheKey($key);
88                 $lock = $this->cache->get($cachekey);
89                 return isset($lock) && ($lock !== false);
90         }
91
92         /**
93          * @param string $key   The original key
94          * @return string               The cache key used for the cache
95          */
96         private static function getCacheKey($key) {
97                 return self::getApp()->get_hostname() . ";lock:" . $key;
98         }
99 }