/[drupal]/contributions/modules/resultcache/resultcache.module
ViewVC logotype

Contents of /contributions/modules/resultcache/resultcache.module

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


Revision 1.2 - (show annotations) (download) (as text)
Wed Apr 2 20:12:41 2008 UTC (19 months, 3 weeks ago) by alexb
Branch: MAIN
CVS Tags: DRUPAL-5--1-0, HEAD
Branch point for: DRUPAL-5
Changes since 1.1: +257 -223 lines
File MIME type: text/x-php
Add 5.x version
1 <?php
2
3 /**
4 * function result cache
5 * alex at developmentseed dot org
6 *
7 * function passed gets cached on first call, subsequent calls pull
8 * the function result from cache. cache is being updated on cron time
9 *
10 * using function result cache makes sense, if you have functions that
11 * are slow but can do with periodic updates.
12 *
13 * @todo: test scalability
14 * the argument col. in result cache is TEXT, first 255 char indexed
15 *
16 */
17
18 /**
19 * help func hook
20 *
21 * @param string $section
22 * @return string
23 */
24 function resultcache_help($section='') {
25
26 $output = '';
27
28 switch ($section) {
29 case "admin/modules#description":
30 $output = t('Croned cache for function results that are text. Call resultcache_getresult(yourfunction, $yourarguments) to use it. (Note: Only MySQL supported.)');
31 break;
32 }
33
34 return $output;
35 }
36
37 function resultcache_settings() {
38 $form = array();
39
40 $form['resultcache_enabled'] = array(
41 '#type' => 'checkbox',
42 '#title' => t('Enable result cache'),
43 '#default_value' => variable_get('resultcache_enabled', 1),
44 '#description' => t('Turn on/off result caching on this site.'),
45 );
46 $form['resultcache_clear'] = array(
47 '#type' => 'markup',
48 '#value' => '<div>'.l(t('Clear entire result cache'), 'admin/resultcache/clear', array('title' => t('Clear entire result cache')), 'destination='.$_GET['q']).'</div>
49 <div>'.t('(Your site might slow down until the cache populates again)').'</div>',
50 );
51 $form['resultcache_refresh'] = array(
52 '#type' => 'markup',
53 '#value' => '<div>'.l(t('Refresh result cache'), 'admin/resultcache/refresh', array('title' => t('Refresh entire result cache')), 'destination='.$_GET['q']).'</div>
54 <div>'.t('(This recalculates all function results stored in the result cache)').'</div>',
55 );
56 return system_settings_form($form);
57 }
58
59 function resultcache_perm() {
60 return array('administer result cache');
61 }
62
63 function resultcache_menu($may_cache = FALSE) {
64 $items = array();
65
66 if ($may_cache) {
67 $items[] = array(
68 'path' => 'admin/resultcache/clear',
69 'title' => t('clear result cache'),
70 'callback' => 'resultcache_page_clear',
71 'access' => user_access('administer result cache'),
72 'type' => MENU_CALLBACK,
73 );
74 $items[] = array(
75 'path' => 'admin/resultcache/refresh',
76 'title' => t('clear result cache'),
77 'callback' => 'resultcache_page_refresh',
78 'access' => user_access('administer result cache'),
79 'type' => MENU_CALLBACK,
80 );
81 $items[] = array(
82 'path' => 'admin/settings/resultcache',
83 'title' => t('Result Cache Settings'),
84 'callback' => 'drupal_get_form',
85 'callback arguments' => 'resultcache_settings',
86 'access' => user_access('administer result cache'),
87 'type' => MENU_NORMAL_ITEM,
88 );
89 }
90 return $items;
91 }
92
93 /**
94 *Implementation of hook_keystroke()
95 */
96 function resultcache_keystroke_info($op = 'list', $arg1 = '') {
97 $strokes = array(
98 'resultcache_keystroke_clear_cache' =>
99 array('title' => t('Result Cache: Clear Cache'),
100 'name' => 'resultcache_keystroke_clear_cache',
101 'type' => 'drupal_callback',
102 'callback' => 'admin/resultcache/clear'),
103 'resultcache_keystroke_refresh_cache' =>
104 array('title' => t('Result Cache: Refresh Cache'),
105 'name' => 'resultcache_keystroke_refresh_cache',
106 'type' => 'drupal_callback',
107 'callback' => 'admin/resultcache/refresh'),
108 );
109
110 if($op == 'list') {
111 return $strokes;
112 }
113
114 if($op == 'search' && in_array($arg1, array_keys($strokes))) {
115 return $strokes[$arg1];
116 }
117 return;
118 }
119
120 /**
121 * menu call back for clearing cache
122 */
123 function resultcache_page_clear() {
124 resultcache_clear();
125 drupal_set_message(t('Cleared result cache'));
126 if (isset($_GET['destination'])) {
127 drupal_goto($_GET['destination']);
128 }
129 }
130
131 /**
132 * menu call back for refreshing cache
133 */
134 function resultcache_page_refresh() {
135 timer_start('result_cache_refresh');
136 resultcache_refresh('result_cache_refresh');
137 drupal_set_message(t('Refreshed result cache (%time ms)', array('%time' => timer_read('result_cache_refresh'))));
138 timer_stop('result_cache_refresh');
139 if (isset($_GET['destination'])) {
140 drupal_goto($_GET['destination']);
141 }
142 }
143
144 /**
145 * cron hook
146 *
147 */
148 function resultcache_cron() {
149 resultcache_refresh();
150 }
151
152 /**
153 * call to refresh all functions in cache
154 * todo: make optional incremental refresh for cron time
155 */
156 function resultcache_refresh() {
157 $r = db_query("SELECT crid, lastused, function, arguments, lastupdated FROM {cache_result}");
158 while ($fr = db_fetch_object($r)) {
159
160 // recalculate once an hour
161 // todo: make this user configurable
162 if ( (time() - $fr->lastupdated) < 3600 )
163 continue;
164
165 // if cached result not used in 2 days, kill it - todo: make user configurable
166 if ((time() - $fr->lastused) > 86400*2) {
167 db_query("DELETE FROM {cache_result} WHERE crid = %d", $fr->crid);
168 }
169 else {
170 if (function_exists($fr->function)) {
171 $result = call_user_func_array($fr->function, unserialize($fr->arguments));
172 db_query("UPDATE {cache_result} SET result = '%s', lastupdated = %d WHERE crid = %d", serialize($result), time(), $fr->crid);
173 }
174 }
175 }
176 }
177
178 /**
179 * call this function the same way as you would call resultcache_getresult()
180 * for invalidating cache
181 *
182 */
183 function resultcache_invalidate(){
184 $arguments = func_get_args();
185 $function = array_shift($arguments);
186 if (func_num_args() == 1)
187 $arguments = "";
188 db_query("DELETE FROM {cache_result} WHERE function = '%s' AND arguments = '%s'", $function, serialize($arguments));
189 }
190
191 /**
192 * clears entire cache
193 */
194 function resultcache_clear(){
195 db_query("DELETE FROM {cache_result}");
196 }
197
198 /**
199 * wrap your function into this one for caching
200 *
201 * resultcache_getresult("functionname", $arg_1, $arg_2 ...)
202 *
203 * First time called, the original function is called an stored in the {cache_result} table
204 * successive calls will draw result from {cache_result}. so be sure to run cron regularly in order
205 * to have up to date function results.
206 *
207 */
208 function resultcache_getresult() {
209
210 timer_start("getres");
211 $time = time();
212
213 $arguments = func_get_args();
214 $function = array_shift($arguments);
215 if (func_num_args() == 1) {
216 $arguments = "";
217 }
218
219 // return result here if result caching off
220 if (!variable_get('resultcache_enabled', 1)) {
221 return call_user_func_array($function, $arguments);
222 }
223
224 $r = db_query("SELECT crid, result FROM {cache_result} WHERE function = '%s' AND arguments = '%s'", $function, serialize($arguments));
225 if ($call = db_fetch_object($r)) {
226
227 $result = unserialize($call->result);
228 if ($result === false) {
229
230 // retrieval of cached result failed, delete cache entry and tell watchdog
231 // calculate function instead of pulling it from db
232 db_query("DELETE FROM {cache_result} WHERE function = '%s' AND arguments = '%s'", $function, serialize($arguments));
233 watchdog("resultcache", "could not unserialize result, function $function", WATCHDOG_ERROR);
234 }
235 else {
236 // successful retrieval. update lastused mark and
237 db_query("UPDATE {cache_result} SET lastused = %d, retrievelapse = %d WHERE crid = %d", $time, timer_read("getres"), $call->crid);
238 timer_stop("getres");
239 return $result;
240 }
241
242 }
243
244 // if called first time
245 // insert result into result table, cron will calculate functions in this table regularily
246 $result = call_user_func_array($function, $arguments);
247
248 // todo: apparantly some ยด` combinations can break unserialize()
249 // eliminate those combinations here
250
251 db_query("INSERT INTO {cache_result}(function, arguments, result, lastused, createlapse) VALUES('%s', '%s', '%s', %d, %d)",
252 $function, serialize($arguments), serialize($result), $time, timer_read("getres") );
253 timer_stop("getres");
254
255 return $result;
256 }
257

  ViewVC Help
Powered by ViewVC 1.1.2