Index: branches/5.2.x/core/kernel/managers/cache_manager.php =================================================================== diff -u -N -r15073 -r15095 --- branches/5.2.x/core/kernel/managers/cache_manager.php (.../cache_manager.php) (revision 15073) +++ branches/5.2.x/core/kernel/managers/cache_manager.php (.../cache_manager.php) (revision 15095) @@ -1,6 +1,6 @@ _getDBCache($name . '_rebuild') ) { - // cache rebuild requested -> rebuild now - $this->deleteDBCache($name . '_rebuild'); - - return false; - } - // no serials in cache key OR cache is outdated $wait_seconds = $max_rebuild_seconds; while (true) { - $cache = $this->_getDBCache($name); - $rebuilding = $this->_getDBCache($name . '_rebuilding'); + $cached_data = $this->_getDBCache(Array ($name, $name . '_rebuilding', $name . '_rebuild')); + if ( $cached_data[$name . '_rebuild'] ) { + // cache rebuild requested -> rebuild now + $this->deleteDBCache($name . '_rebuild'); + + return 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 return false; @@ -620,36 +622,45 @@ /** * Returns value from database cache * - * @param string $name key name + * @param string|Array $names key name * @return mixed * @access protected */ - protected function _getDBCache($name) + protected function _getDBCache($names) { + $res = Array (); + $names = (array)$names; $this->Conn->nextQueryCachable = true; - $sql = 'SELECT Data, Cached, LifeTime + $sql = 'SELECT Data, Cached, LifeTime, VarName FROM ' . TABLE_PREFIX . 'SystemCache - WHERE VarName = ' . $this->Conn->qstr($name); - $data = $this->Conn->GetRow($sql); + WHERE VarName IN (' . implode(',', $this->Conn->qstrArray($names)) . ')'; + $cached_data = $this->Conn->Query($sql, 'VarName'); - if ($data) { - $lifetime = (int)$data['LifeTime']; // in seconds - if (($lifetime > 0) && ($data['Cached'] + $lifetime < adodb_mktime())) { + foreach ($names as $name) { + if ( !isset($cached_data[$name]) ) { + $res[$name] = false; + continue; + } + + $lifetime = (int)$cached_data[$name]['LifeTime']; // in seconds + + if ( ($lifetime > 0) && ($cached_data[$name]['Cached'] + $lifetime < adodb_mktime()) ) { // delete expired $this->Conn->nextQueryCachable = true; $sql = 'DELETE FROM ' . TABLE_PREFIX . 'SystemCache WHERE VarName = ' . $this->Conn->qstr($name); $this->Conn->Query($sql); - return false; + $res[$name] = false; + continue; } - return $data['Data']; + $res[$name] = $cached_data[$name]['Data']; } - return false; + return count($res) == 1 ? array_pop($res) : $res; } /** 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; } /**