Index: branches/5.2.x/core/kernel/utility/cache.php =================================================================== diff -u -N -r14840 -r15095 --- branches/5.2.x/core/kernel/utility/cache.php (.../cache.php) (revision 14840) +++ branches/5.2.x/core/kernel/utility/cache.php (.../cache.php) (revision 15095) @@ -1,6 +1,6 @@ _getCache($name . '_rebuild') ) { + $cached_data = $this->_getCache(Array ($name . '_rebuild', $name . '_serials'), Array (true, true)); + + if ( $cached_data[$name . '_rebuild'] ) { // cache rebuild requested -> rebuild now $this->delete($name . '_rebuild'); return false; } $new_serial = $this->replaceSerials($name); - $old_serial = $this->_getCache($name . '_serials'); + $old_serial = $cached_data[$name . '_serials']; if ( $name == $new_serial || $new_serial != $old_serial ) { // no serials in cache key OR cache is outdated $wait_seconds = $max_rebuild_seconds; while (true) { - $cache = $this->_getCache($name, $store_locally); - $rebuilding = $this->_getCache($name . '_rebuilding', false); + $cached_data = $this->_getCache(Array ($name, $name . '_rebuilding'), Array ($store_locally, false)); + $cache = $cached_data[$name]; + $rebuilding = $cached_data[$name . '_rebuilding']; if ( ($cache === false) && (!$rebuilding || $wait_seconds == 0) ) { // cache missing and nobody rebuilding it -> rebuild; enough waiting for cache to be ready @@ -249,39 +252,77 @@ /** * Returns value from cache * - * @param string $name - * @param bool $store_locally store data locally after retrieved + * @param string|Array $names + * @param bool|Array $store_locally store data locally after retrieved * @return mixed */ - function _getCache($name, $store_locally = true) + function _getCache($names, $store_locally = true) { - $name = $this->prepareKeyName($name); + static $request_number = 1; - if ($store_locally) { - if ( array_key_exists($name, $this->_localStorage) ) { + $res = Array (); + $names = (array)$names; + $store_locally = (array)$store_locally; + $to_get = $prepared_names = array_map(Array (&$this, 'prepareKeyName'), $names); + + foreach ($prepared_names as $index => $prepared_name) { + $name = $names[$index]; + + if ( $store_locally[$index] && array_key_exists($prepared_name, $this->_localStorage) ) { if ( $this->displayCacheStatistics ) { - $this->setStatistics($name, $this->_localStorage[$name]); + $this->setStatistics($prepared_name, $this->_localStorage[$prepared_name]); } - return $this->_localStorage[$name]; + $res[$name] = $this->_localStorage[$prepared_name]; + unset($to_get[$index]); } } - $res = $this->_handler->get($name); + $multi_res = $this->_handler->get($to_get); - if ($this->debugCache) { + foreach ($to_get as $index => $prepared_name) { + $name = $names[$index]; + + if ( array_key_exists($prepared_name, $multi_res) ) { + $res[$name] =& $multi_res[$prepared_name]; + } + else { + $res[$name] = false; + } + + $this->_postProcessGetCache($prepared_name, $res[$name], $store_locally[$index], $request_number); + } + + $request_number++; + + return count($res) == 1 ? array_pop($res) : $res; + } + + /** + * Stores variable in local cache & collects debug info about cache + * + * @param string $name + * @param mixed $res + * @param bool $store_locally + * @param int $request_number + * @return void + * @access protected + */ + protected function _postProcessGetCache($name, &$res, $store_locally = true, $request_number) + { + if ( $this->debugCache ) { // don't display subsequent serial cache retrievals (ones, that are part of keys) - if (is_array($res)) { - $this->Application->Debugger->appendHTML('Restoring key "' . $name . '". Type: ' . gettype($res) . '.'); + if ( is_array($res) ) { + $this->Application->Debugger->appendHTML('r' . $request_number . ': Restoring key "' . $name . '". Type: ' . gettype($res) . '.'); } else { $res_display = strip_tags($res); - if (strlen($res_display) > 200) { + if ( strlen($res_display) > 200 ) { $res_display = substr($res_display, 0, 50) . ' ...'; } - $this->Application->Debugger->appendHTML('Restoring key "' . $name . '" resulted [' . $res_display . ']'); + $this->Application->Debugger->appendHTML('r' . $request_number . ': Restoring key "' . $name . '" resulted [' . $res_display . ']'); } } @@ -292,8 +333,6 @@ $this->setStatistics($name, $res); } } - - return $res; } /** @@ -354,9 +393,23 @@ // [%LangSerial%] - prefix-wide serial in case of any change in "lang" prefix // [%LangIDSerial:5%] - one id-wide serial in case of data, associated with given id was changed // [%CiIDSerial:ItemResourceId:5%] - foreign key-based serial in case of data, associated with given foreign key was changed - foreach ($regs[1] as $serial_name) { - $value = str_replace('[%' . $serial_name . '%]', '[' . $serial_name . '=' . $this->_getCache($serial_name, true) . ']', $value); + $serial_names = $regs[1]; + $serial_count = count($serial_names); + $store_locally = Array (); + + for ($i = 0; $i < $serial_count; $i++) { + $store_locally[] = true; } + + $serial_values = $this->_getCache($serial_names, $store_locally); + + if ( !is_array($serial_values) ) { + $serial_values[ current($serial_names) ] = $serial_values; + } + + foreach ($serial_names as $serial_name) { + $value = str_replace('[%' . $serial_name . '%]', '[' . $serial_name . '=' . $serial_values[$serial_name] . ']', $value); + } } return $value; @@ -454,11 +507,21 @@ /** * Retrieves value from cache * - * @param string $name + * @param string $names * @return mixed */ - function get($name) + function get($names) { + if ( is_array($names) ) { + $res = Array (); + + foreach ($names as $name) { + $res[$name] = false; + } + + return $res; + } + return false; } @@ -670,12 +733,22 @@ /** * Retrieves value from cache * - * @param string $name + * @param string|Array $names * @return mixed */ - function get($name) + function get($names) { - return xcache_isset($name) ? xcache_get($name) : false; + if ( is_array($names) ) { + $res = Array (); + + foreach ($names as $name) { + $res[$name] = $this->get($name); + } + + return $res; + } + + return xcache_isset($names) ? xcache_get($names) : false; } /**