a2a7130f097394215ac3b09c4031aa41f5cd4a44
[yaffs-website] / web / modules / contrib / memcache / src / Lock / MemcacheLockBackend.php
1 <?php
2
3 /**
4  * @file
5  * Contains \Drupal\memcache\MemcacheLockBackend.
6  */
7
8 namespace Drupal\memcache\Lock;
9
10 use Drupal\Core\Lock\LockBackendAbstract;
11 use Drupal\memcache\DrupalMemcacheInterface;
12
13 /**
14  * Defines a Memcache lock backend.
15  */
16 class MemcacheLockBackend extends LockBackendAbstract {
17
18   /**
19    * An array of currently acquired locks.
20    *
21    * @var array
22    */
23   protected $locks = array();
24
25   /**
26    * The bin name for this lock.
27    *
28    * @var string
29    */
30   protected $bin;
31
32   /**
33    * The memcache wrapper object.
34    *
35    * @var \Drupal\memcache\DrupalMemcacheInterface
36    */
37   protected $memcache;
38
39   /**
40    * Constructs a new MemcacheLockBackend.
41    */
42   public function __construct($bin, DrupalMemcacheInterface $memcache) {
43     $this->bin = $bin;
44     $this->memcache = $memcache;
45
46     // __destruct() is causing problems with garbage collections, register a
47     // shutdown function instead.
48     drupal_register_shutdown_function([$this, 'releaseAll']);
49   }
50
51   /**
52    * {@inheritdoc}
53    */
54   public function acquire($name, $timeout = 30.0) {
55     // Ensure that the timeout is at least 1 sec. This is a limitation imposed
56     // by memcached.
57     $timeout = (int) max($timeout, 1);
58
59     $lock_id = $this->getLockId();
60     $key = $this->getKey($name);
61
62     if (isset($this->locks[$name])) {
63       // Try to extend the expiration of a lock we already acquired.
64       $success = !$this->lockMayBeAvailable($name) && $this->memcache->set($key, $lock_id, $timeout);
65
66       if (!$success) {
67         // The lock was broken.
68         unset($this->locks[$name]);
69       }
70
71       return $success;
72     }
73     else {
74       if ($this->lockMayBeAvailable($name)) {
75         $success = $this->memcache->set($key, $lock_id, $timeout);
76
77         if (!$success) {
78           return FALSE;
79         }
80
81         // We track all acquired locks in the global variable, if successful.
82         $this->locks[$name] = TRUE;
83       }
84       else {
85         return FALSE;
86       }
87     }
88
89     return isset($this->locks[$name]);
90   }
91
92   /**
93    * {@inheritdoc}
94    */
95   public function lockMayBeAvailable($name) {
96     return !$this->memcache->get($this->getKey($name));
97   }
98
99   /**
100    * {@inheritdoc}
101    */
102   public function release($name) {
103     $this->memcache->delete($this->getKey($name));
104     // We unset unconditionally since caller assumes lock is released anyway.
105     unset($this->locks[$name]);
106   }
107
108   /**
109    * {@inheritdoc}
110    */
111   public function releaseAll($lock_id = NULL) {
112     if (empty($lock_id)) {
113       $lock_id = $this->getLockId();
114     }
115
116     foreach ($this->locks as $name => $id) {
117       $key = $this->getKey($name);
118       $value = $this->memcache->get($key);
119
120       if ($value == $lock_id) {
121         $this->memcache->delete($key);
122       }
123     }
124
125     $this->locks = [];
126   }
127
128   /**
129    * Gets a storage key based on the lock name.
130    */
131   protected function getKey($name) {
132     return 'lock:' . $this->bin . ':' . $name;
133   }
134
135 }