RubberFileSystem.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2005-2007 by Konstantin V. Arkhipov                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License as        *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  ***************************************************************************/
00011 /* $Id: RubberFileSystem.class.php 4687 2007-12-09 18:57:18Z voxus $ */
00012 
00018     final class RubberFileSystem extends CachePeer
00019     {
00020         private $directory  = null;
00021         
00025         public static function create($directory = 'cache/')
00026         {
00027             return new self($directory);
00028         }
00029 
00030         public function __construct($directory = 'cache/')
00031         {
00032             $directory = ONPHP_TEMP_PATH.$directory;
00033             
00034             if (!is_writable($directory)) {
00035                 if (!mkdir($directory, 0700, true)) {
00036                     throw new WrongArgumentException(
00037                         "can not write to '{$directory}'"
00038                     );
00039                 }
00040             }
00041             
00042             if ($directory[strlen($directory) - 1] != DIRECTORY_SEPARATOR)
00043                 $directory .= DIRECTORY_SEPARATOR;
00044             
00045             $this->directory = $directory;
00046         }
00047         
00048         public function isAlive()
00049         {
00050             return is_writable($this->directory);
00051         }
00052         
00053         public function clean()
00054         {
00055             // just to return 'true'
00056             FileUtils::removeDirectory($this->directory, true);
00057             
00058             return parent::clean();
00059         }
00060 
00061         public function get($key)
00062         {
00063             $path = $this->makePath($key);
00064             
00065             if (is_readable($path)) {
00066                 
00067                 if (filemtime($path) <= time()) {
00068                     try {
00069                         unlink($path);
00070                     } catch (BaseException $e) {
00071                         // we're in race with unexpected clean()
00072                     }
00073                     return null;
00074                 }
00075                 
00076                 return $this->operate($path);
00077             }
00078             
00079             return null;
00080         }
00081         
00082         public function delete($key)
00083         {
00084             try {
00085                 unlink($this->makePath($key));
00086             } catch (BaseException $e) {
00087                 return false;
00088             }
00089             
00090             return true;
00091         }
00092         
00093         protected function store($action, $key, &$value, $expires = 0)
00094         {
00095             $path = $this->makePath($key);
00096             $time = time();
00097             
00098             $directory = dirname($path);
00099             
00100             if (!file_exists($directory)) {
00101                 try {
00102                     mkdir($directory);
00103                 } catch (BaseException $e) {
00104                     // we're in race
00105                 }
00106             }
00107             
00108             // do not add, if file exist and not expired
00109             if (
00110                 $action == 'add'
00111                 && is_readable($path)
00112                 && filemtime($path) > $time
00113             )
00114                 return true;
00115             
00116             // do not replace, when file not exist or expired
00117             if (
00118                 $action == 'replace'
00119             ) {
00120                 if (!is_readable($path)) {
00121                     return false;
00122                 } elseif (filemtime($path) <= $time) {
00123                     $this->delete($key);
00124                     return false;
00125                 }
00126             }
00127             
00128             $this->operate($path, $value, $expires);
00129             
00130             return true;
00131         }
00132         
00133         private function operate($path, $value = null, $expires = null)
00134         {
00135             $key = hexdec(substr(md5($path), 3, 2)) + 1;
00136 
00137             $pool = SemaphorePool::me();
00138             
00139             if (!$pool->get($key))
00140                 return null;
00141             
00142             try {
00143                 $old = umask();
00144                 umask(0077);
00145                 $fp = fopen($path, $value !== null ? 'wb' : 'rb');
00146                 umask($old);
00147             } catch (BaseException $e) {
00148                 $pool->drop($key);
00149                 return null;
00150             }
00151             
00152             if ($value !== null) {
00153                 fwrite($fp, $this->prepareData($value));
00154                 fclose($fp);
00155                 
00156                 if ($expires < parent::TIME_SWITCH)
00157                     $expires += time();
00158                 
00159                 touch($path, $expires);
00160                 
00161                 return $pool->drop($key);
00162             } else {
00163                 if (($size = filesize($path)) > 0)
00164                     $data = fread($fp, $size);
00165                 
00166                 fclose($fp);
00167                 
00168                 $pool->drop($key);
00169                 
00170                 return $this->restoreData($data);
00171             }
00172             
00173             Assert::isUnreachable();
00174         }
00175         
00176         private function makePath($key)
00177         {
00178             return
00179                 $this->directory
00180                 .$key[0].$key[1]
00181                 .DIRECTORY_SEPARATOR
00182                 .substr($key, 2);
00183         }
00184     }
00185 ?>

Generated on Sun Dec 9 21:56:23 2007 for onPHP by  doxygen 1.5.4