From 12e9cabfb7600a1dba0b3353f16f53fab65c2346 Mon Sep 17 00:00:00 2001 From: markjaquith Date: Thu, 1 Feb 2007 08:53:08 +0000 Subject: [PATCH] Introduce Notoptions and Alloptions caching, so that all options (and previously attempted Notoptions) are read from the cache in one go. Should reduce cache misses to zero or close to it. fixes #3726 git-svn-id: http://svn.automattic.com/wordpress/trunk@4855 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/cache.php | 15 +---- wp-includes/functions.php | 115 +++++++++++++++++++++++++++++++------- wp-includes/version.php | 2 +- 3 files changed, 97 insertions(+), 35 deletions(-) diff --git a/wp-includes/cache.php b/wp-includes/cache.php index 09ca7cda7..8bad63ad6 100644 --- a/wp-includes/cache.php +++ b/wp-includes/cache.php @@ -191,21 +191,8 @@ class WP_Object_Cache { foreach ($dogs as $catt) $this->cache['category'][$catt->cat_ID] = $catt; } - } else - if ('options' == $group) { - $wpdb->hide_errors(); - if (!$options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'")) { - $options = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options"); - } - $wpdb->show_errors(); + } - if ( ! $options ) - return; - - foreach ($options as $option) { - $this->cache['options'][$option->option_name] = $option->option_value; - } - } } function make_group_dir($group, $perms) { diff --git a/wp-includes/functions.php b/wp-includes/functions.php index f030bb17e..c96ebd56b 100644 --- a/wp-includes/functions.php +++ b/wp-includes/functions.php @@ -208,20 +208,33 @@ function get_option($setting) { if ( $pre ) return $pre; - $value = wp_cache_get($setting, 'options'); + // prevent non-existent options from triggering multiple queries + $notoptions = wp_cache_get('notoptions', 'options'); + if ( isset($notoptions[$setting]) ) + return false; - if ( false === $value ) { - if ( defined('WP_INSTALLING') ) - $wpdb->hide_errors(); - $row = $wpdb->get_row("SELECT option_value FROM $wpdb->options WHERE option_name = '$setting' LIMIT 1"); - if ( defined('WP_INSTALLING') ) - $wpdb->show_errors(); + $alloptions = wp_load_alloptions(); - if( is_object( $row) ) { // Has to be get_row instead of get_var because of funkiness with 0, false, null values - $value = $row->option_value; - wp_cache_set($setting, $value, 'options'); - } else { - return false; + if ( isset($alloptions[$setting]) ) { + $value = $alloptions[$setting]; + } else { + $value = wp_cache_get($setting, 'options'); + + if ( false === $value ) { + if ( defined('WP_INSTALLING') ) + $wpdb->hide_errors(); + $row = $wpdb->get_row("SELECT option_value FROM $wpdb->options WHERE option_name = '$setting' LIMIT 1"); + if ( defined('WP_INSTALLING') ) + $wpdb->show_errors(); + + if( is_object( $row) ) { // Has to be get_row instead of get_var because of funkiness with 0, false, null values + $value = $row->option_value; + wp_cache_set($setting, $value, 'options'); + } else { // option does not exist, so we must cache its non-existence + $notoptions[$setting] = true; + wp_cache_set('notoptions', $notoptions, 'options'); + return false; + } } } @@ -235,6 +248,12 @@ function get_option($setting) { return apply_filters( 'option_' . $setting, maybe_unserialize($value) ); } +function wp_protect_special_option($option) { + $protected = array('alloptions', 'notoptions'); + if ( in_array($option, $protected) ) + die(sprintf(__('%s is a protected WP option and may not be modified'), wp_specialchars($option))); +} + function form_option($option) { echo attribute_escape(get_option($option)); } @@ -262,9 +281,29 @@ function get_alloptions() { return apply_filters('all_options', $all_options); } +function wp_load_alloptions() { + global $wpdb; + + $alloptions = wp_cache_get('alloptions', 'options'); + + if ( !$alloptions ) { + $wpdb->hide_errors(); + if ( !$alloptions_db = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options WHERE autoload = 'yes'") ) + $alloptions_db = $wpdb->get_results("SELECT option_name, option_value FROM $wpdb->options"); + $wpdb->show_errors(); + $alloptions = array(); + foreach ( (array) $alloptions_db as $o ) + $alloptions[$o->option_name] = $o->option_value; + wp_cache_set('alloptions', $alloptions, 'options'); + } + return $alloptions; +} + function update_option($option_name, $newvalue) { global $wpdb; + wp_protect_special_option($option_name); + if ( is_string($newvalue) ) $newvalue = trim($newvalue); @@ -279,10 +318,22 @@ function update_option($option_name, $newvalue) { return true; } + $notoptions = wp_cache_get('notoptions', 'options'); + if ( isset($notoptions[$option_name]) ) { + unset($notoptions[$option_name]); + wp_cache_set('notoptions', $notoptions, 'options'); + } + $_newvalue = $newvalue; $newvalue = maybe_serialize($newvalue); - wp_cache_set($option_name, $newvalue, 'options'); + $alloptions = wp_load_alloptions(); + if ( isset($alloptions[$option_name]) ) { + $alloptions[$options_name] = $newvalue; + wp_cache_set('alloptions', $alloptions, 'options'); + } else { + wp_cache_set($option_name, $newvalue, 'options'); + } $newvalue = $wpdb->escape($newvalue); $option_name = $wpdb->escape($option_name); @@ -298,13 +349,26 @@ function update_option($option_name, $newvalue) { function add_option($name, $value = '', $description = '', $autoload = 'yes') { global $wpdb; - // Make sure the option doesn't already exist - if ( false !== get_option($name) ) - return; + wp_protect_special_option($name); + + // Make sure the option doesn't already exist we can check the cache before we ask for a db query + $notoptions = wp_cache_get('notoptions', 'options'); + if ( isset($notoptions[$name]) ) { + unset($notoptions[$name]); + wp_cache_set('notoptions', $notoptions, 'options'); + } elseif ( false !== get_option($name) ) { + return; + } $value = maybe_serialize($value); - wp_cache_set($name, $value, 'options'); + if ( 'yes' == $autoload ) { + $alloptions = wp_load_alloptions(); + $alloptions[$name] = $value; + wp_cache_set('alloptions', $alloptions, 'options'); + } else { + wp_cache_set($name, $value, 'options'); + } $name = $wpdb->escape($name); $value = $wpdb->escape($value); @@ -316,11 +380,22 @@ function add_option($name, $value = '', $description = '', $autoload = 'yes') { function delete_option($name) { global $wpdb; + + wp_protect_special_option($name); + // Get the ID, if no ID then return - $option_id = $wpdb->get_var("SELECT option_id FROM $wpdb->options WHERE option_name = '$name'"); - if ( !$option_id ) return false; + $option = $wpdb->get_row("SELECT option_id, autoload FROM $wpdb->options WHERE option_name = '$name'"); + if ( !$option->option_id ) return false; $wpdb->query("DELETE FROM $wpdb->options WHERE option_name = '$name'"); - wp_cache_delete($name, 'options'); + if ( 'yes' == $option->autoload ) { + $alloptions = wp_load_alloptions(); + if ( isset($alloptions[$name]) ) { + unset($alloptions[$name]); + wp_cache_set('alloptions', $alloptions, 'options'); + } + } else { + wp_cache_delete($name, 'options'); + } return true; } diff --git a/wp-includes/version.php b/wp-includes/version.php index 1f55e5174..3bf2ede06 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -3,6 +3,6 @@ // This holds the version number in a separate file so we can bump it without cluttering the SVN $wp_version = '2.2-bleeding'; -$wp_db_version = 4772; +$wp_db_version = 4773; ?>