protected function _parseXmlFile($xmlFilePath) { //Do we have caching enabled? if (function_exists("apc_fetch")) { if ($this->_log->isDebugEnabled()) { $this->_log->debug("APC caching is ENABLED"); } //Do we have a cache entry for this file path? $cacheKey = "bouncexml~{$xmlFilePath}"; $cacheContentSerialized = apc_fetch($cacheKey); //Cache Content structure is: // array( // "xmlFiles" => array( // "/absolute/path/to/parent.xml" => array( // "dev" => 5, //Device number from the underlying O/S // "ino" => 1234567, //Inode number of the file on the device // "mtime" => 124124681274 //Last modified time // ), // "/absolute/path/to/child1.xml" => array( // "dev" => 5, // "ino" => 345346364, // "mtime" => 124124681274 // ), // "/absolute/path/to/child2.xml" => array( // "dev" => 5, // "ino" => 345346364, // "mtime" => 124124681274 // ), // ), // "context" => Config_Context // ) if ($cacheContentSerialized) { if ($this->_log->isDebugEnabled()) { $this->_log->debug("Found cached version on {$xmlFilePath}"); } $cacheContent = unserialize($cacheContentSerialized); //Look at all the files from the cache content array to see //if any of them are different $filesToCheck = $cacheContent["xmlFiles"]; $cacheUpToDate = true; //Be positive ... foreach ($filesToCheck as $fileName => $cachedStatInfo) { //Stat the filename $onDiskStatInfo = $this->_getStatInfo($fileName); if ($onDiskStatInfo["mtime"] != $cachedStatInfo["mtime"] || $onDiskStatInfo["ino"] != $cachedStatInfo["ino"] || $onDiskStatInfo["dev"] != $cachedStatInfo["dev"]) { $cacheUpToDate = false; if ($this->_log->isDebugEnabled()) { $this->_log->debug("Cache out of date: {$fileName} has stat: " . print_r($onDiskStatInfo, true) . " but cached " . print_r($cachedStatInfo, true)); } break; } } if ($cacheUpToDate) { //Yes, so update the list of processed files for completeness, and //return the cached context /*foreach ($filesToCheck as $fileName => $cachedStatInfo) { $this->_processedFiles[$fileName] = $cacheContent["context"]; }*/ //TODO We can't update this any more since it's a map of child contexts, which we don't have if ($this->_log->isDebugEnabled()) { $this->_log->debug("Cache is up to date. Returning cached context"); } return $cacheContent["context"]; } } if ($this->_log->isDebugEnabled()) { $this->_log->debug("Cache item not found or invalid for {$xmlFilePath}. Reloading ..."); } //If we get here, we're basically not up to date one way or another //so load up the context, and cache it. $context = parent::_parseXmlFile($xmlFilePath); //Now create the cache structure. NOTE! It's possible that for a //nested content structure we're going to include files from the //processed list that had been processed *BEFORE* we loaded this //particular XML file. However, we can't tell which ones might //also be dependencies of this child file, and using another //XmlApplicationContext instance is impractical as it means exposing //way more of the internals as public variables purely for the purposes //of the caching system. $cacheContent = array("xmlFiles" => array(), "context" => $context); foreach (array_keys($this->_processedFiles) as $fileName) { $cacheContent["xmlFiles"][$fileName] = $this->_getStatInfo($fileName); } $cacheContentStr = serialize($cacheContent); apc_store($cacheKey, $cacheContentStr); if ($this->_log->isDebugEnabled()) { $this->_log->debug("Cache item added for {$xmlFilePath}"); } //Return it return $context; } else { $this->_log->warn("APC caching is DISABLED"); //No caching possible, so revert to the normal method of //reading from the filesystem all the time return parent::_parseXmlFile($xmlFilePath); } }