=== added file 'doc/source/diagnostics/error_code_histogram.rst'
--- doc/source/diagnostics/error_code_histogram.rst	1970-01-01 00:00:00 +0000
+++ doc/source/diagnostics/error_code_histogram.rst	2011-12-20 19:11:35 +0000
@@ -0,0 +1,39 @@
+.. _errcode_histogram:
+
+=================
+ Error Code Histogram
+=================
+
+This feature adds two plugins and a table ``INFORMATION_SCHEMA.ERRCODE_HISTOGRAM`` . The table can be used to understand the error code distribution of the server.
+
+The two plugins should be installed by command ``"install plugin ERRCODE_AUDIT soname 'adt_errcode_histogram.so'"`` and ``"install plugin ERRCODE_HISTOGRAM soname 'adt_errcode_histogram.so'"``, they work by keeping one hash table in memory. All connections visit and change the same hash table, so global mutex is used.
+
+
+Other Information
+=================
+
+  * Author/Origin:
+     *Percona*; *Percona* added the ``INFORMATION_SCHEMA.ERRCODE_HISTOGRAM`` table .
+
+
+INFORMATION_SCHEMA Tables
+=========================
+
+.. table:: INFORMATION_SCHEMA.ERRCODE_HISTOGRAM
+
+  :column ERROR: The error code which occurd at least once from last start.
+  :column COUNT: The appear times of the error code.
+
+This table holds statistics about error code histogram. 
+
+Example: ::
+
+  mysql> SELECT * FROM INFORMATION_SCHEMA.ERRCODE_HISTOGRAM;
+  +-------+-------+
+  | ERROR | COUNT |
+  +-------+-------+
+  |  1062 |     1 |
+  |  1159 |     1 |
+  |  1054 |     6 |
+  +-------+-------+
+

