List:Internals« Previous MessageNext Message »
From:antony Date:December 20 2005 4:12pm
Subject:bk commit into 5.1 tree (acurtis:1.1995)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of antony. When antony does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.1995 05/12/20 08:12:14 acurtis@stripped +33 -0
  Storage engines as a shared library plugin support

  storage/example/Makefile.am
    1.1 05/12/20 08:12:07 acurtis@stripped +38 -0
    New BitKeeper file ``storage/example/Makefile.am''

  storage/example/Makefile.am
    1.0 05/12/20 08:12:07 acurtis@stripped +0 -0
    BitKeeper file /home/antony/work3/mysql-5.1-plugable-2/storage/example/Makefile.am

  storage/csv/Makefile.am
    1.1 05/12/20 08:12:06 acurtis@stripped +38 -0
    New BitKeeper file ``storage/csv/Makefile.am''

  storage/csv/ha_tina.cc
    1.26 05/12/20 08:12:06 acurtis@stripped +46 -24
    convert into a plugin

  storage/csv/Makefile.am
    1.0 05/12/20 08:12:06 acurtis@stripped +0 -0
    BitKeeper file /home/antony/work3/mysql-5.1-plugable-2/storage/csv/Makefile.am

  sql/table.h
    1.118 05/12/20 08:12:06 acurtis@stripped +1 -0
    PLUGINS information schema

  sql/table.cc
    1.193 05/12/20 08:12:06 acurtis@stripped +2 -2
    ha_resolve_by_name arg changes

  sql/sql_yacc.yy
    1.424 05/12/20 08:12:06 acurtis@stripped +11 -3
    ha_resolve_by_name change
    SHOW PLUGIN support

  sql/sql_show.cc
    1.284 05/12/20 08:12:06 acurtis@stripped +105 -21
    changes to handlerton enumeration
    support for INFORMATION_SCHEMA.PLUGINS

  sql/sql_plugin.h
    1.2 05/12/20 08:12:06 acurtis@stripped +9 -1
    change to init funcs,
    new func plugin_foreach() iterates through plugins

  sql/sql_plugin.cc
    1.4 05/12/20 08:12:06 acurtis@stripped +180 -38
    installing a storage engine plugin installs it

  sql/share/errmsg.txt
    1.57 05/12/20 08:12:06 acurtis@stripped +6 -0
    new error messages

  sql/set_var.cc
    1.150 05/12/20 08:12:06 acurtis@stripped +3 -1
    ha_resolve_by_name args changed

  sql/mysqld.cc
    1.496 05/12/20 08:12:06 acurtis@stripped +9 -2
    need early init of plugin subsystem
    ha_resolve_by_name args changed

  sql/log.cc
    1.177 05/12/20 08:12:06 acurtis@stripped +0 -3
    Remove 3 handlerton entries

  sql/handler.h
    1.170 05/12/20 08:12:06 acurtis@stripped +9 -7
    Remove 3 handlerton entries
    stat_print_fn now takes length arguments
    ha_resolve_by_name now takes THD and LEX_STRING

  sql/handler.cc
    1.196 05/12/20 08:12:06 acurtis@stripped +442 -247
    changes to handlerton enumeration
    functions to install and uninstall

  sql/ha_partition.cc
    1.13 05/12/20 08:12:06 acurtis@stripped +0 -3
    Remove 3 handlerton entries

  sql/ha_myisammrg.cc
    1.75 05/12/20 08:12:06 acurtis@stripped +0 -3
    Remove 3 handlerton entries

  sql/ha_myisam.cc
    1.163 05/12/20 08:12:06 acurtis@stripped +0 -3
    Remove 3 handlerton entries

  sql/ha_innodb.h
    1.110 05/12/20 08:12:06 acurtis@stripped +7 -6
    Remove 3 handlerton entries

  sql/ha_innodb.cc
    1.240 05/12/20 08:12:05 acurtis@stripped +28 -30
    Remove 3 handlerton entries

  sql/ha_heap.cc
    1.77 05/12/20 08:12:05 acurtis@stripped +0 -3
    Remove 3 handlerton entries

  sql/ha_federated.cc
    1.45 05/12/20 08:12:05 acurtis@stripped +0 -3
    Remove 3 handlerton entries

  sql/ha_blackhole.cc
    1.24 05/12/20 08:12:05 acurtis@stripped +0 -3
    Remove 3 handlerton entries

  sql/ha_berkeley.cc
    1.164 05/12/20 08:12:05 acurtis@stripped +60 -16
    Remove 3 handlerton entries
    Savepoint support

  sql/ha_archive.cc
    1.64 05/12/20 08:12:05 acurtis@stripped +0 -3
    Remove 3 handlerton entries

  sql/authors.h
    1.10 05/12/20 08:12:05 acurtis@stripped +2 -1
    amend some details,

  sql/Makefile.am
    1.124 05/12/20 08:12:05 acurtis@stripped +1 -3
    remove tina and example

  include/my_base.h
    1.75 05/12/20 08:12:05 acurtis@stripped +2 -1
    at uninstall, panic is called with HA_PANIC_TRY_CLOSE.
    The storage engine can abort the uninstall (required as plugins does not know about 
    open table cache, so ref count inadequate)

  configure.in
    1.314 05/12/20 08:12:05 acurtis@stripped +8 -2
    pluggable changes

  config/ac-macros/storage.m4
    1.2 05/12/20 08:12:05 acurtis@stripped +7 -4
    if hton name is "no", then we don't install it as a builtin

  storage/csv/ha_tina.h
    1.10 05/12/01 16:11:14 acurtis@stripped +0 -0
    Rename: sql/examples/ha_tina.h -> storage/csv/ha_tina.h

  storage/csv/ha_tina.cc
    1.25 05/12/01 16:11:14 acurtis@stripped +0 -0
    Rename: sql/examples/ha_tina.cc -> storage/csv/ha_tina.cc

  storage/example/ha_example.h
    1.13 05/12/01 16:10:59 acurtis@stripped +0 -0
    Rename: sql/examples/ha_example.h -> storage/example/ha_example.h

  storage/example/ha_example.cc
    1.24 05/12/01 16:10:59 acurtis@stripped +0 -0
    Rename: sql/examples/ha_example.cc -> storage/example/ha_example.cc

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	acurtis
# Host:	localhost.(none)
# Root:	/home/antony/work3/mysql-5.1-plugable-2

--- 1.313/configure.in	2005-11-24 05:23:10 -08:00
+++ 1.314/configure.in	2005-12-20 08:12:05 -08:00
@@ -2411,9 +2411,15 @@
 MYSQL_STORAGE_ENGINE(berkeley,,berkeley-db,,,,storage/bdb,,,[
   MYSQL_SETUP_BERKELEY_DB
 ])
-MYSQL_STORAGE_ENGINE(example)
+dnl MYSQL_STORAGE_ENGINE(example)
+MYSQL_STORAGE_ENGINE(example,,,,,no,storage/example,,,[
+  AC_CONFIG_FILES(storage/example/Makefile)
+])
 MYSQL_STORAGE_ENGINE(archive)
-MYSQL_STORAGE_ENGINE(csv,,,,,tina_hton,,ha_tina.o)
+dnl MYSQL_STORAGE_ENGINE(csv,,,,,tina_hton,,ha_tina.o)
+MYSQL_STORAGE_ENGINE(csv,,,,,no,storage/csv,,,[
+  AC_CONFIG_FILES(storage/csv/Makefile)
+])
 MYSQL_STORAGE_ENGINE(blackhole)
 MYSQL_STORAGE_ENGINE(federated)
 MYSQL_STORAGE_ENGINE(ndbcluster,,ndbcluster,,,,storage/ndb,,,[

--- 1.74/include/my_base.h	2005-11-28 11:07:09 -08:00
+++ 1.75/include/my_base.h	2005-12-20 08:12:05 -08:00
@@ -160,7 +160,8 @@
 enum ha_panic_function {
   HA_PANIC_CLOSE,			/* Close all databases */
   HA_PANIC_WRITE,			/* Unlock and write status */
-  HA_PANIC_READ				/* Lock and read keyinfo */
+  HA_PANIC_READ,			/* Lock and read keyinfo */
+  HA_PANIC_TRY_CLOSE,			/* Close all if no open instance */
 };
 
 	/* The following is parameter to ha_create(); keytypes */

--- 1.123/sql/Makefile.am	2005-11-25 20:26:19 -08:00
+++ 1.124/sql/Makefile.am	2005-12-20 08:12:05 -08:00
@@ -101,9 +101,7 @@
 			ha_innodb.h  ha_berkeley.h  ha_archive.h \
 			ha_blackhole.cc ha_federated.cc ha_ndbcluster.cc \
 			ha_blackhole.h  ha_federated.h  ha_ndbcluster.h \
-			ha_partition.cc ha_partition.h \
-			examples/ha_tina.cc examples/ha_example.cc \
-			examples/ha_tina.h  examples/ha_example.h
+			ha_partition.cc ha_partition.h
 mysqld_DEPENDENCIES =	@mysql_se_objs@
 gen_lex_hash_SOURCES =	gen_lex_hash.cc
 gen_lex_hash_LDADD =	$(LDADD) $(CXXLDFLAGS)

--- 1.163/sql/ha_berkeley.cc	2005-11-23 12:47:26 -08:00
+++ 1.164/sql/ha_berkeley.cc	2005-12-20 08:12:05 -08:00
@@ -114,6 +114,9 @@
 static int berkeley_close_connection(THD *thd);
 static int berkeley_commit(THD *thd, bool all);
 static int berkeley_rollback(THD *thd, bool all);
+static int berkeley_rollback_to_savepoint(THD* thd, void *savepoint);
+static int berkeley_savepoint(THD* thd, void *savepoint);
+static int berkeley_release_savepoint(THD* thd, void *savepoint);
 static handler *berkeley_create_handler(TABLE_SHARE *table);
 
 handlerton berkeley_hton = {
@@ -123,11 +126,11 @@
   DB_TYPE_BERKELEY_DB,
   berkeley_init,
   0, /* slot */
-  0, /* savepoint size */
+  sizeof(DB_TXN *), /* savepoint size */
   berkeley_close_connection,
-  NULL, /* savepoint_set */
-  NULL, /* savepoint_rollback */
-  NULL, /* savepoint_release */
+  berkeley_savepoint, /* savepoint_set */
+  berkeley_rollback_to_savepoint, /* savepoint_rollback */
+  berkeley_release_savepoint, /* savepoint_release */
   berkeley_commit,
   berkeley_rollback,
   NULL, /* prepare */
@@ -140,12 +143,9 @@
   berkeley_create_handler, /* Create a new handler */
   NULL, /* Drop a database */
   berkeley_end, /* Panic call */
-  NULL, /* Release temporary latches */
-  NULL, /* Update Statistics */
   NULL, /* Start Consistent Snapshot */
   berkeley_flush_logs, /* Flush logs */
   berkeley_show_status, /* Show status */
-  NULL, /* Replication Report Sent Binlog */
   HTON_CLOSE_CURSORS_AT_COMMIT | HTON_FLUSH_AFTER_RENAME
 };
 
@@ -157,6 +157,7 @@
 typedef struct st_berkeley_trx_data {
   DB_TXN *all;
   DB_TXN *stmt;
+  DB_TXN *sp_level;
   uint bdb_lock_count;
 } berkeley_trx_data;
 
@@ -309,10 +310,53 @@
   DBUG_RETURN(error);
 }
 
+static int berkeley_savepoint(THD* thd, void *savepoint)
+{
+  int error;
+  DB_TXN **save_txn= (DB_TXN**) savepoint;
+  DBUG_ENTER("berkeley_savepoint");
+  berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+  if (!(error= db_env->txn_begin(db_env, trx->sp_level, save_txn, 0)))
+  {
+    trx->sp_level= *save_txn;
+  }
+  DBUG_RETURN(error);
+}
+
+static int berkeley_rollback_to_savepoint(THD* thd, void *savepoint)
+{
+  int error;
+  DB_TXN *parent, **save_txn= (DB_TXN**) savepoint;
+  DBUG_ENTER("berkeley_rollback_to_savepoint");
+  berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+  parent= (*save_txn)->parent;
+  if (!(error= (*save_txn)->abort(*save_txn)))
+  {
+    trx->sp_level= parent;
+    *save_txn= 0;
+  }
+  DBUG_RETURN(error);
+}
+
+static int berkeley_release_savepoint(THD* thd, void *savepoint)
+{
+  int error;
+  DB_TXN *parent, **save_txn= (DB_TXN**) savepoint;
+  DBUG_ENTER("berkeley_release_savepoint");
+  berkeley_trx_data *trx=(berkeley_trx_data *)thd->ha_data[berkeley_hton.slot];
+  parent= (*save_txn)->parent;
+  if (!(error= (*save_txn)->commit(*save_txn,0)))
+  {
+    trx->sp_level= parent;
+    *save_txn= 0;
+  }
+  DBUG_RETURN(error);
+}
 
 static bool berkeley_show_logs(THD *thd, stat_print_fn *stat_print)
 {
   char **all_logs, **free_logs, **a, **f;
+  uint hton_name_len= strlen(berkeley_hton.name);
   int error=1;
   MEM_ROOT **root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC);
   MEM_ROOT show_logs_root, *old_mem_root= *root_ptr;
@@ -337,19 +381,18 @@
   {
     for (a = all_logs, f = free_logs; *a; ++a)
     {
-      const char *status;
       if (f && *f && strcmp(*a, *f) == 0)
       {
         f++;
-        status= SHOW_LOG_STATUS_FREE;
+        if ((error= stat_print(thd, berkeley_hton.name, hton_name_len,
+                               *a, strlen(*a), SHOW_LOG_STATUS_FREE, 4)))
+          break;
       }
       else
-        status= SHOW_LOG_STATUS_INUSE;
-  
-      if (stat_print(thd, berkeley_hton.name, *a, status))
       {
-        error=1;
-        goto err;
+        if ((error= stat_print(thd, berkeley_hton.name, hton_name_len,
+                               *a, strlen(*a), SHOW_LOG_STATUS_INUSE, 6)))
+          break;
       }
     }
   }
@@ -1900,12 +1943,13 @@
           trx->bdb_lock_count--;        // We didn't get the lock
           DBUG_RETURN(error);
 	}
