Merge lp:~glennpratt/pressflow/module_implements-cache into lp:pressflow

Proposed by Glenn Pratt
Status: Work in progress
Proposed branch: lp:~glennpratt/pressflow/module_implements-cache
Merge into: lp:pressflow
Diff against target: 194 lines (+78/-26)
4 files modified
includes/common.inc (+3/-0)
includes/module.inc (+56/-5)
install.php (+16/-20)
update.php (+3/-1)
To merge this branch: bzr merge lp:~glennpratt/pressflow/module_implements-cache
Reviewer Review Type Date Requested Status
Nathaniel Catchpole (community) Disapprove
Pressflow Administrators Pending
Review via email: mp+48353@code.launchpad.net

Description of the change

Apply backport of Drupal 7 module_implements cache.

http://drupal.org/node/557542#comment-4038288

To post a comment you must log in.
Revision history for this message
Nathaniel Catchpole (catch-drupal) wrote :

There's another merge proposal for this at https://code.launchpad.net/~catch-drupal/pressflow/pressflow_implements

That also (as of today, I forgot to commit it in November) has an additional fix to Pressflow's path.inc - without that the path_alias_cache module (and path aliases in general) will be non-functional when enabled).

review: Disapprove
Revision history for this message
Glenn Pratt (glennpratt) wrote :

Thanks for looking, I will compare your merge and try to migrate to it.

Unmerged revisions

98. By Glenn Pratt

