Documentation is available at lockfile-defs.php
- <?php
- /* ******************************************************************** */
- /* CATALYST PHP Source Code */
- /* -------------------------------------------------------------------- */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2 of the License, or */
- /* (at your option) any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to: */
- /* The Free Software Foundation, Inc., 59 Temple Place, Suite 330, */
- /* Boston, MA 02111-1307 USA */
- /* -------------------------------------------------------------------- */
- /* */
- /* Filename: lockfile-defs.php */
- /* Author: Paul Waite */
- /* Description: Provides a lockfile facility for processes which */
- /* require them. Handles creating and checking lockfiles */
- /* and removing if processes are defunct etc. */
- /* */
- /* ******************************************************************** */
- /** @package file */
- include_once("file-defs.php");
- // ----------------------------------------------------------------------
- // Lockfile error codes..
- /** Lockfile created ok */
- ("LCK_E_OK", 0);
- /** Lockfile */
- ("LCK_E_CREFAIL", 100);
- /** Lockfile process was killed */
- ("LCK_E_KILLED", 101);
- /** Lockfile process was killed with -9 */
- ("LCK_E_KILLED9", 102);
- /** Lockfile process could not be killed */
- ("LCK_E_IMMORTAL", 103);
- /** Lockfile is orphaned (no associated process) */
- ("LCK_E_ORPHAN", 104);
- /** Lockfile was frozen */
- ("LCK_E_FROZEN", 105);
- /** Lockfile could not be read */
- ("LCK_E_READFAIL", 106);
- /** Some error messages which can be associated with the codes. */
- = array(
- LCK_E_OK => "No error",
- LCK_E_CREFAIL => "Failed to create lockfile",
- LCK_E_KILLED => "Process killed",
- LCK_E_KILLED9 => "Process killed (-9)",
- LCK_E_IMMORTAL => "Process is immortal",
- LCK_E_ORPHAN => "Orphaned lockfile removed",
- LCK_E_FROZEN => "Process frozen",
- LCK_E_READFAIL => "Failed to read lockfile"
- );
- // ----------------------------------------------------------------------
- /**
- * A class to handle a lockfile for a running process. The idea is you
- * create one of these for a process each time you run it. If the lockfile
- * already exists, then
- * @package file
- */
- class lockfile {
- /** Name of the lockfile to create */
- var $lockfilename = "";
- /** Name of freeze lockfile to create (internal) */
- var $freezefilename = "";
- /** Process ID of process lockfile is for */
- var $pid = "";
- /** Lockfile age at which we should assume process is hung */
- var $killsecs = 0;
- /** Lockfile age at which we should stop trying to kill hung process */
- var $freezesecs = 0;
- /** Minutes process has been locked for */
- var $lock_mins = 0;
- /** Latest error message */
- var $messages = "";
- /** Latest error code */
- var $errorcode = 0;
- /** True if the lockfile exists */
- var $exists = false;
- /** True if the freeze lockfile exists */
- var $frozen = false;
- // ....................................................................
- /**
- * Make a new lockfile handler object.
- * @param string $lockfilename Name of the lockfile
- * @param string $lockfiledir Directory to create lockfile in
- * @param integer $pid Optional process ID (defaults to current pid)
- */
- function lockfile($lockfilename="", $lockfiledir="/tmp", $pid="") {
- if ($lockfilename == "") {
- $lockfilename = unique_filename("monitor", "LCK");
- }
- $this->lockfilename = $lockfiledir . "/" . $lockfilename;
- $this->freezefilename = $lockfiledir . "/" . $lockfilename . ".ERR";
- if ($pid == "") {
- $pid = posix_getpid();
- }
- $this->pid = $pid;
- // Set lockfile statuses..
- $this->exists = file_exists($this->lockfilename);
- $this->frozen = file_exists($this->freezefilename);
- } // lockfile
- // ....................................................................
- /**
- * Set the time limits. Some commonsense has to be applied here. You
- * should pick times, in mins, which are sensible according to how
- * frequently you are going to be checking the lockfiles. If, for
- * example you pick killmins=5 and freezemins=10 and only run this
- * every hour, then you will never give it chance to kill a hung
- * process between the 5 and 10 mins mark. A better choice for that
- * would be killmins=30 freezemins=130.
- * @param integer $killmins Time after which process is assumed hung
- * @param integer $freezemins Time after which we stop trying to kill it
- */
- function set_timelimits($killmins=0, $freezemins=0) {
- $this->killsecs = $killmins * 60;
- $this->freezesecs = $freezemins * 60;
- } // set_timelimits
- // ....................................................................
- /** Internal method to actually create the lockfile.
- * @return boolean True if the lockfile was created
- * @access private
- */
- function create_lockfile() {
- $LCK = new quickfile($this->lockfilename, $this->pid);
- $this->exists = $LCK->created;
- if (!$this->exists) {
- $this->error = LCK_E_CREFAIL;
- }
- return $this->exists;
- } // create_lockfile
- // ....................................................................
- /**
- * Return any lockfile error message
- * @return string Any error message associated with the lockfile
- */
- function errormsg() {
- global $LCKerrormsg;
- $msg = "";
- if (isset($LCKerrormsg[$this->errorcode])) {
- $msg = $LCKerrormsg[$this->errorcode]
- . " [" . $this->lock_mins . "mins]";
- if ($this->pid != "") {
- $msg .= " (pid=" . $this->pid . ")";
- }
- }
- return $msg;
- } // errormsg
- // ....................................................................
- /**
- * Create the lockfile. We only do this, obviously, if it doesn't
- * already exist. If it DOES exist, then we make a lot of checks. If
- * time-limits are set we possibly try to kill the process and remove
- * the lockfile before creating our new one.
- * If we created a lockfile then we return true, and this measn the
- * calling process should feel free to run. If we return false, then
- * either the lock is valid, or an error condition is present, and
- * the calling process should about/exit without running.
- * @return boolean True if lockfile was created successfully, else false.
- */
- function create() {
- $lockstatus = false;
- if (!$this->exists) {
- // Create brand new lockfile..
- $lockstatus = $this->create_lockfile();
- }
- else {
- // Lockfile exists, check it out..
- $LCK = new inputfile($this->lockfilename);
- if ($LCK->opened) {
- $this->pid = $LCK->readln();
- $LCK->closefile();
- $ts_locked = filemtime($this->lockfilename);
- $lockedfor = time() - $ts_locked;
- $this->lock_mins = floor($lockedfor / 60);
- // Are we in the killing zone?...
- if ($this->killsecs > 0 && $lockedfor >= $this->killsecs && $lockedfor < $this->freezesecs ) {
- // Check if process exists and kill if so..
- if ($this->pid != "") {
- $ps = `ps --no-headers -p $this->pid`;
- if (trim($ps) != "") {
- exec("kill $this->pid");
- sleep(3);
- // Was it killed?...
- $ps = `ps --no-headers -p $this->pid`;
- if (trim($ps) == "") {
- $this->errorcode = LCK_E_KILLED;
- if (file_exists($this->lockfilename)) {
- unlink($this->lockfilename);
- }
- // Try to create the lockfile now..
- $lockstatus = $this->create_lockfile();
- }
- else {
- exec("kill -9 $this->pid");
- sleep(3);
- // Was it killed with extreme predjudice?...
- $ps = `ps --no-headers -p $this->pid`;
- if (trim($ps) == "") {
- $this->errorcode = LCK_E_KILLED9;
- if (file_exists($this->lockfilename)) {
- unlink($this->lockfilename);
- }
- // Try to create the lockfile now..
- $lockstatus = $this->create_lockfile();
- }
- else {
- $this->errorcode = LCK_E_IMMORTAL;
- $lockstatus = false;
- }
- }
- }
- else {
- // Remove orphaned lockfile..
- if (unlink($this->lockfilename)) {
- $this->errorcode = LCK_E_ORPHAN;
- }
- // Try to create the lockfile now..
- $lockstatus = $this->create_lockfile();
- }
- }
- }
- // Are we at the end of our patience?...
- elseif ($this->freezesecs > 0 && $lockedfor >= $this->freezesecs) {
- if (!$this->frozen) {
- $ERR = new quickfile($this->freezefilename);
- $this->errorcode = LCK_E_FROZEN;
- $this->frozen = true;
- $lockstatus = false;
- }
- }
- }
- else {
- // A rather unexpected error, but possible if somebody
- // messes with file permissions for example..
- $this->errorcode = LCK_E_READFAIL;
- }
- }
- // Return status. If true then we created the lockfile and
- // the calling process can go ahead. If false then either the
- // lockfile is present, or an error occurred, so the calling
- // process should not go ahead.
- return $lockstatus;
- } // create
- // ....................................................................
- /**
- * Remove the lockfile. Can't do this if the lock is frozen, which
- * is deemed to require manual intervention.
- * @return boolean True if the lock was removed successfully.
- */
- function remove() {
- $res = false;
- if ($this->exists) {
- if (!$this->frozen) {
- $res = unlink($this->lockfilename);
- }
- }
- else {
- // Already removed somehow..
- $res = true;
- }
- return $res;
- } // remove
- } // lockfile class
- // ----------------------------------------------------------------------
- ?>
Documentation generated by phpDocumentor 1.3.0RC3