Skip to content

Commit

Permalink
Merge pull request yiisoft#2444 from resurtm/fixes-2435-CFileCache-en…
Browse files Browse the repository at this point in the history
…hancements

Fixes yiisoft#2435: CFileCache entry expiration time could now be embedded into the cache file.
  • Loading branch information
resurtm committed May 28, 2013
2 parents 2ea6127 + d749ecf commit 0bb122f
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Version 1.1.14 work in progress
- Enh #2275: Added primary log rotation by copy and truncate to CFileLogRoute (bdstevens)
- Enh #2415: Cancel current ajax request before create a new one in CGridView and CListView (gusnips)
- Enh #2416: Avoid instantiating HTMLPurifier on each CHtmlPurifier::purify() call. Allow to pass array as argument of CHtmlPurifier::purify() (twisted1919)
- Enh #2435: CFileCache entry expiration time could now be embedded into the cache file instead of changing file's modification time to be in future (resurtm)
- Enh #2459: Absolute session timeout in CWebUser (ivokund)
- Enh #2494: Allow to configure CBaseListView emptyText container tag name (ifdattic)
- Chg: Upgraded HTMLPurifier to v4.5.0 (samdark)
Expand Down
34 changes: 28 additions & 6 deletions framework/caching/CFileCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ class CFileCache extends CCache
* The value of this property should not exceed 16 (less than 3 is recommended).
*/
public $directoryLevel=0;
/**
* @var boolean whether cache entry expiration time should be embedded into a physical file.
* Defaults to false meaning that the file modification time will be used to store expire value.
* True value means that first ten bytes of the file would be reserved and used to store expiration time.
* On some systems PHP is not allowed to change file modification time to be in future even with 777
* permissions, so this property could be useful in this case.
* @since 1.1.14
*/
public $embedExpiry=false;

private $_gcProbability=100;
private $_gced=false;
Expand Down Expand Up @@ -103,8 +112,8 @@ protected function flushValues()
protected function getValue($key)
{
$cacheFile=$this->getCacheFile($key);
if(($time=@filemtime($cacheFile))>time())
return @file_get_contents($cacheFile);
if(($time=$this->filemtime($cacheFile))>time())
return @file_get_contents($cacheFile,false,null,$this->embedExpiry ? 10 : -1);
elseif($time>0)
@unlink($cacheFile);
return false;
Expand Down Expand Up @@ -134,10 +143,10 @@ protected function setValue($key,$value,$expire)
$cacheFile=$this->getCacheFile($key);
if($this->directoryLevel>0)
@mkdir(dirname($cacheFile),0777,true);
if(@file_put_contents($cacheFile,$value,LOCK_EX)!==false)
if(@file_put_contents($cacheFile,$this->embedExpiry ? $expire.$value : $value,LOCK_EX)!==false)
{
@chmod($cacheFile,0777);
return @touch($cacheFile,$expire);
return $this->embedExpiry ? true : @touch($cacheFile,$expire);
}
else
return false;
Expand All @@ -155,7 +164,7 @@ protected function setValue($key,$value,$expire)
protected function addValue($key,$value,$expire)
{
$cacheFile=$this->getCacheFile($key);
if(@filemtime($cacheFile)>time())
if($this->filemtime($cacheFile)>time())
return false;
return $this->setValue($key,$value,$expire);
}
Expand Down Expand Up @@ -212,9 +221,22 @@ public function gc($expiredOnly=true,$path=null)
$fullPath=$path.DIRECTORY_SEPARATOR.$file;
if(is_dir($fullPath))
$this->gc($expiredOnly,$fullPath);
elseif($expiredOnly && @filemtime($fullPath)<time() || !$expiredOnly)
elseif($expiredOnly && $this->filemtime($fullPath)<time() || !$expiredOnly)
@unlink($fullPath);
}
closedir($handle);
}

/**
* Returns cache file modification time. {@link $embedExpiry} aware.
* @param string $path to the file, modification time to be retrieved from.
* @return integer file modification time.
*/
private function filemtime($path)
{
if($this->embedExpiry)
return (int)@file_get_contents($path,false,null,0,10);
else
return @filemtime($path);
}
}
53 changes: 53 additions & 0 deletions tests/framework/caching/CFileCacheTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

class CFileCacheTest extends CTestCase
{
/**
* https://github.com/yiisoft/yii/issues/2435
*/
public function testEmbedExpiry()
{
$app=new TestApplication(array(
'id'=>'testApp',
'components'=>array(
'cache'=>array('class'=>'CFileCache'),
),
));
$app->reset();
$cache=$app->cache;

$cache->set('testKey1','testValue1',2);
$files=glob(Yii::getPathOfAlias('application.runtime.cache').'/*.bin');
$this->assertEquals(time()+2,filemtime($files[0]));

$cache->set('testKey2','testValue2',2);
sleep(1);
$this->assertEquals('testValue2',$cache->get('testKey2'));

$cache->set('testKey3','testValue3',2);
sleep(3);
$this->assertEquals(false,$cache->get('testKey2'));


$app=new TestApplication(array(
'id'=>'testApp',
'components'=>array(
'cache'=>array('class'=>'CFileCache','embedExpiry'=>true),
),
));
$app->reset();
$cache=$app->cache;

$cache->set('testKey4','testValue4',2);
$files=glob(Yii::getPathOfAlias('application.runtime.cache').'/*.bin');
$this->assertEquals(time(),filemtime($files[0]));

$cache->set('testKey5','testValue5',2);
sleep(1);
$this->assertEquals('testValue5',$cache->get('testKey5'));

$cache->set('testKey6','testValue6',2);
sleep(3);
$this->assertEquals(false,$cache->get('testKey6'));
}
}

0 comments on commit 0bb122f

Please sign in to comment.