FRED™  3.0
FRED™: Framework for Rapid and Easy Development
Lock.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Rsi\Fred;
4 
5 class Lock extends Component{
6 
7  public $keySeperator = '_'; //!< String to seperate key info with (may not be present in item type or ID).
8  public $multiIndicator = '-----'; //!< String to indicate a lock for all ID's of an item type.
9 
10  public $ext = '.lock'; //!< Extension for lock file.
11 
12  protected $_timeout = null; //!< Number of seconds after which a lock expires (empty = use double of
13  // Rsi\Fred\Alive::interval).
14  protected $_path = null; //!< Path to store the lock files (temp path if empty).
15 
16  public function ping(){
17  $this->refresh();
18  $this->purge();
19  }
20  /**
21  * Generate a lock key.
22  * @param string $item Item type.
23  * @param mixed $id Id of the item.
24  * @param mixed $user User ID of the owner (current user when empty).
25  * @return string
26  */
27  protected function key($item,$id,$user = null){
28  return implode($this->keySeperator,array_merge([$user ?: $this->component('user')->id,$item],is_array($id) ? $id : [$id]));
29  }
30  /**
31  * Filename for a lock file.
32  * @param string $item Item type.
33  * @param mixed $id Id of the item (true = all ID's).
34  * @param mixed $user User ID of the owner (current user when empty).
35  * @return string
36  */
37  protected function filename($item,$id,$user = null){
38  return $this->path . $this->key($item,$id === true ? $this->multiIndicator : $id,$user) . $this->ext;
39  }
40  /**
41  * Find lock files.
42  * @param string $item Item type (empty = return all locks for this user).
43  * @param mixed $id ID of the item (empty = return all locks for this item type).
44  * @param mixed $user User ID of the owner (current user when empty).
45  * @return array Lock filenames.
46  */
47  protected function find($item = null,$id = null,$user = null){
48  return glob($this->filename($item ?: '*',$id ?: '*',$user),GLOB_NOSORT);
49  }
50  /**
51  * Purge old locks.
52  */
53  public function purge(){
54  $this->exists('*');
55  }
56  /**
57  * Check wether a lock exists.
58  * @param string $item Item type.
59  * @param mixed $id ID of the item (empty = check for all items lock).
60  * @param mixed $user User ID of the owner (all users when empty; use false to exclude own locks).
61  * @return int Number of active locks (should be 0 or 1, but in a race condition it could be more).
62  */
63  public function exists($item,$id = null,$user = null){
64  $time = time() - $this->timeout;
65  $count = 0;
66  foreach($this->find($item,$id,$user ?: '*') as $lock)
67  if(filemtime($lock) < $time) \Rsi\File::unlink($lock); //expired
68  elseif(($user !== false) || (\Rsi\Str::part(basename($lock),$this->keySeperator) != $this->component('user')->id)) $count++;
69  return $count;
70  }
71  /**
72  * Request a lock on an item.
73  * @param string $item Item type.
74  * @param mixed $id ID of the item (empty = lock all items).
75  * @return bool True on success.
76  */
77  public function request($item,$id = null){
78  $this->component('alive')->register($this->_name);
79  $lock = $this->filename($item,$id ?: true);
80  $error = false;
81  try{
82  if(!is_file($lock) && ($this->exists($item,$id ?: true,false) || ($id && $this->exists($item,true)))) $lock = false;
83  else $error = \Rsi\File::write($lock,null,0666) === false;
84  }
85  catch(\Exception $e){
86  if($this->_fred->debug) throw $e;
87  $error = true;
88  }
89  if($lock && ($error || ($this->exists($item,$id) > 1) || ($id && $this->exists($item,true)))){
90  \Rsi\File::unlink($lock);
91  $lock = false;
92  }
93  return $lock && is_file($lock);
94  }
95  /**
96  * Refresh one or multiple lock(s).
97  * @param string $item Item type (empty = refresh all locks for this user).
98  * @param mixed $id ID of the item (empty = refresh all locks for this item type).
99  * @return bool True on success.
100  */
101  public function refresh($item = null,$id = null){
102  $result = count($locks = $this->find($item,$id)) > 0;
103  foreach($locks as $lock)
104  if(!touch($lock) || ($this->exists($item,$id) > 1) || ($id && $this->exists($item,true))){
105  \Rsi\File::unlink($lock);
106  $result = false;
107  }
108  return $result;
109  }
110  /**
111  * Release one or multiple lock(s).
112  * @param string $item Item type (empty = release all locks for this user).
113  * @param mixed $id ID of the item (empty = release all locks for this item type).
114  * @return bool True on success.
115  */
116  public function release($item = null,$id = null){
117  $result = true;
118  foreach($this->find($item,$id) as $lock) $result &= \Rsi\File::unlink($lock);
119  return $result;
120  }
121  /**
122  * Who owns a lock.
123  * @param string $item Item type.
124  * @param mixed $id ID of the item.
125  * @return mixed User ID of the owner (false when not locked).
126  */
127  public function owner($item,$id = null){
128  return ($filenames = $this->find($item,$id,'*') ?: ($id ? $this->find($item,true,'*') : null))
129  ? \Rsi\Str::part(basename(array_pop($filenames)),$this->keySeperator)
130  : false;
131  }
132 
133  protected function getPath(){
134  if(!$this->_path) $this->_path = $this->config('path') ?: \Rsi\File::tempDir();
135  return $this->_path;
136  }
137 
138  protected function getTimeout(){
139  if($this->_timeout === null) $this->_timeout = $this->config('timeout') ?: $this->component('alive')->interval * 120; //minutes - >seconds, and double of that
140  return $this->_timeout;
141  }
142 
143 }
$ext
Extension for lock file.
Definition: Lock.php:10
exists($item, $id=null, $user=null)
Check wether a lock exists.
Definition: Lock.php:63
find($item=null, $id=null, $user=null)
Find lock files.
Definition: Lock.php:47
config($key, $default=null)
Retrieve a config value.
Definition: Component.php:53
key($item, $id, $user=null)
Generate a lock key.
Definition: Lock.php:27
refresh($item=null, $id=null)
Refresh one or multiple lock(s).
Definition: Lock.php:101
filemtime($filename)
Filemtime with session cache.
Definition: Component.php:66
owner($item, $id=null)
Who owns a lock.
Definition: Lock.php:127
Basic component class.
Definition: Component.php:8
$multiIndicator
String to indicate a lock for all ID&#39;s of an item type.
Definition: Lock.php:8
$keySeperator
String to seperate key info with (may not be present in item type or ID).
Definition: Lock.php:7
release($item=null, $id=null)
Release one or multiple lock(s).
Definition: Lock.php:116
request($item, $id=null)
Request a lock on an item.
Definition: Lock.php:77
$_timeout
Number of seconds after which a lock expires (empty = use double of.
Definition: Lock.php:12
purge()
Purge old locks.
Definition: Lock.php:53
$_path
Path to store the lock files (temp path if empty).
Definition: Lock.php:14
getTimeout()
Definition: Lock.php:138
component($name)
Get a component (local or default).
Definition: Component.php:80
filename($item, $id, $user=null)
Filename for a lock file.
Definition: Lock.php:37