Permalink
Browse files

Merge pull request #2290 from marcovtwout/2289-CDbCacheDependency-reu…

…seDependentData-fix

FIX: CDbCacheDependency with reuseDependentData did not invalidate cache when getting cache across different requests
  • Loading branch information...
klimov-paul committed Apr 12, 2013
2 parents d5baddb + 0682ec1 commit 0adc8cbac5a19d0ca3bdf5d98ec1f7f73ed2abce
Showing with 68 additions and 59 deletions.
  1. +1 −0 CHANGELOG
  2. +13 −8 framework/caching/dependencies/CCacheDependency.php
  3. +54 −51 tests/framework/caching/CCacheDependencyTest.php
View
@@ -41,6 +41,7 @@ Version 1.1.14 work in progress
- Bug #2244: MessageCommand has been updated, allowing to merge string with value '0' correctly (klimov-paul)
- Bug #2258: CJuiSliderInput didn't support string typed 'range' option (bookin)
- Bug #2283: Gii Model Generator's tooltips are not working and always invisible (resurtm)
- Bug #2289: CDbCacheDependency with reuseDependentData did not invalidate cache when getting cache across different requests (marcovtwout)
- Bug #2299: CMssqlSchema: findTableNames(), getTables() and getTableNames() methods used to prepend schema prefix to the table names twice (resurtm)
- Enh: Better CFileLogRoute performance (Qiang, samdark)
- Enh: Refactored CHttpRequest::getDelete and CHttpRequest::getPut not to use _restParams directly (samdark)
@@ -53,7 +53,7 @@ public function evaluateDependency()
if ($this->reuseDependentData)
{
$hash=$this->getHash();
if (!isset(self::$_reusableData[$hash]['dependentData']))
if(!isset(self::$_reusableData[$hash]['dependentData']))
self::$_reusableData[$hash]['dependentData']=$this->generateDependentData();
$this->_data=self::$_reusableData[$hash]['dependentData'];
}
@@ -69,13 +69,9 @@ public function getHasChanged()
if ($this->reuseDependentData)
{
$hash=$this->getHash();
if (!isset(self::$_reusableData[$hash]['hasChanged']))
{
if (!isset(self::$_reusableData[$hash]['dependentData']))
self::$_reusableData[$hash]['dependentData']=$this->generateDependentData();
self::$_reusableData[$hash]['hasChanged']=self::$_reusableData[$hash]['dependentData']!=$this->_data;
}
return self::$_reusableData[$hash]['hasChanged'];
if(!isset(self::$_reusableData[$hash]['dependentData']))
self::$_reusableData[$hash]['dependentData']=$this->generateDependentData();
return self::$_reusableData[$hash]['dependentData']!=$this->_data;
}
else
return $this->generateDependentData()!=$this->_data;
@@ -90,6 +86,15 @@ public function getDependentData()
return $this->_data;
}
/**
* Resets cached data for reusable dependencies.
* @since 1.1.14
*/
public static function resetReusableData()
{
self::$_reusableData=array();
}
/**
* Generates the data needed to determine if dependency has been changed.
* Derived classes should override this method to generate actual dependent data.
@@ -3,62 +3,65 @@
class CCacheDependencyTest extends CTestCase
{
public function testReusable()
{
$tempFile=dirname(__FILE__).'/../../runtime/foo.txt';
@unlink($tempFile);
$fw=fopen($tempFile,"w");
fwrite($fw,"test");
fclose($fw);
clearstatcache();
$dependency = new MockFileCacheDependency($tempFile);
$dependency->reuseDependentData = true;
$dependency->evaluateDependency();
$this->assertEquals(1,MockFileCacheDependency::$generateDependentDataCalled);
// change file
$fw=fopen($tempFile,"w");
fwrite($fw,"test again");
fclose($fw);
clearstatcache();
$this->assertFalse($dependency->getHasChanged());
$this->assertEquals(1,MockFileCacheDependency::$generateDependentDataCalled);
$dependency2 = new MockDirectoryCacheDependency(dirname($tempFile));
$dependency2->reuseDependentData = true;
// change file
$fw=fopen($tempFile,"w");
fwrite($fw,"test again");
fclose($fw);
clearstatcache();
$this->assertTrue($dependency2->getHasChanged());
$this->assertEquals(1,MockDirectoryCacheDependency::$generateDependentDataCalled);
$dependency3 = new MockDirectoryCacheDependency(dirname($tempFile));
$dependency3->reuseDependentData = true;
$dependency3->evaluateDependency();
$this->assertTrue($dependency3->getHasChanged());
$this->assertEquals(1,MockDirectoryCacheDependency::$generateDependentDataCalled);
}
}
protected $_cacheDependentData=null;
class MockFileCacheDependency extends CFileCacheDependency
{
public static $generateDependentDataCalled = 0;
public function setCacheDependentData($cacheDependentData)
{
$this->_cacheDependentData = $cacheDependentData;
}
public function getCacheDependentData()
{
return $this->_cacheDependentData;
}
public function testReuseDependentData()
{
MockCacheDependency::$generateDependentDataCallback=array($this,'getCacheDependentData');
$dependency1=new MockCacheDependency();
$dependency1->reuseDependentData = true;
$dependency2=new MockCacheDependency();
$dependency2->reuseDependentData = true;
public function generateDependentData()
{
self::$generateDependentDataCalled++;
return parent::generateDependentData();
}
CCacheDependency::resetReusableData();
$this->setCacheDependentData('start');
$dependency1->evaluateDependency();
$dependency2->evaluateDependency();
$this->assertFalse($dependency1->getHasChanged(),'Initial dependency1 changed!');
$this->assertFalse($dependency2->getHasChanged(),'Initial dependency2 changed!');
$this->assertEquals(1,MockCacheDependency::$generateDependentDataCalled,'Extra invokations of "generateDependentData()"!');
// New request:
CCacheDependency::resetReusableData();
MockCacheDependency::$generateDependentDataCalled=0;
$this->assertFalse($dependency1->getHasChanged(),'Dependency1 changed for new request!');
$this->assertFalse($dependency2->getHasChanged(),'Dependency2 changed for new request!');
$this->assertEquals(1,MockCacheDependency::$generateDependentDataCalled,'Extra invokations of "generateDependentData()"!');
// New request:
CCacheDependency::resetReusableData();
MockCacheDependency::$generateDependentDataCalled=0;
$this->setCacheDependentData('change1');
$this->assertTrue($dependency1->getHasChanged(),'Dependency1 is not changed after source change!');
$dependency1->evaluateDependency();
// New request:
CCacheDependency::resetReusableData();
MockCacheDependency::$generateDependentDataCalled=0;
$this->assertFalse($dependency1->getHasChanged(),'Dependency1 has been changed!');
$this->assertTrue($dependency2->getHasChanged(),'Dependency2 has not been changed!');
$this->assertEquals(1,MockCacheDependency::$generateDependentDataCalled,'Extra invokations of "generateDependentData()"!');
}
}
class MockDirectoryCacheDependency extends CDirectoryCacheDependency
class MockCacheDependency extends CCacheDependency
{
public static $generateDependentDataCalled = 0;
public function generateDependentData()
{
self::$generateDependentDataCalled++;
return parent::generateDependentData();
}
public static $generateDependentDataCallback;
public static $generateDependentDataCalled = 0;
public function generateDependentData()
{
self::$generateDependentDataCalled++;
return call_user_func(self::$generateDependentDataCallback);
}
}

0 comments on commit 0adc8cb

Please sign in to comment.