From 4f6b0ae2dabbbe8c07a017bc7f4b5b50482d5bb9 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 26 Jul 2007 09:22:28 +0000 Subject: [PATCH] fixed not working semaphore in asyncservice (we are not supporting table locks anymore / since 1.2) --- phpgwapi/cron/asyncservices.php | 41 +++++++++-------------- phpgwapi/inc/class.asyncservice.inc.php | 44 ++++++++++--------------- 2 files changed, 33 insertions(+), 52 deletions(-) diff --git a/phpgwapi/cron/asyncservices.php b/phpgwapi/cron/asyncservices.php index c70cdd592f..e2e68ee6bd 100644 --- a/phpgwapi/cron/asyncservices.php +++ b/phpgwapi/cron/asyncservices.php @@ -1,27 +1,17 @@ #!/usr/bin/php -q * - * Class for creating cron-job like timed calls of eGroupWare methods * - * -------------------------------------------------------------------------* - * This library is part of the eGroupWare API * - * http://www.egroupware.org/ * - * ------------------------------------------------------------------------ * - * This library is free software; you can redistribute it and/or modify it * - * under the terms of the GNU Lesser General Public License as published by * - * the Free Software Foundation; either version 2.1 of the License, * - * or any later version. * - * This library 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 Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License * - * along with this library; if not, write to the Free Software Foundation, * - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - \**************************************************************************/ - - /* $Id$ */ +/** + * API - Timed Asynchron Services for eGroupWare + * + * @link http://www.egroupware.org + * @author Ralf Becker + * @copyright Ralf Becker + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package api + * @access public + * @version $Id$ + */ $_GET['domain'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : 'default'; $path_to_egroupware = realpath(dirname(__FILE__).'/../..'); // need to be adapted if this script is moved somewhere else @@ -68,11 +58,12 @@ exit(1); } - include(PHPGW_API_INC.'/functions.inc.php'); + include(EGW_API_INC.'/functions.inc.php'); $num = ExecMethod('phpgwapi.asyncservice.check_run','crontab'); - $msg = date('Y/m/d H:i:s ').$_GET['domain'].': '.($num ? "$num job(s) executed" : 'Nothing to execute')."\n\n"; + $msg = date('Y/m/d H:i:s ').$_GET['domain'].': '.($num === false ? 'An error occured: can not obtain semaphore!' : + ($num ? "$num job(s) executed" : 'Nothing to execute'))."\n\n"; // if the following comment got removed, you will get an email from cron for every check performed (*nix only) //echo $msg; @@ -82,4 +73,4 @@ fwrite($f,$msg); fclose($f); } - $GLOBALS['egw']->common->phpgw_exit(); + $GLOBALS['egw']->common->egw_exit(); diff --git a/phpgwapi/inc/class.asyncservice.inc.php b/phpgwapi/inc/class.asyncservice.inc.php index 26767012c2..d0b0c96dca 100644 --- a/phpgwapi/inc/class.asyncservice.inc.php +++ b/phpgwapi/inc/class.asyncservice.inc.php @@ -320,7 +320,7 @@ class asyncservice } /** - * checks when the last check_run was run or set the run-semaphore if $semaphore == True + * checks when the last check_run was run or set the run-semaphore (async_next != 0) if $semaphore == True * * @param boolean $semaphore if False only check, if true try to set/release the semaphore * @param boolean $release if $semaphore == True, tells if we should set or release the semaphore @@ -330,13 +330,6 @@ class asyncservice function last_check_run($semaphore=False,$release=False,$run_by='') { //echo "

last_check_run(semaphore=".($semaphore?'True':'False').",release=".($release?'True':'False').")

\n"; - if ($semaphore) - { - $this->db->lock($this->db_table,'write'); // this will block til we get exclusive access to the table - - @set_time_limit(0); // dont stop for an execution-time-limit - ignore_user_abort(True); - } if ($exists = $this->read('##last-check-run##')) { list(,$last_run) = each($exists); @@ -347,26 +340,21 @@ class asyncservice { return $last_run['data']; } - elseif (!$release && !$last_run['data']['end'] && $last_run['data']['start'] > time()-600) - { - // already one instance running (started not more then 10min ago, else we ignore it) - - $this->db->unlock(); // unlock the table again - - //echo "

An other instance is running !!!

\n"; - return False; - } - // no other instance runs ==> we should run - // + + $where = array(); if ($release) { + $last_run['next'] = 0; $last_run['data']['end'] = time(); } else { + @set_time_limit(0); // dont stop for an execution-time-limit + ignore_user_abort(True); + $last_run = array( 'id' => '##last-check-run##', - 'next' => 0, + 'next' => time(), 'times' => array(), 'method' => 'none', 'data' => array( @@ -375,13 +363,12 @@ class asyncservice 'end' => 0 ) ); + // as the async_next column is used as a semaphore we only update it, + // if it is 0 (semaphore released) or older then 10min to recover from failed or crashed attempts + if ($exists) $where = array('async_next=0 OR async_next<'.time()-600); } //echo "last_run=
"; print_r($last_run); echo "
\n"; - $this->write($last_run,!!$exits); - - $this->db->unlock(); - - return True; + return $this->write($last_run,!!$exits,$where) > 0; } /** @@ -448,7 +435,7 @@ class asyncservice } $this->last_check_run(True,True,$run_by); // release semaphore - return $jobs ? count($jobs) : False; + return $jobs ? count($jobs) : 0; } /** @@ -502,8 +489,10 @@ class asyncservice * * @param array $job db-row as array * @param boolean $exits if True, we do an update, else we check if update or insert necesary + * @param array $where additional where statemetn to update only if a certain condition is met, used for the semaphore + * @return int affected rows, cat be 0 if an additional where statement is given */ - function write($job,$exists = False) + function write($job,$exists = False,$where=array()) { $data = array( 'async_next' => $job['next'], @@ -520,6 +509,7 @@ class asyncservice { $this->db->insert($this->db_table,$data,array('async_id' => $job['id']),__LINE__,__FILE__); } + return $this->db->affected_rows(); } /**