Index: trunk/core/kernel/utility/unit_config_reader.php =================================================================== diff -u -r4594 -r4758 --- trunk/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 4594) +++ trunk/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 4758) @@ -13,6 +13,8 @@ var $CacheExpired = false; + var $prefixFiles = array(); + /** * Scan kernel and user classes * for available configs @@ -22,7 +24,6 @@ function Init($prefix,$special) { parent::Init($prefix,$special); - $this->scanModules(MODULES_PATH); } /** @@ -38,7 +39,8 @@ foreach($this->Application->ModuleInfo as $module_name => $module_info) { $module_path = '/'.$module_info['Path']; - if (substr($config_path, 0, strlen($module_path)) == $module_path) { + if (preg_match('/^'.preg_quote($module_path, '/').'/', $config_path)) { +// if (substr($config_path, 0, strlen($module_path)) == $module_path) { // config file path starts with module folder path $module_found = true; break; @@ -81,17 +83,17 @@ if ( in_array($file, get_required_files()) ) return; global $debugger; - $debugger->IncludeLevel++; + /*$debugger->IncludeLevel++; $before_time = getmicrotime(); - $before_mem = memory_get_usage(); - include_once(FULL_PATH.$file); - $used_time = getmicrotime() - $before_time; + $before_mem = memory_get_usage();*/ + k4_include_once(FULL_PATH.$file); + /*$used_time = getmicrotime() - $before_time; $used_mem = memory_get_usage() - $before_mem; $debugger->IncludeLevel--; $debugger->IncludesData['file'][] = str_replace(FULL_PATH, '', $file); $debugger->IncludesData['mem'][] = $used_mem; $debugger->IncludesData['time'][] = $used_time; - $debugger->IncludesData['level'][] = -1; + $debugger->IncludesData['level'][] = -1;*/ } else { include_once($file); @@ -105,7 +107,7 @@ } } } - + function postProcessConfig($prefix, $config_key, $dst_prefix_var) { $main_config =& $this->configData[$prefix]; @@ -114,27 +116,36 @@ return false; } unset($main_config[$config_key]); - + foreach ($sub_configs as $sub_prefix => $sub_config) { + if ($config_key == 'AggregateConfigs' && !isset($this->configData[$sub_prefix])) { + $this->loadConfig($sub_prefix); + } $sub_config['Prefix'] = $sub_prefix; $this->configData[$sub_prefix] = array_merge_recursive2($this->configData[$$dst_prefix_var], $sub_config); - + // when merging empty array to non-empty results non-empty array, but empty is required foreach ($sub_config as $sub_key => $sub_value) { if (!$sub_value) { unset($this->configData[$sub_prefix][$sub_key]); } } + if ($config_key == 'Clones') { + $this->prefixFiles[$sub_prefix] = $this->prefixFiles[$prefix]; + } $this->postProcessConfig($sub_prefix, $config_key, $dst_prefix_var); + if ($config_key == 'AggregateConfigs') { + $this->postProcessConfig($sub_prefix, 'Clones', 'prefix'); + } } - + if (!$prefix) { // configs, that used only for cloning & not used ifself unset($this->configData[$prefix]); } } - + function ParseConfigs() { foreach ($this->configData as $prefix => $config) { @@ -144,12 +155,101 @@ $this->Application->HandleEvent( new kEvent('m:OnAfterConfigRead') ); } + function CacheParsedData() + { + $event_manager =& $this->Application->recallObject('EventManager'); + $aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray'); + + $config_vars = Array( + 'SessionTimeout', + 'SessionCookieName', + 'SessionReferrerCheck', + 'CookieSessions', + 'UseCronForRegularEvent', + 'User_GuestGroup', + 'User_LoggedInGroup', + 'SessionTimeout', + 'UseModRewrite', + 'AdminDirectory', + ); + + foreach ($config_vars as $var) { + $this->Application->ConfigValue($var); + } + + $cache = Array( + 'Factory.Files' => $this->Application->Factory->Files, + 'Factory.realClasses' => $this->Application->Factory->realClasses, + 'Factory.Dependencies' => $this->Application->Factory->Dependencies, + 'ConfigReader.prefixFiles' => $this->prefixFiles, + 'EventManager.buildEvents' => $event_manager->buildEvents, + 'EventManager.beforeRegularEvents' => $event_manager->beforeRegularEvents, + 'EventManager.afterRegularEvents' => $event_manager->afterRegularEvents, + 'EventManager.beforeHooks' => $event_manager->beforeHooks, + 'EventManager.afterHooks' => $event_manager->afterHooks, + 'TagsAggregator.data' => $aggregator->_Array, + + // the following caches should be reset based on admin interaction (adjusting config, enabling modules etc) + 'Application.Caches.ConfigVariables' => $this->Application->Caches['ConfigVariables'], + 'Application.ConfigCacheIds' => $this->Application->ConfigCacheIds, + 'Application.ConfigHash' => $this->Application->ConfigHash, + 'Application.ModuleInfo' => $this->Application->ModuleInfo, + ); + + $conn =& $this->Application->GetADODBConnection(); + $conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("configs_parsed", '.$conn->qstr(serialize($cache)).', '.adodb_mktime().')'); + } + + function ResetParsedData($include_sections=false) + { + $conn =& $this->Application->GetADODBConnection(); + $conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = "configs_parsed"'); + + if ($include_sections) { + $conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = "sections_parsed"'); + } + } + + function RestoreParsedData() + { + $conn =& $this->Application->GetADODBConnection(); + $data = $conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "configs_parsed"'); + if ($data && $data['Cached'] > 0 ) { + $cache = unserialize($data['Data']); + $this->Application->Factory->Files = $cache['Factory.Files']; + $this->Application->Factory->realClasses = $cache['Factory.realClasses']; + $this->Application->Factory->Dependencies = $cache['Factory.Dependencies']; + $this->prefixFiles = $cache['ConfigReader.prefixFiles']; + + $event_manager =& $this->Application->recallObject('EventManager'); + $event_manager->buildEvents = $cache['EventManager.buildEvents']; + $event_manager->beforeRegularEvents = $cache['EventManager.beforeRegularEvents']; + $event_manager->afterRegularEvents = $cache['EventManager.afterRegularEvents']; + $event_manager->beforeHooks = $cache['EventManager.beforeHooks']; + $event_manager->afterHooks = $cache['EventManager.afterHooks']; + + $aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray'); + $aggregator->_Array = $cache['TagsAggregator.data']; + + $this->Application->ConfigHash = $cache['Application.ConfigHash']; + + $this->Application->Caches['ConfigVariables'] = $cache['Application.ConfigCacheIds']; + $this->Application->ConfigCacheIds = $cache['Application.ConfigCacheIds']; + + $this->Application->ModuleInfo = $cache['Application.ModuleInfo']; + + return true; + + } + else return false; + } + function findConfigFiles($folderPath) { // if FULL_PATH = "/" ensure, that all "/" in $folderPath are not deleted $reg_exp = '/^'.preg_quote(FULL_PATH, '/').'/'; $folderPath = preg_replace($reg_exp, '', $folderPath, 1); // this make sense, since $folderPath may NOT contain FULL_PATH - + $fh=opendir(FULL_PATH.$folderPath); while(($sub_folder=readdir($fh))) { @@ -169,116 +269,48 @@ function includeConfigFiles() { - $db =& $this->Application->GetADODBConnection(); - - foreach ($this->configFiles as $filename) - { - $config_found = file_exists(FULL_PATH.$filename) && $this->configAllowed($filename); - if( $this->Application->isDebugMode() && constOn('DBG_PROFILE_INCLUDES') ) - { - if ( in_array($filename, get_required_files()) ) return; - global $debugger; - $debugger->IncludeLevel++; - $before_time = getmicrotime(); - $before_mem = memory_get_usage(); - if($config_found) include_once(FULL_PATH.$filename); - $used_time = getmicrotime() - $before_time; - $used_mem = memory_get_usage() - $before_mem; - $debugger->IncludeLevel--; - $debugger->IncludesData['file'][] = str_replace(FULL_PATH, '', $filename); - $debugger->IncludesData['mem'][] = $used_mem; - $debugger->IncludesData['time'][] = $used_time; - $debugger->IncludesData['level'][] = -1; - } - else - { - if($config_found) include_once(FULL_PATH.$filename); - } - - if($config_found && isset($config) && $config) - { - $prefix = isset($config['Prefix']) ? $config['Prefix'] : ''; - - preg_match('/\/(.*)\//U', $filename, $rets); - $config['ModuleFolder'] = $rets[1]; - $config['BasePath'] = dirname(FULL_PATH.$filename); - $this->configData[$prefix] = $config; - - $this->postProcessConfig($prefix, 'AggregateConfigs', 'sub_prefix'); - $this->postProcessConfig($prefix, 'Clones', 'prefix'); - } - } - } - - function scanModules($folderPath) - { - global $debugger; - + $this->Application->refreshModuleInfo(); if (defined('CACHE_CONFIGS_FILES')) { $conn =& $this->Application->GetADODBConnection(); $data = $conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "config_files"'); -// if ($data && $data['Cached'] > (adodb_mktime() - 3600) ) { if ($data && $data['Cached'] > 0 ) { $this->configFiles = unserialize($data['Data']); $files_cached = $data['Cached']; } else { - $files_cached = 0; + $this->findConfigFiles($folderPath); } } else { - $files_cached = 0; + $this->findConfigFiles($folderPath); } - if (defined('CACHE_CONFIGS_DATA') && CACHE_CONFIGS_DATA) { - $conn =& $this->Application->GetADODBConnection(); - $data = $conn->GetRow('SELECT Data, Cached FROM '.TABLE_PREFIX.'Cache WHERE VarName = "config_data"'); - if ($data && $data['Cached'] > (adodb_mktime() - 3600) ) { - $this->configData = unserialize($data['Data']); - $data_cached = $data['Cached']; - } - else { - $data_cached = 0; - } - } - else { - $data_cached = 0; - } - if ( !defined('CACHE_CONFIGS_FILES') || $files_cached == 0 ) { - $this->findConfigFiles($folderPath); + foreach ($this->configFiles as $filename) + { + $this->loadConfigFile($filename); } + } - if ( !defined('CACHE_CONFIGS_DATA') || $data_cached == 0) { - $this->includeConfigFiles(); + function scanModules($folderPath) + { + if (defined('CACHE_PARSED_CONFIGS') && CACHE_PARSED_CONFIGS) { + $restored = $this->RestoreParsedData(); + if ($restored) return; } + $this->includeConfigFiles(); + $this->ParseConfigs(); - /*// && (adodb_mktime() - $cached) > 600) - to skip checking files modified dates - if ( !defined('CACHE_CONFIGS') ) { - $fh=opendir($folderPath); - while(($sub_folder=readdir($fh))) - { - $full_path=$folderPath.'/'.$sub_folder.'/units'; - if( $this->isDir($full_path) ) - { - $this->processFolder($full_path, $cached); - } - } - }*/ - - if (defined('CACHE_CONFIGS_DATA') && $data_cached == 0) { - $conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("config_data", '.$conn->qstr(serialize($this->configData)).', '.adodb_mktime().')'); + if (defined('CACHE_PARSED_CONFIGS')) { + $this->CacheParsedData(); } - $this->ParseConfigs(); - if (defined('CACHE_CONFIGS_FILES') && $files_cached == 0) { + $conn =& $this->Application->GetADODBConnection(); $conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("config_files", '.$conn->qstr(serialize($this->configFiles)).', '.adodb_mktime().')'); } unset($this->configFiles); -// unset($this->configData); - } /** @@ -330,16 +362,16 @@ if (isset($config['ParentPrefix']) && $hook['HookToPrefix'] == $config['ParentPrefix']) { trigger_error('Depricated Hook Usage [prefix: '.$config['Prefix'].'; do_prefix: '.$hook['DoPrefix'].'] use #PARENT# and HookToPrefix value where HookToPrefix is same as ParentPrefix', E_USER_NOTICE); } - + if ($hook['HookToPrefix'] == '') { $hook['HookToPrefix'] = $config['Prefix']; // new: set hooktoprefix to current prefix if not set } - + if (isset($config['ParentPrefix']) && $hook['HookToPrefix'] == '#PARENT#') { // new: allow to set hook to parent prefix what ever it is $hook['HookToPrefix'] = $config['ParentPrefix']; } - + $do_prefix = $hook['DoPrefix'] == '' ? $config['Prefix'] : $hook['DoPrefix']; if ( !is_array($hook['HookToEvent']) ) { @@ -395,6 +427,62 @@ } } + function loadConfigFile($filename) + { + $config_found = file_exists(FULL_PATH.$filename) && $this->configAllowed($filename); + + if( defined('DEBUG_MODE') && DEBUG_MODE && constOn('DBG_PROFILE_INCLUDES') ) + { + if ( in_array($filename, get_required_files()) ) return; + global $debugger; + /*$debugger->IncludeLevel++; + $before_time = getmicrotime(); + $before_mem = memory_get_usage();*/ + if($config_found) { + $file = FULL_PATH.$filename; + $debugger->ProfileStart('inc_'.crc32($file), $file); + include_once($file); + $debugger->ProfileFinish('inc_'.crc32($file)); + $debugger->profilerAddTotal('includes', 'inc_'.crc32($file)); + } + /*$used_time = getmicrotime() - $before_time; + $used_mem = memory_get_usage() - $before_mem; + $debugger->IncludeLevel--; + $debugger->IncludesData['file'][] = str_replace(FULL_PATH, '', $filename); + $debugger->IncludesData['mem'][] = $used_mem; + $debugger->IncludesData['time'][] = $used_time; + $debugger->IncludesData['level'][] = -1;*/ + } + else + { + if($config_found) include_once(FULL_PATH.$filename); + } + + if($config_found && isset($config) && $config) + { + $prefix = isset($config['Prefix']) ? $config['Prefix'] : ''; + + preg_match('/\/(.*)\//U', $filename, $rets); + $config['ModuleFolder'] = $rets[1]; + $config['BasePath'] = dirname(FULL_PATH.$filename); + $this->configData[$prefix] = $config; + $this->prefixFiles[$prefix] = $filename; + + $this->postProcessConfig($prefix, 'AggregateConfigs', 'sub_prefix'); + $this->postProcessConfig($prefix, 'Clones', 'prefix'); + } + } + + function loadConfig($prefix) + { + if (!isset($this->prefixFiles[$prefix])) { + trigger_error('Configuration file for prefix '.$prefix.' is unknown', E_USER_ERROR); + return ; + } + $file = $this->prefixFiles[$prefix]; + $this->loadConfigFile($file); + } + /** * Reads unit (specified by $prefix) * option specified by $option @@ -408,9 +496,15 @@ function getUnitOption($prefix, $name, $default = false) { if (preg_match('/(.*)\.(.*)/', $prefix, $rets)) { + if (!isset($this->configData[$rets[1]])) { + $this->loadConfig($rets[1]); + } $ret = getArrayValue($this->configData, $rets[1], $name, $rets[2]); } else { + if (!isset($this->configData[$prefix])) { + $this->loadConfig($prefix); + } $ret = getArrayValue($this->configData, $prefix, $name); } return $ret === false ? $default : $ret;