* @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); } }