MDL-25290 cache: Added UI to view the cache lock setups and tidied up a couple of...
authorSam Hemelryk <sam@moodle.com>
Tue, 18 Sep 2012 01:34:56 +0000 (13:34 +1200)
committerSam Hemelryk <sam@moodle.com>
Sun, 7 Oct 2012 20:53:51 +0000 (09:53 +1300)
cache/admin.php
cache/classes/config.php
cache/forms.php
cache/locallib.php
cache/renderer.php
cache/tests/cache_test.php
lang/en/cache.php
lib/db/caches.php

index 96d086d..81e5400 100644 (file)
@@ -39,6 +39,7 @@ $stores = cache_administration_helper::get_store_summaries();
 $plugins = cache_administration_helper::get_plugin_summaries();
 $definitions = cache_administration_helper::get_definition_summaries();
 $defaultmodestores = cache_administration_helper::get_default_mode_stores();
+$locks = cache_administration_helper::get_lock_summaries();
 
 $title = new lang_string('cacheadmin', 'cache');
 $mform = null;
@@ -60,6 +61,12 @@ if (!empty($action) && confirm_sesskey()) {
             } else if ($data = $mform->get_data()) {
                 $config = cache_administration_helper::get_store_configuration_from_data($data);
                 $writer = cache_config_writer::instance();
+                unset($config['lock']);
+                foreach ($writer->get_locks() as $lock => $lockconfig) {
+                    if ($lock == $data->lock) {
+                        $config['lock'] = $data->lock;
+                    }
+                }
                 $writer->add_plugin_instance($data->name, $data->plugin, $config);
                 redirect($PAGE->url, get_string('addstoresuccess', 'cache', $plugins[$plugin]['name']), 5);
             }
@@ -74,6 +81,12 @@ if (!empty($action) && confirm_sesskey()) {
             } else if ($data = $mform->get_data()) {
                 $config = cache_administration_helper::get_store_configuration_from_data($data);
                 $writer = cache_config_writer::instance();
+                unset($config['lock']);
+                foreach ($writer->get_locks() as $lock => $lockconfig) {
+                    if ($lock == $data->lock) {
+                        $config['lock'] = $data->lock;
+                    }
+                }
                 $writer->edit_plugin_instance($data->name, $data->plugin, $config);
                 redirect($PAGE->url, get_string('editstoresuccess', 'cache', $plugins[$plugin]['name']), 5);
             }
