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  clearstatcache();
65  $time = time() - $this->timeout;
66  $count = 0;
67  foreach($this->find($item,$id,$user ?: '*') as $lock)
68  if(filemtime($lock) < $time) \Rsi\File::unlink($lock); //expired
69  elseif(($user !== false) || (\Rsi\Str::part(basename($lock),$this->keySeperator) != $this->component('user')->id)) $count++;
70  return $count;
71  }
72  /**
73  * Request a lock on an item.
74  * @param string $item Item type.
75  * @param mixed $id ID of the item (empty = lock all items).
76  * @return bool True on success.
77  */
78  public function request($item,$id = null){
79  $this->component('alive')->register($this->_name);
80  clearstatcache(true,$lock = $this->filename($item,$id ?: true));
81  $error = false;
82  try{
83  if(!is_file($lock) && ($this->exists($item,$id ?: true,false) || ($id && $this->exists($item,true)))) $lock = false;
84  else $error = \Rsi\File::write($lock,null,0666) === false;
85  }
86  catch(\Exception $e){
87  if($this->_fred->debug) throw $e;
88  $error = true;
89  }
90  if($lock && ($error || ($this->exists($item,$id) > 1) || ($id && $this->exists($item,true)))){
91  \Rsi\File::unlink($lock);
92  $lock = false;
93  }
94  return $lock && is_file($lock);
95  }
96  /**
97  * Refresh one or multiple lock(s).
98  * @param string $item Item type (empty = refresh all locks for this user).
99  * @param mixed $id ID of the item (empty = refresh all locks for this item type).
100  * @return bool True on success.
101  */
102  public function refresh($item = null,$id = null){
103  $result = count($locks = $this->find($item,$id)) > 0;
104  foreach($locks as $lock)
105  if(!touch($lock) || ($this->exists($item,$id) > 1) || ($id && $this->exists($item,true))){
106  \Rsi\File::unlink($lock);
107  $result = false;
108  }
109  return $result;
110  }
111  /**
112  * Release one or multiple lock(s).
113  * @param string $item Item type (empty = release all locks for this user).
114  * @param mixed $id ID of the item (empty = release all locks for this item type).
115  * @return bool True on success.
116  */
117  public function release($item = null,$id = null){
118  $result = true;
119  foreach($this->find($item,$id) as $lock) $result &= \Rsi\File::unlink($lock);
120  return $result;
121  }
122  /**
123  * Who owns a lock.
124  * @param string $item Item type.
125  * @param mixed $id ID of the item.
126  * @return mixed User ID of the owner (false when not locked).
127  */
128  public function owner($item,$id = null){
129  return ($filenames = $this->find($item,$id,'*') ?: ($id ? $this->find($item,true,'*') : null))
130  ? \Rsi\Str::part(basename(array_pop($filenames)),$this->keySeperator)
131  : false;
132  }
133 
134  protected function getPath(){
135  if(!$this->_path) $this->_path = $this->config('path') ?: \Rsi\File::tempDir();
136  return $this->_path;
137  }
138 
139  protected function getTimeout(){
140  if($this->_timeout === null) $this->_timeout = $this->config('timeout') ?: $this->component('alive')->interval * 120; //minutes -> seconds, and double of that
141  return $this->_timeout;
142  }
143 
144  protected function setTimeout($value){
145  $this->_timeout = $value;
146  }
147 
148 }
Rsi\Fred\Lock\ping
ping()
Ping function.
Definition: Lock.php:16
Rsi
Rsi\Fred\Lock\key
key($item, $id, $user=null)
Generate a lock key.
Definition: Lock.php:27
Rsi\Fred\Lock\refresh
refresh($item=null, $id=null)
Refresh one or multiple lock(s).
Definition: Lock.php:102
Rsi\Fred\Lock\$multiIndicator
$multiIndicator
String to indicate a lock for all ID's of an item type.
Definition: Lock.php:8
Rsi\Fred\Lock\filename
filename($item, $id, $user=null)
Filename for a lock file.
Definition: Lock.php:37
Rsi\Fred\Lock\find
find($item=null, $id=null, $user=null)
Find lock files.
Definition: Lock.php:47
Rsi\Fred\Component\filemtime
filemtime($filename)
Filemtime with session cache.
Definition: Component.php:66
Rsi\Fred\Lock\purge
purge()
Purge old locks.
Definition: Lock.php:53
Rsi\Fred\Lock\getTimeout
getTimeout()
Definition: Lock.php:139
Rsi\Fred\Lock\getPath
getPath()
Definition: Lock.php:134
Rsi\Fred\Lock\release
release($item=null, $id=null)
Release one or multiple lock(s).
Definition: Lock.php:117
Rsi\Fred\Lock\$ext
$ext
Extension for lock file.
Definition: Lock.php:10
Rsi\Fred\Lock\setTimeout
setTimeout($value)
Definition: Lock.php:144
Rsi\Fred\Component
Basic component class.
Definition: Component.php:8
Rsi\Fred\Lock\$_timeout
$_timeout
Number of seconds after which a lock expires (empty = use double of.
Definition: Lock.php:12
Rsi\Fred\Lock\$_path
$_path
Path to store the lock files (temp path if empty).
Definition: Lock.php:14
Rsi\Fred\Lock\request
request($item, $id=null)
Request a lock on an item.
Definition: Lock.php:78
Rsi\Fred\Component\component
component($name)
Get a component (local or default).
Definition: Component.php:81
Rsi\Fred\Component\config
config($key, $default=null)
Retrieve a config value.
Definition: Component.php:53
Rsi\Fred\Lock\owner
owner($item, $id=null)
Who owns a lock.
Definition: Lock.php:128
Rsi\Fred\Lock\exists
exists($item, $id=null, $user=null)
Check wether a lock exists.
Definition: Lock.php:63
Rsi\Fred\Lock
Definition: Lock.php:5
Rsi\Fred\Lock\$keySeperator
$keySeperator
String to seperate key info with (may not be present in item type or ID).
Definition: Lock.php:7
Rsi\Fred\Exception
Definition: Exception.php:5
Rsi\Fred
Definition: Alive.php:3