extract and fix lock methods
This commit is contained in:
parent
7b0460f23b
commit
192698148b
@ -17,5 +17,4 @@ if (!defined('DC_RC_PATH')) {
|
|||||||
class initActivityReport
|
class initActivityReport
|
||||||
{
|
{
|
||||||
public const ACTIVITY_TABLE_NAME = 'activity';
|
public const ACTIVITY_TABLE_NAME = 'activity';
|
||||||
public const CACHE_DIR_NAME = 'activityreport';
|
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,8 @@ class ActivityReport
|
|||||||
/** @var ActivityReport $instance ActivityReport instance */
|
/** @var ActivityReport $instance ActivityReport instance */
|
||||||
private static $instance;
|
private static $instance;
|
||||||
|
|
||||||
/** @var null|resource $lock File lock for update */
|
/** @var null|string $lock File lock for update */
|
||||||
private $lock = null;
|
private static $lock = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor sets activity main type.
|
* Constructor sets activity main type.
|
||||||
@ -495,75 +495,49 @@ class ActivityReport
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock update.
|
|
||||||
*
|
|
||||||
* Lock a file to see if an update is ongoing.
|
* Lock a file to see if an update is ongoing.
|
||||||
*
|
*
|
||||||
* @return bool The lock success
|
* @return bool True if file is locked
|
||||||
*/
|
*/
|
||||||
public function lockUpdate(): bool
|
public function lockUpdate(): bool
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
# Need flock function
|
|
||||||
if (!function_exists('flock')) {
|
|
||||||
throw new Exception("Can't call php function named flock");
|
|
||||||
}
|
|
||||||
# Cache writable ?
|
# Cache writable ?
|
||||||
if (!is_writable(DC_TPL_CACHE)) {
|
if (!is_writable(DC_TPL_CACHE)) {
|
||||||
throw new Exception("Can't write in cache fodler");
|
throw new Exception("Can't write in cache fodler");
|
||||||
}
|
}
|
||||||
# Set file path
|
# Set file path
|
||||||
$f_md5 = md5((string) dcCore::app()->blog?->id);
|
$f_md5 = md5((string) dcCore::app()->blog?->id);
|
||||||
$cached_file = sprintf(
|
$file = sprintf(
|
||||||
'%s/%s/%s/%s/%s.txt',
|
'%s/%s/%s/%s/%s.txt',
|
||||||
DC_TPL_CACHE,
|
DC_TPL_CACHE,
|
||||||
My::CACHE_DIR_NAME,
|
My::id(),
|
||||||
substr($f_md5, 0, 2),
|
substr($f_md5, 0, 2),
|
||||||
substr($f_md5, 2, 2),
|
substr($f_md5, 2, 2),
|
||||||
$f_md5
|
$f_md5
|
||||||
);
|
);
|
||||||
# Real path
|
|
||||||
$cached_file = (string) Path::real($cached_file, false);
|
$file = Lock::lock($file);
|
||||||
// make dir
|
if (is_null($file) || empty($file)) {
|
||||||
if (!is_dir(dirname($cached_file))) {
|
|
||||||
Files::makeDir(dirname($cached_file), true);
|
|
||||||
}
|
|
||||||
//ake file
|
|
||||||
if (!file_exists($cached_file)) {
|
|
||||||
!$fp = @fopen($cached_file, 'w');
|
|
||||||
if ($fp === false) {
|
|
||||||
throw new Exception("Can't create file");
|
|
||||||
}
|
|
||||||
fwrite($fp, '1', strlen('1'));
|
|
||||||
fclose($fp);
|
|
||||||
}
|
|
||||||
// open file
|
|
||||||
if (!($fp = @fopen($cached_file, 'r+'))) {
|
|
||||||
throw new Exception("Can't open file");
|
|
||||||
}
|
|
||||||
// lock file
|
|
||||||
if (!flock($fp, LOCK_EX | LOCK_NB)) {
|
|
||||||
//throw new Exception("Can't lock file");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->lock = $fp;
|
self::$lock = $file;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
// what ?
|
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unlock update.
|
* Unlock file of update process.
|
||||||
*/
|
*/
|
||||||
public function unlockUpdate(): void
|
public function unlockUpdate(): void
|
||||||
{
|
{
|
||||||
if ($this->lock) {
|
if (!is_null(self::$lock)) {
|
||||||
@fclose($this->lock);
|
Lock::unlock(self::$lock);
|
||||||
$this->lock = null;
|
self::$lock = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
148
src/Lock.php
Normal file
148
src/Lock.php
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* @brief activityReport, a plugin for Dotclear 2
|
||||||
|
*
|
||||||
|
* @package Dotclear
|
||||||
|
* @subpackage Plugin
|
||||||
|
*
|
||||||
|
* @author Jean-Christian Denis and contributors
|
||||||
|
*
|
||||||
|
* @copyright Jean-Christian Denis
|
||||||
|
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Dotclear\Plugin\activityReport;
|
||||||
|
|
||||||
|
use Dotclear\Helper\File\{
|
||||||
|
Files,
|
||||||
|
Path
|
||||||
|
};
|
||||||
|
|
||||||
|
class Lock
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Locked files resource stack.
|
||||||
|
*
|
||||||
|
* @var array<string,resource>
|
||||||
|
*/
|
||||||
|
protected static $lock_stack = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locked files status stack.
|
||||||
|
*
|
||||||
|
* @var array<string,bool>
|
||||||
|
*/
|
||||||
|
protected static $lock_disposable = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last lock attempt error
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected static $lock_error = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock file.
|
||||||
|
*
|
||||||
|
* @param string $file The file path
|
||||||
|
* @param bool $disposable File only use to lock
|
||||||
|
*
|
||||||
|
* @return null|string Clean file path on success, empty string on error, null if already locked
|
||||||
|
*/
|
||||||
|
public static function lock(string $file, bool $disposable = false): ?string
|
||||||
|
{
|
||||||
|
# Real path
|
||||||
|
$file = Path::real($file, false);
|
||||||
|
if (false === $file) {
|
||||||
|
self::$lock_error = __("Can't get file path");
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
# not a dir
|
||||||
|
if (is_dir($file)) {
|
||||||
|
self::$lock_error = __("Can't lock a directory");
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
# already marked as locked
|
||||||
|
if (isset(self::$lock_stack[$file]) || $disposable && file_exists($file)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Need flock function
|
||||||
|
if (!function_exists('flock')) {
|
||||||
|
self::$lock_error = __("Can't call php function named flock");
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make dir
|
||||||
|
if (!is_dir(dirname($file))) {
|
||||||
|
Files::makeDir(dirname($file), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Open new file
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
$resource = @fopen($file, 'w');
|
||||||
|
if ($resource === false) {
|
||||||
|
self::$lock_error = __("Can't create file");
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
fwrite($resource, '1', strlen('1'));
|
||||||
|
//fclose($resource);
|
||||||
|
} else {
|
||||||
|
# Open existsing file
|
||||||
|
$resource = @fopen($file, 'r+');
|
||||||
|
if ($resource === false) {
|
||||||
|
self::$lock_error = __("Can't open file");
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Lock file
|
||||||
|
if (!flock($resource, LOCK_EX | LOCK_NB)) {
|
||||||
|
self::$lock_error = __("Can't lock file");
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$lock_stack[$file] = $resource;
|
||||||
|
self::$lock_disposable[$file] = $disposable;
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlock file.
|
||||||
|
*
|
||||||
|
* @param string $file The file to unlock
|
||||||
|
*/
|
||||||
|
public static function unlock(string $file): void
|
||||||
|
{
|
||||||
|
if (isset(self::$lock_stack[$file])) {
|
||||||
|
fclose(self::$lock_stack[$file]);
|
||||||
|
if (!empty(self::$lock_disposable[$file]) && file_exists($file)) {
|
||||||
|
@unlink($file);
|
||||||
|
}
|
||||||
|
unset(
|
||||||
|
self::$lock_stack[$file],
|
||||||
|
self::$lock_disposable[$file]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last error from lock method.
|
||||||
|
*
|
||||||
|
* @return string The last lock error
|
||||||
|
*/
|
||||||
|
public static function getlastLockError(): string
|
||||||
|
{
|
||||||
|
return self::$lock_error;
|
||||||
|
}
|
||||||
|
}
|
@ -24,9 +24,6 @@ class My
|
|||||||
/** @var string Activity database table name */
|
/** @var string Activity database table name */
|
||||||
public const ACTIVITY_TABLE_NAME = 'activity';
|
public const ACTIVITY_TABLE_NAME = 'activity';
|
||||||
|
|
||||||
/** @var string Cache sub directory name */
|
|
||||||
public const CACHE_DIR_NAME = 'activityreport';
|
|
||||||
|
|
||||||
/** @var int Incremental version by breaking changes */
|
/** @var int Incremental version by breaking changes */
|
||||||
public const COMPATIBILITY_VERSION = 3;
|
public const COMPATIBILITY_VERSION = 3;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user