From e4a626b983784fad74bd5ce7e459c3b190a910b1 Mon Sep 17 00:00:00 2001 From: sam marshall Date: Tue, 21 Dec 2010 16:37:22 +0000 Subject: [PATCH] cron MDL-25370 Update Petr's changes to fix bug regarding lastcron, add comments/doc --- lib/cronlib.php | 114 +++++++++++++++++++++++----------------------- lib/moodlelib.php | 2 +- 2 files changed, 59 insertions(+), 57 deletions(-) diff --git a/lib/cronlib.php b/lib/cronlib.php index a444be79411..f8f1413f749 100644 --- a/lib/cronlib.php +++ b/lib/cronlib.php @@ -441,11 +441,13 @@ function cron_run() { // all other plugins cron_execute_plugin_type('message', 'message plugins'); cron_execute_plugin_type('filter', 'filters'); - cron_execute_plugin_type('editor', 'editor'); + cron_execute_plugin_type('editor', 'editors'); cron_execute_plugin_type('format', 'course formats'); cron_execute_plugin_type('profilefield', 'profile fields'); cron_execute_plugin_type('webservice', 'webservices'); - //cron_execute_plugin_type('repository', 'repositories'); TODO: repository lib.php files are messed up, sorry + // TODO: Repository lib.php files are messed up (include many other files, etc), so it is + // currently not possible to implement repository plugin cron using this infrastructure + // cron_execute_plugin_type('repository', 'repository plugins'); cron_execute_plugin_type('qtype', 'question types'); cron_execute_plugin_type('plagiarism', 'plagiarism plugins'); cron_execute_plugin_type('theme', 'themes'); @@ -464,50 +466,31 @@ function cron_run() { mtrace('done.'); } - // NOTE: Other types of plugin could also be supported in this loop, which - // can handle generic cron function. - foreach (array('report', 'coursereport') as $plugintype) { - mtrace('Starting plugin type: ' . $plugintype); - // These reports do not have a database table that lists them. Instead - // a report has cron.php with function report_reportname_cron() if it - // wishes to be cronned. It is up to this function to handle e.g. if it - // only needs to actually do anything occasionally. - $reports = get_plugin_list_with_function( - $plugintype, 'cron', 'cron.php'); - foreach($reports as $report => $cronfunction) { - mtrace('Processing cron function for ' . $report . '...', ''); - $pre_dbqueries = null; - $pre_dbqueries = $DB->perf_get_queries(); - $pre_time = microtime(true); - $cronfunction(); - if (isset($pre_dbqueries)) { - mtrace("... used " . - ($DB->perf_get_queries() - $pre_dbqueries) . - " dbqueries"); - mtrace("... used " . round(microtime(true) - $pre_time, 2) . - " seconds"); - } - mtrace('done.'); - } - mtrace('Finished plugin type: ' . $plugintype); - } - mtrace("Cron script completed correctly"); $difftime = microtime_diff($starttime, microtime()); mtrace("Execution took ".$difftime." seconds"); - } +/** + * Executes cron functions for a specific type of plugin. + * @param string $plugintype Plugin type (e.g. 'report') + * @param string $description If specified, will display 'Starting (whatever)' + * and 'Finished (whatever)' lines, otherwise does not display + */ function cron_execute_plugin_type($plugintype, $description = null) { global $DB; + // Get list of all plugin directories of this type $allplugins = get_plugin_list($plugintype); - $plugins = get_plugin_list_with_function($plugintype, 'cron', 'lib.php'); - // add BC compatible file locations and old cron function names - $plugins = cron_plugins_functions_bc_hacks($plugintype, $plugins); + // Get list from plugin => function for all plugins + $plugins = get_plugin_list_with_function($plugintype, 'cron'); + // Modify list for backward compatibility (different files/names) + $plugins = cron_bc_hack_plugin_functions($plugintype, $plugins); + + // Return if no plugins with cron function to process if (!$plugins) { return; } @@ -517,7 +500,12 @@ function cron_execute_plugin_type($plugintype, $description = null) { } foreach ($plugins as $component=>$cronfunction) { - $dir = $allplugins[$component]; + // Get short name of plugin without frankenstyle prefix, use this to find out plugin + // directory from the array + $nameonly = preg_replace('~^.*?_~', '', $component); + $dir = $allplugins[$nameonly]; + + // Get cron period if specified in version.php, otherwise assume every cron $cronperiod = 0; if (file_exists("$dir/version.php")) { $plugin = new stdClass(); @@ -527,69 +515,83 @@ function cron_execute_plugin_type($plugintype, $description = null) { } } + // Using last cron and cron period, don't run if it already ran recently $lastcron = get_config($component, 'lastcron'); - if ($cronperiod and $lastcron) { + if ($cronperiod && $lastcron) { if ($lastcron + $cronperiod > time()) { // do not execute cron yet continue; } } - mtrace('Processing cron function for '.$component.'...'); + mtrace('Processing cron function for ' . $component . '...'); $pre_dbqueries = $DB->perf_get_queries(); - $pre_time = microtime(true); + $pre_time = microtime(true); $cronfunction(); - mtrace("... used " . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries"); - mtrace("... used " . round(microtime(true) - $pre_time, 2) . " seconds"); - mtrace('done.'); + mtrace("done. (" . ($DB->perf_get_queries() - $pre_dbqueries) . " dbqueries, " . + round(microtime(true) - $pre_time, 2) . " seconds)"); set_config('lastcron', time(), $component); } if ($description) { - mtrace('Finished '.$description); + mtrace('Finished ' . $description); } } -function cron_plugins_functions_bc_hacks($plugintype, $plugins) { - global $CFG; // mandatory because the lib functions do not define it global! +/** + * Used to add in old-style cron functions within plugins that have not been converted to the + * new standard API. (The standard API is frankenstyle_name_cron() in lib.php; some types used + * cron.php and some used a different name.) + * @param string $plugintype Plugin type e.g. 'report' + * @param array $plugins Array from plugin name (e.g. 'report_frog') to function name (e.g. + * 'report_frog_cron') for plugin cron functions that were already found using the new API + * @return array Revised version of $plugins that adds in any extra plugin functions found by + * looking in the older location + */ +function cron_bc_hack_plugin_functions($plugintype, $plugins) { + global $CFG; // mandatory in case it is referenced by include()d PHP script - if ($plugintype === 'report' or $plugintype === 'coursereport') { - // admin and course reports - foreach(get_plugin_list($plugintype) as $pluginname=>$dir) { - $component = $plugintype.'_'.$pluginname; + if ($plugintype === 'report') { + // Admin reports only - not course report because course report was + // never implemented before, so doesn't need BC + foreach (get_plugin_list($plugintype) as $pluginname=>$dir) { + $component = $plugintype . '_' . $pluginname; if (isset($plugins[$component])) { - // we already have the new type + // We already have detected the function using the new API continue; } if (!file_exists("$dir/cron.php")) { - //no old style corn file present + // No old style cron file present continue; } include_once("$dir/cron.php"); - $cronfunction = $component.'_cron'; + $cronfunction = $component . '_cron'; if (function_exists($cronfunction)) { $plugins[$component] = $cronfunction; } else { - debugging("Invalid legacy cron.php detected in $component, please use lib.php instead"); + debugging("Invalid legacy cron.php detected in $component, " . + "please use lib.php instead"); } } - } else if (strpos($plugintype, 'grade') === 0) { - // detect old style cron functio names + // Detect old style cron function names + // Plugin gradeexport_frog used to use grade_export_frog_cron() instead of + // new standard API gradeexport_frog_cron(). Also applies to gradeimport, gradereport foreach(get_plugin_list($plugintype) as $pluginname=>$dir) { $component = $plugintype.'_'.$pluginname; if (isset($plugins[$component])) { - // we already have the new type + // We already have detected the function using the new API continue; } if (!file_exists("$dir/lib.php")) { continue; } include_once("$dir/lib.php"); - $cronfunction = str_replace('grade', 'grade_', $plugintype).'_'.$pluginname.'_cron'; + $cronfunction = str_replace('grade', 'grade_', $plugintype) . '_' . + $pluginname . '_cron'; if (function_exists($cronfunction)) { $plugins[$component] = $cronfunction; } diff --git a/lib/moodlelib.php b/lib/moodlelib.php index e59ae81b35f..e3e3c2a1e4f 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -7333,7 +7333,7 @@ function get_plugin_list($plugintype) { * 'forum_hook') */ function get_plugin_list_with_function($plugintype, $function, $file='lib.php') { - global $CFG; // mandatory because the lib functions do not define it global! + global $CFG; // mandatory in case it is referenced by include()d PHP script $result = array(); // Loop through list of plugins with given type