+        trx->sp_level= trx->all;
         trans_register_ha(thd, TRUE, &berkeley_hton);
 	if (thd->in_lock_tables)
 	  DBUG_RETURN(0);			// Don't create stmt trans
       }
       DBUG_PRINT("trans",("starting transaction stmt"));
-      if ((error= db_env->txn_begin(db_env, trx->all, &trx->stmt, 0)))
+      if ((error= db_env->txn_begin(db_env, trx->sp_level, &trx->stmt, 0)))
       {
 	/* We leave the possible master transaction open */
         trx->bdb_lock_count--;                  // We didn't get the lock
@@ -1959,7 +2003,7 @@
   if (!trx->stmt)
   {
     DBUG_PRINT("trans",("starting transaction stmt"));
-    error= db_env->txn_begin(db_env, trx->all, &trx->stmt, 0);
+    error= db_env->txn_begin(db_env, trx->sp_level, &trx->stmt, 0);
     trans_register_ha(thd, FALSE, &berkeley_hton);
   }
   transaction= trx->stmt;

--- 1.76/sql/ha_heap.cc	2005-11-23 12:44:55 -08:00
+++ 1.77/sql/ha_heap.cc	2005-12-20 08:12:05 -08:00
@@ -50,12 +50,9 @@
   heap_create_handler,    /* Create a new handler */
   NULL,    /* Drop a database */
   heap_panic,    /* Panic call */
-  NULL,    /* Release temporary latches */
-  NULL,    /* Update Statistics */
   NULL,    /* Start Consistent Snapshot */
   NULL,    /* Flush logs */
   NULL,    /* Show status */
-  NULL,    /* Replication Report Sent Binlog */
   HTON_CAN_RECREATE
 };
 

--- 1.162/sql/ha_myisam.cc	2005-11-23 12:44:55 -08:00
+++ 1.163/sql/ha_myisam.cc	2005-12-20 08:12:06 -08:00
@@ -82,12 +82,9 @@
   myisam_create_handler,    /* Create a new handler */
   NULL,    /* Drop a database */
   mi_panic,/* Panic call */
-  NULL,    /* Release temporary latches */
-  NULL,    /* Update Statistics */
   NULL,    /* Start Consistent Snapshot */
   NULL,    /* Flush logs */
   NULL,    /* Show status */
-  NULL,    /* Replication Report Sent Binlog */
   HTON_CAN_RECREATE
 };
 

--- 1.74/sql/ha_myisammrg.cc	2005-11-23 12:47:26 -08:00
+++ 1.75/sql/ha_myisammrg.cc	2005-12-20 08:12:06 -08:00
@@ -60,12 +60,9 @@
   myisammrg_create_handler,    /* Create a new handler */
   NULL,    /* Drop a database */
   myrg_panic,    /* Panic call */
-  NULL,    /* Release temporary latches */
-  NULL,    /* Update Statistics */
   NULL,    /* Start Consistent Snapshot */
   NULL,    /* Flush logs */
   NULL,    /* Show status */
-  NULL,    /* Replication Report Sent Binlog */
   HTON_CAN_RECREATE
 };
 

--- 1.195/sql/handler.cc	2005-11-28 11:07:09 -08:00
+++ 1.196/sql/handler.cc	2005-12-20 08:12:06 -08:00
@@ -38,8 +38,6 @@
 #include "ha_partition.h"
 #endif
 
-extern handlerton *sys_table_types[];
-  
 /* static functions defined in this file */
 
 static SHOW_COMP_OPTION have_yes= SHOW_OPTION_YES;
@@ -74,26 +72,28 @@
 static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
 uint known_extensions_id= 0;
 
-enum db_type ha_resolve_by_name(const char *name, uint namelen)
+enum db_type ha_resolve_by_name(THD *thd, LEX_STRING *name)
 {
-  THD *thd= current_thd;
   show_table_alias_st *table_alias;
-  handlerton **types;
+  handlerton *types;
+  LEX_STRING alias;
+  st_plugin_int *plugin;
 
   if (thd && !my_strnncoll(&my_charset_latin1,
-                           (const uchar *)name, namelen,
+                           (const uchar *)name->str, name->length,
                            (const uchar *)"DEFAULT", 7))
     return (enum db_type) thd->variables.table_type;
 
-retest:
-  for (types= sys_table_types; *types; types++)
+  if ((plugin= plugin_lock(name, MYSQL_STORAGE_ENGINE_PLUGIN)))
   {
-    if ((!my_strnncoll(&my_charset_latin1,
-                       (const uchar *)name, namelen,
-                       (const uchar *)(*types)->name,
-                        strlen((*types)->name))) &&
-        !((*types)->flags & HTON_NOT_USER_SELECTABLE))
-      return (enum db_type) (*types)->db_type;
+    types= (handlerton *) plugin->plugin->info;
+    if (!(types->flags & HTON_NOT_USER_SELECTABLE))
+    {
+      enum db_type db_type= types->db_type;
+      plugin_unlock(plugin);
+      return db_type;
+    }
+    plugin_unlock(plugin);
   }
 
   /*
@@ -102,13 +102,13 @@
   for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
   {
     if (!my_strnncoll(&my_charset_latin1,
-                      (const uchar *)name, namelen,
+                      (const uchar *)name->str, name->length,
                       (const uchar *)table_alias->alias,
                       strlen(table_alias->alias)))
     {
-      name= table_alias->type;
-      namelen= strlen(name);
-      goto retest;
+      alias.str= (char *)table_alias->type;
+      alias.length= strlen(alias.str);
+      return ha_resolve_by_name(thd, &alias);
     }
   }
 
@@ -116,39 +116,65 @@
 }
 
 
-const char *ha_get_storage_engine(enum db_type db_type)
+struct plugin_find_dbtype_st
 {
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
+  enum db_type db_type;
+  handlerton *hton;
+};
+
+
+static my_bool plugin_find_dbtype(THD *unused, st_plugin_int *plugin,
+                                  void *arg)
+{
+  handlerton *types= (handlerton *) plugin->plugin->info;
+  if (types->db_type == ((struct plugin_find_dbtype_st *)arg)->db_type)
   {
-    if (db_type == (*types)->db_type)
-      return (*types)->name;
+    ((struct plugin_find_dbtype_st *)arg)->hton= types;
+    return TRUE;
   }
-  return "*NONE*";
+  return FALSE;
+}
+
+
+const char *ha_get_storage_engine(enum db_type db_type)
+{
+  struct plugin_find_dbtype_st info;
+  
+  info.db_type= db_type;
+  
+  if (!plugin_foreach(NULL, plugin_find_dbtype, 
+                      MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+    return "*NONE*";
+
+  return info.hton->name;
 }
 
 
 bool ha_check_storage_engine_flag(enum db_type db_type, uint32 flag)
 {
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
-  {
-    if (db_type == (*types)->db_type)
-      return test((*types)->flags & flag);
-  }
-  return FALSE;                                 // No matching engine
+  struct plugin_find_dbtype_st info;
+
+  info.db_type= db_type;
+
+  if (!plugin_foreach(NULL, plugin_find_dbtype, 
+                      MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+    return FALSE;
+
+  return test(info.hton->flags & flag);
 }
 
 
 my_bool ha_storage_engine_is_enabled(enum db_type database_type)
 {
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
-  {
-    if (database_type == (*types)->db_type)
-      return ((*types)->state == SHOW_OPTION_YES) ? TRUE : FALSE;
-  }
-  return FALSE;
+  struct plugin_find_dbtype_st info;
+
+  info.db_type= database_type;
+
+  if (!plugin_foreach(NULL, plugin_find_dbtype, 
+                      MYSQL_STORAGE_ENGINE_PLUGIN, &info))
+    return FALSE;
+
+  return test(info.hton->state == SHOW_OPTION_YES);
 }
 
 
@@ -192,8 +218,8 @@
 handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
                          enum db_type db_type)
 {
+  struct plugin_find_dbtype_st info;
   handler *file= NULL;
-  handlerton **types;
   /*
     handlers are allocated with new in the handlerton create() function
     we need to set the thd mem_root for these to be allocated correctly
@@ -201,15 +227,19 @@
   THD *thd= current_thd;
   MEM_ROOT *thd_save_mem_root= thd->mem_root;
   thd->mem_root= alloc;
-  for (types= sys_table_types; *types; types++)
+
+
+  info.db_type= db_type;
+
+  if (plugin_foreach(NULL, plugin_find_dbtype, 
+                     MYSQL_STORAGE_ENGINE_PLUGIN, &info))
   {
-    if (db_type == (*types)->db_type && (*types)->create)
+    if (info.hton->state == SHOW_OPTION_YES && info.hton->create)
     {
-      file= ((*types)->state == SHOW_OPTION_YES) ?
-		(*types)->create(share) : NULL;
-      break;
+      file= info.hton->create(share);
     }
   }
+
   thd->mem_root= thd_save_mem_root;
 
   if (!file)
@@ -341,16 +371,38 @@
 }
 
 
-static inline void ha_was_inited_ok(handlerton **ht)
+void ha_was_inited_ok(handlerton *ht)
 {
-  uint tmp= (*ht)->savepoint_offset;
-  (*ht)->savepoint_offset= savepoint_alloc_size;
+  uint tmp= ht->savepoint_offset;
+  ht->savepoint_offset= savepoint_alloc_size;
   savepoint_alloc_size+= tmp;
-  (*ht)->slot= total_ha++;
-  if ((*ht)->prepare)
+  ht->slot= total_ha++;
+  if (ht->prepare)
     total_ha_2pc++;
 }
 
+static byte* handler_get_key(handlerton *hton,uint *length,
+			     my_bool not_used __attribute__((unused)))
+{
+  *length=(uint) strlen(hton->name);
+  return (byte*) hton->name;
+}
+
+static my_bool init_handlerton(THD *unused1, st_plugin_int *plugin,
+                               void *unused2)
+{
+  if (plugin->state == PLUGIN_IS_UNINITIALIZED)
+  {
+    handlerton *hton= (handlerton *) plugin->plugin->info;
+    if (!hton->init || !hton->init())
+      ha_was_inited_ok(hton);
+    else
+      hton->state= SHOW_OPTION_DISABLED;
+    plugin->state= PLUGIN_IS_READY;
+  }
+  return FALSE;
+}
+
 int ha_init()
 {
   int error= 0;
@@ -361,16 +413,8 @@
   if (ha_init_errors())
     return 1;
 
-  /*
-    We now initialize everything here.
-  */
-  for (types= sys_table_types; *types; types++)
-  {
-    if (!(*types)->init || !(*types)->init())
-      ha_was_inited_ok(types); 
-    else
-      (*types)->state= SHOW_OPTION_DISABLED;
-  }
+  if (plugin_foreach(NULL, init_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0))
+    return 1;
 
   DBUG_ASSERT(total_ha < MAX_HA);
   /*
@@ -386,40 +430,59 @@
 	/* close, flush or restart databases */
 	/* Ignore this for other databases than ours */
 
-int ha_panic(enum ha_panic_function flag)
+static my_bool panic_handlerton(THD *unused1, st_plugin_int *plugin,
+                               void *arg)
 {
-  int error=0;
-  handlerton **types;
+  handlerton *hton= (handlerton *) plugin->plugin->info;  
+  if (hton->state == SHOW_OPTION_YES && hton->panic)
+    ((int*)arg)[0]|= hton->panic((enum ha_panic_function)((int*)arg)[1]);
+  return FALSE;
+}
 
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES && (*types)->panic)
-        error|= (*types)->panic(flag);
-  }
-  if (ha_finish_errors())
-    error= 1;
-  return error;
+int ha_panic(enum ha_panic_function flag)
+{
+  int error[2];
+  
+  error[0]= 0; error[1]= (int)flag;
+  plugin_foreach(NULL, panic_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, error);
+  
+  if (flag == HA_PANIC_CLOSE && ha_finish_errors())
+    error[0]= 1;
+  return error[0];
 } /* ha_panic */
 
