135 lines
4.1 KiB
PHP
135 lines
4.1 KiB
PHP
<?php
|
|
|
|
/** DomFramework
|
|
* @package domframework
|
|
* @author Dominique Fournier <dominique@fournier38.fr>
|
|
* @license BSD
|
|
*/
|
|
|
|
namespace Domframework;
|
|
|
|
/** The lock management of files
|
|
*/
|
|
class Lockfile
|
|
{
|
|
/** The Exclusive lock file */
|
|
public $storagelock = "./data/lockfile.lock";
|
|
/** The Read-Only lock file */
|
|
private $storagelockRO = false;
|
|
|
|
/** This function lock the storage file until all is written.
|
|
If an other processus want to lock, it hang until the lock is released */
|
|
public function lockRW()
|
|
{
|
|
if (!is_dir(dirname($this->storagelock))) {
|
|
@mkdir(dirname($this->storagelock));
|
|
}
|
|
if (!is_dir(dirname($this->storagelock))) {
|
|
throw new \Exception(
|
|
"Can't create '" . dirname($this->storagelock) .
|
|
"' directory for lockfile",
|
|
500
|
|
);
|
|
}
|
|
$lockid = uniqid() . '_' . md5(mt_rand());
|
|
$startTime = microtime(true);
|
|
// Stale lock : 60s old min
|
|
if (
|
|
file_exists($this->storagelock) &&
|
|
filemtime($this->storagelock) < time() - 60
|
|
) {
|
|
// TODO : Log the Stale lock removing
|
|
unlink($this->storagelock);
|
|
}
|
|
|
|
// Wait RW Lock
|
|
while (1) {
|
|
while (file_exists($this->storagelock)) {
|
|
usleep(100000);
|
|
clearstatcache(true, $this->storagelock);
|
|
if (microtime(true) > $startTime + 10) {
|
|
throw new \Exception(
|
|
"Can't have the authorization lock RW in 10s",
|
|
500
|
|
);
|
|
}
|
|
}
|
|
|
|
file_put_contents($this->storagelock, $lockid, FILE_APPEND);
|
|
clearstatcache(true, $this->storagelock);
|
|
$cnt = file_get_contents($this->storagelock);
|
|
if (substr($cnt, 0, strlen($lockid)) === $lockid) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Wait all the RO lock to go away
|
|
$startTime = microtime(true);
|
|
while (count(glob($this->storagelock . "-*")) > 0) {
|
|
usleep(100000);
|
|
if (microtime(true) > $startTime + 10) {
|
|
throw new \Exception(
|
|
"Can't have the authorization lock RO in 10s",
|
|
500
|
|
);
|
|
}
|
|
}
|
|
|
|
// I have the lock and no RO lock !
|
|
return true;
|
|
}
|
|
|
|
/** This function lock the storage in share mode (to read the file without
|
|
modification at the same time) */
|
|
public function lockRO()
|
|
{
|
|
if (!is_dir(dirname($this->storagelock))) {
|
|
@mkdir(dirname($this->storagelock));
|
|
}
|
|
if (!is_dir(dirname($this->storagelock))) {
|
|
throw new \Exception(
|
|
"Can't create '" . dirname($this->storagelock) . "'",
|
|
500
|
|
);
|
|
}
|
|
$lockid = uniqid() . '_' . md5(mt_rand());
|
|
// Stale lock : 60s old min
|
|
if (
|
|
file_exists($this->storagelock) &&
|
|
filemtime($this->storagelock) < time() - 60
|
|
) {
|
|
// TODO : Log the Stale lock removing
|
|
unlink($this->storagelock);
|
|
}
|
|
|
|
// wait the removing of lockRW
|
|
$startTime = microtime(true);
|
|
while (file_exists($this->storagelock)) {
|
|
usleep(100000);
|
|
clearstatcache(true, $this->storagelock);
|
|
if (microtime(true) > $startTime + 10) {
|
|
throw new \Exception("Can't have the authorization lock in 10s", 500);
|
|
}
|
|
}
|
|
|
|
touch($this->storagelock . "-" . $lockid);
|
|
$this->storagelockRO = $this->storagelock . "-" . $lockid;
|
|
}
|
|
|
|
/** This function unlock RW the storage file */
|
|
public function unlockRW()
|
|
{
|
|
if (file_exists($this->storagelock)) {
|
|
unlink($this->storagelock);
|
|
}
|
|
}
|
|
|
|
/** This function unlock RO the storage file */
|
|
public function unlockRO()
|
|
{
|
|
if ($this->storagelockRO !== false && file_exists($this->storagelockRO)) {
|
|
unlink($this->storagelockRO);
|
|
}
|
|
}
|
|
}
|