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