+static my_bool dropdb_handlerton(THD *unused1, st_plugin_int *plugin,
+                                 void *path)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;  
+  if (hton->state == SHOW_OPTION_YES && hton->drop_database)
+    hton->drop_database((char *)path);
+  return FALSE;
+}
+
+
 void ha_drop_database(char* path)
 {
-  handlerton **types;
+  plugin_foreach(NULL, dropdb_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, path);
+}
 
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES && (*types)->drop_database)
-      (*types)->drop_database(path);
-  }
+
+static my_bool closecon_handlerton(THD *thd, st_plugin_int *plugin,
+                                   void *unused)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;  
+	/* XXX Maybe do a rollback if close_connection == NULL ? */
+  if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
+      thd->ha_data[hton->slot])
+    hton->close_connection(thd);
+  return FALSE;
 }
 
+
 /* don't bother to rollback here, it's done already */
 void ha_close_connection(THD* thd)
 {
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
-	/* XXX Maybe do a rollback if close_connection == NULL ? */
-    if (thd->ha_data[(*types)->slot] && (*types)->close_connection)
-      (*types)->close_connection(thd);
+  plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);
 }
 
 /* ========================================================================
@@ -729,21 +792,46 @@
 }
 
 
-int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
+struct xahton_st {
+  XID *xid;
+  int result;
+};
+
+static my_bool xacommit_handlerton(THD *unused1, st_plugin_int *plugin,
+                                   void *arg)
 {
-  handlerton **types;
-  int res= 1;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  if (hton->state == SHOW_OPTION_YES && hton->recover)
+  {
+    hton->commit_by_xid(((struct xahton_st *)arg)->xid);
+    ((struct xahton_st *)arg)->result= 0;
+  }
+  return FALSE;
+}
 
-  for (types= sys_table_types; *types; types++)
+static my_bool xarollback_handlerton(THD *unused1, st_plugin_int *plugin,
+                                     void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  if (hton->state == SHOW_OPTION_YES && hton->recover)
   {
-    if ((*types)->state == SHOW_OPTION_YES && (*types)->recover)
-    {
-      if ((*(commit ? (*types)->commit_by_xid :
-             (*types)->rollback_by_xid))(xid));
-      res= 0;
-    }
+    hton->rollback_by_xid(((struct xahton_st *)arg)->xid);
+    ((struct xahton_st *)arg)->result= 0;
   }
-  return res;
+  return FALSE;
+}
+
+
+int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
+{
+  struct xahton_st xaop;
+  xaop.xid= xid;
+  xaop.result= 1;
+  
+  plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
+                 MYSQL_STORAGE_ENGINE_PLUGIN, &xaop);
+
+  return xaop.result;
 }
 
 
@@ -819,99 +907,122 @@
      in this case commit_list==0, tc_heuristic_recover == 0
      there should be no prepared transactions in this case.
 */
-int ha_recover(HASH *commit_list)
-{
-  int len, got, found_foreign_xids=0, found_my_xids=0;
-  handlerton **types;
-  XID *list=0;
-  bool dry_run=(commit_list==0 && tc_heuristic_recover==0);
-  DBUG_ENTER("ha_recover");
-
-  /* commit_list and tc_heuristic_recover cannot be set both */
-  DBUG_ASSERT(commit_list==0 || tc_heuristic_recover==0);
-  /* if either is set, total_ha_2pc must be set too */
-  DBUG_ASSERT(dry_run || total_ha_2pc>(ulong)opt_bin_log);
-
-  if (total_ha_2pc <= (ulong)opt_bin_log)
-    DBUG_RETURN(0);
-
-  if (commit_list)
-    sql_print_information("Starting crash recovery...");
-
-#ifndef WILL_BE_DELETED_LATER
-  /*
-    for now, only InnoDB supports 2pc. It means we can always safely
-    rollback all pending transactions, without risking inconsistent data
-  */
-  DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
-  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
-  dry_run=FALSE;
-#endif
 
-  for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2)
-  {
-    list=(XID *)my_malloc(len*sizeof(XID), MYF(0));
-  }
-  if (!list)
-  {
-    sql_print_error(ER(ER_OUTOFMEMORY), len*sizeof(XID));
-    DBUG_RETURN(1);
-  }
+struct xarecover_st
+{
+  int len, found_foreign_xids, found_my_xids;
+  XID *list;
+  HASH *commit_list;
+  bool dry_run;
+};
 
-  for (types= sys_table_types; *types; types++)
+static my_bool xarecover_handlerton(THD *unused, st_plugin_int *plugin,
+                                    void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  struct xarecover_st *info= (struct xarecover_st *) arg;
+  int got;
+  
+  if (hton->state == SHOW_OPTION_YES && hton->recover)
   {
-    if ((*types)->state != SHOW_OPTION_YES || !(*types)->recover)
-      continue;
-    while ((got=(*(*types)->recover)(list, len)) > 0 )
+    while ((got= hton->recover(info->list, info->len)) > 0 )
     {
       sql_print_information("Found %d prepared transaction(s) in %s",
-                            got, (*types)->name);
+                            got, hton->name);
       for (int i=0; i < got; i ++)
       {
-        my_xid x=list[i].get_my_xid();
+        my_xid x=info->list[i].get_my_xid();
         if (!x) // not "mine" - that is generated by external TM
         {
 #ifndef DBUG_OFF
           char buf[XIDDATASIZE*4+6]; // see xid_to_str
-          sql_print_information("ignore xid %s", xid_to_str(buf, list+i));
+          sql_print_information("ignore xid %s", xid_to_str(buf, info->list+i));
 #endif
-          xid_cache_insert(list+i, XA_PREPARED);
-          found_foreign_xids++;
+          xid_cache_insert(info->list+i, XA_PREPARED);
+          info->found_foreign_xids++;
           continue;
         }
-        if (dry_run)
+        if (info->dry_run)
         {
-          found_my_xids++;
+          info->found_my_xids++;
           continue;
         }
         // recovery mode
-        if (commit_list ?
-            hash_search(commit_list, (byte *)&x, sizeof(x)) != 0 :
+        if (info->commit_list ?
+            hash_search(info->commit_list, (byte *)&x, sizeof(x)) != 0 :
             tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
         {
 #ifndef DBUG_OFF
           char buf[XIDDATASIZE*4+6]; // see xid_to_str
-          sql_print_information("commit xid %s", xid_to_str(buf, list+i));
+          sql_print_information("commit xid %s", xid_to_str(buf, info->list+i));
 #endif
-          (*(*types)->commit_by_xid)(list+i);
+          hton->commit_by_xid(info->list+i);
         }
         else
         {
 #ifndef DBUG_OFF
           char buf[XIDDATASIZE*4+6]; // see xid_to_str
-          sql_print_information("rollback xid %s", xid_to_str(buf, list+i));
+          sql_print_information("rollback xid %s",
+                                xid_to_str(buf, info->list+i));
 #endif
-          (*(*types)->rollback_by_xid)(list+i);
+          hton->rollback_by_xid(info->list+i);
         }
       }
-      if (got < len)
+      if (got < info->len)
         break;
     }
   }
-  my_free((gptr)list, MYF(0));
-  if (found_foreign_xids)
-    sql_print_warning("Found %d prepared XA transactions", found_foreign_xids);
-  if (dry_run && found_my_xids)
+  return FALSE;
+}
+
+int ha_recover(HASH *commit_list)
+{
+  struct xarecover_st info;
+  DBUG_ENTER("ha_recover");
+  info.found_foreign_xids= info.found_my_xids= 0;
+  info.commit_list= commit_list;
+  info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
+
+  /* commit_list and tc_heuristic_recover cannot be set both */
+  DBUG_ASSERT(info.commit_list==0 || tc_heuristic_recover==0);
+  /* if either is set, total_ha_2pc must be set too */
+  DBUG_ASSERT(info.dry_run || total_ha_2pc>(ulong)opt_bin_log);
+
+  if (total_ha_2pc <= (ulong)opt_bin_log)
+    DBUG_RETURN(0);
+
+  if (info.commit_list)
+    sql_print_information("Starting crash recovery...");
+
+#ifndef WILL_BE_DELETED_LATER
+  /*
+    for now, only InnoDB supports 2pc. It means we can always safely
+    rollback all pending transactions, without risking inconsistent data
+  */
+  DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
+  tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
+  info.dry_run=FALSE;
+#endif
+
+  for (info.len= MAX_XID_LIST_SIZE ; 
+       info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
+  {
+    info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
+  }
+  if (!info.list)
+  {
+    sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
+    DBUG_RETURN(1);
+  }
+
+  plugin_foreach(NULL, xarecover_handlerton, 
+                 MYSQL_STORAGE_ENGINE_PLUGIN, &info);
+
+  my_free((gptr)info.list, MYF(0));
+  if (info.found_foreign_xids)
+    sql_print_warning("Found %d prepared XA transactions", 
+                      info.found_foreign_xids);
+  if (info.dry_run && info.found_my_xids)
   {
     sql_print_error("Found %d prepared transactions! It means that mysqld was "
                     "not shut down properly last time and critical recovery "
@@ -919,10 +1030,10 @@
                     "after a crash. You have to start mysqld with "
                     "--tc-heuristic-recover switch to commit or rollback "
                     "pending transactions.",
-                    found_my_xids, opt_tc_log_file);
+                    info.found_my_xids, opt_tc_log_file);
     DBUG_RETURN(1);
   }
-  if (commit_list)
+  if (info.commit_list)
     sql_print_information("Crash recovery finished.");
   DBUG_RETURN(0);
 }
@@ -995,14 +1106,12 @@
 
 int ha_release_temporary_latches(THD *thd)
 {
-  handlerton **types;
-
-  for (types= sys_table_types; *types; types++)
+  TABLE *table= thd->open_tables;
+  while (table)
   {
-    if ((*types)->state == SHOW_OPTION_YES &&
-        (*types)->release_temporary_latches)
-      (*types)->release_temporary_latches(thd);
-  }
+    table->file->release_temporary_latches(thd);
+    table= table->next;
+  } 
   return 0;
 }
 
