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