=== added file 'patches/error_code_histogram.patch'
--- patches/error_code_histogram.patch	1970-01-01 00:00:00 +0000
+++ patches/error_code_histogram.patch	2011-12-20 19:11:35 +0000
@@ -0,0 +1,410 @@
+--- a/plugin/audit_errcode_histogram/audit_errcode_histogram.cc	1970-01-01 08:00:00.000000000 +0800
++++ b/plugin/audit_errcode_histogram/audit_errcode_histogram.cc	2011-12-19 13:15:13.000000000 +0800
+@@ -0,0 +1,308 @@
++/* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
++
++  This program is free software; you can redistribute it and/or
++  modify it under the terms of the GNU General Public License
++  as published by the Free Software Foundation; version 2 of
++  the License.
++
++  This program is distributed in the hope that it will be useful,
++  but WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++  GNU General Public License for more details.
++
++  You should have received a copy of the GNU General Public License
++  along with this program; if not, write to the Free Software
++  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
++
++#include <mysql/plugin_audit.h>
++#include "unireg.h"
++#include "sql_show.h"
++
++#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8)
++#define __attribute__(A)
++#endif
++
++/* lock management */
++
++mysql_mutex_t LOCK_errcode_;
++
++#ifdef HAVE_PSI_INTERFACE
++PSI_mutex_key key_ss_mutex_LOCK_errcode_;
++static PSI_mutex_info all_semisync_mutexes[]=
++{
++  { &key_ss_mutex_LOCK_errcode_, "LOCK_errcode_", 0}
++};
++
++static void init_semisync_psi_keys(void)
++{
++  const char* category= "semisync";
++  int count;
++
++  if (PSI_server == NULL)
++    return;
++
++  count= array_elements(all_semisync_mutexes);
++  PSI_server->register_mutex(category, all_semisync_mutexes, count);
++
++}
++#endif /* HAVE_PSI_INTERFACE */
++
++/* hash management */
++static HASH error_code_hash;
++
++struct st_errcode_item
++{
++  uint error_code;
++  ulonglong count;
++};
++
++void free_errcode_hash_item(st_errcode_item *entry)
++{
++  my_free(entry);
++}
++
++const uchar *get_errcode_key(st_errcode_item *entry, size_t *length,
++                              my_bool not_used __attribute__((unused)))
++{
++  *length= sizeof(int);
++  return (const uchar *)&entry->error_code;
++}
++
++void add_notify_error_code(int error_code)
++{
++  mysql_mutex_lock(&LOCK_errcode_);
++
++  st_errcode_item *item= (st_errcode_item*) my_hash_search(&error_code_hash, (const uchar*)&error_code, sizeof(int));
++  if (item)
++  {
++    item->count++;
++  }
++  else
++  {
++    item= new st_errcode_item;
++    item->error_code= error_code;
++    item->count= 1;
++
++    if (my_hash_insert(&error_code_hash, (uchar*)item))
++    {
++      my_error(ER_OUT_OF_RESOURCES, MYF(0));
++    }
++  }
++
++  mysql_mutex_unlock(&LOCK_errcode_);
++}
++
++/*
++  Initialize the plugin at server start or plugin installation.
++
++  SYNOPSIS
++    audit_errcode_histogram_plugin_init()
++
++  DESCRIPTION
++    Does nothing.
++
++  RETURN VALUE
++    0                    success
++    1                    failure (cannot happen)
++*/
++
++static int audit_errcode_histogram_plugin_init(void *arg __attribute__((unused)))
++{
++#ifdef HAVE_PSI_INTERFACE
++  init_semisync_psi_keys();
++#endif
++
++  mysql_mutex_init(key_ss_mutex_LOCK_errcode_,
++                   &LOCK_errcode_, MY_MUTEX_INIT_FAST);
++
++  if (my_hash_init(&error_code_hash, system_charset_info, 200, 0, 0,
++                  (my_hash_get_key) get_errcode_key,(my_hash_free_key) free_errcode_hash_item, 0))
++    return 1;
++
++  return 0; 
++}
++
++
++/*
++  Terminate the plugin at server shutdown or plugin deinstallation.
++
++  SYNOPSIS
++    audit_errcode_histogram_plugin_deinit()
++    Does nothing.
++
++  RETURN VALUE
++    0                    success
++    1                    failure (cannot happen)
++*/
++
++static int audit_errcode_histogram_plugin_deinit(void *arg __attribute__((unused)))
++{
++  mysql_mutex_lock(&LOCK_errcode_);
++  my_hash_free(&error_code_hash);
++  mysql_mutex_unlock(&LOCK_errcode_);
++
++  mysql_mutex_destroy(&LOCK_errcode_);
++  return 0;
++}
++
++
++/*
++  Foo
++
++  SYNOPSIS
++    audit_errcode_histogram_notify()
++      thd                connection context
++
++  DESCRIPTION
++*/
++
++static void audit_errcode_histogram_notify(MYSQL_THD thd __attribute__((unused)),
++                              unsigned int event_class,
++                              const void *event)
++{
++  if (event_class == MYSQL_AUDIT_GENERAL_CLASS)
++  {
++    const struct mysql_event_general *event_general=
++      (const struct mysql_event_general *) event;
++    if (event_general->event_subclass != MYSQL_AUDIT_GENERAL_ERROR)
++      return;
++
++    add_notify_error_code(event_general->general_error_code);
++  }
++}
++
++
++/*
++  Plugin type-specific descriptor
++*/
++
++static struct st_mysql_audit audit_errcode_histogram_descriptor=
++{
++  MYSQL_AUDIT_INTERFACE_VERSION,                    /* interface version    */
++  NULL,                                             /* release_thd function */
++  audit_errcode_histogram_notify,                                /* notify function      */
++  { (unsigned long) MYSQL_AUDIT_GENERAL_CLASSMASK } /* class mask           */
++};
++
++
++static ST_FIELD_INFO i_s_errcode_histogram_fields[] =
++{
++#define I_S_ERROR_CODE 0
++  {"ERROR", 21 , MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE},
++#define I_S_ERROR_CODE_COUNT 1
++  {"COUNT", 21, MYSQL_TYPE_LONGLONG, 0, 0, 0, SKIP_OPEN_TABLE}
++};
++
++
++int i_s_fill_table_errcode_histogram(THD* thd, TABLE_LIST* tables, COND* cond)
++{
++  TABLE *table= tables->table;
++
++  st_errcode_item *item= NULL;
++  uint i;
++  for (i= 0; i < error_code_hash.records; i++)
++  {
++    mysql_mutex_lock(&LOCK_errcode_);
++    item= (st_errcode_item*) my_hash_element(&error_code_hash, i);
++    mysql_mutex_unlock(&LOCK_errcode_);
++
++    table->field[I_S_ERROR_CODE]->store((longlong)item->error_code, TRUE);
++    table->field[I_S_ERROR_CODE_COUNT]->store((longlong)item->count, TRUE);
++    schema_table_store_record(thd, table);
++  }
++  return 0;
++}
++
++
++/*
++  Initialize the plugin at server start or plugin installation.
++
++  SYNOPSIS
++    audit_errcode_histogram_plugin_init()
++
++  DESCRIPTION
++    Does nothing.
++
++  RETURN VALUE
++    0                    success
++    1                    failure (cannot happen)
++*/
++
++static int i_s_errcode_histogram_plugin_init(void *arg __attribute__((unused)))
++{
++  ST_SCHEMA_TABLE*        schema;
++
++  schema = (ST_SCHEMA_TABLE*) arg;
++
++  schema->fields_info = i_s_errcode_histogram_fields;
++  schema->fill_table = i_s_fill_table_errcode_histogram;
++  return 0;
++}
++
++
++/*
++  Terminate the plugin at server shutdown or plugin deinstallation.
++
++  SYNOPSIS
++    audit_errcode_histogram_plugin_deinit()
++    Does nothing.
++
++  RETURN VALUE
++    0                    success
++    1                    failure (cannot happen)
++
++*/
++
++static int i_s_errcode_histogram_plugin_deinit(void *arg __attribute__((unused)))
++{
++  return(0);
++}
++
++/*
++  Plugin type-specific descriptor
++*/
++
++static struct st_mysql_information_schema i_s_error_histogram=
++{
++  MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
++};
++
++
++/*
++  Plugin library descriptor
++*/
++
++mysql_declare_plugin(adt_errcode_histogram)
++{
++  MYSQL_AUDIT_PLUGIN,         /* type                            */
++  &audit_errcode_histogram_descriptor,     /* descriptor                      */
++  "ERRCODE_AUDIT",               /* name                            */
++  "Percona",              /* author                          */
++  "Error code histogram Audit",        /* description                     */
++  PLUGIN_LICENSE_GPL,
++  audit_errcode_histogram_plugin_init,     /* init function (when loaded)     */
++  audit_errcode_histogram_plugin_deinit,   /* deinit function (when unloaded) */
++  0x0001,                     /* version                         */
++  NULL,              /* status variables                */
++  NULL,                       /* system variables                */
++  NULL,
++  0,
++},
++{
++  MYSQL_INFORMATION_SCHEMA_PLUGIN,         /* type                            */
++  &i_s_error_histogram,     /* descriptor                      */
++  "ERRCODE_HISTOGRAM",               /* name                            */
++  "Percona",              /* author                          */
++  "Error code histogram in memory",        /* description                     */
++  PLUGIN_LICENSE_GPL,
++  i_s_errcode_histogram_plugin_init,     /* init function (when loaded)     */
++  i_s_errcode_histogram_plugin_deinit,   /* deinit function (when unloaded) */
++  0x0001,                     /* version                         */
++  NULL,              /* status variables                */
++  NULL,                       /* system variables                */
++  NULL,
++  0,
++}
++
++mysql_declare_plugin_end;
++
+--- a/plugin/audit_errcode_histogram/CMakeLists.txt	1970-01-01 08:00:00.000000000 +0800
++++ b/plugin/audit_errcode_histogram/CMakeLists.txt	2011-12-19 13:15:13.000000000 +0800
+@@ -0,0 +1,17 @@
++# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
++# 
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; version 2 of the License.
++# 
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++# 
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
++
++MYSQL_ADD_PLUGIN(audit_errcode_histogram audit_errcode_histogram.cc
++  MODULE_ONLY MODULE_OUTPUT_NAME "adt_errcode_histogram")
+--- a/mysql-test/include/have_errcode_histogram.inc	1970-01-01 08:00:00.000000000 +0800
++++ b/mysql-test/include/have_errcode_histogram.inc	2011-12-19 13:18:28.000000000 +0800
+@@ -0,0 +1,21 @@
++#
++# Check if server has support for loading plugins
++#
++if (`SELECT @@have_dynamic_loading != 'YES'`) {
++  --skip Requires dynamic loading
++}
++
++#
++# Check if the variable ERRCODE_AUDIT is set
++#
++if (!$ERRCODE_AUDIT)
++{
++  skip Need errcode_audit plugins;
++}
++
++#
++# Check if --plugin-dir was setup for errcode_audit
++#
++if (`SELECT CONCAT('--plugin-dir=', @@plugin_dir) != '$ERRCODE_AUDIT_OPT'`) {
++  --skip ERRCODE_AUDIT plugin requires that --plugin-dir is set to the errcode_audit plugin dir (either the .opt file does not contain \$ERRCODE_AUDIT_OPT or another plugin is in use)
++}
+--- a/mysql-test/include/plugin.defs	2011-12-13 17:00:43.000000000 +0800
++++ b/mysql-test/include/plugin.defs	2011-12-19 13:15:56.000000000 +0800
+@@ -40,3 +40,5 @@
+ ha_federated       storage/federated  FEDERATED_PLUGIN
+ mypluglib          plugin/fulltext    SIMPLE_PARSER
+ libdaemon_example  plugin/daemon_example DAEMONEXAMPLE
++adt_errcode_histogram  plugin/audit_errcode_histogram ERRCODE_AUDIT
++adt_errcode_histogram  plugin/audit_errcode_histogram ERRCODE_HISTOGRAM 
+--- a/mysql-test/r/error_code_histogram.result	1970-01-01 08:00:00.000000000 +0800
++++ b/mysql-test/r/error_code_histogram.result	2011-12-19 13:15:13.000000000 +0800
+@@ -0,0 +1,19 @@
++#
++# feature: error code histogram
++#
++install plugin ERRCODE_AUDIT soname 'adt_errcode_histogram.so';
++install plugin ERRCODE_HISTOGRAM soname 'adt_errcode_histogram.so';
++use db_not_exists;
++ERROR 42000: Unknown database 'db_not_exists'
++error_syntax_command;
++ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'error_syntax_command' at line 1
++use db_not_exists2;
++ERROR 42000: Unknown database 'db_not_exists2'
++SELECT * from information_schema.errcode_histogram;
++ERROR	COUNT
++1049	2
++1064	1
++uninstall plugin ERRCODE_HISTOGRAM;
++uninstall plugin ERRCODE_AUDIT;
++Warnings:
++Warning	1620	Plugin is busy and will be uninstalled on shutdown
+--- a/mysql-test/t/error_code_histogram-master.opt	1970-01-01 08:00:00.000000000 +0800
++++ b/mysql-test/t/error_code_histogram-master.opt	2011-12-19 13:15:35.000000000 +0800
+@@ -0,0 +1 @@
++$ERRCODE_AUDIT_OPT
+--- a/mysql-test/t/error_code_histogram.test	1970-01-01 08:00:00.000000000 +0800
++++ b/mysql-test/t/error_code_histogram.test	2011-12-19 13:19:37.000000000 +0800
+@@ -0,0 +1,18 @@
++--source include/not_embedded.inc
++--source include/have_errcode_histogram.inc
++--echo #
++--echo # feature: error code histogram
++--echo #
++install plugin ERRCODE_AUDIT soname 'adt_errcode_histogram.so';  
++install plugin ERRCODE_HISTOGRAM soname 'adt_errcode_histogram.so'; 
++
++--error 1049
++use db_not_exists;
++--error 1064
++error_syntax_command;
++--error 1049
++use db_not_exists2;
++SELECT * from information_schema.errcode_histogram;
++
++uninstall plugin ERRCODE_HISTOGRAM;
++uninstall plugin ERRCODE_AUDIT;

=== modified file 'patches/series'
--- patches/series	2011-12-16 09:37:26 +0000
+++ patches/series	2011-12-20 19:11:35 +0000
@@ -62,3 +62,4 @@
 bug45702.patch
 group_commit.patch
 warning_fixes.patch
+error_code_histogram.patch