@@ -1012,15 +1121,38 @@
   InnoDB.
 */
 
-int ha_update_statistics()
+struct updstat_arg_st
 {
-  handlerton **types;
+  TABLE dummy_table;
+  TABLE_SHARE dummy_share;
+};
 
-  for (types= sys_table_types; *types; types++)
+static my_bool updstat_handlerton(THD *unused, st_plugin_int *plugin,
+                                  void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  struct updstat_arg_st *info= (struct updstat_arg_st *) arg;
+  handler *file;
+  
+  if (hton->state == SHOW_OPTION_YES && hton->create && 
+      (file= hton->create(&info->dummy_share)))
   {
-    if ((*types)->state == SHOW_OPTION_YES && (*types)->update_statistics)
-      (*types)->update_statistics();
+    file->update_statistics();
+    delete file;
   }
+  return FALSE;
+}
+
+int ha_update_statistics()
+{
+  struct updstat_arg_st info;
+
+  bzero((char*) &info.dummy_table, sizeof(info.dummy_table));
+  bzero((char*) &info.dummy_share, sizeof(info.dummy_share));
+  info.dummy_table.s= &info.dummy_share;
+
+  plugin_foreach(NULL, updstat_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &info);
+
   return 0;
 }
 
@@ -1129,20 +1261,25 @@
 }
 
 
+static my_bool snapshot_handlerton(THD *thd, st_plugin_int *plugin,
+                                   void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  if (hton->state == SHOW_OPTION_YES &&
+      hton->start_consistent_snapshot)
+  {
+    hton->start_consistent_snapshot(thd);
+    *((bool *)arg)= false;
+  }
+  return FALSE;
+}
+
 int ha_start_consistent_snapshot(THD *thd)
 {
   bool warn= true;
-  handlerton **types;
 
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES &&
-        (*types)->start_consistent_snapshot)
-    {
-      (*types)->start_consistent_snapshot(thd);
-      warn= false; /* hope user is using engine */
-    }
-  }
+  plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn);
+
   /*
     Same idea as when one wants to CREATE TABLE in one engine which does not
     exist:
@@ -1155,22 +1292,26 @@
 }
 
 
-bool ha_flush_logs(enum db_type db_type)
+static my_bool flush_handlerton(THD *thd, st_plugin_int *plugin,
+                                void *arg)
 {
-  bool result=0;
-  handlerton **types;
-
-  for (types= sys_table_types; *types; types++)
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  enum db_type db_type= *(enum db_type *)arg;
+  if (hton->state == SHOW_OPTION_YES &&
+      (db_type == DB_TYPE_DEFAULT || db_type == hton->db_type) &&
+      hton->flush_logs)
   {
-    if ((*types)->state == SHOW_OPTION_YES && 
-        (db_type == DB_TYPE_DEFAULT || db_type == (*types)->db_type) &&
-        (*types)->flush_logs)
-    {
-      if ((*types)->flush_logs())
-        result= 1;
-    }
+    if (hton->flush_logs())
+      return TRUE;
   }
-  return result;
+  return FALSE;
+}
+
+
+bool ha_flush_logs(enum db_type db_type)
+{
+  return plugin_foreach(NULL, flush_handlerton,
+                        MYSQL_STORAGE_ENGINE_PLUGIN, &db_type) ? 1 : 0;
 }
 
 /*
@@ -2486,40 +2627,50 @@
     pointer		pointer to TYPELIB structure
 */
 
+static my_bool exts_handlerton(THD *unused, st_plugin_int *plugin,
+                               void *arg)
+{
+  List<char> *found_exts= (List<char> *) arg;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  handler *file;
+  if (hton->state == SHOW_OPTION_YES && hton->create &&
+      (file= hton->create((TABLE_SHARE*) 0)))
+  {
+    List_iterator_fast<char> it(*found_exts);
+    const char **ext, *old_ext;
+    
+    for (ext= file->bas_ext(); *ext; ext++)
+    {
+      while ((old_ext= it++))
+      {
+        if (!strcmp(old_ext, *ext))
+	  break;
+      }
+      if (!old_ext)
+        found_exts->push_back((char *) *ext);
+
+      it.rewind();
+    }
+    delete file;
+  }
+  return FALSE;
+}
+
 TYPELIB *ha_known_exts(void)
 {
   MEM_ROOT *mem_root= current_thd->mem_root;
   if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
   {
-    handlerton **types;
     List<char> found_exts;
-    List_iterator_fast<char> it(found_exts);
     const char **ext, *old_ext;
 
     known_extensions_id= mysys_usage_id;
     found_exts.push_back((char*) triggers_file_ext);
     found_exts.push_back((char*) trigname_file_ext);
-    for (types= sys_table_types; *types; types++)
-    {
-      if ((*types)->state == SHOW_OPTION_YES)
-      {
-	handler *file= get_new_handler((TABLE_SHARE*) 0, mem_root,
-                                       (enum db_type) (*types)->db_type);
-	for (ext= file->bas_ext(); *ext; ext++)
-	{
-	  while ((old_ext= it++))
-          {
-	    if (!strcmp(old_ext, *ext))
-	      break;
-          }
-	  if (!old_ext)
-	    found_exts.push_back((char *) *ext);
-
-	  it.rewind();
-	}
-	delete file;
-      }
-    }
+    
+    plugin_foreach(NULL, exts_handlerton, 
+                   MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
+
     ext= (const char **) my_once_alloc(sizeof(char *)*
                                        (found_exts.elements+1),
                                        MYF(MY_WME | MY_FAE));
@@ -2528,6 +2679,7 @@
     known_extensions.count= found_exts.elements;
     known_extensions.type_names= ext;
 
+    List_iterator_fast<char> it(found_exts);
     while ((old_ext= it++))
       *ext++= old_ext;
     *ext= 0;
@@ -2535,24 +2687,55 @@
   return &known_extensions;
 }
 
-static bool stat_print(THD *thd, const char *type, const char *file,
-                       const char *status)
+static bool stat_print(THD *thd, const char *type, uint type_len,
+                       const char *file, uint file_len,
+                       const char *status, uint status_len)
 {
   Protocol *protocol= thd->protocol;
   protocol->prepare_for_resend();
-  protocol->store(type, system_charset_info);
-  protocol->store(file, system_charset_info);
-  protocol->store(status, system_charset_info);
+  protocol->store(type, type_len, system_charset_info);
+  protocol->store(file, file_len, system_charset_info);
+  protocol->store(status, status_len, system_charset_info);
   if (protocol->write())
     return TRUE;
   return FALSE;
 }
 
+struct showstat_arg_st
+{
+  enum db_type db_type;
+  enum ha_stat_type stat;
+};
+
+static my_bool showstat_handlerton(THD *thd, st_plugin_int *plugin,
+                                   void *arg)
+{
+  struct showstat_arg_st *info= (struct showstat_arg_st *) arg;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+
+  if (hton->state == SHOW_OPTION_YES &&
+      (info->db_type == DB_TYPE_DEFAULT || info->db_type == hton->db_type) &&
+      hton->show_status)
+  {
+    return (hton->show_status(thd, stat_print, info->stat)) ? 1 : 0;
+  }
+  if (info->db_type == hton->db_type &&
+      hton->state != SHOW_OPTION_YES)
+  {
+    return stat_print(thd, hton->name, strlen(hton->name), 
+                      "", 0, "DISABLED", 8) ? 1 : 0;
+  }
+  return FALSE;
+}
+
 bool ha_show_status(THD *thd, enum db_type db_type, enum ha_stat_type stat)
 {
-  handlerton **types;
   List<Item> field_list;
   Protocol *protocol= thd->protocol;
+  struct showstat_arg_st info;
+  bool result;
+  info.db_type= db_type;
+  info.stat= stat;
 
   field_list.push_back(new Item_empty_string("Type",10));
   field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
@@ -2562,25 +2745,12 @@
                             Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
     return TRUE;
 
-  for (types= sys_table_types; *types; types++)
-  {
-    if ((*types)->state == SHOW_OPTION_YES &&
-        (db_type == DB_TYPE_DEFAULT || db_type == (*types)->db_type) &&
-        (*types)->show_status)
-    {
-      if ((*types)->show_status(thd, stat_print, stat))
-        return TRUE;
-    }
-    else if (db_type == (*types)->db_type &&
-             (*types)->state != SHOW_OPTION_YES)
-    {
-      if (stat_print(thd, (*types)->name, "", "DISABLED"))
-	return TRUE;
-    }
-  }
+  result= plugin_foreach(thd, showstat_handlerton, 
+                         MYSQL_STORAGE_ENGINE_PLUGIN, &info);
 
-  send_eof(thd);
-  return FALSE;
+  if (!result)
+    send_eof(thd);
+  return result;
 }
 
 
@@ -2603,22 +2773,46 @@
     Always 0 (= success)  
 */
 
-int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
-                               my_off_t end_offset)
+struct binlog_arg_st
 {
-  int result= 0;
-  handlerton **types;
+  TABLE dummy_table;
+  TABLE_SHARE dummy_share;
+  char *log_file_name;
+  my_off_t end_offset;
+};
 
-  for (types= sys_table_types; *types; types++)
+
+static my_bool binlog_handlerton(THD *thd, st_plugin_int *plugin,
+                                 void *arg)
+{
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+  struct binlog_arg_st *info= (struct binlog_arg_st *) arg;
+  handler *file;
+  
+  if (hton->state == SHOW_OPTION_YES && hton->create && 
+      (file= hton->create(&info->dummy_share)))
   {
-    if ((*types)->state == SHOW_OPTION_YES &&
-        (*types)->repl_report_sent_binlog)
-    {
-      (*types)->repl_report_sent_binlog(thd,log_file_name,end_offset);
-      result= 0;
-    }
+    file->repl_report_sent_binlog(thd,info->log_file_name,info->end_offset);
+    delete file;
   }
-  return result;
+  return FALSE;
+}
+
+
+int ha_repl_report_sent_binlog(THD *thd, char *log_file_name,
+                               my_off_t end_offset)
+{
+  struct binlog_arg_st info;
+
+  bzero((char*) &info.dummy_table, sizeof(info.dummy_table));
+  bzero((char*) &info.dummy_share, sizeof(info.dummy_share));
+  info.dummy_table.s= &info.dummy_share;
+  info.log_file_name= log_file_name;
+  info.end_offset= end_offset;
+
+  plugin_foreach(thd, binlog_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &info);
+
+  return 0;
 }
 
 
@@ -2643,3 +2837,4 @@
   return 0;
 }
 #endif /* HAVE_REPLICATION */
