Go to the documentation of this file.00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00017 final class RubberFileSystem extends CachePeer
00018 {
00019 private $directory = null;
00020
00024 public static function create($directory = 'cache/')
00025 {
00026 return new self($directory);
00027 }
00028
00029 public function __construct($directory = 'cache/')
00030 {
00031 $directory = ONPHP_TEMP_PATH.$directory;
00032
00033 if (!is_writable($directory)) {
00034 if (!mkdir($directory, 0700, true)) {
00035 throw new WrongArgumentException(
00036 "can not write to '{$directory}'"
00037 );
00038 }
00039 }
00040
00041 if ($directory[strlen($directory) - 1] != DIRECTORY_SEPARATOR)
00042 $directory .= DIRECTORY_SEPARATOR;
00043
00044 $this->directory = $directory;
00045 }
00046
00047 public function isAlive()
00048 {
00049 if (!is_writable($this->directory))
00050 return mkdir($this->directory, 0700, true);
00051 else
00052 return true;
00053 }
00054
00058 public function clean()
00059 {
00060
00061 FileUtils::removeDirectory($this->directory, true);
00062
00063 return parent::clean();
00064 }
00065
00066 public function increment($key, $value)
00067 {
00068 $path = $this->makePath($key);
00069
00070 if (null !== ($current = $this->operate($path))) {
00071 $this->operate($path, $current += $value);
00072
00073 return $current;
00074 }
00075
00076 return null;
00077 }
00078
00079 public function decrement($key, $value)
00080 {
00081 $path = $this->makePath($key);
00082
00083 if (null !== ($current = $this->operate($path))) {
00084 $this->operate($path, $current -= $value);
00085
00086 return $current;
00087 }
00088
00089 return null;
00090 }
00091
00092 public function get($key)
00093 {
00094 $path = $this->makePath($key);
00095
00096 if (is_readable($path)) {
00097
00098 if (filemtime($path) <= time()) {
00099 try {
00100 unlink($path);
00101 } catch (BaseException $e) {
00102
00103 }
00104 return null;
00105 }
00106
00107 return $this->operate($path);
00108 }
00109
00110 return null;
00111 }
00112
00113 public function delete($key)
00114 {
00115 try {
00116 unlink($this->makePath($key));
00117 } catch (BaseException $e) {
00118 return false;
00119 }
00120
00121 return true;
00122 }
00123
00124 public function append($key, $data)
00125 {
00126 $path = $this->makePath($key);
00127
00128 $directory = dirname($path);
00129
00130 if (!file_exists($directory)) {
00131 try {
00132 mkdir($directory);
00133 } catch (BaseException $e) {
00134
00135 }
00136 }
00137
00138 if (!is_writable($path))
00139 return false;
00140
00141 try {
00142 $fp = fopen($path, 'ab');
00143 } catch (BaseException $e) {
00144 return false;
00145 }
00146
00147 fwrite($fp, $data);
00148
00149 fclose($fp);
00150
00151 return true;
00152 }
00153
00154 protected function store($action, $key, $value, $expires = 0)
00155 {
00156 $path = $this->makePath($key);
00157 $time = time();
00158
00159 $directory = dirname($path);
00160
00161 if (!file_exists($directory)) {
00162 try {
00163 mkdir($directory);
00164 } catch (BaseException $e) {
00165
00166 }
00167 }
00168
00169
00170 if (
00171 $action == 'add'
00172 && is_readable($path)
00173 && filemtime($path) > $time
00174 )
00175 return true;
00176
00177
00178 if ($action == 'replace') {
00179
00180 if (!is_readable($path)) {
00181 return false;
00182 } elseif (filemtime($path) <= $time) {
00183 $this->delete($key);
00184 return false;
00185 }
00186 }
00187
00188 $this->operate($path, $value, $expires);
00189
00190 return true;
00191 }
00192
00193 private function operate($path, $value = null, $expires = null)
00194 {
00195 $key = hexdec(substr(md5($path), 3, 2)) + 1;
00196
00197 $pool = SemaphorePool::me();
00198
00199 if (!$pool->get($key))
00200 return null;
00201
00202 try {
00203 $old = umask(0077);
00204 $fp = fopen($path, $value !== null ? 'wb' : 'rb');
00205 umask($old);
00206 } catch (BaseException $e) {
00207 $pool->drop($key);
00208 return null;
00209 }
00210
00211 if ($value !== null) {
00212 fwrite($fp, $this->prepareData($value));
00213 fclose($fp);
00214
00215 if ($expires < parent::TIME_SWITCH)
00216 $expires += time();
00217
00218 try {
00219 touch($path, $expires);
00220 } catch (BaseException $e) {
00221
00222 }
00223
00224 return $pool->drop($key);
00225 } else {
00226 if (($size = filesize($path)) > 0)
00227 $data = fread($fp, $size);
00228 else
00229 $data = null;
00230
00231 fclose($fp);
00232
00233 $pool->drop($key);
00234
00235 return $data ? $this->restoreData($data) : null;
00236 }
00237
00238 Assert::isUnreachable();
00239 }
00240
00241 private function makePath($key)
00242 {
00243 return
00244 $this->directory
00245 .$key[0].$key[1]
00246 .DIRECTORY_SEPARATOR
00247 .substr($key, 2);
00248 }
00249 }
00250 ?>