Drupal Caching Analysis

Drupal processing:

From /drupal/index.php, bootstrap.inc is brought in and then drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); is executed.

  • drupal_bootstrap executes all of the phases up to and including DRUPAL_BOOTSTRAP_FULL:
    • DRUPAL_BOOTSTRAP_CONFIGURATION: Initializes configuration.
    • DRUPAL_BOOTSTRAP_PAGE_CACHE: Tries to serve a cached page.
    • DRUPAL_BOOTSTRAP_DATABASE: Initializes the database layer.
    • DRUPAL_BOOTSTRAP_VARIABLES: Initializes the variable system.
    • DRUPAL_BOOTSTRAP_SESSION: Initializes session handling.
    • DRUPAL_BOOTSTRAP_PAGE_HEADER: Sets up the page header.
    • DRUPAL_BOOTSTRAP_LANGUAGE: Finds out the language of the page.
    • DRUPAL_BOOTSTRAP_FULL: Fully loads Drupal. Validates and fixes input data.
    • If drupal_bootstrap is called again internally, it will check to see if all of the phases up to the requested phase have been run and will run them only if they have not previously been run.
    • Most of the actual processing occurs in the last stage (function _drupal_bootstrap_full() is located in common.inc). Note however that delivery of a cached page occurs in the 2nd phase and this terminates further page processing.

On return from drupal_bootstrap, index.php then runs menu_execute_active_handler(); (function is located in menu.inc.) This function takes care of delivering a message to the user in case of an exception in page processing (Such as system offline, page not found, etc.) Note that index.php has invalid syntax - there is no terminator for the php block.

Bootstrap phase DRUPAL_BOOTSTRAP_PAGE_CACHE runs _drupal_bootstrap_page_cache() (located in bootstrap.inc).

After checking a few qualifiers, this function calls drupal_page_get_cache() (located in bootstrap.inc). drupal_page_get_cache() calls cache_get($base_root . request_uri(), 'cache_page'); (located in cache.inc) Note that the information passed in the arguments only includes the page that was requested.

Conclusions:

The call to cache_get() clearly shows that the only selection criteria provided for getting a cached page is the URL. To implement per-page/per-theme caching, the following changes are necessary:

  • Theme selection must be performed ahead of the DRUPAL_BOOTSTRAP_PAGE_CACHE phase so the required theme is defined. The only means to intervene ahead of the DRUPAL_BOOTSTRAP_PAGE_CACHE phase is through hook_boot(), so all theme selection must be implemented at this point. The information required for theme selection may require that additional phases be run to initialize Drupal to the point where the information is available. This may have to be coded explicitly outside of drupal_bootstrap() since any attempt to have drupal_bootstrap() bring the system up to a point later than DRUPAL_BOOTSTRAP_PAGE_CACHE will again run DRUPAL_BOOTSTRAP_PAGE_CACHE creating an infinite recursion.
  • All accesses to the page cache must be recoded to use a key containing both the page URL and the theme. This will require a lot of changes since there are quite a few of this type of access.
  • The changes required will create an upgrade headche since all of the changes must be reapplied whenever a new upgrade is installed. Creating patch files for the changes would ease this process but patch files are not foolproof. If major changes have been made in the upgrade, patch may not be able to resolve the additional changes.
  • An alternative approach might be to add the theme to Drupal's internal URL variable so that caching is for the combination of actual URL+theme. This may require some modification of the alias and node resolution to strip off the theme for those purposes.