Source for file FileStorage.php
Documentation is available at FileStorage.php
6: * Copyright (c) 2004, 2009 David Grudl (http://davidgrudl.com)
8: * This source file is subject to the "Nette license" that is bundled
9: * with this package in the file license.txt.
11: * For more information please see http://nettephp.com
13: * @copyright Copyright (c) 2004, 2009 David Grudl
14: * @license http://nettephp.com/license Nette license
15: * @link http://nettephp.com
17: * @package Nette\Caching
22: require_once dirname(__FILE__) .
'/../Object.php';
24: require_once dirname(__FILE__) .
'/../Caching/ICacheStorage.php';
29: * Cache file storage.
31: * @author David Grudl
32: * @copyright Copyright (c) 2004, 2009 David Grudl
33: * @package Nette\Caching
38: * Atomic thread safe logic:
40: * 1) reading: open(r+b), lock(SH), read
41: * - delete?: lock(EX), truncate*, unlink*, close
42: * 2) deleting: open(r+b), lock(EX), truncate*, unlink*, close
43: * 3) writing: open(r+b || wb), lock(EX), truncate*, write data, write meta, close
45: * *unlink fails in windows
48: /**#@+ internal cache file structure */
49: const META_HEADER_LEN =
28; // 22b signature + 6b meta-struct size + serialized meta-struct + data
50: // meta structure: array of
56: const META_ITEMS =
'di'; // array of dependent items (file => timestamp)
57: const META_TAGS =
'tags'; // array of tags (tag => [foo])
61: /**#@+ additional cache structure */
67: /** @var float probability that the clean() routine is started */
68: public static $gcProbability =
0.001;
101: if ($meta &&
$this->verify($meta)) {
112: * Verifies dependencies.
116: private function verify($meta)
119: if (!empty($meta[self::META_DELTA])) {
120: // meta[file] was added by readMeta()
124: } elseif (!empty($meta[self::META_EXPIRE]) &&
$meta[self::META_EXPIRE] <
time()) {
132: if (!empty($meta[self::META_ITEMS])) {
133: foreach ($meta[self::META_ITEMS] as $depFile =>
$time) {
135: if ($m[self::META_TIME] !==
$time) break 2;
136: if ($m &&
!$this->verify($m)) break 2;
143: // meta[handle] was added by readMeta()
146: @unlink($meta[self::FILE]); // intentionally @; meta[file] was added by readMeta()
154: * Writes item into the cache.
157: * @param array dependencies
158: * @return bool TRUE if no problem
160: public function write($key, $data, array $dp)
163: self::META_TIME =>
microtime(),
166: if (!is_string($data)) {
167: $data =
serialize($data);
172: $meta[self::META_PRIORITY] = (int)
$dp[Cache::PRIORITY];
177: $meta[self::META_EXPIRE] =
$dp[Cache::EXPIRE] +
time(); // absolute time
179: $meta[self::META_DELTA] = (int)
$dp[Cache::EXPIRE]; // sliding time
188: foreach ((array)
$dp[Cache::ITEMS] as $item) {
191: $meta[self::META_ITEMS][$depFile] =
$m[self::META_TIME];
197: $meta[self::META_CALLBACKS] =
$dp[Cache::CALLBACKS];
208: $handle =
@fopen($cacheFile, 'r+b'); // intentionally @
210: $handle =
@fopen($cacheFile, 'wb'); // intentionally @
221: $head =
'<?php //netteCache[01]' .
str_pad((string)
strlen($head), 6, '0', STR_PAD_LEFT) .
$head;
226: if (fwrite($handle, $data, $dataLen) ===
$dataLen) {
228: if (fwrite($handle, $head, $headLen) ===
$headLen) {
244: * Removes item from the cache.
246: * @return bool TRUE if no problem
252: if (!$meta) return TRUE;
263: * Removes items from the cache by conditions & garbage collector.
264: * @param array conditions
265: * @return bool TRUE if no problem
269: $tags =
isset($conds[Cache::TAGS]) ?
array_flip((array)
$conds[Cache::TAGS]) :
array();
271: $priority =
isset($conds[Cache::PRIORITY]) ?
$conds[Cache::PRIORITY] : -
1;
273: $all =
!empty($conds[Cache::ALL]);
277: $base =
$this->dir .
DIRECTORY_SEPARATOR .
'c';
278: $iterator =
new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->dir), RecursiveIteratorIterator::CHILD_FIRST);
279: foreach ($iterator as $entry) {
283: if ($entry->isDir()) {
284: @rmdir((string)
$entry); // intentionally @
289: if (!$meta ||
$all) continue 2;
291: if (!empty($meta[self::META_EXPIRE]) &&
$meta[self::META_EXPIRE] <
$now) {
295: if (!empty($meta[self::META_PRIORITY]) &&
$meta[self::META_PRIORITY] <=
$priority) {
319: * Reads cache data from disk.
320: * @param string file path
321: * @param int lock mode
322: * @return array|NULL
326: $handle =
@fopen($file, 'r+b'); // intentionally @
327: if (!$handle) return NULL;
332: if ($head &&
strlen($head) ===
self::META_HEADER_LEN) {
337: fseek($handle, $size +
self::META_HEADER_LEN); // needed by PHP < 5.2.6
338: $meta[self::FILE] =
$file;
339: $meta[self::HANDLE] =
$handle;
351: * Reads cache data from disk and closes cache file handle.
360: if (empty($meta[self::META_SERIALIZED])) {
370: * Returns file name.
376: if ($this->useSubdir) {