Add module_implement cache backport from Drupal 7. See http://drupal.org/node/557542

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'includes/common.inc'
2--- includes/common.inc 2010-12-16 19:39:23 +0000
3+++ includes/common.inc 2011-02-02 17:49:08 +0000
4@@ -1622,6 +1622,9 @@
5 }
6
7 module_invoke_all('exit');
8+
9+ // Update the hook implementation cache.
10+ module_implements('', FALSE, FALSE, TRUE);
11 }
12
13 /**
14
15=== modified file 'includes/module.inc'
16--- includes/module.inc 2010-12-16 19:28:18 +0000
17+++ includes/module.inc 2011-02-02 17:49:08 +0000
18@@ -406,27 +406,78 @@
19 * @param $sort
20 * By default, modules are ordered by weight and filename, settings this option
21 * to TRUE, module list will be ordered by module name.
22- * @param $refresh
23+ * @param $reset
24 * For internal use only: Whether to force the stored list of hook
25 * implementations to be regenerated (such as after enabling a new module,
26 * before processing hook_enable).
27+ * @param $write_cache
28+ * For internal use only: Update the persistent cache of hook implementations.
29 * @return
30 * An array with the names of the modules which are implementing this hook.
31 */
32-function module_implements($hook, $sort = FALSE, $refresh = FALSE) {
33+function module_implements($hook, $sort = FALSE, $reset = FALSE, $write_cache = FALSE) {
34 static $implementations;
35
36- if ($refresh) {
37+ // We maintain a persistent cache of hook implementations in addition to the
38+ // static cache to avoid looping through every module and every hook on each
39+ // request. Benchmarks show that the benefit of this caching outweighs the
40+ // additional database hit even when using the default database caching
41+ // backend and only a small number of modules are enabled. The cost of the
42+ // cache_get() is more or less constant and reduced further when non-database
43+ // caching backends are used, so there will be more significant gains when a
44+ // large number of modules are installed or hooks invoked, since this can
45+ // quickly lead to module_hook() being called several thousand times
46+ // per request.
47+ if ($reset) {
48 $implementations = array();
49- return;
50+ cache_set('module_implements', array());
51+ return;
52+ }
53+
54+ if ($write_cache) {
55+ // Check whether we should write the cache. We do not want to cache hooks
56+ // which are only invoked on HTTP POST requests since these do not need to
57+ // be optimized as tightly, and not doing so keeps the cache entry smaller.
58+ if (isset($implementations['#write_cache']) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD')) {
59+ unset($implementations['#write_cache']);
60+ cache_set('module_implements', $implementations);
61+ }
62+ return;
63+ }
64+
65+ // Fetch implementations from cache.
66+ if (empty($implementations)) {
67+ $cache = cache_get('module_implements');
68+ if (!$cache) {
69+ $implementations = array();
70+ }
71+ else {
72+ $implementations = $cache->data;
73+ }
74 }
75
76 if (!isset($implementations[$hook])) {
77+ // The hook is not cached, so ensure that whether or not it has
78+ // implementations, that the cache is updated at the end of the request.
79+ $implementations['#write_cache'] = TRUE;
80 $implementations[$hook] = array();
81 $list = module_list(FALSE, TRUE, $sort);
82 foreach ($list as $module) {
83 if (module_hook($module, $hook)) {
84- $implementations[$hook][] = $module;
85+ $implementations[$hook][$module] = $module;
86+ }
87+ }
88+ }
89+ else {
90+ foreach ($implementations[$hook] as $module) {
91+ // It is possible that a module removed a hook implementation without the
92+ // implementations cache being rebuilt yet, so we check module_hook() on
93+ // each request to avoid undefined function errors.
94+ if (!module_hook($module, $hook)) {
95+ // Clear out the stale implementation from the cache and force a cache
96+ // refresh to forget about no longer existing hook implementations.
97+ unset($implementations[$hook][$module]);
98+ $implementations['#write_cache'] = TRUE;
99 }
100 }
101 }
102
103=== modified file 'install.php'
104--- install.php 2010-12-16 19:39:23 +0000
105+++ install.php 2011-02-02 17:49:08 +0000
106@@ -48,6 +48,18 @@
107 drupal_load('module', 'system');
108 drupal_load('module', 'filter');
109
110+ // Load the cache infrastructure using a "fake" cache implementation that
111+ // does not attempt to write to the database. We need this during the initial
112+ // part of the installer because the database is not available yet. We
113+ // continue to use it even when the database does become available, in order
114+ // to preserve consistency between interactive and command-line installations
115+ // (the latter complete in one page request and therefore are forced to
116+ // continue using the cache implementation they started with) and also
117+ // because any data put in the cache during the installer is inherently
118+ // suspect, due to the fact that Drupal is not fully set up yet.
119+ require_once './includes/cache-install.inc';
120+ $conf['cache_inc'] = './includes/cache-install.inc';
121+
122 // Install profile chosen, set the global immediately.
123 // This needs to be done before the theme cache gets
124 // initialized in drupal_maintenance_theme().
125@@ -62,12 +74,6 @@
126 $verify = install_verify_settings();
127
128 if ($verify) {
129- // Since we have a database connection, we use the normal cache system.
130- // This is important, as the installer calls into the Drupal system for
131- // the clean URL checks, so we should maintain the cache properly.
132- require_once './includes/cache.inc';
133- $conf['cache_inc'] = './includes/cache.inc';
134-
135 // Establish a connection to the database.
136 require_once './includes/database.inc';
137 db_set_active();
138@@ -79,13 +85,6 @@
139 }
140 }
141 else {
142- // Since no persistent storage is available yet, and functions that check
143- // for cached data will fail, we temporarily replace the normal cache
144- // system with a stubbed-out version that short-circuits the actual
145- // caching process and avoids any errors.
146- require_once './includes/cache-install.inc';
147- $conf['cache_inc'] = './includes/cache-install.inc';
148-
149 $task = NULL;
150 }
151
152@@ -816,17 +815,14 @@
153
154 // The end of the install process. Remember profile used.
155 if ($task == 'done') {
156- // Rebuild menu to get content type links registered by the profile,
157- // and possibly any other menu items created through the tasks.
158- menu_rebuild();
159+ // Flush all caches to ensure that any full bootstraps during the installer
160+ // do not leave stale cached data, and that any content types or other items
161+ // registered by the install profile are registered correctly.
162+ drupal_flush_all_caches();
163
164 // Register actions declared by any modules.
165 actions_synchronize();
166
167- // Randomize query-strings on css/js files, to hide the fact that
168- // this is a new install, not upgraded yet.
169- _drupal_flush_css_js();
170-
171 variable_set('install_profile', $profile);
172 }
173
174
175=== modified file 'update.php'
176--- update.php 2010-12-16 19:39:23 +0000
177+++ update.php 2011-02-02 17:49:08 +0000
178@@ -595,7 +595,7 @@
179 $op = isset($_REQUEST['op']) ? $_REQUEST['op'] : '';
180 if (empty($op)) {
181 // Minimum load of components.
182- drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
183+ drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
184
185 require_once './includes/install.inc';
186 require_once './includes/file.inc';
187@@ -606,6 +606,8 @@
188 $module_list['system']['filename'] = 'modules/system/system.module';
189 $module_list['filter']['filename'] = 'modules/filter/filter.module';
190 module_list(TRUE, FALSE, FALSE, $module_list);
191+ module_implements('', FALSE, TRUE);
192+
193 drupal_load('module', 'system');
194 drupal_load('module', 'filter');
195

Subscribers

People subscribed via source and target branches

to status/vote changes: