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