Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
59ece2e3
Commit
59ece2e3
authored
Nov 11, 2008
by
Dries Buytaert
Browse files
- Patch
#325665
by chx, Damien Tournoud, justinrandell et al: improved the cache registry lookups.
parent
9d631d22
Changes
10
Hide whitespace changes
Inline
Side-by-side
includes/bootstrap.inc
View file @
59ece2e3
...
...
@@ -206,6 +206,16 @@
*/
define
(
'PASS_THROUGH'
,
-
1
);
/**
* Signals that the registry lookup cache should be reset.
*/
define
(
'REGISTRY_RESET_LOOKUP_CACHE'
,
1
);
/**
* Signals that the registry lookup cache should be written to storage.
*/
define
(
'REGISTRY_WRITE_LOOKUP_CACHE'
,
2
);
/**
* @} End of "Title text filtering flags".
*/
...
...
@@ -655,7 +665,7 @@ function page_get_cache() {
* The name of the bootstrap hook we wish to invoke.
*/
function
bootstrap_invoke_all
(
$hook
)
{
foreach
(
module_
list
(
TRUE
,
TRUE
)
as
$module
)
{
foreach
(
module_
implements
(
$hook
)
as
$module
)
{
module_invoke
(
$module
,
$hook
);
}
}
...
...
@@ -1412,7 +1422,6 @@ function drupal_function_exists($function) {
$checked
[
$function
]
=
FALSE
;
if
(
function_exists
(
$function
))
{
registry_mark_code
(
'function'
,
$function
);
$checked
[
$function
]
=
TRUE
;
return
TRUE
;
}
...
...
@@ -1456,8 +1465,52 @@ function drupal_autoload_class($class) {
/**
* Helper to check for a resource in the registry.
*
* @param $type
* The type of resource we are looking up, or one of the constants
* REGISTRY_RESET_LOOKUP_CACHE or REGISTRY_WRITE_LOOKUP_CACHE, which
* signal that we should reset or write the cache, respectively.
* @param $name
* The name of the resource, or NULL if either of the REGISTRY_* constants
* is passed in.
* @return
* TRUE if the resource was found, FALSE if not.
* NULL if either of the REGISTRY_* constants is passed in as $type.
*/
function
_registry_check_code
(
$type
,
$name
)
{
function
_registry_check_code
(
$type
,
$name
=
NULL
)
{
static
$lookup_cache
,
$cache_update_needed
;
if
(
!
isset
(
$lookup_cache
))
{
$lookup_cache
=
_registry_get_lookup_cache
();
}
// When we rebuild the registry, we need to reset this cache so
// we don't keep lookups for resources that changed during the rebuild.
if
(
$type
==
REGISTRY_RESET_LOOKUP_CACHE
)
{
$cache_update_needed
=
TRUE
;
$lookup_cache
=
NULL
;
return
;
}
// Called from drupal_page_footer, we write to permanent storage if there
// changes to the lookup cache for this request.
if
(
$type
==
REGISTRY_WRITE_LOOKUP_CACHE
)
{
if
(
$cache_update_needed
)
{
_registry_set_lookup_cache
(
$lookup_cache
);
}
return
;
}
// $type can be one of 'function', 'interface' or 'class', so we only need the
// first letter to keep the cache key unique.
$cache_key
=
$type
[
0
]
.
$name
;
if
(
isset
(
$lookup_cache
[
$cache_key
]))
{
if
(
$lookup_cache
[
$cache_key
])
{
require_once
DRUPAL_ROOT
.
'/'
.
$lookup_cache
[
$cache_key
];
}
return
$lookup_cache
[
$cache_key
];
}
// This function may get called when the default database is not active, but
// there is no reason we'd ever want to not use the default database for
// this query.
...
...
@@ -1466,38 +1519,20 @@ function _registry_check_code($type, $name) {
':type'
=>
$type
,
))
->
fetchField
();
// Flag that we've run a lookup query and need to update the cache.
$cache_update_needed
=
TRUE
;
// Misses are valuable information worth caching, so cache even if
// $file is FALSE.
$lookup_cache
[
$cache_key
]
=
$file
;
if
(
$file
)
{
require_once
DRUPAL_ROOT
.
'/'
.
$file
;
registry_mark_code
(
$type
,
$name
);
return
TRUE
;
}
return
FALSE
;
}
/**
* Collect the resources used for this request.
*
* @param $type
* The type of resource.
* @param $name
* The name of the resource.
* @param $return
* Boolean flag to indicate whether to return the resources.
*/
function
registry_mark_code
(
$type
,
$name
,
$return
=
FALSE
)
{
static
$resources
=
array
();
if
(
$type
&&
$name
)
{
if
(
!
isset
(
$resources
[
$type
]))
{
$resources
[
$type
]
=
array
();
}
if
(
!
in_array
(
$name
,
$resources
[
$type
]))
{
$resources
[
$type
][]
=
$name
;
}
}
if
(
$return
)
{
return
$resources
;
else
{
return
FALSE
;
}
}
...
...
@@ -1513,60 +1548,35 @@ function registry_rebuild() {
}
/**
*
Save the files required by the registry for this path
.
*
Wrapper function to perform array to string conversion of lookup cache
.
*/
function
registry_cache_path_files
()
{
if
(
$used_code
=
registry_mark_code
(
NULL
,
NULL
,
TRUE
))
{
$files
=
array
();
$type_sql
=
array
();
$params
=
array
();
// This function may get called when the default database is not active, but
// there is no reason we'd ever want to not use the default database for
// this query.
$select
=
Database
::
getConnection
(
'default'
)
->
select
(
'registry'
)
->
distinct
();
$select
->
addField
(
'registry'
,
'filename'
);
// This creates a series of 2-clause AND conditions that are then ORed together.
$ors
=
db_or
();
foreach
(
$used_code
as
$type
=>
$names
)
{
$and
=
db_and
()
->
condition
(
'name'
,
$names
,
'IN'
)
->
condition
(
'type'
,
$type
);
$ors
->
condition
(
$and
);
}
$select
->
condition
(
$ors
);
$files
=
$select
->
execute
()
->
fetchCol
();
if
(
$files
)
{
sort
(
$files
);
// Only write this to cache if the file list we are going to cache
// is different to what we loaded earlier in the request.
if
(
$files
!=
registry_load_path_files
(
TRUE
))
{
$menu
=
menu_get_item
();
cache_set
(
'registry:'
.
$menu
[
'path'
],
implode
(
';'
,
$files
),
'cache_registry'
);
}
}
function
_registry_set_lookup_cache
(
array
$lookup_cache
)
{
// Cache a string, not an array, so we can avoid the memory usage hit
// from serialize() in the cache system.
$key_value_pairs
=
array
();
foreach
(
$lookup_cache
as
$key
=>
$value
)
{
$key_value_pairs
[]
=
"
$key
|"
.
(
$value
?
$value
:
''
);
}
return
cache_set
(
'lookup_cache'
,
implode
(
';'
,
$key_value_pairs
),
'cache_registry'
);
}
/**
*
registry_load_path_files
*
Wrapper function to perform string to array conversion of lookup cache.
*/
function
registry_load_path_files
(
$return
=
FALSE
)
{
static
$file_cache_data
=
array
();
if
(
$return
)
{
sort
(
$file_cache_data
);
return
$file_cache_data
;
}
$menu
=
menu_get_item
();
$cache
=
cache_get
(
'registry:'
.
$menu
[
'path'
],
'cache_registry'
);
if
(
!
empty
(
$cache
->
data
))
{
foreach
(
explode
(
';'
,
$cache
->
data
)
as
$file
)
{
require_once
DRUPAL_ROOT
.
'/'
.
$file
;
$file_cache_data
[]
=
$file
;
function
_registry_get_lookup_cache
()
{
// In _registry_set_lookup_cache, we cache a string, not an array, to avoid
// serialize() in the cache system. serialize() makes a copy, and thus uses
// extra memory, which we are trying to avoid.
$lookup_cache
=
array
();
if
(
$cache
=
cache_get
(
'lookup_cache'
,
'cache_registry'
))
{
// Each item is separated by ';'.
foreach
(
explode
(
';'
,
$cache
->
data
)
as
$lookup
)
{
// Key value pairs are separated by '|'.
list
(
$resource
,
$result
)
=
explode
(
'|'
,
$lookup
);
$lookup_cache
[
$resource
]
=
$result
;
}
}
return
$lookup_cache
;
}
/**
...
...
includes/common.inc
View file @
59ece2e3
...
...
@@ -1641,7 +1641,7 @@ function drupal_page_footer() {
module_invoke_all
(
'exit'
);
module_implements
(
MODULE_IMPLEMENTS_WRITE_CACHE
);
registry_c
ache_path_files
(
);
_
registry_c
heck_code
(
REGISTRY_WRITE_LOOKUP_CACHE
);
}
/**
...
...
includes/menu.inc
View file @
59ece2e3
...
...
@@ -393,7 +393,6 @@ function menu_execute_active_handler($path = NULL) {
menu_rebuild
();
}
if
(
$router_item
=
menu_get_item
(
$path
))
{
registry_load_path_files
();
if
(
$router_item
[
'access'
])
{
if
(
drupal_function_exists
(
$router_item
[
'page_callback'
]))
{
return
call_user_func_array
(
$router_item
[
'page_callback'
],
$router_item
[
'page_arguments'
]);
...
...
includes/module.inc
View file @
59ece2e3
...
...
@@ -90,7 +90,7 @@ function module_list($refresh = FALSE, $bootstrap = TRUE, $sort = FALSE, $fixed_
* The array of filesystem objects used to rebuild the cache.
*/
function
module_rebuild_cache
()
{
// Get current list of modules
// Get current list of modules
, including uninstalled modules.
$files
=
drupal_system_listing
(
'/\.module$/'
,
'modules'
,
'name'
,
0
);
// Extract current files from database.
...
...
@@ -128,7 +128,8 @@ function module_rebuild_cache() {
// Log the critical hooks implemented by this module.
$bootstrap
=
0
;
foreach
(
bootstrap_hooks
()
as
$hook
)
{
if
(
module_hook
(
$file
->
name
,
$hook
))
{
// Only look for hooks in installed modules.
if
(
!
empty
(
$file
->
status
)
&&
in_array
(
$file
->
name
,
module_implements
(
$hook
)))
{
$bootstrap
=
1
;
break
;
}
...
...
includes/registry.inc
View file @
59ece2e3
...
...
@@ -69,10 +69,26 @@ function _registry_rebuild() {
->
execute
();
}
}
_registry_parse_files
(
$files
);
$parsed_files
=
_registry_parse_files
(
$files
);
$unchanged_resources
=
array
();
foreach
(
_registry_get_lookup_cache
()
as
$key
=>
$file
)
{
// If the file for this cached resource is carried over unchanged from
// the last registry build, then we can safely re-cache it.
if
(
$file
&&
in_array
(
$file
,
array_keys
(
$files
))
&&
!
in_array
(
$file
,
$parsed_files
))
{
$unchanged_resources
[
$key
]
=
$file
;
}
}
_registry_check_code
(
REGISTRY_RESET_LOOKUP_CACHE
);
module_implements
(
MODULE_IMPLEMENTS_CLEAR_CACHE
);
cache_clear_all
(
'*'
,
'cache_registry'
,
TRUE
);
// We have some unchanged resources, warm up the cache - no need to pay
// for looking them up again.
if
(
count
(
$unchanged_resources
)
>
0
)
{
_registry_set_lookup_cache
(
$unchanged_resources
);
}
}
/**
...
...
@@ -92,12 +108,13 @@ function registry_get_parsed_files() {
* The list of files to check and parse.
*/
function
_registry_parse_files
(
$files
)
{
$
chang
ed_files
=
array
();
$
pars
ed_files
=
array
();
foreach
(
$files
as
$filename
=>
$file
)
{
$contents
=
file_get_contents
(
$filename
);
$md5
=
md5
(
$contents
);
$new_file
=
!
isset
(
$file
[
'md5'
]);
if
(
$new_file
||
$md5
!=
$file
[
'md5'
])
{
$parsed_files
[]
=
$filename
;
// We update the md5 after we've saved the files resources rather than here, so if we
// don't make it through this rebuild, the next run will reparse the file.
_registry_parse_file
(
$filename
,
$contents
,
$file
[
'module'
],
$file
[
'weight'
]);
...
...
@@ -108,6 +125,7 @@ function _registry_parse_files($files) {
->
execute
();
}
}
return
$parsed_files
;
}
/**
...
...
modules/block/block.module
View file @
59ece2e3
...
...
@@ -239,7 +239,7 @@ function _block_rehash() {
// Valid region names for the theme.
$regions
=
system_region_list
(
$theme_key
);
foreach
(
module_
list
(
)
as
$module
)
{
foreach
(
module_
implements
(
'block'
)
as
$module
)
{
$module_blocks
=
module_invoke
(
$module
,
'block'
,
'list'
);
if
(
$module_blocks
)
{
foreach
(
$module_blocks
as
$delta
=>
$block
)
{
...
...
modules/system/system.admin.inc
View file @
59ece2e3
...
...
@@ -657,7 +657,7 @@ function system_modules($form_state = array()) {
}
}
// Generate link for module's help page, if there is one.
if
(
$help_arg
&&
module
_hook
(
$filename
,
'help'
))
{
if
(
$help_arg
&&
$
module
->
status
&&
in_array
(
$filename
,
module_implements
(
'help'
))
)
{
if
(
module_invoke
(
$filename
,
'help'
,
"admin/help#
$filename
"
,
$help_arg
))
{
// Module has a help page.
$extra
[
'help'
]
=
theme
(
'more_help_link'
,
url
(
"admin/help/
$filename
"
));
...
...
modules/system/system.module
View file @
59ece2e3
...
...
@@ -1398,12 +1398,12 @@ function system_get_module_admin_tasks($module) {
$admin_tasks
=
array
();
$admin_task_count
=
0
;
// Check for permissions.
if
(
module_hook
(
$module
,
'perm'
)
&&
$admin_access
)
{
if
(
in_array
(
$module
,
module_implements
(
'perm'
)
)
&&
$admin_access
)
{
$admin_tasks
[
-
1
]
=
l
(
t
(
'Configure permissions'
),
'admin/user/permissions'
,
array
(
'fragment'
=>
'module-'
.
$module
));
}
// Check for menu items that are admin links.
if
(
$menu
=
module_invoke
(
$module
,
'menu'
))
{
if
(
in_array
(
$module
,
module_implements
(
'menu'
))
&&
$menu
=
module_invoke
(
$module
,
'menu'
))
{
foreach
(
array_keys
(
$menu
)
as
$path
)
{
if
(
isset
(
$items
[
$path
]))
{
$admin_tasks
[
$items
[
$path
][
'title'
]
.
$admin_task_count
++
]
=
l
(
$items
[
$path
][
'title'
],
$path
);
...
...
modules/user/user.admin.inc
View file @
59ece2e3
...
...
@@ -510,7 +510,7 @@ function user_admin_perm($form_state, $rid = NULL) {
// Render role/permission overview:
$options
=
array
();
$hide_descriptions
=
!
system_admin_compact_mode
();
foreach
(
module_
list
(
FALSE
,
FALSE
,
TRUE
)
as
$module
)
{
foreach
(
module_
implements
(
'perm'
)
as
$module
)
{
if
(
$permissions
=
module_invoke
(
$module
,
'perm'
))
{
$form
[
'permission'
][]
=
array
(
'#markup'
=>
$module
,
...
...
modules/user/user.module
View file @
59ece2e3
...
...
@@ -1917,7 +1917,7 @@ function user_help($path, $arg) {
function
_user_categories
(
$account
)
{
$categories
=
array
();
foreach
(
module_
list
(
)
as
$module
)
{
foreach
(
module_
implements
(
'user_categories'
)
as
$module
)
{
if
(
$data
=
module_invoke
(
$module
,
'user_categories'
,
NULL
,
$account
,
''
))
{
$categories
=
array_merge
(
$data
,
$categories
);
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment