PHP Classes

File: src/CommonAbstract.php

Recommend this page to a friend!
  Classes of Joseluis Laso  >  Asynchronous Long Server Tasks  >  src/CommonAbstract.php  >  Download  
File: src/CommonAbstract.php
Role: Class source
Content type: text/plain
Description: Class source
Class: Asynchronous Long Server Tasks
Start background tasks and query progress status
Author: By
Last change: fixing locking of status file in order to prevent concurrent R/W
Date: 7 years ago
Size: 3,753 bytes
 

Contents

Class file image Download
<?php

namespace JLaso\ToolsLib;

/**
 * Both main classes must extends from this one, in order to have in one place all the stuff related with
 * the status control file
 */
abstract class CommonAbstract
{
    const
STATUS_FILE = "status.pid";

   
/** @var string */
   
protected $dataFolder;
   
/** @var bool */
   
protected $debug;
   
/** @var string */
   
protected $file;
   
/** @var string */
   
protected $task;
   
/** @var string */
   
protected $oldFile;

    protected
$handle = null;

    const
DONT_UNLOCK = true;

   
/**
     * CommonAbstract constructor.
     * @param string $task
     * @param bool $debug
     * @internal param string $dataFolder
     */
   
public function __construct($task, $debug = false)
    {
       
$this->task = $task;
       
$this->dataFolder = dirname(dirname(__FILE__)).'/data';
       
$this->debug = $debug;
        if (!
file_exists($this->dataFolder)) {
           
mkdir ($this->dataFolder, 0777);
        }
       
$this->file = $this->dataFolder.'/'.$task.'-'.self::STATUS_FILE;
       
$this->oldFile = $this->dataFolder.'/'.$task.'-'.self::STATUS_FILE.'.old';
    }

   
/**
     * @return string
     */
   
public function getStatusFile()
    {
        return
$this->file;
    }

   
/**
     * @return bool
     */
   
public function existsStatusFile()
    {
        return
file_exists($this->file);
    }

   
/**
     * the mechanism of control of the task process is the status file, to notice to subsequents calls that
     * the process is started already have to create this file, and on it is written the status of the
     * different tasks
     */
   
public function touchStatusFile()
    {
        if (
file_exists($this->oldFile)){
           
rename($this->oldFile, $this->file);
        }else {
           
touch($this->file);
        }
       
chmod($this->file, 0777);
    }

   
/**
     * get (in raw) the content of the status file
     *
     * @return string
     */
   
public function getStatusFileContent($dontUnlock = false)
    {
        if (
$this->handle == null){
           
$this->lockStatusFile(true);
        }
       
$content = fread($this->handle, filesize($this->file));
        if (!
$dontUnlock){
           
$this->unlockStatusFile();
        }
        return
$content;
    }

    public function
lockStatusFile($read = true)
    {
       
$this->handle = fopen($this->file, "r+");
        while (!
flock($this->handle, LOCK_EX | LOCK_NB)){ usleep(rand($read ? 100 : 1000,$read ? 500 :1500)); }
    }

    public function
unlockStatusFile()
    {
       
flock($this->handle, LOCK_UN);
       
fclose($this->handle);
       
$this->handle = null;
    }

   
/**
     * saves into the status file the content passed
     *
     * @param string $content
     */
   
public function putStatusFileContent($content)
    {
        if (
$this->handle == null){
           
$this->lockStatusFile();
        }
       
ftruncate ($this->handle, 0);
       
fwrite($this->handle, $content);
       
fflush($this->handle);
       
usleep(1000);
       
$this->unlockStatusFile();
    }

   
/**
     * when the main process finish have to call this method in order to allow subsequents calls,
     * be in mind that the status file is the mechanism that allow this system to know if the task
     * large process is still running or not
     */
   
public function freeStatusFile()
    {
       
unlink($this->file);
    }

   
/**
     * In the even the main process hangs it must call this in order to allow next process calls.
     */
   
public function hangOn()
    {
        if (
$this->existsStatusFile()) {
            @
unlink($this->oldFile);
           
rename($this->file, $this->oldFile);
           
chmod($this->file, 0777);
        }
    }
}