+

--- 1.169/sql/handler.h	2005-11-28 11:07:10 -08:00
+++ 1.170/sql/handler.h	2005-12-20 08:12:06 -08:00
@@ -315,8 +315,9 @@
 typedef struct st_table_share TABLE_SHARE;
 struct st_foreign_key_info;
 typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
-typedef bool (stat_print_fn)(THD *thd, const char *type, const char *file,
-                             const char *status);
+typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
+                             const char *file, uint file_len,
+                             const char *status, uint status_len);
 enum ha_stat_type { HA_ENGINE_STATUS, HA_ENGINE_LOGS, HA_ENGINE_MUTEX };
 
 /*
@@ -416,13 +417,9 @@
    handler *(*create)(TABLE_SHARE *table);
    void (*drop_database)(char* path);
    int (*panic)(enum ha_panic_function flag);
-   int (*release_temporary_latches)(THD *thd);
-   int (*update_statistics)();
    int (*start_consistent_snapshot)(THD *thd);
    bool (*flush_logs)();
    bool (*show_status)(THD *thd, stat_print_fn *print, enum ha_stat_type stat);
-   int (*repl_report_sent_binlog)(THD *thd, char *log_file_name,
-                                  my_off_t end_offset);
    uint32 flags;                                /* global handler flags */
 } handlerton;
 
@@ -1306,6 +1303,10 @@
   virtual bool is_crashed() const  { return 0; }
   virtual bool auto_repair() const { return 0; }
 
+  virtual int release_temporary_latches(THD *thd) const { return 0; }
+  virtual int update_statistics() const { return 0; }
+  virtual int repl_report_sent_binlog(THD *thd, char *log_file_name,
+                                  my_off_t end_offset) const { return 0; }
   /*
     default rename_table() and delete_table() rename/delete files with a
     given name and extensions from bas_ext()
@@ -1413,7 +1414,7 @@
 #define ha_rollback(thd) (ha_rollback_trans((thd), TRUE))
 
 /* lookups */
-enum db_type ha_resolve_by_name(const char *name, uint namelen);
+enum db_type ha_resolve_by_name(THD *thd, LEX_STRING *name);
 const char *ha_get_storage_engine(enum db_type db_type);
 handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
                          enum db_type db_type);
@@ -1423,6 +1424,7 @@
 
 /* basic stuff */
 int ha_init(void);
+void ha_was_inited_ok(handlerton *ht);
 TYPELIB *ha_known_exts(void);
 int ha_panic(enum ha_panic_function flag);
 int ha_update_statistics();

--- 1.176/sql/log.cc	2005-11-23 04:04:08 -08:00
+++ 1.177/sql/log.cc	2005-12-20 08:12:06 -08:00
@@ -71,12 +71,9 @@
   NULL,                         /* Create a new handler */
   NULL,                         /* Drop a database */
   NULL,                         /* Panic call */
-  NULL,                         /* Release temporary latches */
-  NULL,                         /* Update Statistics */
   NULL,                         /* Start Consistent Snapshot */
   NULL,                         /* Flush logs */
   NULL,                         /* Show status */
-  NULL,                         /* Replication Report Sent Binlog */
   HTON_NOT_USER_SELECTABLE | HTON_HIDDEN
 };
 

--- 1.495/sql/mysqld.cc	2005-11-30 13:43:49 -08:00
+++ 1.496/sql/mysqld.cc	2005-12-20 08:12:06 -08:00
@@ -2622,6 +2622,12 @@
   strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
   strmov(fn_ext(pidfile_name),".pid");		// Add proper extension
 
+  if (plugin_init())
+  {
+    sql_print_error("Failed to register built-in plugins.");
+    unireg_abort(1);
+  }
+
   load_defaults(conf_file_name, groups, &argc, &argv);
   defaults_argv=argv;
   get_options(argc,argv);
@@ -3470,7 +3476,7 @@
 
   if (!opt_noacl)
   {
-    plugin_init();
+    plugin_load();
 #ifdef HAVE_DLOPEN
     udf_init();
 #endif
@@ -6805,8 +6811,9 @@
     break;
   case OPT_STORAGE_ENGINE:
   {
+    LEX_STRING name= { argument, strlen(argument) };
     if ((enum db_type)((global_system_variables.table_type=
-                        ha_resolve_by_name(argument, strlen(argument)))) ==
+                        ha_resolve_by_name(current_thd, &name))) ==
         DB_TYPE_UNKNOWN)
     {
       fprintf(stderr,"Unknown/unsupported table type: %s\n",argument);

--- 1.283/sql/sql_show.cc	2005-11-28 11:07:13 -08:00
+++ 1.284/sql/sql_show.cc	2005-12-20 08:12:06 -08:00
@@ -48,6 +48,33 @@
 ** List all table types supported 
 ***************************************************************************/
 
+static my_bool show_handlerton(THD *thd, st_plugin_int *plugin,
+                               void *arg)
+{
+  const char *default_type_name= (const char *) arg;
+  Protocol *protocol= thd->protocol;
+  handlerton *hton= (handlerton *) plugin->plugin->info;
+
+  if (!(hton->flags & HTON_HIDDEN))
+  {
+    protocol->prepare_for_resend();
+    protocol->store(hton->name, system_charset_info);
+    const char *option_name= show_comp_option_name[(int) hton->state];
+
+    if (hton->state == SHOW_OPTION_YES &&
+        !my_strcasecmp(system_charset_info, default_type_name, hton->name))
+      option_name= "DEFAULT";
+    protocol->store(option_name, system_charset_info);
+    protocol->store(hton->comment, system_charset_info);
+    protocol->store(hton->commit ? "YES" : "NO", system_charset_info);
+    protocol->store(hton->prepare ? "YES" : "NO", system_charset_info);
+    protocol->store(hton->savepoint_set ? "YES" : "NO", system_charset_info);
+    
+    return protocol->write() ? 1 : 0;
+  }
+  return 0;  
+}
+
 bool mysqld_show_storage_engines(THD *thd)
 {
   List<Item> field_list;
@@ -68,31 +95,75 @@
   const char *default_type_name= 
     ha_get_storage_engine((enum db_type)thd->variables.table_type);
 
-  handlerton **types;
-  for (types= sys_table_types; *types; types++)
-  {
-    if (!((*types)->flags & HTON_HIDDEN))
-    {
-      protocol->prepare_for_resend();
-      protocol->store((*types)->name, system_charset_info);
-      const char *option_name= show_comp_option_name[(int) (*types)->state];
-
-      if ((*types)->state == SHOW_OPTION_YES &&
-          !my_strcasecmp(system_charset_info, default_type_name, (*types)->name))
-        option_name= "DEFAULT";
-      protocol->store(option_name, system_charset_info);
-      protocol->store((*types)->comment, system_charset_info);
-      protocol->store((*types)->commit ? "YES" : "NO", system_charset_info);
-      protocol->store((*types)->prepare ? "YES" : "NO", system_charset_info);
-      protocol->store((*types)->savepoint_set ? "YES" : "NO", system_charset_info);
-      if (protocol->write())
-        DBUG_RETURN(TRUE);
-    }
-  }
+  if (plugin_foreach(thd, show_handlerton, 
+                     MYSQL_STORAGE_ENGINE_PLUGIN, (void *)default_type_name))
+    DBUG_RETURN(TRUE);
+
   send_eof(thd);
   DBUG_RETURN(FALSE);
 }
 
+static my_bool show_plugins(THD *thd, st_plugin_int *plugin,
+                            void *arg)
+{
+  TABLE *table= (TABLE*) arg;
+  struct st_mysql_plugin *plug= plugin->plugin;
+  Protocol *protocol= thd->protocol;
+  CHARSET_INFO *cs= system_charset_info;
+
+  restore_record(table, s->default_values);
+  
+  switch (plug->type)
+  {
+  case MYSQL_UDF_PLUGIN:
+    table->field[0]->store("UDF", 3, cs);
+    break;
+  case MYSQL_STORAGE_ENGINE_PLUGIN:
+    table->field[0]->store("STORAGE", 7, cs);
+    break;
+  case MYSQL_FTPARSER_PLUGIN:
+    table->field[0]->store("FTPARSER", 8, cs);
+    break;
+  default:
+    table->field[0]->store("UNKNOWN", 7, cs);
+    break;
+  }
+  
+  table->field[1]->store(plugin->name.str, plugin->name.length, cs);
+  
+  if (plugin->plugin_dl)
+    table->field[2]->store(plugin->plugin_dl->dl.str, 
+                           plugin->plugin_dl->dl.length, cs);
+  else
+    table->field[2]->store("(built-in)", 10, cs);
+  
+  
+  if (plug->author)
+    table->field[3]->store(plug->author, strlen(plug->author), cs);
+  else
+    table->field[3]->store("(unknown)", 9, cs);
+
+  if (plug->descr)
+    table->field[4]->store(plug->descr, strlen(plug->descr), cs);
+  else
+    table->field[4]->store("(no description)", 16, cs);
+
+  return schema_table_store_record(thd, table);
+}
+
+
+int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+  DBUG_ENTER("fill_plugins");
+  TABLE *table= tables->table;
+
+  if (plugin_foreach(thd, show_plugins, MYSQL_ANY_PLUGIN, table))
+    DBUG_RETURN(1);
+    
+  DBUG_RETURN(0);
+}
+
+
 /***************************************************************************
 ** List all Authors.
 ** If you can update it, you get to be in it :)
@@ -4172,6 +4243,17 @@
 };
 
 
+ST_FIELD_INFO plugin_fields_info[]=
+{
+  {"PLUGIN_TYPE", 81, MYSQL_TYPE_STRING, 0, 0, "Type"},
+  {"PLUGIN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
+  {"PLUGIN_LIBRARY", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Library"},
+  {"PLUGIN_AUTHOR", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+  {"PLUGIN_DESCRIPTION", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
+  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
 /*
   Description of ST_FIELD_INFO in table.h
 */
