Changeset 1547

Show
Ignore:
Timestamp:
12/03/2006 04:57:44 PM (2 years ago)
Author:
xue
Message:

added cache dependency classes.

Location:
trunk
Files:
4 added
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/HISTORY

    r1541 r1547  
    22============================ 
    33BUG: Ticket#188 - Postback js caused controls not inheritable (Qiang) 
    4 ENH: Ticket#180, #222 - Prado js files are not rendered at the beginning of the form (Qiang) 
    54ENH: Ticket#99 - TXmlTransform control (Knut) 
    65ENH: Ticket#117 - added support to configure subproperties in a group. (Qiang) 
     6ENH: Ticket#180, #222 - Prado js files are not rendered at the beginning of the form (Qiang) 
     7CHG: All validators ClientSide.OnSuccess becomes ClientSide.OnValidationSuccess, and OnSuccess event becomes OnValidationSuccess. (Wei) 
     8CHG: All validators ClientSide.OnError becomes ClientSide.OnValidationError, and OnError event becomes OnValidationError. (Wei) 
    79NEW: Ajax support and active controls (Wei) 
    810NEW: Data abstraction layer based on PDO (Qiang) 
     
    1315NEW: TFeedService, TRssFeedDocument (Knut, Qiang) 
    1416NEW: TJsonService 
    15 CHG: All validators ClientSide.OnSuccess becomes ClientSide.OnValidationSuccess, and OnSuccess event becomes OnValidationSuccess. (Wei) 
    16 CHG: All validators ClientSide.OnError becomes ClientSide.OnValidationError, and OnError event becomes OnValidationError. (Wei) 
     17NEW: TCacheDependency, TFileCacheDependency, TDirectoryCacheDependency, TGlobalStateCacheDependency, TChainedCacheDependency 
    1718 
    1819Version 3.0.6 December 4, 2006 
  • trunk/framework/Caching/TCache.php

    r1398 r1547  
    11<?php 
    22/** 
    3  * TCache class file. 
     3 * TCache and cache dependency classes. 
    44 * 
    55 * @author Qiang Xue <qiang.xue@gmail.com> 
     
    1010 * @package System.Caching 
    1111 */ 
     12 
     13Prado::using('System.Collections.TList'); 
    1214 
    1315/** 
     
    230232} 
    231233 
     234 
     235/** 
     236 * TCacheDependency class. 
     237 * 
     238 * TCacheDependency is the base class implementing {@link ICacheDependency} interface. 
     239 * Descendant classes must implement {@link checkChanges()} to provide 
     240 * actual dependency checking logic. 
     241 * 
     242 * The property value of {@link getHasChanged HasChanged} tells whether 
     243 * the dependency is changed or not. 
     244 * 
     245 * You may disable the dependency checking by setting {@link setEnabled Enabled} 
     246 * to false. 
     247 * 
     248 * Note, since the dependency objects often need to be serialized so that 
     249 * they can persist across requests, you may need to implement __sleep() and 
     250 * __wakeup() if the dependency objects contain resource handles which are 
     251 * not serializable. 
     252 * 
     253 * Currently, the following dependency classes are provided in the PRADO release: 
     254 * - {@link TFileCacheDependency}: checks whether a file is changed or not 
     255 * - {@link TDirectoryCacheDependency}: checks whether a directory is changed or not 
     256 * - {@link TGlobalStateCacheDependency}: checks whether a global state is changed or not 
     257 * - {@link TChainedCacheDependency}: checks whether any of a list of dependencies is changed or not 
     258 * 
     259 * @author Qiang Xue <qiang.xue@gmail.com> 
     260 * @version $Id $ 
     261 * @package System.Caching 
     262 * @since 3.1.0 
     263 */ 
     264abstract class TCacheDependency extends TComponent implements ICacheDependency 
     265{ 
     266        private $_enabled=true; 
     267 
     268        /** 
     269         * @return boolean whether this dependency is enabled. Default value is true. 
     270         */ 
     271        public function getEnabled() 
     272        { 
     273                return $this->_enabled; 
     274        } 
     275 
     276        /** 
     277         * Sets a value indicating whether this cache dependency is enabled or not. 
     278         * Cache dependency checking is only performed when it is enabled. 
     279         * @param boolean whether this dependency is to be enabled. 
     280         */ 
     281        public function setEnabled($value) 
     282        { 
     283                $this->_enabled=TPropertyValue::ensureBoolean($value); 
     284        } 
     285 
     286        /** 
     287         * @return boolean whether the dependency is changed or not. 
     288         * If the dependency checking is disabled, it always returns false. 
     289         */ 
     290        public function getHasChanged() 
     291        { 
     292                return $this->_enabled ? $this->checkChanges() : false; 
     293        } 
     294 
     295        /** 
     296         * Performs the actual dependency checking. 
     297         * This method must be implemented by child classes. 
     298         * @return boolean whether the dependency is changed or not. 
     299         */ 
     300        abstract protected function checkChanges(); 
     301} 
     302 
     303 
     304/** 
     305 * TFileCacheDependency class. 
     306 * 
     307 * TFileCacheDependency performs dependency checking based on the 
     308 * last modification time of the file specified via {@link setFileName FileName}. 
     309 * The dependency is reported as unchanged if and only if the file's 
     310 * last modification time remains unchanged. 
     311 * 
     312 * @author Qiang Xue <qiang.xue@gmail.com> 
     313 * @version $Id $ 
     314 * @package System.Caching 
     315 * @since 3.1.0 
     316 */ 
     317class TFileCacheDependency extends TCacheDependency 
     318{ 
     319        private $_fileName; 
     320        private $_timestamp; 
     321 
     322        /** 
     323         * Constructor. 
     324         * @param string name of the file whose change is to be checked. 
     325         */ 
     326        public function __construct($fileName) 
     327        { 
     328                $this->setFileName($fileName); 
     329        } 
     330 
     331        /** 
     332         * @return string the name of the file whose change is to be checked 
     333         */ 
     334        public function getFileName() 
     335        { 
     336                return $this->_fileName; 
     337        } 
     338 
     339        /** 
     340         * @param string the name of the file whose change is to be checked 
     341         */ 
     342        public function setFileName($value) 
     343        { 
     344                $this->_fileName=$value; 
     345                $this->_timestamp=@filemtime($value); 
     346        } 
     347 
     348        /** 
     349         * @return int the last modification time of the file 
     350         */ 
     351        public function getTimestamp() 
     352        { 
     353                return $this->_timestamp; 
     354        } 
     355 
     356        /** 
     357         * Performs the actual dependency checking. 
     358         * This method returns true if the last modification time of the file is changed. 
     359         * @return boolean whether the dependency is changed or not. 
     360         */ 
     361        protected function checkChanges() 
     362        { 
     363                return @filemtime($this->_fileName)!==$this->_timestamp; 
     364        } 
     365} 
     366 
     367/** 
     368 * TDirectoryCacheDependency class. 
     369 * 
     370 * TDirectoryCacheDependency performs dependency checking based on the 
     371 * modification time of the files contained in the specified directory. 
     372 * The directory being checked is specified via {@link setDirectory Directory}. 
     373 * 
     374 * By default, all files under the specified directory and subdirectories 
     375 * will be checked. If the last modification time of any of them is changed 
     376 * or if different number of files are contained in a directory, the dependency 
     377 * is reported as changed. By specifying {@link setRecursiveCheck RecursiveCheck} 
     378 * and {@link setRecursiveLevel RecursiveLevel}, one can limit the checking 
     379 * to a certain depth of the subdirectories. 
     380 * 
     381 * @author Qiang Xue <qiang.xue@gmail.com> 
     382 * @version $Id $ 
     383 * @package System.Caching 
     384 * @since 3.1.0 
     385 */ 
     386class TDirectoryCacheDependency extends TCacheDependency 
     387{ 
     388        private $_recursiveCheck=true; 
     389        private $_recursiveLevel=-1; 
     390        private $_timestamps; 
     391        private $_directory; 
     392 
     393        /** 
     394         * Constructor. 
     395         * @param string the directory to be checked 
     396         */ 
     397        public function __construct($directory) 
     398        { 
     399                $this->setDirectory($directory); 
     400        } 
     401 
     402        /** 
     403         * @return string the directory to be checked 
     404         */ 
     405        public function getDirectory() 
     406        { 
     407                return $this->_directory; 
     408        } 
     409 
     410        /** 
     411         * @param string the directory to be checked 
     412         * @throws TInvalidDataValueException if the directory does not exist 
     413         */ 
     414        public function setDirectory($directory) 
     415        { 
     416                if(($path=realpath($directory))===false || !is_dir($path)) 
     417                        throw new TInvalidDataValueException('directorycachedependency_directory_invalid',$directory); 
     418                $this->_directory=$path; 
     419                $this->_timestamps=$this->generateTimestamps($path); 
     420        } 
     421 
     422        /** 
     423         * @return boolean whether the subdirectories of the directory will also be checked. 
     424         * It defaults to true. 
     425         */ 
     426        public function getRecursiveCheck() 
     427        { 
     428                return $this->_recursiveCheck; 
     429        } 
     430 
     431        /** 
     432         * @param boolean whether the subdirectories of the directory will also be checked. 
     433         */ 
     434        public function setRecursiveCheck($value) 
     435        { 
     436                $this->_recursiveCheck=TPropertyValue::ensureBoolean($value); 
     437        } 
     438 
     439        /** 
     440         * @return int the depth of the subdirectories to be checked. 
     441         * It defaults to -1, meaning unlimited depth. 
     442         */ 
     443        public function getRecursiveLevel() 
     444        { 
     445                return $this->_recursiveLevel; 
     446        } 
     447 
     448        /** 
     449         * Sets a value indicating the depth of the subdirectories to be checked. 
     450         * This is meaningful only when {@link getRecursiveCheck RecursiveCheck} 
     451         * is true. 
     452         * @param int the depth of the subdirectories to be checked. 
     453         * If the value is less than 0, it means unlimited depth. 
     454         * If the value is 0, it means checking the files directly under the specified directory. 
     455         */ 
     456        public function setRecursiveLevel($value) 
     457        { 
     458                $this->_recursiveLevel=TPropertyValue::ensureInteger($value); 
     459        } 
     460 
     461        /** 
     462         * Performs the actual dependency checking. 
     463         * This method returns true if the directory is changed. 
     464         * @return boolean whether the dependency is changed or not. 
     465         */ 
     466        protected function checkChanges() 
     467        { 
     468                return $this->generateTimestamps($this->_directory)!=$this->_timestamps; 
     469        } 
     470 
     471        /** 
     472         * Checks to see if the file should be checked for dependency. 
     473         * This method is invoked when dependency of the whole directory is being checked. 
     474         * By default, it always returns true, meaning the file should be checked. 
     475         * You may override this method to check only certain files. 
     476         * @param string the name of the file that may be checked for dependency. 
     477         * @return boolean whether this file should be checked. 
     478         */ 
     479        protected function validateFile($fileName) 
     480        { 
     481                return true; 
     482        } 
     483 
     484        /** 
     485         * Checks to see if the specified subdirectory should be checked for dependency. 
     486         * This method is invoked when dependency of the whole directory is being checked. 
     487         * By default, it always returns true, meaning the subdirectory should be checked. 
     488         * You may override this method to check only certain subdirectories. 
     489         * @param string the name of the subdirectory that may be checked for dependency. 
     490         * @return boolean whether this subdirectory should be checked. 
     491         */ 
     492        protected function validateDirectory($directory) 
     493        { 
     494                return true; 
     495        } 
     496 
     497        /** 
     498         * Determines the last modification time for files under the directory. 
     499         * This method may go recurisvely into subdirectories if 
     500         * {@link setRecursiveCheck RecursiveCheck} is set true. 
     501         * @param string the directory name 
     502         * @param int level of the recursion 
     503         * @return array list of file modification time indexed by the file path 
     504         */ 
     505        protected function generateTimestamps($directory,$level=0) 
     506        { 
     507                if(($dir=opendir($directory))===false) 
     508                        throw new TIOException('directorycachedependency_directory_invalid',$directory); 
     509                $timestamps=array(); 
     510                while(($file=readdir($dir))!==false) 
     511                { 
     512                        $path=$directory.DIRECTORY_SEPARATOR.$file; 
     513                        if($file==='.' || $file==='..') 
     514                                continue; 
     515                        else if(is_dir($path)) 
     516                        { 
     517                                if(($this->_recursiveLevel<0 || $level<$this->_recursiveLevel) && $this->validateDirectory($path)) 
     518                                        $timestamps=array_merge($this->generateTimestamps($path,$level+1)); 
     519                        } 
     520                        else if($this->validateFile($path)) 
     521                                $timestamps[$path]=filemtime($path); 
     522                } 
     523                closedir($dir); 
     524                return $timestamps; 
     525        } 
     526} 
     527 
     528 
     529/** 
     530 * TGlobalStateCacheDependency class. 
     531 * 
     532 * TGlobalStateCacheDependency checks if a global state is changed or not. 
     533 * If the global state is changed, the dependency is reported as changed. 
     534 * To specify which global state this dependency should check with, 
     535 * set {@link setStateName StateName} to the name of the global state. 
     536 * 
     537 * @author Qiang Xue <qiang.xue@gmail.com> 
     538 * @version $Id $ 
     539 * @package System.Caching 
     540 * @since 3.1.0 
     541 */ 
     542class TGlobalStateCacheDependency extends TCacheDependency 
     543{ 
     544        private $_stateName; 
     545        private $_stateValue; 
     546 
     547        /** 
     548         * Constructor. 
     549         * @param string the name of the global state 
     550         */ 
     551        public function __construct($name) 
     552        { 
     553                $this->setStateName($name); 
     554        } 
     555 
     556        /** 
     557         * @return string the name of the global state 
     558         */ 
     559        public function getStateName() 
     560        { 
     561                return $this->_stateName; 
     562        } 
     563 
     564        /** 
     565         * @param string the name of the global state 
     566         * @see TApplication::setGlobalState 
     567         */ 
     568        public function setStateName($value) 
     569        { 
     570                $this->_stateName=$value; 
     571                $this->_stateValue=Prado::getApplication()->getGlobalState($value); 
     572        } 
     573 
     574        /** 
     575         * Performs the actual dependency checking. 
     576         * This method returns true if the specified global state is changed. 
     577         * @return boolean whether the dependency is changed or not. 
     578         */ 
     579        protected function checkChanges() 
     580        { 
     581                return $this->_stateValue!==Prado::getApplication()->getGlobalState($value); 
     582        } 
     583} 
     584 
     585 
     586/** 
     587 * TChainedCacheDependency class. 
     588 * 
     589 * TChainedCacheDependency represents a list of cache dependency objects 
     590 * and performs the dependency checking based on the checking results of 
     591 * these objects. If any of them reports a dependency change, TChainedCacheDependency 
     592 * will return true for the checking. 
     593 * 
     594 * To add dependencies to TChainedCacheDependency, use {@link getDependencies Dependencies} 
     595 * which gives a {@link TCacheDependencyList} instance and can be used like an array 
     596 * (see {@link TList} for more details}). 
     597 * 
     598 * @author Qiang Xue <qiang.xue@gmail.com> 
     599 * @version $Id $ 
     600 * @package System.Caching 
     601 * @since 3.1.0 
     602 */ 
     603class TChainedCacheDependency extends TCacheDependency 
     604{ 
     605        private $_dependencies=null; 
     606 
     607        /** 
     608         * @return TCacheDependencyList list of dependency objects 
     609         */ 
     610        public function getDependencies() 
     611        { 
     612                if($this->_dependencies===null) 
     613                        $this->_dependencies=new TCacheDependencyList; 
     614                return $this->_dependencies; 
     615        } 
     616 
     617        /** 
     618         * Performs the actual dependency checking. 
     619         * This method returns true if any of the dependency objects 
     620         * reports a dependency change. 
     621         * @return boolean whether the dependency is changed or not. 
     622         */ 
     623        protected function checkChanges() 
     624        { 
     625                if($this->_dependencies!==null) 
     626                { 
     627                        foreach($this->_dependencies as $dependency) 
     628                                if($dependency->getHasChanged()) 
     629                                        return true; 
     630                } 
     631                return false; 
     632        } 
     633} 
     634 
     635 
     636/** 
     637 * TCacheDependencyList class. 
     638 * 
     639 * TCacheDependencyList represents a list of cache dependency objects. 
     640 * Only objects implementing {@link ICacheDependency} can be added into this list. 
     641 * 
     642 * TCacheDependencyList can be used like an array. See {@link TList} 
     643 * for more details. 
     644 * 
     645 * @author Qiang Xue <qiang.xue@gmail.com> 
     646 * @version $Id $ 
     647 * @package System.Caching 
     648 * @since 3.1.0 
     649 */ 
     650class TCacheDependencyList extends TList 
     651{ 
     652        /** 
     653         * Inserts an item at the specified position. 
     654         * This overrides the parent implementation by performing additional type checking 
     655         * for each newly added item. 
     656         * @param integer the speicified position. 
     657         * @param mixed new item 
     658         * @throws TInvalidDataTypeException if the item to be inserted is not a dependency instance 
     659         */ 
     660        public function insertAt($index,$item) 
     661        { 
     662                if($item instanceof ICacheDependency) 
     663                        parent::insertAt($index,$item); 
     664                else 
     665                        throw new TInvalidDataTypeException('cachedependencylist_cachedependency_required'); 
     666        } 
     667} 
     668 
    232669?> 
  • trunk/framework/Exceptions/messages.txt

    r1541 r1547  
    364364dbdatareader_rewind_invalid                             = TDbDataReader is a forward-only stream. It can only be traversed once. 
    365365dbtransaction_transaction_inactive              = TDbTransaction is inactive. 
     366 
     367directorycachedependency_directory_invalid = TDirectoryCacheDependency.Directory {0} does not refer to a valid directory. 
     368cachedependencylist_cachedependency_required = Only objects implementing ICacheDependency can be added into TCacheDependencyList. 
  • trunk/framework/interfaces.php

    r1399 r1547  
    230230 * cache dependencies. 
    231231 * 
     232 * Classes implementing this interface must support serialization and unserialization. 
     233 * 
    232234 * @author Qiang Xue <qiang.xue@gmail.com> 
    233235 * @version $Id$ 
     
    283285/** 
    284286 * IActiveControl interface. 
    285  *  
     287 * 
    286288 * Active controls must implement IActiveControl interface. 
    287  *  
     289 * 
    288290 * @author Wei Zhuo <weizhuo[at]gamil[dot]com> 
    289291 * @version $Id$ 
     
    296298         * @return TBaseActiveControl Active control properties. 
    297299         */ 
    298         public function getActiveControl();      
     300        public function getActiveControl(); 
    299301} 
    300302 
    301303/** 
    302304 * ICallbackEventHandler interface. 
    303  *  
     305 * 
    304306 * If a control wants to respond to callback event, it must implement this 
    305307 * interface. 
    306  *   
     308 * 
    307309 * @author Wei Zhuo <weizhuo[at]gamil[dot]com> 
    308310 * @version $Id$