@@ -28,14 +28,14 @@ function __construct($config = array()) {
2828 }
2929
3030 }
31-
31+
3232 private function encodeFilename ($ keyword ) {
33- return trim (trim (preg_replace ("/[^a-zA-Z0-9]+/ " ,"_ " ,$ keyword ),"_ " ));
33+ return trim (trim (preg_replace ("/[^a-zA-Z0-9]+/ " ,"_ " ,$ keyword ),"_ " ));
3434 // return rtrim(base64_encode($keyword), '=');
3535 }
36-
36+
3737 private function decodeFilename ($ filename ) {
38- return $ filename ;
38+ return $ filename ;
3939 // return base64_decode($filename);
4040 }
4141
@@ -44,41 +44,39 @@ private function decodeFilename($filename) {
4444 */
4545 private function getFilePath ($ keyword , $ skip = false ) {
4646 $ path = $ this ->getPath ();
47-
48- $ filename = $ this ->encodeFilename ($ keyword );
47+
48+ $ filename = $ this ->encodeFilename ($ keyword );
4949 $ folder = substr ($ filename ,0 ,2 );
5050 $ path = rtrim ($ path ,"/ " )."/ " .$ folder ;
5151 /*
5252 * Skip Create Sub Folders;
5353 */
5454 if ($ skip == false ) {
55- if (!file_exists ($ path )) {
56- if (!@mkdir ($ path ,$ this ->__setChmodAuto ())) {
55+ //if it doesn't exist, I can't create it, and nobody beat me to creating it:
56+ if (!@is_dir ($ path ) && !@mkdir ($ path ,$ this ->__setChmodAuto ()) && !@is_dir ($ path )) {
57+ throw new Exception ("PLEASE CHMOD " .$ this ->getPath ()." - 0777 OR ANY WRITABLE PERMISSION! " ,92 );
58+ }
59+ //if it does exist (after someone beat me to it, perhaps), but isn't writable or fixable:
60+ if (@is_dir ($ path ) && !is_writeable ($ path ) && !@chmod ($ path ,$ this ->__setChmodAuto ())) {
5761 throw new Exception ("PLEASE CHMOD " .$ this ->getPath ()." - 0777 OR ANY WRITABLE PERMISSION! " ,92 );
58- }
59-
60- } elseif (!is_writeable ($ path )) {
61- if (!chmod ($ path ,$ this ->__setChmodAuto ())) {
62- die ("PLEASE CHMOD " .$ this ->getPath ()." - 0777 OR ANY WRITABLE PERMISSION! MAKE SURE PHP/Apache/WebServer have Write Permission " );
63- }
6462 }
6563 }
6664
6765 $ file_path = $ path ."/ " .$ filename .".txt " ;
6866 return $ file_path ;
6967 }
7068
71-
7269 function driver_set ($ keyword , $ value = "" , $ time = 300 , $ option = array () ) {
7370 $ file_path = $ this ->getFilePath ($ keyword );
71+ $ tmp_path = $ file_path . ".tmp " ;
7472 // echo "<br>DEBUG SET: ".$keyword." - ".$value." - ".$time."<br>";
7573 $ data = $ this ->encode ($ value );
7674
7775 $ toWrite = true ;
7876 /*
7977 * Skip if Existing Caching in Options
8078 */
81- if (isset ($ option ['skipExisting ' ]) && $ option ['skipExisting ' ] == true && file_exists ($ file_path )) {
79+ if (isset ($ option ['skipExisting ' ]) && $ option ['skipExisting ' ] == true && @ file_exists ($ file_path )) {
8280 $ content = $ this ->readfile ($ file_path );
8381 $ old = $ this ->decode ($ content );
8482 $ toWrite = false ;
@@ -87,25 +85,39 @@ function driver_set($keyword, $value = "", $time = 300, $option = array() ) {
8785 }
8886 }
8987
90- if ($ toWrite == true ) {
88+ $ written = true ;
89+ /*
90+ * write to intent file to prevent race during read; race during write is ok
91+ * because first-to-lock wins and the file will exist before the writer attempts
92+ * to write.
93+ */
94+ if ($ toWrite == true && !@file_exists ($ tmp_path ) && !@file_exists ($ file_path )) {
9195 try {
92- $ f = fopen ($ file_path , "w+ " );
93- fwrite ($ f , $ data );
94- fclose ($ f );
96+ $ f = @fopen ($ tmp_path , "c " );
97+ if ($ f ) {
98+ if (flock ($ f ,LOCK_EX | LOCK_NB )) {
99+ $ written = ($ written && fwrite ($ f , $ data ));
100+ $ written = ($ written && fflush ($ f ));
101+ $ written = ($ written && flock ($ f , LOCK_UN ));
102+ } else {
103+ //arguably the file is being written to so the job is done
104+ $ written = false ;
105+ }
106+ $ written = ($ written && @fclose ($ f ));
107+ $ written = ($ written && @rename ($ tmp_path ,$ file_path ));
108+ }
95109 } catch (Exception $ e ) {
96110 // miss cache
97- return false ;
111+ $ written = false ;
98112 }
99113 }
114+ return $ written ;
100115 }
101116
102-
103-
104-
105117 function driver_get ($ keyword , $ option = array ()) {
106118
107119 $ file_path = $ this ->getFilePath ($ keyword );
108- if (!file_exists ($ file_path )) {
120+ if (!@ file_exists ($ file_path )) {
109121 return null ;
110122 }
111123
@@ -122,7 +134,7 @@ function driver_get($keyword, $option = array()) {
122134
123135 function driver_delete ($ keyword , $ option = array ()) {
124136 $ file_path = $ this ->getFilePath ($ keyword ,true );
125- if (@unlink ($ file_path )) {
137+ if (file_exists ( $ file_path ) && @unlink ($ file_path )) {
126138 return true ;
127139 } else {
128140 return false ;
@@ -147,35 +159,47 @@ function driver_stats($option = array()) {
147159
148160 $ total = 0 ;
149161 $ removed = 0 ;
150- while ($ file =readdir ($ dir )) {
162+ $ content = array ();
163+ while ($ file =@readdir ($ dir )) {
151164 if ($ file !=". " && $ file !=".. " && is_dir ($ path ."/ " .$ file )) {
152165 // read sub dir
153166 $ subdir = @opendir ($ path ."/ " .$ file );
154167 if (!$ subdir ) {
155168 throw new Exception ("Can't read path: " .$ path ."/ " .$ file ,93 );
156169 }
157170
158- while ($ f = readdir ($ subdir )) {
171+ while ($ f = @ readdir ($ subdir )) {
159172 if ($ f !=". " && $ f !=".. " ) {
160173 $ file_path = $ path ."/ " .$ file ."/ " .$ f ;
161- $ size = filesize ($ file_path );
174+ $ size = @ filesize ($ file_path );
162175 $ object = $ this ->decode ($ this ->readfile ($ file_path ));
176+
177+ if (strpos ($ f ,". " ) === false ) {
178+ $ key = $ f ;
179+ }
180+ else {
181+ //Because PHP 5.3, this cannot be written in single line
182+ $ key = explode (". " , $ f );
183+ $ key = $ key [0 ];
184+ }
185+ $ content [$ key ] = array ("size " =>$ size ,"write_time " =>$ object ["write_time " ]);
163186 if ($ this ->isExpired ($ object )) {
164187 @unlink ($ file_path );
165- $ removed = $ removed + $ size ;
188+ $ removed += $ size ;
166189 }
167- $ total = $ total + $ size ;
190+ $ total += $ size ;
168191 }
169192 } // end read subdir
170193 } // end if
171194 } // end while
172195
173- $ res ['size ' ] = $ total - $ removed ;
196+ $ res ['size ' ] = $ total - $ removed ;
174197 $ res ['info ' ] = array (
175- "Total " => $ total ,
176- "Removed " => $ removed ,
177- "Current " => $ res ['size ' ],
198+ "Total [bytes] " => $ total ,
199+ "Expired and removed [bytes] " => $ removed ,
200+ "Current [bytes] " => $ res ['size ' ],
178201 );
202+ $ res ["data " ] = $ content ;
179203 return $ res ;
180204 }
181205
@@ -195,15 +219,15 @@ function driver_clean($option = array()) {
195219 throw new Exception ("Can't read PATH: " .$ path ,94 );
196220 }
197221
198- while ($ file =readdir ($ dir )) {
222+ while ($ file =@ readdir ($ dir )) {
199223 if ($ file !=". " && $ file !=".. " && is_dir ($ path ."/ " .$ file )) {
200224 // read sub dir
201225 $ subdir = @opendir ($ path ."/ " .$ file );
202226 if (!$ subdir ) {
203227 throw new Exception ("Can't read path: " .$ path ."/ " .$ file ,93 );
204228 }
205229
206- while ($ f = readdir ($ subdir )) {
230+ while ($ f = @ readdir ($ subdir )) {
207231 if ($ f !=". " && $ f !=".. " ) {
208232 $ file_path = $ path ."/ " .$ file ."/ " .$ f ;
209233 @unlink ($ file_path );
@@ -212,13 +236,11 @@ function driver_clean($option = array()) {
212236 } // end if
213237 } // end while
214238
215-
216239 }
217240
218-
219241 function driver_isExisting ($ keyword ) {
220242 $ file_path = $ this ->getFilePath ($ keyword ,true );
221- if (!file_exists ($ file_path )) {
243+ if (!@ file_exists ($ file_path )) {
222244 return false ;
223245 } else {
224246 // check expired or not
@@ -232,15 +254,11 @@ function driver_isExisting($keyword) {
232254 }
233255
234256 function isExpired ($ object ) {
235-
236- if (isset ($ object ['expired_time ' ]) && @date ("U " ) >= $ object ['expired_time ' ]) {
257+ if (isset ($ object ['expired_time ' ]) && time () >= $ object ['expired_time ' ]) {
237258 return true ;
238259 } else {
239260 return false ;
240261 }
241262 }
242263
243-
244-
245-
246264}
0 commit comments