@@ -4192,6 +4274,8 @@
     get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0},
   {"OPEN_TABLES", open_tables_fields_info, create_schema_table,
    fill_open_tables, make_old_format, 0, -1, -1, 1},
+  {"PLUGINS", plugin_fields_info, create_schema_table,
+    fill_plugins, make_old_format, 0, -1, -1, 0},
   {"ROUTINES", proc_fields_info, create_schema_table, 
     fill_schema_proc, make_proc_old_format, 0, -1, -1, 0},
   {"SCHEMATA", schema_fields_info, create_schema_table,

--- 1.423/sql/sql_yacc.yy	2005-11-23 04:56:50 -08:00
+++ 1.424/sql/sql_yacc.yy	2005-12-20 08:12:06 -08:00
@@ -3193,7 +3193,7 @@
 storage_engines:
 	ident_or_text
 	{
-	  $$ = ha_resolve_by_name($1.str,$1.length);
+	  $$ = ha_resolve_by_name(YYTHD, &$1);
 	  if ($$ == DB_TYPE_UNKNOWN &&
 	      test(YYTHD->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION))
 	  {
@@ -7010,6 +7010,14 @@
             if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES))
               YYABORT;
 	  }
+        | PLUGIN_SYM
+	  {
+	    LEX *lex= Lex;
+            lex->sql_command= SQLCOM_SELECT;
+            lex->orig_sql_command= SQLCOM_SHOW_OPEN_TABLES;
+            if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
+              YYABORT;
+	  }
 	| ENGINE_SYM storage_engines 
 	  { Lex->create_info.db_type= $2; }
 	  show_engine_param
@@ -9828,7 +9836,7 @@
     ;
 
 install:
-  INSTALL_SYM PLUGIN_SYM IDENT_sys SONAME_SYM TEXT_STRING_sys
+  INSTALL_SYM PLUGIN_SYM ident_or_text SONAME_SYM TEXT_STRING_sys
   {
     LEX *lex= Lex;
     lex->sql_command= SQLCOM_INSTALL_PLUGIN;
@@ -9837,7 +9845,7 @@
   };
 
 uninstall:
-  UNINSTALL_SYM PLUGIN_SYM IDENT_sys
+  UNINSTALL_SYM PLUGIN_SYM ident_or_text
   {
     LEX *lex= Lex;
     lex->sql_command= SQLCOM_UNINSTALL_PLUGIN;

--- 1.192/sql/table.cc	2005-11-30 13:43:49 -08:00
+++ 1.193/sql/table.cc	2005-12-20 08:12:06 -08:00
@@ -513,8 +513,8 @@
     if (next_chunk + 2 < buff_end)
     {
       uint str_db_type_length= uint2korr(next_chunk);
-      enum db_type tmp_db_type= ha_resolve_by_name(next_chunk + 2,
-                                                   str_db_type_length);
+      LEX_STRING name= { next_chunk + 2, str_db_type_length };
+      enum db_type tmp_db_type= ha_resolve_by_name(thd, &name);
       if (tmp_db_type != DB_TYPE_UNKNOWN)
       {
         share->db_type= tmp_db_type;

--- 1.117/sql/table.h	2005-11-23 12:44:57 -08:00
+++ 1.118/sql/table.h	2005-12-20 08:12:06 -08:00
@@ -324,6 +324,7 @@
   SCH_COLUMN_PRIVILEGES,
   SCH_KEY_COLUMN_USAGE,
   SCH_OPEN_TABLES,
+  SCH_PLUGINS,
   SCH_PROCEDURES,
   SCH_SCHEMATA,
   SCH_SCHEMA_PRIVILEGES,

--- 1.1/config/ac-macros/storage.m4	2005-11-07 07:24:45 -08:00
+++ 1.2/config/ac-macros/storage.m4	2005-12-20 08:12:05 -08:00
@@ -34,11 +34,14 @@
 [mysql_cv_use_]m4_bpatsubst([$3], -, _)=[$with_]m4_bpatsubst([$3], -, _))
 AH_TEMPLATE([$5], [Build $2])
 if test "[$mysql_cv_use_]m4_bpatsubst([$3], -, _)" != no; then
-AC_DEFINE([$5])
-mysql_se_decls="${mysql_se_decls},$6"
-mysql_se_htons="${mysql_se_htons},&$6"
+if test "$6" != "no"
+then
+  AC_DEFINE([$5])
+  mysql_se_decls="${mysql_se_decls},$6"
+  mysql_se_htons="${mysql_se_htons},&$6"
+  mysql_se_objs="$mysql_se_objs $8"
+fi
 mysql_se_dirs="$mysql_se_dirs $7"
-mysql_se_objs="$mysql_se_objs $8"
 mysql_se_libs="$mysql_se_libs $9"
 $10
 fi
--- New file ---
+++ storage/csv/Makefile.am	05/12/20 08:12:06
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
#
# 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; either version 2 of the License, or
# (at your option) any later version.
#
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#called from the top level Makefile

MYSQLDATAdir =          $(localstatedir)
MYSQLSHAREdir =         $(pkgdatadir)
MYSQLBASEdir=           $(prefix)
MYSQLLIBdir=            $(pkglibdir)
INCLUDES =              -I$(top_srcdir)/include \
			-I$(top_srcdir)/regex \
			-I$(top_srcdir)/sql \
                        -I$(srcdir)
WRAPLIBS=

lib_LTLIBRARIES =       libhacsv.la

libhacsv_la_SOURCES =	ha_tina.cc

LDADD =

DEFS =                  -DMYSQL_SERVER @DEFS@

# Don't update the files from bitkeeper
%::SCCS/s.%

--- New file ---
+++ storage/example/Makefile.am	05/12/20 08:12:07
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
#
# 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; either version 2 of the License, or
# (at your option) any later version.
#
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#called from the top level Makefile

MYSQLDATAdir =          $(localstatedir)
MYSQLSHAREdir =         $(pkgdatadir)
MYSQLBASEdir=           $(prefix)
MYSQLLIBdir=            $(pkglibdir)
INCLUDES =              -I$(top_srcdir)/include \
			-I$(top_srcdir)/regex \
			-I$(top_srcdir)/sql \
                        -I$(srcdir)
WRAPLIBS=

lib_LTLIBRARIES =       libhaexample.la

libhaexample_la_SOURCES = ha_example.cc

LDADD =

DEFS =                  -DMYSQL_SERVER @DEFS@

# Don't update the files from bitkeeper
%::SCCS/s.%


--- 1.56/sql/share/errmsg.txt	2005-11-23 16:56:09 -08:00
+++ 1.57/sql/share/errmsg.txt	2005-12-20 08:12:06 -08:00
@@ -5721,3 +5721,9 @@
 ER_PLUGIN_IS_NOT_LOADED
 	eng "Plugin '%-.64s' is not loaded"
+ER_STORAGE_ENGINE_BUSY
+	eng "Storage engine '%-.64s' busy. Try using 'FLUSH TABLES' first."
+ER_STORAGE_ENGINE_INIT_FAIL
+	eng "Storage engine '%-.64s' initialization failed."
+ER_STORAGE_ENGINE_EXISTS
+	eng "Storage engine '%-.64s' already installed."

--- 1.63/sql/ha_archive.cc	2005-11-23 12:44:54 -08:00
+++ 1.64/sql/ha_archive.cc	2005-12-20 08:12:05 -08:00
@@ -163,12 +163,9 @@
   archive_create_handler,    /* Create a new handler */
   NULL,    /* Drop a database */
   archive_db_end,    /* Panic call */
-  NULL,    /* Release temporary latches */
-  NULL,    /* Update Statistics */
   NULL,    /* Start Consistent Snapshot */
   NULL,    /* Flush logs */
   NULL,    /* Show status */
-  NULL,    /* Replication Report Sent Binlog */
   HTON_NO_FLAGS
 };
 

--- 1.24/sql/examples/ha_tina.cc	2005-11-23 18:08:03 -08:00
+++ 1.26/storage/csv/ha_tina.cc	2005-12-20 08:12:06 -08:00
@@ -51,18 +51,21 @@
 #include "ha_tina.h"
 #include <sys/mman.h>
 
+#include <plugin.h>
+
 /* Stuff for shares */
 pthread_mutex_t tina_mutex;
 static HASH tina_open_tables;
 static int tina_init= 0;
 static handler *tina_create_handler(TABLE_SHARE *table);
+static int tina_init_func();
 
 handlerton tina_hton= {
   "CSV",
   SHOW_OPTION_YES,
   "CSV storage engine", 
   DB_TYPE_CSV_DB,
-  NULL,    /* One needs to be written! */
+  (bool (*)()) tina_init_func,
   0,       /* slot */
   0,       /* savepoint size. */
   NULL,    /* close_connection */
@@ -81,12 +84,9 @@
   tina_create_handler,    /* Create a new handler */
   NULL,    /* Drop a database */
   tina_end,    /* Panic call */
-  NULL,    /* Release temporary latches */
-  NULL,    /* Update Statistics */
   NULL,    /* Start Consistent Snapshot */
   NULL,    /* Flush logs */
   NULL,    /* Show status */
-  NULL,    /* Replication Report Sent Binlog */
   HTON_CAN_RECREATE
 };
 
@@ -155,6 +155,35 @@
   DBUG_RETURN(0);
 }
 
+
+static int tina_init_func()
+{
+  if (!tina_init)
+  {
+    tina_init++;
+    VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
+    (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
+                     (hash_get_key) tina_get_key,0,0);
+  }
+  return 0;
+}
+
+static int tina_done_func()
+{
+  if (tina_init)
+  {
+    if (tina_open_tables.records)
+    {
+      return 1;
+    }
+    hash_free(&tina_open_tables);
+    pthread_mutex_destroy(&tina_mutex);
+    tina_init--;
+  }
+  return 0;
+}
+	
+
 /*
   Simple lock controls.
 */
@@ -164,19 +193,6 @@
   char *tmp_name;
   uint length;
 
-  if (!tina_init)
-  {
-    /* Hijack a mutex for init'ing the storage engine */
-    pthread_mutex_lock(&LOCK_mysql_create_db);
-    if (!tina_init)
-    {
-      tina_init++;
-      VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
-      (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
-                       (hash_get_key) tina_get_key,0,0);
-    }
-    pthread_mutex_unlock(&LOCK_mysql_create_db);
-  }
   pthread_mutex_lock(&tina_mutex);
   length=(uint) strlen(table_name);
   if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
