/** * Test the maxsize option. */ public function test_maxsize() { $defid = 'phpunit/testmaxsize'; $config = cache_config_phpunittest::instance(); $config->phpunit_add_definition($defid, array('mode' => cache_store::MODE_REQUEST, 'component' => 'phpunit', 'area' => 'testmaxsize', 'maxsize' => 3)); $definition = cache_definition::load($defid, $config->get_definition_by_id($defid)); $instance = cachestore_static::initialise_test_instance($definition); $this->assertTrue($instance->set('key1', 'value1')); $this->assertTrue($instance->set('key2', 'value2')); $this->assertTrue($instance->set('key3', 'value3')); $this->assertTrue($instance->has('key1')); $this->assertTrue($instance->has('key2')); $this->assertTrue($instance->has('key3')); $this->assertTrue($instance->set('key4', 'value4')); $this->assertTrue($instance->set('key5', 'value5')); $this->assertFalse($instance->has('key1')); $this->assertFalse($instance->has('key2')); $this->assertTrue($instance->has('key3')); $this->assertTrue($instance->has('key4')); $this->assertTrue($instance->has('key5')); $this->assertFalse($instance->get('key1')); $this->assertFalse($instance->get('key2')); $this->assertEquals('value3', $instance->get('key3')); $this->assertEquals('value4', $instance->get('key4')); $this->assertEquals('value5', $instance->get('key5')); // Test adding one more. $this->assertTrue($instance->set('key6', 'value6')); $this->assertFalse($instance->get('key3')); // Test reducing and then adding to make sure we don't lost one. $this->assertTrue($instance->delete('key6')); $this->assertTrue($instance->set('key7', 'value7')); $this->assertEquals('value4', $instance->get('key4')); // Set the same key three times to make sure it doesn't count overrides. for ($i = 0; $i < 3; $i++) { $this->assertTrue($instance->set('key8', 'value8')); } $this->assertEquals('value7', $instance->get('key7'), 'Overrides are incorrectly incrementing size'); // Test adding many. $this->assertEquals(3, $instance->set_many(array(array('key' => 'keyA', 'value' => 'valueA'), array('key' => 'keyB', 'value' => 'valueB'), array('key' => 'keyC', 'value' => 'valueC')))); $this->assertEquals(array('key4' => false, 'key5' => false, 'key6' => false, 'key7' => false, 'keyA' => 'valueA', 'keyB' => 'valueB', 'keyC' => 'valueC'), $instance->get_many(array('key4', 'key5', 'key6', 'key7', 'keyA', 'keyB', 'keyC'))); }
/** * Purges a store given its name. * * @param string $storename * @return bool */ public static function purge_store($storename) { $config = cache_config::instance(); $stores = $config->get_all_stores(); if (!array_key_exists($storename, $stores)) { // The store does not exist. return false; } $store = $stores[$storename]; $class = $store['class']; // Found the store: is it ready? $instance = new $class($store['name'], $store['configuration']); if (!$instance->is_ready()) { unset($instance); return false; } foreach ($config->get_definitions_by_store($storename) as $id => $definition) { $definition = cache_definition::load($id, $definition); $instance = new $class($store['name'], $store['configuration']); $instance->initialise($definition); $instance->purge(); unset($instance); } return true; }
/** * Creates a definition instance or returns the existing one if it has already been created. * @param string $component * @param string $area * @param string $aggregate * @return cache_definition */ public function create_definition($component, $area, $aggregate = null) { $id = $component . '/' . $area; if ($aggregate) { $id .= '::' . $aggregate; } if (!array_key_exists($id, $this->definitions)) { // This is the first time this definition has been requested. if ($this->is_initialising()) { // We're initialising the cache right now. Don't try to create another config instance. // We'll just use an ad-hoc cache for the time being. $definition = cache_definition::load_adhoc(cache_store::MODE_REQUEST, $component, $area); } else { // Load all the known definitions and find the desired one. $instance = $this->create_config_instance(); $definition = $instance->get_definition_by_id($id); if (!$definition) { // Oh-oh the definition doesn't exist. // There are several things that could be going on here. // We may be installing/upgrading a site and have hit a definition that hasn't been used before. // Of the developer may be trying to use a newly created definition. if ($this->is_updating()) { // The cache is presently initialising and the requested cache definition has not been found. // This means that the cache initialisation has requested something from a cache (I had recursive nightmares about this). // To serve this purpose and avoid errors we are going to make use of an ad-hoc cache rather than // search for the definition which would possibly cause an infitite loop trying to initialise the cache. $definition = cache_definition::load_adhoc(cache_store::MODE_REQUEST, $component, $area); if ($aggregate !== null) { // If you get here you deserve a warning. We have to use an ad-hoc cache here, so we can't find the definition and therefor // can't find any information about the datasource or any of its aggregated. // Best of luck. debugging('An unknown cache was requested during development with an aggregate that could not be loaded. Ad-hoc cache used instead.', DEBUG_DEVELOPER); $aggregate = null; } } else { // Either a typo of the developer has just created the definition and is using it for the first time. $this->reset(); $instance = $this->create_config_instance(true); $instance->update_definitions(); $definition = $instance->get_definition_by_id($id); if (!$definition) { throw new coding_exception('The requested cache definition does not exist.' . $id, $id); } else { if (!$this->is_disabled()) { debugging('Cache definitions reparsed causing cache reset in order to locate definition. You should bump the version number to ensure definitions are reprocessed.', DEBUG_DEVELOPER); } } $definition = cache_definition::load($id, $definition, $aggregate); } } else { $definition = cache_definition::load($id, $definition, $aggregate); } } $this->definitions[$id] = $definition; } return $this->definitions[$id]; }
/** * Returns an array of stores that would meet the requirements for every definition. * * These stores would be 100% suitable to map as defaults for cache modes. * * @return array[] An array of stores, keys are the store names. */ public static function get_stores_suitable_for_mode_default() { $factory = cache_factory::instance(); $config = $factory->create_config_instance(); $requirements = 0; foreach ($config->get_definitions() as $definition) { $definition = cache_definition::load($definition['component'] . '/' . $definition['area'], $definition); $requirements = $requirements | $definition->get_requirements_bin(); } $stores = array(); foreach ($config->get_all_stores() as $name => $store) { if (!empty($store['features']) && $store['features'] & $requirements) { $stores[$name] = $store; } } return $stores; }
/** * Creates a definition instance or returns the existing one if it has already been created. * @param string $component * @param string $area * @param string $aggregate * @return cache_definition */ public function create_definition($component, $area, $aggregate = null) { $id = $component . '/' . $area; if ($aggregate) { $id .= '::' . $aggregate; } if (!array_key_exists($id, $this->definitions)) { $instance = $this->create_config_instance(); $definition = $instance->get_definition_by_id($id); if (!$definition) { $this->reset(); $instance = $this->create_config_instance(true); $instance->update_definitions(); $definition = $instance->get_definition_by_id($id); if (!$definition) { throw new coding_exception('The requested cache definition does not exist.' . $id, $id); } else { debugging('Cache definitions reparsed causing cache reset in order to locate definition. You should bump the version number to ensure definitions are reprocessed.', DEBUG_DEVELOPER); } } $this->definitions[$id] = cache_definition::load($id, $definition, $aggregate); } return $this->definitions[$id]; }
/** * Purges a cache of all information on a given event. * * @param string $event */ public static function purge_by_event($event) { $instance = cache_config::instance(); $invalidationeventset = false; $factory = cache_factory::instance(); foreach ($instance->get_definitions() as $name => $definitionarr) { $definition = cache_definition::load($name, $definitionarr); if ($definition->invalidates_on_event($event)) { // Purge the cache. $cache = $factory->create_cache($definition); $cache->purge(); // We need to flag the event in the "Event invalidation" cache if it hasn't already happened. if ($invalidationeventset === false) { // Get the event invalidation cache. $cache = cache::make('core', 'eventinvalidation'); // Create a key to invalidate all. $data = array('purged' => cache::now()); // Set that data back to the cache. $cache->set($event, $data); // This only needs to occur once. $invalidationeventset = true; } } } }
/** * Returns an array about the definitions. All the information a renderer needs. * @return array */ public static function get_definition_summaries() { $factory = cache_factory::instance(); $config = $factory->create_config_instance(); $storenames = array(); foreach ($config->get_all_stores() as $key => $store) { if (!empty($store['default'])) { $storenames[$key] = new lang_string('store_' . $key, 'cache'); } else { $storenames[$store['name']] = $store['name']; } } /* @var cache_definition[] $definitions */ $definitions = array(); foreach ($config->get_definitions() as $key => $definition) { $definitions[$key] = cache_definition::load($definition['component'] . '/' . $definition['area'], $definition); } foreach ($definitions as $id => $definition) { $mappings = array(); foreach (cache_helper::get_stores_suitable_for_definition($definition) as $store) { $mappings[] = $storenames[$store->my_name()]; } $return[$id] = array('id' => $id, 'name' => $definition->get_name(), 'mode' => $definition->get_mode(), 'component' => $definition->get_component(), 'area' => $definition->get_area(), 'mappings' => $mappings, 'canuselocalstore' => $definition->can_use_localstore(), 'sharingoptions' => self::get_definition_sharing_options($definition->get_sharing_options(), false), 'selectedsharingoption' => self::get_definition_sharing_options($definition->get_selected_sharing_option(), true), 'userinputsharingkey' => $definition->get_user_input_sharing_key()); } return $return; }