@@ -172,6 +185,7 @@ if ($mform instanceof moodleform) {
     echo $renderer->plugin_summaries($plugins);
     echo $renderer->store_summariers($stores, $plugins);
     echo $renderer->definition_summaries($definitions, cache_administration_helper::get_definition_actions($context));
+    echo $renderer->lock_summaries($locks);
 
     $applicationstore = join(', ', $defaultmodestores[cache_store::MODE_APPLICATION]);
     $sessionstore = join(', ', $defaultmodestores[cache_store::MODE_SESSION]);
index d45b84e..5f2b189 100644 (file)
@@ -141,7 +141,8 @@ class cache_config {
                 debugging('Duplicate cache lock detected. This should never happen.', DEBUG_DEVELOPER);
                 continue;
             }
-            if ($defaultlock === null || !empty($this->configlocks['default'])) {
+            $conf['default'] = (!empty($conf['default']));
+            if ($defaultlock === null || $conf['default']) {
                 $defaultlock = $name;
             }
             $this->configlocks[$name] = $conf;
@@ -175,13 +176,9 @@ class cache_config {
             if (!array_key_exists('configuration', $store) || !is_array($store['configuration'])) {
                 $store['configuration'] = array();
             }
-            if (!empty($store['useforlocking'])) {
-                // The site has a specified cache for locking.
-                unset($this->configstores['default_locking']);
-            }
             $store['class'] = $class;
             $store['default'] = !empty($store['default']);
-            if (!array_key_exists('lock', $store) || !array_key_exists($this->configlocks, $store['lock'])) {
+            if (!array_key_exists('lock', $store) || !array_key_exists($store['lock'], $this->configlocks)) {
                 $store['lock'] = $defaultlock;
             }
 
@@ -434,7 +431,7 @@ class cache_config {
 
     /**
      * Returns an array of the configured locks.
-     * @return array
+     * @return array Array of name => config
      */
     public function get_locks() {
         return $this->configlocks;
index b6c014f..da6db91 100644 (file)
@@ -46,6 +46,7 @@ class cachestore_addinstance_form extends moodleform {
         $form = $this->_form;
         $store = $this->_customdata['store'];
         $plugin = $this->_customdata['plugin'];
+        $locks = $this->_customdata['locks'];
 
         $form->addElement('hidden', 'plugin', $plugin);
         $form->addElement('hidden', 'editing', !empty($this->_customdata['store']));
@@ -60,6 +61,14 @@ class cachestore_addinstance_form extends moodleform {
             $form->addElement('static', 'name-value', get_string('storename', 'cache'), $store);
         }
 
+        if (is_array($locks)) {
+            $form->addElement('select', 'lock', get_string('lockmethod', 'cache'), $locks);
+            $form->addHelpButton('lock', 'lockmethod', 'cache');
+            $form->setType('lock', PARAM_TEXT);
+        } else {
+            $form->addElement('hidden', 'lock', '');
+            $form->addElement('static', 'lock-value', get_string('lockmethod', 'cache'), '<em>'.get_string('nativelocking', 'cache').'</em>');
+        }
 
         if (method_exists($this, 'configuration_definition')) {
             $form->addElement('header', 'storeconfiguration', get_string('storeconfiguration', 'cache'));
index add82cd..aa21252 100644 (file)
@@ -137,10 +137,12 @@ class cache_config_writer extends cache_config {
             'configuration' => $configuration,
             'features' => $class::get_supported_features($configuration),
             'modes' => $class::get_supported_modes($configuration),
-            'mappingsonly' => !empty($configuration['mappingsonly']),
-            'useforlocking' => !empty($configuration['useforlocking'])
-
+            'mappingsonly' => !empty($configuration['mappingsonly'])
         );
+        if (array_key_exists('lock', $configuration)) {
+            $this->configstores[$name]['lock'] = $configuration['lock'];
+            unset($this->configstores[$name]['configuration']['lock']);
+        }
         $this->config_save();
         return true;
     }
@@ -228,9 +230,12 @@ class cache_config_writer extends cache_config {
             'configuration' => $configuration,
             'features' => $class::get_supported_features($configuration),
             'modes' => $class::get_supported_modes($configuration),
-            'mappingsonly' => !empty($configuration['mappingsonly']),
-            'useforlocking' => !empty($configuration['useforlocking'])
+            'mappingsonly' => !empty($configuration['mappingsonly'])
         );
+        if (array_key_exists('lock', $configuration)) {
+            $this->configstores[$name]['lock'] = $configuration['lock'];
+            unset($this->configstores[$name]['configuration']['lock']);
+        }
         $this->config_save();
         return true;
     }
@@ -285,17 +290,6 @@ class cache_config_writer extends cache_config {
 
         $writer = new self;
         $writer->configstores = array(
-            'default_locking' => array(
-                'name' => 'default_locking',
-                'plugin' => 'file',
-                'configuration' => array(),
-                'features' => cachestore_file::get_supported_features(),
-                'modes' => cache_store::MODE_APPLICATION,
-                'useforlocking' => true,
-                'mappingsonly' => true,
-                'default' => true,
-                //'class' => 'cachestore_file'
-            ),
             'default_application' => array(
                 'name' => 'default_application',
                 'plugin' => 'file',
@@ -342,18 +336,12 @@ class cache_config_writer extends cache_config {
                 'sort' => -1
             )
         );
-        $writer->configdefinitionmappings = array(
-            array(
-                'store' => 'default_locking',
-                'definition' => 'core/locking',
-                'sort' => -1
-            )
-        );
         $writer->configlocks = array(
             'default_file_lock' => array(
-                'name' => 'default_file_lock',
+                'name' => 'cachelock_file_default',
                 'type' => 'cachelock_file',
-                'dir' => 'filelocks'
+                'dir' => 'filelocks',
+                'default' => true
             )
         );
         $writer->config_save();
@@ -740,8 +728,33 @@ abstract class cache_administration_helper extends cache_helper {
             }
         }
 
+        $supportsnativelocking = false;
+        if (file_exists($plugindir.'/lib.php')) {
+            require_once($plugindir.'/lib.php');
+            $pluginclass = 'cachestore_'.$plugin;
+            if (class_exists($pluginclass)) {
+                $supportsnativelocking = array_key_exists('cache_is_lockable', class_implements($pluginclass));
+            }
+        }
+
+        if (!$supportsnativelocking) {
+            $config = cache_config::instance();
+            $locks = array();
+            foreach ($config->get_locks() as $lock => $conf) {
+                debug($conf);
+                if (!empty($conf['default'])) {
+                    $name = get_string($lock, 'cache');
+                } else {
+                    $name = $lock;
+                }
+                $locks[$lock] = $name;
+            }
+        } else {
+            $locks = false;
+        }
+
         $url = new moodle_url('/cache/admin.php', array('action' => 'addstore'));
-        return new $class($url, array('plugin' => $plugin, 'store' => null));
+        return new $class($url, array('plugin' => $plugin, 'store' => null, 'locks' => $locks));
     }
 
     /**
@@ -821,9 +834,7 @@ abstract class cache_administration_helper extends cache_helper {
             }
         }
         foreach ($possiblestores as $key => $store) {
-            if ($key === 'default_locking') {
-                unset($possiblestores[$key]);
-            } else if ($store['default']) {
+            if ($store['default']) {
                 unset($possiblestores[$key]);
                 $possiblestores[$key] = $store;
             }
@@ -863,4 +874,34 @@ abstract class cache_administration_helper extends cache_helper {
         }
         return $modemappings;
     }
+
+    /**
+     * Returns an array summarising the locks available in the system
+     */
+    public static function get_lock_summaries() {
+        $locks = array();
+        $instance = cache_config::instance();
+        $stores = $instance->get_all_stores();
+        foreach ($instance->get_locks() as $lock) {
+            $default = !empty($lock['default']);
+            if ($default) {
+                $name = new lang_string($lock['name'], 'cache');
+            } else {
+                $name = $lock['name'];
+            }
+            $uses = 0;
+            foreach ($stores as $store) {
+                if (!empty($store['lock']) && $store['lock'] === $lock['name']) {
+                    $uses++;
+                }
+            }
+            $lockdata = array(
+                'name' => $name,
+                'default' => $default,
+                'uses' => $uses
+            );
+            $locks[] = $lockdata;
+        }
+        return $locks;
+    }
 }
\ No newline at end of file
index 95f999b..3022e8f 100644 (file)
@@ -282,4 +282,49 @@ class core_cache_renderer extends plugin_renderer_base {
         $html .= html_writer::end_tag('div');
         return $html;
     }
+
+    /**
+     * Display basic information about lock instances.
+     *
+     * @todo Add some actions so that people can configure lock instances.
+     *
+     * @param array $locks
+     * @return string
+     */
+    public function lock_summaries(array $locks) {
+        $table = new html_table();
+        $table->colclasses = array(
+            'name',
+            'default',
+            'uses',
+            // 'actions'
+        );
+        $table->rowclasses = array(
+            'lock_name',
+            'lock_default',
+            'lock_uses',
+            // 'lock_actions',
+        );
+        $table->head = array(
+            get_string('lockname', 'cache'),
+            get_string('lockdefault', 'cache'),
+            get_string('lockuses', 'cache'),
+            // get_string('actions', 'cache')
+        );
+        $table->data = array();
+        $tick = $this->output->pix_icon('i/tick_green_big', '');
+        foreach ($locks as $lock) {
+            $table->data[] = new html_table_row(array(
+                new html_table_cell($lock['name']),
+                new html_table_cell($lock['default'] ? $tick : ''),
+                new html_table_cell($lock['uses']),
+            ));
+        }
+
+        $html = html_writer::start_tag('div', array('id' => 'core-cache-lock-summary'));
+        $html .= $this->output->heading(get_string('locksummary', 'cache'), 3);
+        $html .= html_writer::table($table);
+        $html .= html_writer::end_tag('div');
+        return $html;
+    }
 }
\ No newline at end of file
index 9035230..9b38be8 100644 (file)
@@ -102,21 +102,15 @@ class cache_phpunit_tests extends advanced_testcase {
         }
 
         $definitions = $instance->get_definitions();
-        // The default locking definition is required for the cache API and must be there.
-        $this->assertArrayHasKey('core/locking', $definitions);
         // The event invalidation definition is required for the cache API and must be there.
         $this->assertArrayHasKey('core/eventinvalidation', $definitions);
 
         $definitionmappings = $instance->get_definition_mappings();
-        // There should be a mapping for default locking to default_locking
         $found = false;
         foreach ($definitionmappings as $mapping) {
             // Required attributes = definition + store
             $this->assertArrayHasKey('definition', $mapping);
             $this->assertArrayHasKey('store', $mapping);
-            if ($mapping['store'] == 'default_locking' && $mapping['definition'] == 'core/locking') {
-                $found = true;
-            }
         }
         $this->assertTrue($found, 'The expected mapping for default locking definition to the default locking store was not found.');
     }
index 7ffc742..acd1b2a 100644 (file)
@@ -13,6 +13,7 @@ $string['cachedef_databasemeta'] = 'Database meta information';
 $string['cachedef_eventinvalidation'] = 'Event invalidation';
 $string['cachedef_locking'] = 'Locking';
 $string['cachedef_string'] = 'Language string cache';
+$string['cachelock_file_default'] = 'Default file locking';
 $string['cachestores'] = 'Cache stores';
 $string['component'] = 'Component';
 $string['confirmstoredeletion'] = 'Confirm store deletion';
@@ -20,7 +21,6 @@ $string['defaultmappings'] = 'Default mappings';
 $string['defaultmappings_help'] = 'These are the default stores that will be used if you don\'t map one or more stores to the cache definition.';
 $string['defaultstoreactions'] = 'Default stores cannot be modified';
 $string['default_application'] = 'Default application store';
-$string['default_locking'] = 'Default store for locking';
 $string['default_request'] = 'Default request store';
 $string['default_session'] = 'Default session store';
 $string['definition'] = 'Definition';
@@ -41,6 +41,12 @@ $string['gethit'] = 'Get - Hit';
 $string['getmiss'] = 'Get - Miss';
 $string['invalidplugin'] = 'Invalid plugin';
 $string['invalidstore'] = 'Invalid cache store provided';
+$string['lockdefault'] = 'Default';
+$string['lockmethod'] = 'Lock method';
+$string['lockmethod_help'] = 'This is the method used for locking when required of this store.';
+$string['lockname'] = 'Name';
+$string['locksummary'] = 'Summary of cache lock instances.';
+$string['lockuses'] = 'Uses';
 $string['mappings'] = 'Store mappings';
 $string['mappingdefault'] = '(default)';
 $string['mappingprimary'] = 'Primary store';
@@ -50,6 +56,7 @@ $string['modes'] = 'Modes';
 $string['mode_1'] = 'Application';
 $string['mode_2'] = 'Session';
 $string['mode_4'] = 'Request';
+$string['nativelocking'] = 'This plugin handles its own locking.';
 $string['none'] = 'None';
 $string['plugin'] = 'Plugin';
 $string['pluginsummaries'] = 'Plugin summaries';
@@ -70,7 +77,6 @@ $string['storeresults_request'] = 'Store requests when used as a request cache.'
 $string['storeresults_session'] = 'Store requests when used as a session cache.';
 $string['stores'] = 'Stores';
 $string['store_default_application'] = 'Default file store for application caches';
-$string['store_default_locking'] = 'Default file store for locking';
 $string['store_default_request'] = 'Default static store for request caches';
 $string['store_default_session'] = 'Default session store for session caches';
 $string['storesummaries'] = 'Store summaries';
index a3a32f2..7e2a076 100644 (file)
@@ -1,11 +1,32 @@
 <?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle 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 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle 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 Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Core cache definitions.
+ *
+ * This file is part of Moodle's cache API, affectionately called MUC.
+ * It contains the components that are requried in order to use caching.
+ *
+ * @package    core
+ * @category   cache
+ * @copyright  2012 Sam Hemelryk
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
 
 $definitions = array(
-    // Default cache for locking
-    'locking' => array(
-        'mode' => cache_store::MODE_APPLICATION,
-        'mappingsonly' => true,
-    ),
     'string' => array(
         'mode' => cache_store::MODE_APPLICATION,
         'component' => 'core',