@@ -262,13 +278,7 @@
 
 int tina_end(ha_panic_function type)
 {
-  if (tina_init)
-  {
-    hash_free(&tina_open_tables);
-    VOID(pthread_mutex_destroy(&tina_mutex));
-  }
-  tina_init= 0;
-  return 0;
+  return tina_done_func();
 }
 
 /*
@@ -932,4 +942,16 @@
 
   DBUG_RETURN(0);
 }
+
+mysql_declare_plugin
+{
+  MYSQL_STORAGE_ENGINE_PLUGIN,
+  &tina_hton,
+  tina_hton.name,
+  "MySQL AB",
+  "CSV Storage Engine",
+  tina_init_func, /* Plugin Init */
+  tina_done_func  /* Plugin Deinit */
+}
+mysql_declare_plugin_end;
 

--- 1.9/sql/authors.h	2005-11-30 13:51:19 -08:00
+++ 1.10/sql/authors.h	2005-12-20 08:12:05 -08:00
@@ -62,7 +62,8 @@
   { "Albert Chin-A-Young", "",
     "Tru64 port, large file support, better TCP wrappers support" },
   { "Jorge del Conde", "Mexico City, Mexico", "Windows development" },
-  { "Antony T. Curtis", "Norwalk, CA, USA", "Parser, port to OS/2" },
+  { "Antony T. Curtis", "Norwalk, CA, USA",
+    "Parser, port to OS/2, storage engines and some random stuff" },
   { "Yuri Dario", "", "OS/2 port" },
   { "Sergei Golubchik", "Kerpen, Germany",
     "Full-text search, precision math" },

--- 1.23/sql/ha_blackhole.cc	2005-11-23 12:44:54 -08:00
+++ 1.24/sql/ha_blackhole.cc	2005-12-20 08:12:05 -08:00
@@ -53,12 +53,9 @@
   blackhole_create_handler,    /* Create a new handler */
   NULL,    /* Drop a database */
   NULL,    /* Panic call */
-  NULL,    /* Release temporary latches */
-  NULL,    /* Update Statistics */
   NULL,    /* Start Consistent Snapshot */
   NULL,    /* Flush logs */
   NULL,    /* Show status */
-  NULL,    /* Replication Report Sent Binlog */
   HTON_CAN_RECREATE
 };
 

--- 1.239/sql/ha_innodb.cc	2005-11-23 12:47:26 -08:00
+++ 1.240/sql/ha_innodb.cc	2005-12-20 08:12:05 -08:00
@@ -231,16 +231,9 @@
   innobase_create_handler,	/* Create a new handler */
   innobase_drop_database,	/* Drop a database */
   innobase_end,			/* Panic call */
-  innobase_release_temporary_latches,    /* Release temporary latches */
-  innodb_export_status,		/* Update Statistics */
   innobase_start_trx_and_assign_read_view,    /* Start Consistent Snapshot */
   innobase_flush_logs,		/* Flush logs */
   innobase_show_status,		/* Show status */
-#ifdef HAVE_REPLICATION
-  innobase_repl_report_sent_binlog,    /* Replication Report Sent Binlog */
-#else
-  NULL,
-#endif
   HTON_NO_FLAGS
 };
 
@@ -412,9 +405,9 @@
 documentation, see handler.cc. */
 
 int
