]> git.mxchange.org Git - friendica.git/blob - src/Core/Lock.php
Adding multihost - locking
[friendica.git] / src / Core / Lock.php
1 <?php
2 /**
3  * @file src/Util/Lock.php
4  */
5 namespace Friendica\Core;
6
7 /**
8  * @file src/Core/Lock.php
9  * @brief Functions for preventing parallel execution of functions
10  */
11
12 use Friendica\Core\Cache\CacheDriverFactory;
13 use Friendica\Core\Cache\IMemoryCacheDriver;
14
15 /**
16  * @brief This class contain Functions for preventing parallel execution of functions
17  */
18 class Lock
19 {
20         /**
21          * @var Lock\ILockDriver;
22          */
23         static $driver = null;
24
25         public static function init()
26         {
27                 $lock_driver = Config::get('system', 'lock_driver', 'default');
28
29                 try {
30                         switch ($lock_driver) {
31                                 case 'memcache':
32                                         $cache_driver = CacheDriverFactory::create('memcache');
33                                         if ($cache_driver instanceof IMemoryCacheDriver) {
34                                                 self::$driver = new Lock\CacheLockDriver($cache_driver);
35                                         }
36                                         break;
37
38                                 case 'memcached':
39                                         $cache_driver = CacheDriverFactory::create('memcached');
40                                         if ($cache_driver instanceof IMemoryCacheDriver) {
41                                                 self::$driver = new Lock\CacheLockDriver($cache_driver);
42                                         }
43                                         break;
44
45                                 case 'redis':
46                                         $cache_driver = CacheDriverFactory::create('redis');
47                                         if ($cache_driver instanceof IMemoryCacheDriver) {
48                                                 self::$driver = new Lock\CacheLockDriver($cache_driver);
49                                         }
50                                         break;
51
52                                 case 'database':
53                                         self::$driver = new Lock\DatabaseLockDriver();
54                                         break;
55
56                                 case 'semaphore':
57                                         self::$driver = new Lock\SemaphoreLockDriver();
58                                         break;
59
60                                 default:
61                                         self::useAutoDriver();
62                         }
63                 } catch (\Exception $exception) {
64                         logger ('Driver \'' . $lock_driver . '\' failed - Fallback to \'useAutoDriver()\'');
65                         self::useAutoDriver();
66                 }
67         }
68
69         /**
70          * @brief This method tries to find the best - local - locking method for Friendica
71          *
72          * The following sequence will be tried:
73          * 1. Semaphore Locking
74          * 2. Cache Locking
75          * 3. Database Locking
76          *
77          */
78         private static function useAutoDriver() {
79
80                 // 1. Try to use Semaphores for - local - locking
81                 if (function_exists('sem_get')) {
82                         try {
83                                 self::$driver = new Lock\SemaphoreLockDriver();
84                                 return;
85                         } catch (\Exception $exception) {
86                                 logger ('Using Semaphore driver for locking failed: ' . $exception->getMessage());
87                         }
88                 }
89
90                 // 2. Try to use Cache Locking (don't use the DB-Cache Locking because it works different!)
91                 $cache_driver = Config::get('system', 'cache_driver', 'database');
92                 if ($cache_driver != 'database') {
93                         try {
94                                 $lock_driver = CacheDriverFactory::create($cache_driver);
95                                 if ($lock_driver instanceof IMemoryCacheDriver) {
96                                         self::$driver = new Lock\CacheLockDriver($lock_driver);
97                                 }
98                                 return;
99                         } catch (\Exception $exception) {
100                                 logger('Using Cache driver for locking failed: ' . $exception->getMessage());
101                         }
102                 }
103
104                 // 3. Use Database Locking as a Fallback
105                 self::$driver = new Lock\DatabaseLockDriver();
106         }
107
108         /**
109          * Returns the current cache driver
110          *
111          * @return Lock\ILockDriver;
112          */
113         private static function getDriver()
114         {
115                 if (self::$driver === null) {
116                         self::init();
117                 }
118
119                 return self::$driver;
120         }
121
122         /**
123          * @brief Acquires a lock for a given name
124          *
125          * @param string  $key Name of the lock
126          * @param integer $timeout Seconds until we give up
127          *
128          * @return boolean Was the lock successful?
129          */
130         public static function acquireLock($key, $timeout = 120)
131         {
132                 return self::getDriver()->acquireLock($key, $timeout);
133         }
134
135         /**
136          * @brief Releases a lock if it was set by us
137          *
138          * @param string $key Name of the lock
139          * @return mixed
140          */
141         public static function releaseLock($key)
142         {
143                 return self::getDriver()->releaseLock($key);
144         }
145
146         /**
147          * @brief Releases all lock that were set by us
148          * @return void
149          */
150         public static function releaseAll()
151         {
152                 self::getDriver()->releaseAll();
153         }
154 }