]> git.mxchange.org Git - friendica.git/blob - src/Factory/LockFactory.php
Merge pull request #7988 from friendica/MrPetovan-notice
[friendica.git] / src / Factory / LockFactory.php
1 <?php
2
3 namespace Friendica\Factory;
4
5 use Friendica\Core\Cache\Cache;
6 use Friendica\Core\Cache\IMemoryCache;
7 use Friendica\Core\Config\Configuration;
8 use Friendica\Core\Lock;
9 use Friendica\Database\Database;
10 use Psr\Log\LoggerInterface;
11
12 /**
13  * Class LockFactory
14  *
15  * @package Friendica\Core\Cache
16  *
17  * A basic class to generate a LockDriver
18  */
19 class LockFactory
20 {
21         /**
22          * @var string The default driver for caching
23          */
24         const DEFAULT_DRIVER = 'default';
25
26         /**
27          * @var Configuration The configuration to read parameters out of the config
28          */
29         private $config;
30
31         /**
32          * @var Database The database connection in case that the cache is used the dba connection
33          */
34         private $dba;
35
36         /**
37          * @var CacheFactory The memory cache driver in case we use it
38          */
39         private $cacheFactory;
40
41         /**
42          * @var LoggerInterface The Friendica Logger
43          */
44         private $logger;
45
46         public function __construct(CacheFactory $cacheFactory, Configuration $config, Database $dba, LoggerInterface $logger)
47         {
48                 $this->cacheFactory = $cacheFactory;
49                 $this->config       = $config;
50                 $this->dba          = $dba;
51                 $this->logger       = $logger;
52         }
53
54         public function create()
55         {
56                 $lock_type = $this->config->get('system', 'lock_driver', self::DEFAULT_DRIVER);
57
58                 try {
59                         switch ($lock_type) {
60                                 case Cache::TYPE_MEMCACHE:
61                                 case Cache::TYPE_MEMCACHED:
62                                 case Cache::TYPE_REDIS:
63                                 case Cache::TYPE_APCU:
64                                         $cache = $this->cacheFactory->create($lock_type);
65                                         if ($cache instanceof IMemoryCache) {
66                                                 return new Lock\CacheLock($cache);
67                                         } else {
68                                                 throw new \Exception(sprintf('Incompatible cache driver \'%s\' for lock used', $lock_type));
69                                         }
70                                         break;
71
72                                 case 'database':
73                                         return new Lock\DatabaseLock($this->dba);
74                                         break;
75
76                                 case 'semaphore':
77                                         return new Lock\SemaphoreLock();
78                                         break;
79
80                                 default:
81                                         return self::useAutoDriver();
82                         }
83                 } catch (\Exception $exception) {
84                         $this->logger->alert('Driver \'' . $lock_type . '\' failed - Fallback to \'useAutoDriver()\'', ['exception' => $exception]);
85                         return self::useAutoDriver();
86                 }
87         }
88
89         /**
90          * @brief This method tries to find the best - local - locking method for Friendica
91          *
92          * The following sequence will be tried:
93          * 1. Semaphore Locking
94          * 2. Cache Locking
95          * 3. Database Locking
96          *
97          * @return Lock\ILock
98          */
99         private function useAutoDriver()
100         {
101                 // 1. Try to use Semaphores for - local - locking
102                 if (function_exists('sem_get')) {
103                         try {
104                                 return new Lock\SemaphoreLock();
105                         } catch (\Exception $exception) {
106                                 $this->logger->debug('Using Semaphore driver for locking failed.', ['exception' => $exception]);
107                         }
108                 }
109
110                 // 2. Try to use Cache Locking (don't use the DB-Cache Locking because it works different!)
111                 $cache_type = $this->config->get('system', 'cache_driver', 'database');
112                 if ($cache_type != Cache::TYPE_DATABASE) {
113                         try {
114                                 $cache = $this->cacheFactory->create($cache_type);
115                                 if ($cache instanceof IMemoryCache) {
116                                         return new Lock\CacheLock($cache);
117                                 }
118                         } catch (\Exception $exception) {
119                                 $this->logger->debug('Using Cache driver for locking failed.', ['exception' => $exception]);
120                         }
121                 }
122
123                 // 3. Use Database Locking as a Fallback
124                 return new Lock\DatabaseLock($this->dba);
125         }
126 }