-innobase_release_temporary_latches(
+ha_innobase::release_temporary_latches(
 /*===============================*/
-        THD *thd)
+        THD *thd) const
 {
 	trx_t*	trx;
 
@@ -1965,7 +1958,7 @@
 function is used in a replication master. */
 
 int
-innobase_repl_report_sent_binlog(
+ha_innobase::repl_report_sent_binlog(
 /*=============================*/
                                 /* out: 0 */
         THD*    thd,            /* in: thread doing the binlog communication to
@@ -1973,6 +1966,7 @@
         char*   log_file_name,  /* in: binlog file name */
         my_off_t end_offset)    /* in: the offset in the binlog file up to
                                 which we sent the contents to the slave */
+                                const
 {
         int     cmp;
         ibool   can_release_threads     = 0;
@@ -6472,7 +6466,7 @@
 Here we export InnoDB status variables to MySQL.  */
 
 int
-innodb_export_status(void)
+ha_innobase::update_statistics() const
 /*======================*/
 {
   srv_export_innodb_status();
@@ -6562,7 +6556,8 @@
 
 	bool result = FALSE;
 
-	if (stat_print(thd, innobase_hton.name, "", str)) {
+	if (stat_print(thd, innobase_hton.name, strlen(innobase_hton.name), 
+                       "", 0, str, flen)) {
 		result= TRUE;
 	}
 	my_free(str, MYF(0));
@@ -6587,6 +6582,7 @@
   ulint   rw_lock_count_os_wait= 0;
   ulint   rw_lock_count_os_yield= 0;
   ulonglong rw_lock_wait_time= 0;
+  uint    hton_name_len= strlen(innobase_hton.name), buf1len, buf2len;
   DBUG_ENTER("innodb_mutex_show_status");
 
 #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
@@ -6601,16 +6597,17 @@
     {
       if (mutex->count_using > 0)
       {
-	my_snprintf(buf1, sizeof(buf1), "%s:%s",
-		    mutex->cmutex_name, mutex->cfile_name);
-	my_snprintf(buf2, sizeof(buf2),
-		    "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
-		    "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
-		    mutex->count_using, mutex->count_spin_loop,
-		    mutex->count_spin_rounds,
-		    mutex->count_os_wait, mutex->count_os_yield,
-		    mutex->lspent_time/1000);
-	if (stat_print(thd, innobase_hton.name, buf1, buf2))
+	buf1len= my_snprintf(buf1, sizeof(buf1), "%s:%s",
+		             mutex->cmutex_name, mutex->cfile_name);
+	buf2len= my_snprintf(buf2, sizeof(buf2),
+		             "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
+		             "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
+		             mutex->count_using, mutex->count_spin_loop,
+		             mutex->count_spin_rounds,
+		             mutex->count_os_wait, mutex->count_os_yield,
+		             mutex->lspent_time/1000);
+	if (stat_print(thd, innobase_hton.name, hton_name_len, 
+                       buf1, buf1len, buf2, buf2len))
         {
 #ifdef MUTEX_PROTECT_TO_BE_ADDED_LATER
           mutex_exit(&mutex_list_mutex);
@@ -6632,15 +6629,16 @@
     mutex = UT_LIST_GET_NEXT(list, mutex);
   }
 
-  my_snprintf(buf2, sizeof(buf2),
-	      "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
-	      "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
-	      rw_lock_count, rw_lock_count_spin_loop,
-	      rw_lock_count_spin_rounds,
-	      rw_lock_count_os_wait, rw_lock_count_os_yield,
-	      rw_lock_wait_time/1000);
+  buf2len= my_snprintf(buf2, sizeof(buf2),
+	               "count=%lu, spin_waits=%lu, spin_rounds=%lu, "
+	               "os_waits=%lu, os_yields=%lu, os_wait_times=%lu",
+	               rw_lock_count, rw_lock_count_spin_loop,
+	               rw_lock_count_spin_rounds,
+	               rw_lock_count_os_wait, rw_lock_count_os_yield,
+	               rw_lock_wait_time/1000);
 
-  if (stat_print(thd, innobase_hton.name, "rw_lock_mutexes", buf2))
+  if (stat_print(thd, innobase_hton.name, hton_name_len, 
+                 "rw_lock_mutexes", 15, buf2, buf2len))
   {
     DBUG_RETURN(1);
   }

--- 1.109/sql/ha_innodb.h	2005-11-23 12:44:55 -08:00
+++ 1.110/sql/ha_innodb.h	2005-12-20 08:12:06 -08:00
@@ -208,6 +208,13 @@
         int cmp_ref(const byte *ref1, const byte *ref2);
 	bool check_if_incompatible_data(HA_CREATE_INFO *info,
 					uint table_changes);
+
+	int release_temporary_latches(THD *thd) const;
+	int update_statistics() const;
+#ifdef HAVE_REPLICATION
+	int repl_report_sent_binlog(THD *thd, char *log_file_name,
+                                  my_off_t end_offset) const;
+#endif
 };
 
 extern struct show_var_st innodb_status_variables[];
@@ -275,9 +282,6 @@
 
 void innobase_drop_database(char *path);
 bool innobase_show_status(THD* thd, stat_print_fn*, enum ha_stat_type);
-int innodb_export_status(void);
-
-int innobase_release_temporary_latches(THD *thd);
 
 void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
 
@@ -324,9 +328,6 @@
 
 int innobase_xa_end(THD *thd);
 
-
-int innobase_repl_report_sent_binlog(THD *thd, char *log_file_name,
-                               my_off_t end_offset);
 
 /***********************************************************************
 Create a consistent view for a cursor based on current transaction

--- 1.149/sql/set_var.cc	2005-11-25 20:20:46 -08:00
+++ 1.150/sql/set_var.cc	2005-12-20 08:12:06 -08:00
@@ -3034,10 +3034,12 @@
 
   if (var->value->result_type() == STRING_RESULT)
   {
+    LEX_STRING name;
     enum db_type db_type;
     if (!(res=var->value->val_str(&str)) ||
+        !(name.str= (char *)res->ptr()) || !(name.length= res->length()) ||
 	!(var->save_result.ulong_value=
-          (ulong) (db_type= ha_resolve_by_name(res->ptr(), res->length()))) ||
+          (ulong) (db_type= ha_resolve_by_name(thd, &name))) ||
         ha_checktype(thd, db_type, 1, 0) != db_type)
     {
       value= res ? res->c_ptr() : "NULL";

--- 1.3/sql/sql_plugin.cc	2005-11-29 04:17:15 -08:00
+++ 1.4/sql/sql_plugin.cc	2005-12-20 08:12:06 -08:00
@@ -33,6 +33,7 @@
 static rw_lock_t THR_LOCK_plugin;
 static bool initialized= 0;
 
+extern handlerton *sys_table_types[];
 
 static struct st_plugin_dl *plugin_dl_find(LEX_STRING *dl)
 {
@@ -352,6 +353,7 @@
 {
   uint i;
   DBUG_ENTER("plugin_call_initializer");
+redo:
   for (i= 0; i < plugin_array.elements; i++)
   {
     struct st_plugin_int *tmp= dynamic_element(&plugin_array, i,
@@ -366,10 +368,32 @@
         DBUG_PRINT("warning", ("Plugin '%s' init function returned error.",
                                tmp->name.str))
         plugin_del(&tmp->name);
+        goto redo;
       }
     }
     if (tmp->state == PLUGIN_IS_UNINITIALIZED)
+    {
+      switch (tmp->plugin->type)
+      {
+      case MYSQL_STORAGE_ENGINE_PLUGIN:
+      {
+        handlerton *hton= (handlerton*) tmp->plugin->info;
+        if (!hton)
+        {
+          plugin_del(&tmp->name);
+          goto redo;
+        }
+        if (!hton->init || !hton->init())
+          ha_was_inited_ok(hton);
+        else
+          hton->state= SHOW_OPTION_DISABLED;
+        break;
+      }
+      default:
+        break;
+      }
       tmp->state= PLUGIN_IS_READY;
+    }
   }
   DBUG_VOID_RETURN;
 }
@@ -410,42 +434,89 @@
 }
 
 
-void plugin_init(void)
+int plugin_init(void)
+{
+  struct st_plugin_int tmp;
+  int i;
+  DBUG_ENTER("plugin_init");
+
+  if (initialized)
+    DBUG_RETURN(0);
+
+  my_rwlock_init(&THR_LOCK_plugin, NULL);
+
+  if (my_init_dynamic_array(&plugin_dl_array,
+                            sizeof(struct st_plugin_dl),16,16) ||
+      my_init_dynamic_array(&plugin_array,
+                            sizeof(struct st_plugin_int),16,16))
+    goto err;
+
+  for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
+  {
+    if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
+                  get_hash_key, NULL, 0))
+      goto err;
+  }
+  
+  /* Install the built-in storage engines */
+  
+  for (handlerton **hton= sys_table_types; *hton; hton++)
+  {
+    struct st_mysql_plugin *plugin= 
+      (struct st_mysql_plugin *) my_once_alloc(sizeof(struct st_mysql_plugin), 
+                                               MYF(MY_WME | MY_ZEROFILL));
+    if (!plugin)                                            
+      goto err;
+    plugin->type= MYSQL_STORAGE_ENGINE_PLUGIN;
+    plugin->info= *hton;
+    plugin->name= (*hton)->name;
+    plugin->author= "";
+    plugin->descr= (*hton)->comment;
+    
+    tmp.plugin= plugin;
+    tmp.name.str= (char *)plugin->name;
+    tmp.name.length= strlen(plugin->name);
+    tmp.ref_count= 1;
+    tmp.state= PLUGIN_IS_UNINITIALIZED;
+    tmp.plugin_dl= 0;
+
+    if (insert_dynamic(&plugin_array, (gptr)&tmp))
+      goto err;
+
+    if (my_hash_insert(&plugin_hash[plugin->type],
+                       (byte*)dynamic_element(&plugin_array,
+                                              plugin_array.elements - 1,
+                                              struct st_plugin_int *)))
+      goto err;
+  }
+
+  initialized= 1;
+
+  DBUG_RETURN(0);
+  
+err:
+  DBUG_RETURN(1);
+}
+
+void plugin_load(void)
 {
   TABLE_LIST tables;
   TABLE *table;
   READ_RECORD read_record_info;
   int error, i;
   MEM_ROOT mem;
-  DBUG_ENTER("plugin_init");
-  if (initialized)
-    DBUG_VOID_RETURN;
-  my_rwlock_init(&THR_LOCK_plugin, NULL);
-  THD *new_thd = new THD;
-  if (!new_thd ||
-      my_init_dynamic_array(&plugin_dl_array,sizeof(struct st_plugin_dl),16,16) ||
-      my_init_dynamic_array(&plugin_array,sizeof(struct st_plugin_int),16,16))
+  THD *new_thd;
+  DBUG_ENTER("plugin_load");
+  
+  DBUG_ASSERT(initialized);
+  
+  if (!(new_thd= new THD))
   {
     sql_print_error("Can't allocate memory for plugin structures");
     delete new_thd;
-    delete_dynamic(&plugin_dl_array);
-    delete_dynamic(&plugin_array);
     DBUG_VOID_RETURN;
   }
-  for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
-  {
-    if (hash_init(&plugin_hash[i], system_charset_info, 16, 0, 0,
-                  get_hash_key, NULL, 0))
-    {
-      sql_print_error("Can't allocate memory for plugin structures");
-      delete new_thd;
-      delete_dynamic(&plugin_dl_array);
-      delete_dynamic(&plugin_array);
-      DBUG_VOID_RETURN;
-    }
-  }
   init_sql_alloc(&mem, 1024, 0);
-  initialized= 1;
   new_thd->thread_stack= (char*) &tables;
   new_thd->store_globals();
   new_thd->db= my_strdup("mysql", MYF(0));
@@ -458,10 +529,6 @@
   {
     DBUG_PRINT("error",("Can't open plugin table"));
     sql_print_error("Can't open the mysql.plugin table. Please run the mysql_install_db script to create it.");
-    delete_dynamic(&plugin_dl_array);
-    delete_dynamic(&plugin_array);
-    for (i= 0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
-      hash_free(&plugin_hash[i]);
     goto end;
   }
   table= tables.table;
@@ -530,11 +597,17 @@
   int error;
   struct st_plugin_int *tmp;
   DBUG_ENTER("mysql_install_plugin");
+
   bzero(&tables, sizeof(tables));
   tables.db= (char *)"mysql";
   tables.table_name= tables.alias= (char *)"plugin";
   if (check_table_access(thd, INSERT_ACL, &tables, 0))
     DBUG_RETURN(TRUE);
+    
+  /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
+  if (! (table = open_ltable(thd, &tables, TL_WRITE)))
+    DBUG_RETURN(TRUE);
+
   rw_wrlock(&THR_LOCK_plugin);
   if (plugin_add(name, dl, REPORT_TO_USER))
     goto err;
@@ -547,10 +620,9 @@
                "Plugin initialization function failed.");
       goto err;
     }
-    tmp->state= PLUGIN_IS_READY;
   }
-  if (! (table = open_ltable(thd, &tables, TL_WRITE)))
-    goto deinit;
+  tmp->state= PLUGIN_IS_READY;
+
   restore_record(table, s->default_values);
   table->field[0]->store(name->str, name->length, system_charset_info);
   table->field[1]->store(dl->str, dl->length, files_charset_info);
@@ -560,6 +632,22 @@
     table->file->print_error(error, MYF(0));
     goto deinit;
   }
+  
+  switch (tmp->plugin->type)
+  {
+  case MYSQL_STORAGE_ENGINE_PLUGIN:
+  {
+    handlerton *hton= (handlerton *) tmp->plugin->info;
+    if (!hton->init || !hton->init())
+      ha_was_inited_ok(hton);
+    else
+      hton->state= SHOW_OPTION_DISABLED;
+    break;
+  }  
+  default:
+    break;
+  }
+  
   rw_unlock(&THR_LOCK_plugin);
   DBUG_RETURN(FALSE);
 deinit:
@@ -577,14 +665,46 @@
   TABLE *table;
   TABLE_LIST tables;
   struct st_plugin_int *plugin;
+  bool busy= FALSE;
   DBUG_ENTER("mysql_uninstall_plugin");
+
+  bzero(&tables, sizeof(tables));
+  tables.db= (char *)"mysql";
+  tables.table_name= tables.alias= (char *)"plugin";
+
+  /* need to open before acquiring THR_LOCK_plugin or it will deadlock */
+  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
+    DBUG_RETURN(TRUE);
+
   rw_wrlock(&THR_LOCK_plugin);
-  if (! (plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+  if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
   {
     my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
     goto err;
   }
-  if (plugin->ref_count)
+  if (!plugin->plugin_dl)
+  {
+    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
+                 "Built-in plugins cannot be deleted,.");
+    my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
+    goto err;
+  }
+  
+  switch (plugin->plugin->type)
+  {
+  case MYSQL_STORAGE_ENGINE_PLUGIN:
+  {
+    handlerton *hton= (handlerton *) plugin->plugin->info;
+    if (hton->state == SHOW_OPTION_YES && hton->panic &&
+        hton->panic(HA_PANIC_TRY_CLOSE))
+      busy= TRUE;
+    break;
+  }
+  default:
+    break;
+  }
+
+  if (plugin->ref_count || busy)
   {
     plugin->state= PLUGIN_IS_DELETED;
     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
@@ -596,11 +716,7 @@
       plugin->plugin->deinit();
     plugin_del(name);
   }
-  bzero(&tables, sizeof(tables));
-  tables.db= (char *)"mysql";
-  tables.table_name= tables.alias= (char *)"plugin";
-  if (! (table= open_ltable(thd, &tables, TL_WRITE)))
-    goto err;
+
   table->field[0]->store(name->str, name->length, system_charset_info);
   table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
   if (! table->file->index_read_idx(table->record[0], 0,
@@ -615,6 +731,32 @@
       goto err;
     }
   }
+  rw_unlock(&THR_LOCK_plugin);
+  DBUG_RETURN(FALSE);
+err:
+  rw_unlock(&THR_LOCK_plugin);
+  DBUG_RETURN(TRUE);
+}
+
+
+my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
+                       int type, void *arg)
+{
+  uint idx;
+  struct st_plugin_int *plugin;
+  DBUG_ENTER("mysql_uninstall_plugin");
+  rw_rdlock(&THR_LOCK_plugin);
+
+  for (idx= 0; idx < plugin_array.elements; idx++)
+  {
+    plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
+    if ((plugin->state != PLUGIN_IS_FREED) &&
+        (plugin->state != PLUGIN_IS_DELETED) &&
+        (type == MYSQL_ANY_PLUGIN || type == plugin->plugin->type) &&
+        (!func || func(thd, plugin, arg)))
+      goto err;
+  }
+  
   rw_unlock(&THR_LOCK_plugin);
   DBUG_RETURN(FALSE);
 err:

--- 1.1/sql/sql_plugin.h	2005-11-05 03:20:32 -08:00
+++ 1.2/sql/sql_plugin.h	2005-12-20 08:12:06 -08:00
@@ -53,11 +53,19 @@
 
 extern char *opt_plugin_dir_ptr;
 extern char opt_plugin_dir[FN_REFLEN];
-extern void plugin_init(void);
+extern int plugin_init(void);
+extern void plugin_load(void);
 extern void plugin_free(void);
 extern my_bool plugin_is_ready(LEX_STRING *name, int type);
 extern st_plugin_int *plugin_lock(LEX_STRING *name, int type);
 extern void plugin_unlock(struct st_plugin_int *plugin);
 extern my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl);
 extern my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name);
+
+
+typedef my_bool (plugin_foreach_func)(THD *thd, 
+                                      st_plugin_int *plugin,
+                                      void *arg);
+extern my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
+                              int type, void *arg);
 #endif

--- 1.12/sql/ha_partition.cc	2005-11-25 20:17:12 -08:00
+++ 1.13/sql/ha_partition.cc	2005-12-20 08:12:06 -08:00
@@ -92,12 +92,9 @@
   partition_create_handler, /* Create a new handler */
   NULL, /* Drop a database */
   NULL, /* Panic call */
-  NULL, /* Release temporary latches */
-  NULL, /* Update Statistics */
   NULL, /* Start Consistent Snapshot */
   NULL, /* Flush logs */
   NULL, /* Show status */
-  NULL, /* Replication Report Sent Binlog */
   HTON_NOT_USER_SELECTABLE
 };
 

--- 1.44/sql/ha_federated.cc	2005-11-23 18:08:01 -08:00
+++ 1.45/sql/ha_federated.cc	2005-12-20 08:12:05 -08:00
@@ -390,12 +390,9 @@
   federated_create_handler,    /* Create a new handler */
   NULL,    /* Drop a database */
   federated_db_end,    /* Panic call */
-  NULL,    /* Release temporary latches */
-  NULL,    /* Update Statistics */
   NULL,    /* Start Consistent Snapshot */
   NULL,    /* Flush logs */
   NULL,    /* Show status */
-  NULL,    /* Replication Report Sent Binlog */
   HTON_ALTER_NOT_SUPPORTED
 };
 
Thread
bk commit into 5.1 tree (acurtis:1.1995)antony20 Dec