summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/user_ldap/appinfo/app.php2
-rw-r--r--apps/user_ldap/lib/jobs.php19
-rw-r--r--cron.php109
-rw-r--r--db_structure.xml30
-rw-r--r--lib/backgroundjob/job.php49
-rw-r--r--lib/backgroundjob/joblist.php172
-rw-r--r--lib/backgroundjob/legacy/queuedjob.php18
-rw-r--r--lib/backgroundjob/legacy/regularjob.php15
-rw-r--r--lib/backgroundjob/queuedjob.php28
-rw-r--r--lib/backgroundjob/queuedtask.php105
-rw-r--r--lib/backgroundjob/regulartask.php52
-rw-r--r--lib/backgroundjob/timedjob.php41
-rw-r--r--lib/backgroundjob/worker.php118
-rw-r--r--lib/base.php12
-rw-r--r--lib/cache/fileglobalgc.php8
-rw-r--r--lib/public/backgroundjob.php169
-rwxr-xr-xlib/util.php2
-rw-r--r--tests/lib/backgroundjob/dummyjoblist.php131
-rw-r--r--tests/lib/backgroundjob/queuedjob.php42
-rw-r--r--tests/lib/backgroundjob/timedjob.php68
20 files changed, 773 insertions, 417 deletions
diff --git a/apps/user_ldap/appinfo/app.php b/apps/user_ldap/appinfo/app.php
index 81eaa0404b7..593e846bc03 100644
--- a/apps/user_ldap/appinfo/app.php
+++ b/apps/user_ldap/appinfo/app.php
@@ -49,7 +49,7 @@ $entry = array(
'name' => 'LDAP'
);
-OCP\Backgroundjob::addRegularTask('OCA\user_ldap\lib\Jobs', 'updateGroups');
+OCP\Backgroundjob::registerJob('OCA\user_ldap\lib\Jobs');
if(OCP\App::isEnabled('user_webdavauth')) {
OCP\Util::writeLog('user_ldap',
'user_ldap and user_webdavauth are incompatible. You may experience unexpected behaviour',
diff --git a/apps/user_ldap/lib/jobs.php b/apps/user_ldap/lib/jobs.php
index 094d11db3d5..60ecc0da33d 100644
--- a/apps/user_ldap/lib/jobs.php
+++ b/apps/user_ldap/lib/jobs.php
@@ -23,20 +23,22 @@
namespace OCA\user_ldap\lib;
-class Jobs {
+class Jobs extends \OC\BackgroundJob\TimedJob {
static private $groupsFromDB;
static private $groupBE;
static private $connector;
+ public function __construct(){
+ $this->interval = self::getRefreshInterval();
+ }
+
+ public function run($argument){
+ Jobs::updateGroups();
+ }
+
static public function updateGroups() {
\OCP\Util::writeLog('user_ldap', 'Run background job "updateGroups"', \OCP\Util::DEBUG);
- $lastUpdate = \OCP\Config::getAppValue('user_ldap', 'bgjUpdateGroupsLastRun', 0);
- if((time() - $lastUpdate) < self::getRefreshInterval()) {
- \OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – last run too fresh, aborting.', \OCP\Util::DEBUG);
- //komm runter Werner die Maurer geben ein aus
- return;
- }
$knownGroups = array_keys(self::getKnownGroups());
$actualGroups = self::getGroupBE()->getGroups();
@@ -45,7 +47,6 @@ class Jobs {
\OCP\Util::writeLog('user_ldap',
'bgJ "updateGroups" – groups do not seem to be configured properly, aborting.',
\OCP\Util::INFO);
- \OCP\Config::setAppValue('user_ldap', 'bgjUpdateGroupsLastRun', time());
return;
}
@@ -53,8 +54,6 @@ class Jobs {
self::handleCreatedGroups(array_diff($actualGroups, $knownGroups));
self::handleRemovedGroups(array_diff($knownGroups, $actualGroups));
- \OCP\Config::setAppValue('user_ldap', 'bgjUpdateGroupsLastRun', time());
-
\OCP\Util::writeLog('user_ldap', 'bgJ "updateGroups" – Finished.', \OCP\Util::DEBUG);
}
diff --git a/cron.php b/cron.php
index 69bfed8d056..95cedf8bf4c 100644
--- a/cron.php
+++ b/cron.php
@@ -1,24 +1,24 @@
<?php
/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 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 AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Jakob Sack
+ * @copyright 2012 Jakob Sack owncloud@jakobsack.de
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
// Unfortunately we need this class for shutdown function
class TemporaryCronClass {
@@ -30,17 +30,16 @@ class TemporaryCronClass {
// We use this function to handle (unexpected) shutdowns
function handleUnexpectedShutdown() {
// Delete lockfile
- if( !TemporaryCronClass::$keeplock && file_exists( TemporaryCronClass::$lockfile )) {
- unlink( TemporaryCronClass::$lockfile );
+ if (!TemporaryCronClass::$keeplock && file_exists(TemporaryCronClass::$lockfile)) {
+ unlink(TemporaryCronClass::$lockfile);
}
-
+
// Say goodbye if the app did not shutdown properly
- if( !TemporaryCronClass::$sent ) {
- if( OC::$CLI ) {
- echo 'Unexpected error!'.PHP_EOL;
- }
- else{
- OC_JSON::error( array( 'data' => array( 'message' => 'Unexpected error!')));
+ if (!TemporaryCronClass::$sent) {
+ if (OC::$CLI) {
+ echo 'Unexpected error!' . PHP_EOL;
+ } else {
+ OC_JSON::error(array('data' => array('message' => 'Unexpected error!')));
}
}
}
@@ -50,8 +49,8 @@ require_once 'lib/base.php';
session_write_close();
// Don't do anything if ownCloud has not been installed
-if( !OC_Config::getValue( 'installed', false )) {
- exit( 0 );
+if (!OC_Config::getValue('installed', false)) {
+ exit(0);
}
// Handle unexpected errors
@@ -62,50 +61,54 @@ OC_Helper::cleanTmpNoClean();
// Exit if background jobs are disabled!
$appmode = OC_BackgroundJob::getExecutionType();
-if( $appmode == 'none' ) {
+if ($appmode == 'none') {
TemporaryCronClass::$sent = true;
- if( OC::$CLI ) {
- echo 'Background Jobs are disabled!'.PHP_EOL;
+ if (OC::$CLI) {
+ echo 'Background Jobs are disabled!' . PHP_EOL;
+ } else {
+ OC_JSON::error(array('data' => array('message' => 'Background jobs disabled!')));
}
- else{
- OC_JSON::error( array( 'data' => array( 'message' => 'Background jobs disabled!')));
- }
- exit( 1 );
+ exit(1);
}
-if( OC::$CLI ) {
+if (OC::$CLI) {
// Create lock file first
- TemporaryCronClass::$lockfile = OC_Config::getValue( "datadirectory", OC::$SERVERROOT.'/data' ).'/cron.lock';
-
+ TemporaryCronClass::$lockfile = OC_Config::getValue("datadirectory", OC::$SERVERROOT . '/data') . '/cron.lock';
+
// We call ownCloud from the CLI (aka cron)
- if( $appmode != 'cron' ) {
+ if ($appmode != 'cron') {
// Use cron in feature!
- OC_BackgroundJob::setExecutionType('cron' );
+ OC_BackgroundJob::setExecutionType('cron');
}
// check if backgroundjobs is still running
- if( file_exists( TemporaryCronClass::$lockfile )) {
+ if (file_exists(TemporaryCronClass::$lockfile)) {
TemporaryCronClass::$keeplock = true;
TemporaryCronClass::$sent = true;
echo "Another instance of cron.php is still running!";
- exit( 1 );
+ exit(1);
}
// Create a lock file
- touch( TemporaryCronClass::$lockfile );
+ touch(TemporaryCronClass::$lockfile);
// Work
- OC_BackgroundJob_Worker::doAllSteps();
-}
-else{
+ $jobList = new \OC\BackgroundJob\JobList();
+ $jobs = $jobList->getAll();
+ foreach ($jobs as $job) {
+ $job->execute($jobList);
+ }
+} else {
// We call cron.php from some website
- if( $appmode == 'cron' ) {
+ if ($appmode == 'cron') {
// Cron is cron :-P
- OC_JSON::error( array( 'data' => array( 'message' => 'Backgroundjobs are using system cron!')));
- }
- else{
+ OC_JSON::error(array('data' => array('message' => 'Backgroundjobs are using system cron!')));
+ } else {
// Work and success :-)
- OC_BackgroundJob_Worker::doNextStep();
+ $jobList = new \OC\BackgroundJob\JobList();
+ $job = $jobList->getNext();
+ $job->execute($jobList);
+ $jobList->setLastJob($job);
OC_JSON::success();
}
}
diff --git a/db_structure.xml b/db_structure.xml
index a902374e01f..feb7c0d122d 100644
--- a/db_structure.xml
+++ b/db_structure.xml
@@ -859,7 +859,7 @@
<table>
- <name>*dbprefix*queuedtasks</name>
+ <name>*dbprefix*jobs</name>
<declaration>
@@ -874,35 +874,35 @@
</field>
<field>
- <name>app</name>
+ <name>class</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
- <length>255</length>
+ <length>256</length>
</field>
<field>
- <name>klass</name>
+ <name>argument</name>
<type>text</type>
<default></default>
<notnull>true</notnull>
- <length>255</length>
+ <length>256</length>
</field>
<field>
- <name>method</name>
- <type>text</type>
+ <name>last_run</name>
+ <type>timestamp</type>
<default></default>
- <notnull>true</notnull>
- <length>255</length>
+ <notnull>false</notnull>
</field>
- <field>
- <name>parameters</name>
- <type>text</type>
- <notnull>true</notnull>
- <length>255</length>
- </field>
+ <index>
+ <name>job_class_index</name>
+ <field>
+ <name>class</name>
+ <sorting>ascending</sorting>
+ </field>
+ </index>
</declaration>
diff --git a/lib/backgroundjob/job.php b/lib/backgroundjob/job.php
new file mode 100644
index 00000000000..49fbffbd684
--- /dev/null
+++ b/lib/backgroundjob/job.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\BackgroundJob;
+
+abstract class Job {
+ protected $id;
+ protected $lastRun;
+ protected $argument;
+
+ /**
+ * @param JobList $jobList
+ */
+ public function execute($jobList) {
+ $jobList->setLastRun($this);
+ $this->run($this->argument);
+ }
+
+ abstract protected function run($argument);
+
+ public function setId($id) {
+ $this->id = $id;
+ }
+
+ public function setLastRun($lastRun) {
+ $this->lastRun = $lastRun;
+ }
+
+ public function setArgument($argument) {
+ $this->argument = $argument;
+ }
+
+ public function getId() {
+ return $this->id;
+ }
+
+ public function getLastRun() {
+ return $this->lastRun;
+ }
+
+ public function getArgument() {
+ return $this->argument;
+ }
+}
diff --git a/lib/backgroundjob/joblist.php b/lib/backgroundjob/joblist.php
new file mode 100644
index 00000000000..cc803dd9b5f
--- /dev/null
+++ b/lib/backgroundjob/joblist.php
@@ -0,0 +1,172 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\BackgroundJob;
+
+/**
+ * Class QueuedJob
+ *
+ * create a background job that is to be executed once
+ *
+ * @package OC\BackgroundJob
+ */
+class JobList {
+ /**
+ * @param Job|string $job
+ * @param mixed $argument
+ */
+ public function add($job, $argument = null) {
+ if (!$this->has($job, $argument)) {
+ if ($job instanceof Job) {
+ $class = get_class($job);
+ } else {
+ $class = $job;
+ }
+ $argument = json_encode($argument);
+ $query = \OC_DB::prepare('INSERT INTO `*PREFIX*jobs`(`class`, `argument`, `last_run`) VALUES(?, ?, 0)');
+ $query->execute(array($class, $argument));
+ }
+ }
+
+ /**
+ * @param Job|string $job
+ * @param mixed $argument
+ */
+ public function remove($job, $argument = null) {
+ if ($job instanceof Job) {
+ $class = get_class($job);
+ } else {
+ $class = $job;
+ }
+ if (!is_null($argument)) {
+ $argument = json_encode($argument);
+ $query = \OC_DB::prepare('DELETE FROM `*PREFIX*jobs` WHERE `class` = ? AND `argument` = ?');
+ $query->execute(array($class, $argument));
+ } else {
+ $query = \OC_DB::prepare('DELETE FROM `*PREFIX*jobs` WHERE `class` = ?');
+ $query->execute(array($class));
+ }
+ }
+
+ /**
+ * check if a job is in the list
+ *
+ * @param $job
+ * @param mixed $argument
+ * @return bool
+ */
+ public function has($job, $argument) {
+ if ($job instanceof Job) {
+ $class = get_class($job);
+ } else {
+ $class = $job;
+ }
+ $argument = json_encode($argument);
+ $query = \OC_DB::prepare('SELECT `id` FROM `*PREFIX*jobs` WHERE `class` = ? AND `argument` = ?');
+ $result = $query->execute(array($class, $argument));
+ return (bool)$result->fetchRow();
+ }
+
+ /**
+ * get all jobs in the list
+ *
+ * @return Job[]
+ */
+ public function getAll() {
+ $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs`');
+ $result = $query->execute();
+ $jobs = array();
+ while ($row = $result->fetchRow()) {
+ $jobs[] = $this->buildJob($row);
+ }
+ return $jobs;
+ }
+
+ /**
+ * get the next job in the list
+ *
+ * @return Job
+ */
+ public function getNext() {
+ $lastId = $this->getLastJob();
+ $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` WHERE `id` > ? ORDER BY `id` ASC', 1);
+ $result = $query->execute(array($lastId));
+ if ($row = $result->fetchRow()) {
+ return $this->buildJob($row);
+ } else {
+ //begin at the start of the queue
+ $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` ORDER BY `id` ASC', 1);
+ $result = $query->execute();
+ if ($row = $result->fetchRow()) {
+ return $this->buildJob($row);
+ } else {
+ return null; //empty job list
+ }
+ }
+ }
+
+ /**
+ * @param int $id
+ * @return Job
+ */
+ public function getById($id) {
+ $query = \OC_DB::prepare('SELECT `id`, `class`, `last_run`, `argument` FROM `*PREFIX*jobs` WHERE `id` = ?');
+ $result = $query->execute(array($id));
+ if ($row = $result->fetchRow()) {
+ return $this->buildJob($row);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * get the job object from a row in the db
+ *
+ * @param array $row
+ * @return Job
+ */
+ private function buildJob($row) {
+ $class = $row['class'];
+ /**
+ * @var Job $job
+ */
+ $job = new $class();
+ $job->setId($row['id']);
+ $job->setLastRun($row['last_run']);
+ $job->setArgument(json_decode($row['argument']));
+ return $job;
+ }
+
+ /**
+ * set the job that was last ran
+ *
+ * @param Job $job
+ */
+ public function setLastJob($job) {
+ \OC_Appconfig::setValue('backgroundjob', 'lastjob', $job->getId());
+ }
+
+ /**
+ * get the id of the last ran job
+ *
+ * @return int
+ */
+ public function getLastJob() {
+ return \OC_Appconfig::getValue('backgroundjob', 'lastjob', 0);
+ }
+
+ /**
+ * set the lastRun of $job to now
+ *
+ * @param Job $job
+ */
+ public function setLastRun($job) {
+ $query = \OC_DB::prepare('UPDATE `*PREFIX*jobs` SET `last_run` = ? WHERE `id` = ?');
+ $query->execute(array(time(), $job->getId()));
+ }
+}
diff --git a/lib/backgroundjob/legacy/queuedjob.php b/lib/backgroundjob/legacy/queuedjob.php
new file mode 100644
index 00000000000..2bc001103b8
--- /dev/null
+++ b/lib/backgroundjob/legacy/queuedjob.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\BackgroundJob\Legacy;
+
+class QueuedJob extends \OC\BackgroundJob\QueuedJob {
+ public function run($argument) {
+ $class = $argument['klass'];
+ $method = $argument['method'];
+ $parameters = $argument['parameters'];
+ call_user_func(array($class, $method), $parameters);
+ }
+}
diff --git a/lib/backgroundjob/legacy/regularjob.php b/lib/backgroundjob/legacy/regularjob.php
new file mode 100644
index 00000000000..d4cfa348cea
--- /dev/null
+++ b/lib/backgroundjob/legacy/regularjob.php
@@ -0,0 +1,15 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\BackgroundJob\Legacy;
+
+class RegularJob extends \OC\BackgroundJob\Job {
+ public function run($argument) {
+ call_user_func($argument);
+ }
+}
diff --git a/lib/backgroundjob/queuedjob.php b/lib/backgroundjob/queuedjob.php
new file mode 100644
index 00000000000..1714182820d
--- /dev/null
+++ b/lib/backgroundjob/queuedjob.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\BackgroundJob;
+
+/**
+ * Class QueuedJob
+ *
+ * create a background job that is to be executed once
+ *
+ * @package OC\BackgroundJob
+ */
+abstract class QueuedJob extends Job {
+ /**
+ * run the job, then remove it from the joblist
+ *
+ * @param JobList $jobList
+ */
+ public function execute($jobList) {
+ $jobList->remove($this);
+ $this->run($this->argument);
+ }
+}
diff --git a/lib/backgroundjob/queuedtask.php b/lib/backgroundjob/queuedtask.php
deleted file mode 100644
index b2ce6f39ed8..00000000000
--- a/lib/backgroundjob/queuedtask.php
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 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 AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * This class manages our queued tasks.
- */
-class OC_BackgroundJob_QueuedTask{
- /**
- * @brief Gets one queued task
- * @param $id ID of the task
- * @return associative array
- */
- public static function find( $id ) {
- $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks` WHERE `id` = ?' );
- $result = $stmt->execute(array($id));
- return $result->fetchRow();
- }
-
- /**
- * @brief Gets all queued tasks
- * @return array with associative arrays
- */
- public static function all() {
- // Array for objects
- $return = array();
-
- // Get Data
- $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks`' );
- $result = $stmt->execute(array());
- while( $row = $result->fetchRow()) {
- $return[] = $row;
- }
-
- return $return;
- }
-
- /**
- * @brief Gets all queued tasks of a specific app
- * @param $app app name
- * @return array with associative arrays
- */
- public static function whereAppIs( $app ) {
- // Array for objects
- $return = array();
-
- // Get Data
- $stmt = OC_DB::prepare( 'SELECT * FROM `*PREFIX*queuedtasks` WHERE `app` = ?' );
- $result = $stmt->execute(array($app));
- while( $row = $result->fetchRow()) {
- $return[] = $row;
- }
-
- // Und weg damit
- return $return;
- }
-
- /**
- * @brief queues a task
- * @param $app app name
- * @param $klass class name
- * @param $method method name
- * @param $parameters all useful data as text
- * @return id of task
- */
- public static function add( $app, $klass, $method, $parameters ) {
- $stmt = OC_DB::prepare( 'INSERT INTO `*PREFIX*queuedtasks` (`app`, `klass`, `method`, `parameters`)'
- .' VALUES(?,?,?,?)' );
- $result = $stmt->execute(array($app, $klass, $method, $parameters ));
-
- return OC_DB::insertid();
- }
-
- /**
- * @brief deletes a queued task
- * @param $id id of task
- * @return true/false
- *
- * Deletes a report
- */
- public static function delete( $id ) {
- $stmt = OC_DB::prepare( 'DELETE FROM `*PREFIX*queuedtasks` WHERE `id` = ?' );
- $result = $stmt->execute(array($id));
-
- return true;
- }
-}
diff --git a/lib/backgroundjob/regulartask.php b/lib/backgroundjob/regulartask.php
deleted file mode 100644
index 9976872ee13..00000000000
--- a/lib/backgroundjob/regulartask.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 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 AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * This class manages the regular tasks.
- */
-class OC_BackgroundJob_RegularTask{
- static private $registered = array();
-
- /**
- * @brief creates a regular task
- * @param $klass class name
- * @param $method method name
- * @return true
- */
- static public function register( $klass, $method ) {
- // Create the data structure
- self::$registered["$klass-$method"] = array( $klass, $method );
-
- // No chance for failure ;-)
- return true;
- }
-
- /**
- * @brief gets all regular tasks
- * @return associative array
- *
- * key is string "$klass-$method", value is array( $klass, $method )
- */
- static public function all() {
- return self::$registered;
- }
-}
diff --git a/lib/backgroundjob/timedjob.php b/lib/backgroundjob/timedjob.php
new file mode 100644
index 00000000000..ae9f33505ab
--- /dev/null
+++ b/lib/backgroundjob/timedjob.php
@@ -0,0 +1,41 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace OC\BackgroundJob;
+
+/**
+ * Class QueuedJob
+ *
+ * create a background job that is to be executed at an interval
+ *
+ * @package OC\BackgroundJob
+ */
+abstract class TimedJob extends Job {
+ protected $interval = 0;
+
+ /**
+ * set the interval for the job
+ *
+ * @param int $interval
+ */
+ public function setInterval($interval) {
+ $this->interval = $interval;
+ }
+
+ /**
+ * run the job if
+ *
+ * @param JobList $jobList
+ */
+ public function execute($jobList) {
+ if ((time() - $this->lastRun) > $this->interval) {
+ $jobList->setLastRun($this);
+ $this->run($this->argument);
+ }
+ }
+}
diff --git a/lib/backgroundjob/worker.php b/lib/backgroundjob/worker.php
deleted file mode 100644
index e966ac9647c..00000000000
--- a/lib/backgroundjob/worker.php
+++ /dev/null
@@ -1,118 +0,0 @@
-<?php
-/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 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 AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-/**
- * This class does the dirty work.
- *
- * TODO: locking in doAllSteps
- */
-class OC_BackgroundJob_Worker{
- /**
- * @brief executes all tasks
- * @return boolean
- *
- * This method executes all regular tasks and then all queued tasks.
- * This method should be called by cli scripts that do not let the user
- * wait.
- */
- public static function doAllSteps() {
- // Do our regular work
- $lasttask = OC_Appconfig::getValue( 'core', 'backgroundjobs_task', '' );
-
- $regular_tasks = OC_BackgroundJob_RegularTask::all();
- ksort( $regular_tasks );
- foreach( $regular_tasks as $key => $value ) {
- if( strcmp( $key, $lasttask ) > 0 ) {
- // Set "restart here" config value
- OC_Appconfig::setValue( 'core', 'backgroundjobs_task', $key );
- call_user_func( $value );
- }
- }
- // Reset "start here" config value
- OC_Appconfig::setValue( 'core', 'backgroundjobs_task', '' );
-
- // Do our queued tasks
- $queued_tasks = OC_BackgroundJob_QueuedTask::all();
- foreach( $queued_tasks as $task ) {
- OC_BackgroundJob_QueuedTask::delete( $task['id'] );
- call_user_func( array( $task['klass'], $task['method'] ), $task['parameters'] );
- }
-
- return true;
- }
-
- /**
- * @brief does a single task
- * @return boolean
- *
- * This method executes one task. It saves the last state and continues
- * with the next step. This method should be used by webcron and ajax
- * services.
- */
- public static function doNextStep() {
- $laststep = OC_Appconfig::getValue( 'core', 'backgroundjobs_step', 'regular_tasks' );
-
- if( $laststep == 'regular_tasks' ) {
- // get last app
- $lasttask = OC_Appconfig::getValue( 'core', 'backgroundjobs_task', '' );
-
- // What's the next step?
- $regular_tasks = OC_BackgroundJob_RegularTask::all();
- ksort( $regular_tasks );
- $done = false;
-
- // search for next background job
- foreach( $regular_tasks as $key => $value ) {
- if( strcmp( $key, $lasttask ) > 0 ) {
- OC_Appconfig::setValue( 'core', 'backgroundjobs_task', $key );
- $done = true;
- call_user_func( $value );
- break;
- }
- }
-
- if( $done == false ) {
- // Next time load queued tasks
- OC_Appconfig::setValue( 'core', 'backgroundjobs_step', 'queued_tasks' );
- }
- }
- else{
- $tasks = OC_BackgroundJob_QueuedTask::all();
- if( count( $tasks )) {
- $task = $tasks[0];
- // delete job before we execute it. This prevents endless loops
- // of failing jobs.
- OC_BackgroundJob_QueuedTask::delete($task['id']);
-
- // execute job
- call_user_func( array( $task['klass'], $task['method'] ), $task['parameters'] );
- }
- else{
- // Next time load queued tasks
- OC_Appconfig::setValue( 'core', 'backgroundjobs_step', 'regular_tasks' );
- OC_Appconfig::setValue( 'core', 'backgroundjobs_task', '' );
- }
- }
-
- return true;
- }
-}
diff --git a/lib/base.php b/lib/base.php
index 9d1d4b5e058..d2a3d90f825 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -537,9 +537,15 @@ class OC {
* register hooks for the cache
*/
public static function registerCacheHooks() {
- // register cache cleanup jobs
- OC_BackgroundJob_RegularTask::register('OC_Cache_FileGlobal', 'gc');
- OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener');
+ if (OC_Config::getValue('installed', false)) { //don't try to do this before we are properly setup
+ // register cache cleanup jobs
+ try { //if this is executed before the upgrade to the new backgroundjob system is completed it will throw an exception
+ \OCP\BackgroundJob::registerJob('OC_Cache_FileGlobalGC');
+ } catch (Exception $e) {
+
+ }
+ OC_Hook::connect('OC_User', 'post_login', 'OC_Cache_File', 'loginListener');
+ }
}
/**
diff --git a/lib/cache/fileglobalgc.php b/lib/cache/fileglobalgc.php
new file mode 100644
index 00000000000..a29c31f9063
--- /dev/null
+++ b/lib/cache/fileglobalgc.php
@@ -0,0 +1,8 @@
+<?php
+
+
+class OC_Cache_FileGlobalGC extends \OC\BackgroundJob\Job{
+ public function run($argument){
+ OC_Cache_FileGlobal::gc();
+ }
+}
diff --git a/lib/public/backgroundjob.php b/lib/public/backgroundjob.php
index 601046fe691..cc076a3a845 100644
--- a/lib/public/backgroundjob.php
+++ b/lib/public/backgroundjob.php
@@ -1,49 +1,46 @@
<?php
/**
-* ownCloud
-*
-* @author Jakob Sack
-* @copyright 2012 Jakob Sack owncloud@jakobsack.de
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
-* License as published by the Free Software Foundation; either
-* version 3 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 AFFERO GENERAL PUBLIC LICENSE for more details.
-*
-* You should have received a copy of the GNU Affero General Public
-* License along with this library. If not, see <http://www.gnu.org/licenses/>.
-*
-*/
+ * ownCloud
+ *
+ * @author Jakob Sack
+ * @copyright 2012 Jakob Sack owncloud@jakobsack.de
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 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 AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
/**
- * Public interface of ownCloud forbackground jobs.
+ * Public interface of ownCloud for background jobs.
*/
// use OCP namespace for all classes that are considered public.
// This means that they should be used by apps instead of the internal ownCloud classes
namespace OCP;
+use \OC\BackgroundJob\JobList;
+
/**
- * This class provides functions to manage backgroundjobs in ownCloud
- *
- * There are two kind of background jobs in ownCloud: regular tasks and
- * queued tasks.
+ * This class provides functions to register backgroundjobs in ownCloud
*
- * Regular tasks have to be registered in appinfo.php and
- * will run on a regular base. Fetching news could be a task that should run
- * frequently.
+ * To create a new backgroundjob create a new class that inharits from either \OC\BackgroundJob\Job,
+ * \OC\BackgroundJob\QueuedJob or \OC\BackgroundJob\TimedJob and register it using
+ * \OCP\BackgroundJob->registerJob($job, $argument), $argument will be passed to the run() function
+ * of the job when the job is executed.
*
- * Queued tasks have to be registered each time you want to execute them.
- * An example of the queued task would be the creation of the thumbnail. As
- * soon as the user uploads a picture the gallery app registers the queued
- * task "create thumbnail" and saves the path in the parameter instead of doing
- * the work right away. This makes the app more responsive. As soon as the task
- * is done it will be deleted from the list.
+ * A regular Job will be executed every time cron.php is run, a QueuedJob will only run once and a TimedJob
+ * will only run at a specific interval which is to be specified in the constructor of the job by calling
+ * $this->setInterval($interval) with $interval in seconds.
*/
class BackgroundJob {
/**
@@ -59,82 +56,136 @@ class BackgroundJob {
/**
* @brief sets the background jobs execution type
- * @param $type execution type
+ * @param string $type execution type
* @return boolean
*
* This method sets the execution type of the background jobs. Possible types
* are "none", "ajax", "webcron", "cron"
*/
- public static function setExecutionType( $type ) {
- return \OC_BackgroundJob::setExecutionType( $type );
+ public static function setExecutionType($type) {
+ return \OC_BackgroundJob::setExecutionType($type);
+ }
+
+ /**
+ * @param \OC\BackgroundJob\Job|string $job
+ * @param mixed $argument
+ */
+ public static function registerJob($job, $argument = null) {
+ $jobList = new JobList();
+ $jobList->add($job, $argument);
}
/**
+ * @deprecated
* @brief creates a regular task
- * @param $klass class name
- * @param $method method name
+ * @param string $klass class name
+ * @param string $method method name
* @return true
*/
- public static function addRegularTask( $klass, $method ) {
- return \OC_BackgroundJob_RegularTask::register( $klass, $method );
+ public static function addRegularTask($klass, $method) {
+ self::registerJob('OC\BackgroundJob\Legacy\RegularJob', array($klass, $method));
+ return true;
}
/**
+ * @deprecated
* @brief gets all regular tasks
* @return associative array
*
* key is string "$klass-$method", value is array( $klass, $method )
*/
static public function allRegularTasks() {
- return \OC_BackgroundJob_RegularTask::all();
+ $jobList = new JobList();
+ $allJobs = $jobList->getAll();
+ $regularJobs = array();
+ foreach ($allJobs as $job) {
+ if ($job instanceof RegularLegacyJob) {
+ $key = implode('-', $job->getArgument());
+ $regularJobs[$key] = $job->getArgument();
+ }
+ }
+ return $regularJobs;
}
/**
+ * @deprecated
* @brief Gets one queued task
- * @param $id ID of the task
+ * @param int $id ID of the task
* @return associative array
*/
- public static function findQueuedTask( $id ) {
- return \OC_BackgroundJob_QueuedTask::find( $id );
+ public static function findQueuedTask($id) {
+ $jobList = new JobList();
+ return $jobList->getById($id);
}
/**
+ * @deprecated
* @brief Gets all queued tasks
* @return array with associative arrays
*/
public static function allQueuedTasks() {
- return \OC_BackgroundJob_QueuedTask::all();
+ $jobList = new JobList();
+ $allJobs = $jobList->getAll();
+ $queuedJobs = array();
+ foreach ($allJobs as $job) {
+ if ($job instanceof QueuedLegacyJob) {
+ $queuedJob = $job->getArgument();
+ $queuedJob['id'] = $job->getId();
+ $queuedJobs[] = $queuedJob;
+ }
+ }
+ return $queuedJobs;
}
/**
+ * @deprecated
* @brief Gets all queued tasks of a specific app
- * @param $app app name
+ * @param string $app app name
* @return array with associative arrays
*/
- public static function queuedTaskWhereAppIs( $app ) {
- return \OC_BackgroundJob_QueuedTask::whereAppIs( $app );
+ public static function queuedTaskWhereAppIs($app) {
+ $jobList = new JobList();
+ $allJobs = $jobList->getAll();
+ $queuedJobs = array();
+ foreach ($allJobs as $job) {
+ if ($job instanceof QueuedLegacyJob) {
+ $queuedJob = $job->getArgument();
+ $queuedJob['id'] = $job->getId();
+ if ($queuedJob['app'] === $app) {
+ $queuedJobs[] = $queuedJob;
+ }
+ }
+ }
+ return $queuedJobs;
}
/**
+ * @deprecated
* @brief queues a task
- * @param $app app name
- * @param $klass class name
- * @param $method method name
- * @param $parameters all useful data as text
- * @return id of task
+ * @param string $app app name
+ * @param string $class class name
+ * @param string $method method name
+ * @param string $parameters all useful data as text
+ * @return int id of task
*/
- public static function addQueuedTask( $app, $klass, $method, $parameters ) {
- return \OC_BackgroundJob_QueuedTask::add( $app, $klass, $method, $parameters );
+ public static function addQueuedTask($app, $class, $method, $parameters) {
+ self::registerJob('OC\BackgroundJob\Legacy\QueuedJob', array('app' => $app, 'klass' => $class, 'method' => $method, 'parameters' => $parameters));
+ return true;
}
/**
+ * @deprecated
* @brief deletes a queued task
- * @param $id id of task
- * @return true/false
+ * @param int $id id of task
+ * @return bool
*
* Deletes a report
*/
- public static function deleteQueuedTask( $id ) {
- return \OC_BackgroundJob_QueuedTask::delete( $id );
+ public static function deleteQueuedTask($id) {
+ $jobList = new JobList();
+ $job = $jobList->getById($id);
+ if ($job) {
+ $jobList->remove($job);
+ }
}
}
diff --git a/lib/util.php b/lib/util.php
index 035815c057f..95af22ed0ee 100755
--- a/lib/util.php
+++ b/lib/util.php
@@ -80,7 +80,7 @@ class OC_Util {
public static function getVersion() {
// hint: We only can count up. Reset minor/patchlevel when
// updating major/minor version number.
- return array(5, 80, 04);
+ return array(5, 80, 05);
}
/**
diff --git a/tests/lib/backgroundjob/dummyjoblist.php b/tests/lib/backgroundjob/dummyjoblist.php
new file mode 100644
index 00000000000..d91d6b344b5
--- /dev/null
+++ b/tests/lib/backgroundjob/dummyjoblist.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\BackgroundJob;
+
+class JobRun extends \Exception {
+}
+
+/**
+ * Class DummyJobList
+ *
+ * in memory job list for testing purposes
+ */
+class DummyJobList extends \OC\BackgroundJob\JobList {
+ /**
+ * @var \OC\BackgroundJob\Job[]
+ */
+ private $jobs = array();
+
+ private $last = 0;
+
+ /**
+ * @param \OC\BackgroundJob\Job|string $job
+ * @param mixed $argument
+ */
+ public function add($job, $argument = null) {
+ $job->setArgument($argument);
+ if (!$this->has($job, null)) {
+ $this->jobs[] = $job;
+ }
+ }
+
+ /**
+ * @param \OC\BackgroundJob\Job|string $job
+ * @param mixed $argument
+ */
+ public function remove($job, $argument = null) {
+ $index = array_search($job, $this->jobs);
+ if ($index !== false) {
+ unset($this->jobs[$index]);
+ }
+ }
+
+ /**
+ * check if a job is in the list
+ *
+ * @param $job
+ * @param mixed $argument
+ * @return bool
+ */
+ public function has($job, $argument) {
+ return array_search($job, $this->jobs) !== false;
+ }
+
+ /**
+ * get all jobs in the list
+ *
+ * @return \OC\BackgroundJob\Job[]
+ */
+ public function getAll() {
+ return $this->jobs;
+ }
+
+ /**
+ * get the next job in the list
+ *
+ * @return \OC\BackgroundJob\Job
+ */
+ public function getNext() {
+ if (count($this->jobs) > 0) {
+ if ($this->last < (count($this->jobs) - 1)) {
+ $i = $this->last + 1;
+ } else {
+ $i = 0;
+ }
+ return $this->jobs[$i];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * set the job that was last ran
+ *
+ * @param \OC\BackgroundJob\Job $job
+ */
+ public function setLastJob($job) {
+ $i = array_search($job, $this->jobs);
+ if ($i !== false) {
+ $this->last = $i;
+ } else {
+ $this->last = 0;
+ }
+ }
+
+ /**
+ * @param int $id
+ * @return Job
+ */
+ public function getById($id) {
+ foreach ($this->jobs as $job) {
+ if ($job->getId() === $id) {
+ return $job;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * get the id of the last ran job
+ *
+ * @return int
+ */
+ public function getLastJob() {
+ return $this->last;
+ }
+
+ /**
+ * set the lastRun of $job to now
+ *
+ * @param \OC\BackgroundJob\Job $job
+ */
+ public function setLastRun($job) {
+ $job->setLastRun(time());
+ }
+}
diff --git a/tests/lib/backgroundjob/queuedjob.php b/tests/lib/backgroundjob/queuedjob.php
new file mode 100644
index 00000000000..1d373473cd7
--- /dev/null
+++ b/tests/lib/backgroundjob/queuedjob.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\BackgroundJob;
+
+class TestQueuedJob extends \OC\BackgroundJob\QueuedJob {
+ public function run($argument) {
+ throw new JobRun(); //throw an exception so we can detect if this function is called
+ }
+}
+
+class QueuedJob extends \PHPUnit_Framework_TestCase {
+ /**
+ * @var DummyJobList $jobList
+ */
+ private $jobList;
+ /**
+ * @var \OC\BackgroundJob\TimedJob $job
+ */
+ private $job;
+
+ public function setup() {
+ $this->jobList = new DummyJobList();
+ $this->job = new TestQueuedJob();
+ $this->jobList->add($this->job);
+ }
+
+ public function testJobShouldBeRemoved() {
+ try {
+ $this->assertTrue($this->jobList->has($this->job, null));
+ $this->job->execute($this->jobList);
+ $this->fail("job should have been run");
+ } catch (JobRun $e) {
+ $this->assertFalse($this->jobList->has($this->job, null));
+ }
+ }
+}
diff --git a/tests/lib/backgroundjob/timedjob.php b/tests/lib/backgroundjob/timedjob.php
new file mode 100644
index 00000000000..0af933afef8
--- /dev/null
+++ b/tests/lib/backgroundjob/timedjob.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+namespace Test\BackgroundJob;
+
+class TestTimedJob extends \OC\BackgroundJob\TimedJob {
+ public function __construct() {
+ $this->setInterval(10);
+ }
+
+ public function run($argument) {
+ throw new JobRun(); //throw an exception so we can detect if this function is called
+ }
+}
+
+class TimedJob extends \PHPUnit_Framework_TestCase {
+ /**
+ * @var DummyJobList $jobList
+ */
+ private $jobList;
+ /**
+ * @var \OC\BackgroundJob\TimedJob $job
+ */
+ private $job;
+
+ public function setup() {
+ $this->jobList = new DummyJobList();
+ $this->job = new TestTimedJob();
+ $this->jobList->add($this->job);
+ }
+
+ public function testShouldRunAfterInterval() {
+ $this->job->setLastRun(time() - 12);
+ try {
+ $this->job->execute($this->jobList);
+ $this->fail("job should have run");
+ } catch (JobRun $e) {
+ }
+ }
+
+ public function testShouldNotRunWithinInterval() {
+ $this->job->setLastRun(time() - 5);
+ try {
+ $this->job->execute($this->jobList);
+ } catch (JobRun $e) {
+ $this->fail("job should not have run");
+ }
+ }
+
+ public function testShouldNotTwice() {
+ $this->job->setLastRun(time() - 15);
+ try {
+ $this->job->execute($this->jobList);
+ $this->fail("job should have run the first time");
+ } catch (JobRun $e) {
+ try {
+ $this->job->execute($this->jobList);
+ } catch (JobRun $e) {
+ $this->fail("job should not have run the second time");
+ }
+ }
+ }
+}