summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2008-03-14 08:51:37 +0000
committerDries Buytaert <dries@buytaert.net>2008-03-14 08:51:37 +0000
commita5c2ad2178cfd10d25c9ad78079af462507c5f61 (patch)
tree59ef7b1db72c64c8c8e78b34f87edcce475d0299
parentef706b824eb72c3ac3e12ac39b3d0e9d5c99b5ec (diff)
downloadbrdo-a5c2ad2178cfd10d25c9ad78079af462507c5f61.tar.gz
brdo-a5c2ad2178cfd10d25c9ad78079af462507c5f61.tar.bz2
- Patch #231587 by pwolanin et al: fixed scalability issue in the menu system.
-rw-r--r--includes/menu.inc53
-rw-r--r--modules/book/book.module23
2 files changed, 59 insertions, 17 deletions
diff --git a/includes/menu.inc b/includes/menu.inc
index b856176df..7d9b81322 100644
--- a/includes/menu.inc
+++ b/includes/menu.inc
@@ -773,16 +773,22 @@ function menu_tree_all_data($menu_name = 'navigation', $item = NULL) {
// Use $mlid as a flag for whether the data being loaded is for the whole tree.
$mlid = isset($item['mlid']) ? $item['mlid'] : 0;
- // Generate the cache ID.
- $cid = 'links:'. $menu_name .':all:'. $mlid;
+ // Generate a cache ID (cid) specific for this $menu_name and $item.
+ $cid = 'links:'. $menu_name .':all-cid:'. $mlid;
if (!isset($tree[$cid])) {
// If the static variable doesn't have the data, check {cache_menu}.
$cache = cache_get($cid, 'cache_menu');
if ($cache && isset($cache->data)) {
- $data = $cache->data;
+ // If the cache entry exists, it will just be the cid for the actual data.
+ // This avoids duplication of large amounts of data.
+ $cache = cache_get($cache->data, 'cache_menu');
+ if ($cache && isset($cache->data)) {
+ $data = $cache->data;
+ }
}
- else {
+ // If the tree data was not in the cache, $data will be NULL.
+ if (!isset($data)) {
// Build and run the query, and build the tree.
if ($mlid) {
// The tree is for a single item, so we need to match the values in its
@@ -814,8 +820,13 @@ function menu_tree_all_data($menu_name = 'navigation', $item = NULL) {
ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents);
$data['node_links'] = array();
menu_tree_collect_node_links($data['tree'], $data['node_links']);
- // Cache the data.
- cache_set($cid, $data, 'cache_menu');
+ // Cache the data, if it is not already in the cache.
+ $tree_cid = _menu_tree_cid($menu_name, $data);
+ if (!cache_get($tree_cid, 'cache_menu')) {
+ cache_set($tree_cid, $data, 'cache_menu');
+ }
+ // Cache the cid of the (shared) data using the menu and item-specific cid.
+ cache_set($cid, $tree_cid, 'cache_menu');
}
// Check access for the current user to each item in the tree.
menu_tree_check_access($data['tree'], $data['node_links']);
@@ -845,16 +856,22 @@ function menu_tree_page_data($menu_name = 'navigation') {
// Load the menu item corresponding to the current page.
if ($item = menu_get_item()) {
- // Generate the cache ID.
- $cid = 'links:'. $menu_name .':page:'. $item['href'] .':'. (int)$item['access'];
+ // Generate a cache ID (cid) specific for this page.
+ $cid = 'links:'. $menu_name .':page-cid:'. $item['href'] .':'. (int)$item['access'];
if (!isset($tree[$cid])) {
// If the static variable doesn't have the data, check {cache_menu}.
$cache = cache_get($cid, 'cache_menu');
if ($cache && isset($cache->data)) {
- $data = $cache->data;
+ // If the cache entry exists, it will just be the cid for the actual data.
+ // This avoids duplication of large amounts of data.
+ $cache = cache_get($cache->data, 'cache_menu');
+ if ($cache && isset($cache->data)) {
+ $data = $cache->data;
+ }
}
- else {
+ // If the tree data was not in the cache, $data will be NULL.
+ if (!isset($data)) {
// Build and run the query, and build the tree.
if ($item['access']) {
// Check whether a menu link exists that corresponds to the current path.
@@ -910,8 +927,13 @@ function menu_tree_page_data($menu_name = 'navigation') {
ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args), $parents);
$data['node_links'] = array();
menu_tree_collect_node_links($data['tree'], $data['node_links']);
- // Cache the data.
- cache_set($cid, $data, 'cache_menu');
+ // Cache the data, if it is not already in the cache.
+ $tree_cid = _menu_tree_cid($menu_name, $data);
+ if (!cache_get($tree_cid, 'cache_menu')) {
+ cache_set($tree_cid, $data, 'cache_menu');
+ }
+ // Cache the cid of the (shared) data using the page-specific cid.
+ cache_set($cid, $tree_cid, 'cache_menu');
}
// Check access for the current user to each item in the tree.
menu_tree_check_access($data['tree'], $data['node_links']);
@@ -924,6 +946,13 @@ function menu_tree_page_data($menu_name = 'navigation') {
}
/**
+ * Helper function - compute the real cache ID for menu tree data.
+ */
+function _menu_tree_cid($menu_name, $data) {
+ return 'links:'. $menu_name .':tree-data:'. md5(serialize($data));
+}
+
+/**
* Recursive helper function - collect node links.
*/
function menu_tree_collect_node_links(&$tree, &$node_links) {
diff --git a/modules/book/book.module b/modules/book/book.module
index 31ddb5526..b62eb234e 100644
--- a/modules/book/book.module
+++ b/modules/book/book.module
@@ -1049,14 +1049,21 @@ function book_link_load($mlid) {
function book_menu_subtree_data($item) {
static $tree = array();
- $cid = 'links:'. $item['menu_name'] .':subtree:'. $item['mlid'];
+ // Generate a cache ID (cid) specific for this $menu_name and $item.
+ $cid = 'links:'. $item['menu_name'] .':subtree-cid:'. $item['mlid'];
if (!isset($tree[$cid])) {
$cache = cache_get($cid, 'cache_menu');
if ($cache && isset($cache->data)) {
- $data = $cache->data;
+ // If the cache entry exists, it will just be the cid for the actual data.
+ // This avoids duplication of large amounts of data.
+ $cache = cache_get($cache->data, 'cache_menu');
+ if ($cache && isset($cache->data)) {
+ $data = $cache->data;
+ }
}
- else {
+ // If the subtree data was not in the cache, $data will be NULL.
+ if (!isset($data)) {
$match = array("menu_name = '%s'");
$args = array($item['menu_name']);
$i = 1;
@@ -1075,8 +1082,14 @@ function book_menu_subtree_data($item) {
$data['tree'] = menu_tree_data(db_query($sql, $args), array(), $item['depth']);
$data['node_links'] = array();
menu_tree_collect_node_links($data['tree'], $data['node_links']);
- // Cache the data.
- cache_set($cid, $data, 'cache_menu');
+ // Compute the real cid for book subtree data.
+ $tree_cid = 'links:'. $menu_name .':subtree-data:'. md5(serialize($data));
+ // Cache the data, if it is not already in the cache.
+ if (!cache_get($tree_cid, 'cache_menu')) {
+ cache_set($tree_cid, $data, 'cache_menu');
+ }
+ // Cache the cid of the (shared) data using the menu and item-specific cid.
+ cache_set($cid, $tree_cid, 'cache_menu');
}
// Check access for the current user to each item in the tree.
menu_tree_check_access($data['tree'], $data['node_links']);