/[drupal]/contributions/modules/fastpath_fscache/cache.fs.inc
ViewVC logotype

Contents of /contributions/modules/fastpath_fscache/cache.fs.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.7 - (show annotations) (download) (as text)
Mon Jul 30 21:25:50 2007 UTC (2 years, 3 months ago) by weitzman
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-5, DRUPAL-6--1
Changes since 1.6: +6 -2 lines
File MIME type: text/x-php
cache_clear_all again
1 <?php
2 // $Id: cache.fs.inc,v 1.6 2007/07/30 21:19:48 weitzman Exp $
3
4 /**
5 * @file
6 * File-based caching API
7 */
8
9 define('FASTPATH_FSCACHE_PATH', './files/cache');
10
11 /**
12 * Return data from the persistent cache.
13 *
14 * @param $key
15 * The cache ID of the data to retrieve.
16 * @param $table
17 * The table $table to store the data in. Valid core values are 'cache_filter',
18 * 'cache_menu', 'cache_page', or 'cache' for the default cache.
19 */function cache_get($key, $table = 'cache') {
20 global $user;
21
22 $cache_lifetime = variable_get('cache_lifetime', 0);
23
24 if (variable_get('page_cache_fastpath', 0)) {
25 $cache = cache_get_file($key, $table);
26 }
27 else {
28 // garbage collection necessary when enforcing a minimum cache lifetime
29 $cache_flush = variable_get('cache_flush', 0);
30 if ($cache_flush && ($cache_flush + $cache_lifetime <= time())) {
31 variable_set('cache_flush', 0);
32 }
33 }
34
35 if (isset($cache->data)) {
36 // If enforcing a minimum cache lifetime, validate that the data is
37 // currently valid for this user before we return it by making sure the
38 // cache entry was created before the timestamp in the current session's
39 // cache timer. The cache variable is loaded into the $user object by
40 // sess_read() in session.inc.
41 if ($user->cache > $cache->created) {
42 // This cache data is too old and thus not valid for us, ignore it.
43 return 0;
44 }
45 return $cache;
46 }
47 return 0;
48 }
49
50 /**
51 * Return data from the persistent disk cache.
52 *
53 * @param $key
54 * The cache ID of the data to retrieve.
55 */
56 function cache_get_file($key, $table) {
57 $cache = NULL;
58 $cache_file = cache_filename($key, $table);
59
60 if (file_exists($cache_file)) {
61 if ($fp = fopen($cache_file, 'r')) {
62 if (flock($fp, LOCK_SH)) {
63 $data = fread($fp, filesize($cache_file));
64 flock($fp, LOCK_UN);
65 $cache = unserialize($data);
66 }
67 fclose($fp);
68 }
69 }
70 return $cache;
71 }
72
73
74 /**
75 * Store data in the persistent cache.
76 *
77 * The persistent cache is split up into four database
78 * tables. Contributed modules can add additional tables.
79 *
80 * 'cache_page': This table stores generated pages for anonymous
81 * users. This is the only table affected by the page cache setting on
82 * the administrator panel.
83 *
84 * 'cache_menu': Stores the cachable part of the users' menus.
85 *
86 * 'cache_filter': Stores filtered pieces of content. This table is
87 * periodically cleared of stale entries by cron.
88 *
89 * 'cache': Generic cache storage table.
90 *
91 * The reasons for having several tables are as follows:
92 *
93 * - smaller tables allow for faster selects and inserts
94 * - we try to put fast changing cache items and rather static
95 * ones into different tables. The effect is that only the fast
96 * changing tables will need a lot of writes to disk. The more
97 * static tables will also be better cachable with MySQL's query cache
98 *
99 * @param $cid
100 * The cache ID of the data to store.
101 * @param $table
102 * The table $table to store the data in. Valid core values are 'cache_filter',
103 * 'cache_menu', 'cache_page', or 'cache'.
104 * @param $data
105 * The data to store in the cache. Complex data types must be serialized first.
106 * @param $expire
107 * One of the following values:
108 * - CACHE_PERMANENT: Indicates that the item should never be removed unless
109 * explicitly told to using cache_clear_all() with a cache ID.
110 * - CACHE_TEMPORARY: Indicates that the item should be removed at the next
111 * general cache wipe.
112 * - A Unix timestamp: Indicates that the item should be kept at least until
113 * the given time, after which it behaves like CACHE_TEMPORARY.
114 * @param $headers
115 * A string containing HTTP header information for cached pages.
116 */function cache_set($cid, $table = 'cache', $data, $expire = CACHE_PERMANENT, $headers = NULL) {
117 static $subdirectories;
118
119 if (variable_get('page_cache_fastpath', 0)) {
120 // prepare the cache before grabbing the file lock
121 $cache->cid = $cid;
122 $cache->table = $table;
123 $cache->data = $data;
124 $cache->created = time();
125 $cache->expire = $expire;
126 $cache->headers = $headers;
127 $data = serialize($cache);
128
129 $file = cache_filename($cid, $table);
130 if ($fp = @fopen($file, 'w')) {
131 // only write to the cache file if we can obtain an exclusive lock
132 if (flock($fp, LOCK_EX)) {
133 fwrite($fp, $data);
134 flock($fp, LOCK_UN);
135 }
136 fclose($fp);
137 }
138 else {
139 // t() may not be loaded
140 drupal_set_message(strtr('Cache write error, failed to open file "%file"', array('%file' => $file)), 'error');
141 }
142 }
143 }
144
145 /**
146 *
147 * Expire data from the cache. If called without arguments, expirable
148 * entries will be cleared from the cache_page table.
149 *
150 * @param $cid
151 * If set, the cache ID to delete. Otherwise, all cache entries that can
152 * expire are deleted.
153 *
154 * @param $table
155 * If set, the table $table to delete from. Mandatory
156 * argument if $cid is set.
157 *
158 * @param $wildcard
159 * If set to TRUE, the $cid is treated as a substring
160 * to match rather than a complete ID. The match is a right hand
161 * match. If '*' is given as $cid, the table $table will be emptied.
162 */
163 function cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
164 global $user;
165
166 $file_cache = variable_get('fastpath_fscache_path', FASTPATH_FSCACHE_PATH);
167 $cache_lifetime = variable_get('cache_lifetime', 0);
168
169 if ($cid == '*') {
170 fastpath_fscache_purge_loop($table);
171 }
172
173 if ($wildcard) {
174 // TODO: what about wildcards? Won't work with md5's...
175 return;
176 }
177
178 // No arguments. clear page cache.
179 if (is_null($cid) && is_null($table) && !$wildcard) {
180 fastpath_fscache_purge_loop('cache_page');
181 }
182
183 if (empty($cid)) {
184 if ($cache_lifetime || variable_get('page_cache_fastpath', 0)) {
185 // We store the time in the current user's $user->cache variable which
186 // will be saved into the sessions table by sess_write(). We then
187 // simulate that the cache was flushed for this user by not returning
188 // cached data that was cached before the timestamp.
189 $user->cache = time();
190
191 $cache_flush = variable_get('cache_flush', 0);
192 $cache_files_expired = variable_get('cache_files_expired', 0);
193
194 if (variable_get('page_cache_fastpath', 0)) {
195 if ($cache_files_expired == 0) {
196 // updating cache_flush invalidates all data cached before this time
197 variable_set('cache_flush', time());
198 // updating cache_files_expired so cron can delete expired files
199 variable_set('cache_files_expired', time());
200 }
201
202 if (time() > ($cache_flush + $cache_lifetime)) {
203 variable_set('cache_flush', time());
204 }
205 }
206 }
207 }
208 else {
209 $file = cache_filename($cid, $table);
210 if ($fp = fopen($file, 'w')) {
211 // only delete the cache file once we obtain an exclusive lock to prevent
212 // deleting a cache file that is currently being read.
213 if (flock($fp, LOCK_EX)) {
214 unlink($file);
215 }
216 }
217 }
218 }
219
220 /**
221 * Sanitize the cache ID for use as a filename when caching to the filesystem.
222 *
223 * @param $cid
224 * The unique ID of the cache data to store.
225 */
226 function cache_filename($cid, $table = 'cache') {
227 $fspath = variable_get('file_cache', FASTPATH_FSCACHE_PATH);
228 // lazily create the subdirs for this table if needed.
229 cache_filename_create($fspath, $cid, $table);
230
231 $hash = md5($cid);
232 return "$fspath/$table/". $hash{0}. '/'. md5($cid);
233 }
234
235 // Assure that the subdirectory for $table exists, and letter/number subdirs. if not, create them.
236 // Static variable cache insures that this happens once per table per request. see http://drupal.org/node/82738
237 function cache_filename_create($fspath, $cid, $table) {
238 if (!isset($subdirectories[$table])) {
239 $subdirectory = "$fspath/$table/";
240 if (!is_dir($subdirectory)) {
241 if (!@mkdir($subdirectory)) {
242 // t() is not available
243 drupal_set_message(strtr('The directory %directory must be created by an administrator, along with 1 character subdirectories.', array('%directory' => $subdirectory)));
244 }
245 else {
246 @chmod($subdirectory, 0775); // Necessary for non-webserver users.
247 // create number/letter specific subdirs.
248 $ivalfrom = ord("a");
249 $ivalto = ord("f");
250 for($i = $ivalfrom; $i <= $ivalto; $i++) {
251 @mkdir($subdirectory. chr($i), 0777);
252 }
253
254 for($i = 0; $i<10; $i++) {
255 mkdir($subdirectory. $i, 0777);
256 }
257 }
258 $subdirectories[$table] = TRUE;
259 }
260 }
261 }
262
263 /**
264 * Main callback from DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE phase
265 */
266 function page_cache_fastpath() {
267 global $base_root;
268 $file_cache = variable_get('fastpath_fscache_path', FASTPATH_FSCACHE_PATH);
269 if ($file_cache && is_dir($file_cache)) {
270 $cache = cache_get($base_root . request_uri(), 'cache_page');
271 if (!empty($cache)) {
272 // display cached page and exit
273 drupal_page_header();
274 if (function_exists('gzencode')) {
275 header('Content-Encoding: gzip');
276 }
277 print $cache->data;
278 return TRUE;
279 }
280 }
281 else {
282 // Warning message that $file_cache isn't set. We don't have access to the
283 // t() function at this point.
284 //drupal_set_message(t('Cache error, failed to locate cache directory "%dir"', array('%dir' => $file_cache)), 'error');
285 }
286 }

  ViewVC Help
Powered by ViewVC 1.1.2