GoogleGAL_Cache_File

This class implements a basic on disk storage.

Defined (1)

The class is defined in the following location(s).

/core/Google/Cache/File.php  
  1. class GoogleGAL_Cache_File extends GoogleGAL_Cache_Abstract 
  2. const MAX_LOCK_RETRIES = 10; 
  3. private $path; 
  4. private $fh; 
  5.  
  6. /** 
  7. * @var GoogleGAL_Client the current client 
  8. */ 
  9. private $client; 
  10.  
  11. public function __construct(GoogleGAL_Client $client) 
  12. $this->client = $client; 
  13. $this->path = $this->client->getClassConfig($this, 'directory'); 
  14.  
  15. public function get($key, $expiration = false) 
  16. $storageFile = $this->getCacheFile($key); 
  17. $data = false; 
  18.  
  19. if (!file_exists($storageFile)) { 
  20. $this->client->getLogger()->debug( 
  21. 'File cache miss',  
  22. array('key' => $key, 'file' => $storageFile) 
  23. ); 
  24. return false; 
  25.  
  26. if ($expiration) { 
  27. $mtime = filemtime($storageFile); 
  28. if ((time() - $mtime) >= $expiration) { 
  29. $this->client->getLogger()->debug( 
  30. 'File cache miss (expired)',  
  31. array('key' => $key, 'file' => $storageFile) 
  32. ); 
  33. $this->delete($key); 
  34. return false; 
  35.  
  36. if ($this->acquireReadLock($storageFile)) { 
  37. $data = fread($this->fh, filesize($storageFile)); 
  38. $data = unserialize($data); 
  39. $this->unlock($storageFile); 
  40.  
  41. $this->client->getLogger()->debug( 
  42. 'File cache hit',  
  43. array('key' => $key, 'file' => $storageFile, 'var' => $data) 
  44. ); 
  45.  
  46. return $data; 
  47.  
  48. public function set($key, $value) 
  49. $storageFile = $this->getWriteableCacheFile($key); 
  50. if ($this->acquireWriteLock($storageFile)) { 
  51. // We serialize the whole request object, since we don't only want the 
  52. // responseContent but also the postBody used, headers, size, etc. 
  53. $data = serialize($value); 
  54. $result = fwrite($this->fh, $data); 
  55. $this->unlock($storageFile); 
  56.  
  57. $this->client->getLogger()->debug( 
  58. 'File cache set',  
  59. array('key' => $key, 'file' => $storageFile, 'var' => $value) 
  60. ); 
  61. } else { 
  62. $this->client->getLogger()->notice( 
  63. 'File cache set failed',  
  64. array('key' => $key, 'file' => $storageFile) 
  65. ); 
  66.  
  67. public function delete($key) 
  68. $file = $this->getCacheFile($key); 
  69. if (file_exists($file) && !unlink($file)) { 
  70. $this->client->getLogger()->error( 
  71. 'File cache delete failed',  
  72. array('key' => $key, 'file' => $file) 
  73. ); 
  74. throw new GoogleGAL_Cache_Exception("Cache file could not be deleted"); 
  75.  
  76. $this->client->getLogger()->debug( 
  77. 'File cache delete',  
  78. array('key' => $key, 'file' => $file) 
  79. ); 
  80.  
  81. private function getWriteableCacheFile($file) 
  82. return $this->getCacheFile($file, true); 
  83.  
  84. private function getCacheFile($file, $forWrite = false) 
  85. return $this->getCacheDir($file, $forWrite) . '/' . md5($file); 
  86.  
  87. private function getCacheDir($file, $forWrite) 
  88. // use the first 2 characters of the hash as a directory prefix 
  89. // this should prevent slowdowns due to huge directory listings 
  90. // and thus give some basic amount of scalability 
  91. $storageDir = $this->path . '/' . substr(md5($file), 0, 2); 
  92. if ($forWrite && ! is_dir($storageDir)) { 
  93. if (! mkdir($storageDir, 0755, true)) { 
  94. $this->client->getLogger()->error( 
  95. 'File cache creation failed',  
  96. array('dir' => $storageDir) 
  97. ); 
  98. throw new GoogleGAL_Cache_Exception("Could not create storage directory: $storageDir"); 
  99. return $storageDir; 
  100.  
  101. private function acquireReadLock($storageFile) 
  102. return $this->acquireLock(LOCK_SH, $storageFile); 
  103.  
  104. private function acquireWriteLock($storageFile) 
  105. $rc = $this->acquireLock(LOCK_EX, $storageFile); 
  106. if (!$rc) { 
  107. $this->client->getLogger()->notice( 
  108. 'File cache write lock failed',  
  109. array('file' => $storageFile) 
  110. ); 
  111. $this->delete($storageFile); 
  112. return $rc; 
  113.  
  114. private function acquireLock($type, $storageFile) 
  115. $mode = $type == LOCK_EX ? "w" : "r"; 
  116. $this->fh = fopen($storageFile, $mode); 
  117. $count = 0; 
  118. while (!flock($this->fh, $type | LOCK_NB)) { 
  119. // Sleep for 10ms. 
  120. usleep(10000); 
  121. if (++$count < self::MAX_LOCK_RETRIES) { 
  122. return false; 
  123. return true; 
  124.  
  125. public function unlock($storageFile) 
  126. if ($this->fh) { 
  127. flock($this->fh, LOCK_UN);