MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Guilhem Bichot Date:December 9 2008 1:12pm
Subject:bzr commit into mysql-6.0 branch (guilhem:2927)
View as plain text  
#At file:///home/mysql_src/bzrrepos/mysql-6.0-maria/ based on revid:guilhem@stripped

 2927 Guilhem Bichot	2008-12-09 [merge]
      merge of 5.1-maria into 6.0-maria
removed:
  mysql-test/include/wait_until_disconnected.inc
added:
  mysql-test/include/mysqladmin_shutdown.inc
  mysql-test/include/wait_until_disconnected.inc
  mysql-test/suite/maria/r/maria-recovery3.result
  mysql-test/suite/maria/t/maria-recovery3-master.opt
  mysql-test/suite/maria/t/maria-recovery3.test
modified:
  client/mysqlslap.c
  dbug/dbug.c
  mysql-test/include/maria_empty_logs.inc
  mysql-test/include/wait_until_connected_again.inc
  mysql-test/mysql-test-run.pl
  storage/maria/ha_maria.cc
  storage/maria/ma_bitmap.c
  storage/maria/ma_blockrec.c
  storage/maria/ma_blockrec.h
  storage/maria/ma_checkpoint.c
  storage/maria/ma_close.c
  storage/maria/ma_commit.c
  storage/maria/ma_loghandler.c
  storage/maria/ma_open.c
  storage/maria/ma_recovery.c
  storage/maria/ma_state.c
  storage/maria/ma_state.h
  storage/maria/maria_def.h
  storage/maria/trnman.c
  storage/maria/trnman_public.h

=== modified file 'client/mysqlslap.c'
--- a/client/mysqlslap.c	2008-07-14 14:24:32 +0000
+++ b/client/mysqlslap.c	2008-12-09 13:11:48 +0000
@@ -2175,10 +2175,17 @@ limit_not_met:
         {
           if (mysql_field_count(&mysql))
           {
-            result= mysql_store_result(&mysql);
-            while ((row = mysql_fetch_row(result)))
-              counter++;
-            mysql_free_result(result);
+            if ((result= mysql_store_result(&mysql)))
+            {
+              while ((row = mysql_fetch_row(result)))
+                counter++;
+              mysql_free_result(result);
+            }
+            else
+            {
+              fprintf(stderr,"%s: Error in mysql_store_result(): %d %s\n",
+                      my_progname, mysql_errno(&mysql), mysql_error(&mysql));
+            }
           }
         } while(mysql_next_result(&mysql) == 0);
       }

=== modified file 'dbug/dbug.c'
--- a/dbug/dbug.c	2008-10-20 09:16:47 +0000
+++ b/dbug/dbug.c	2008-12-09 13:11:48 +0000
@@ -177,7 +177,11 @@
 static void perror();          /* Fake system/library error print routine */
 #endif
 
+#ifdef SAFEMALLOC
 IMPORT int _sanity(const char *file,uint line); /* safemalloc sanity checker */
+#else
+#define _sanity(X,Y) (1)
+#endif
 
 /*
  *      The user may specify a list of functions to trace or
@@ -287,7 +291,7 @@ static void PushState(CODE_STATE *cs);
 	/* Free memory associated with debug state. */
 static void FreeState (CODE_STATE *cs, struct settings *state, int free_state);
         /* Test for tracing enabled */
-static int DoTrace(CODE_STATE *cs, int tracing);
+static int DoTrace(CODE_STATE *cs);
 /*
   return values of DoTrace.
   Can also be used as bitmask: ret & DO_TRACE
@@ -728,7 +732,7 @@ void FixTraceFlags_helper(CODE_STATE *cs
     It's ok, because cs->framep may only affect DO_TRACE/DONT_TRACE return
     values, but we ignore them here anyway
   */
-  switch(DoTrace(cs, 1)) {
+  switch(DoTrace(cs)) {
   case ENABLE_TRACE:
     framep->level|= TRACE_ON;
     break;
@@ -1167,18 +1171,23 @@ void _db_enter_(const char *_func_, cons
     (void) fflush(cs->stack->prof_file);
   }
 #endif
-  switch (DoTrace(cs, TRACING)) {
+  switch (DoTrace(cs)) {
   case ENABLE_TRACE:
     cs->framep->level|= TRACE_ON;
     if (!TRACING) break;
     /* fall through */
   case DO_TRACE:
-    if (!cs->locked)
-      pthread_mutex_lock(&THR_LOCK_dbug);
-    DoPrefix(cs, _line_);
-    Indent(cs, cs->level);
-    (void) fprintf(cs->stack->out_file, ">%s\n", cs->func);
-    DbugFlush(cs);                       /* This does a unlock */
+    if ((cs->stack->flags & SANITY_CHECK_ON) && _sanity(_file_,_line_))
+      cs->stack->flags &= ~SANITY_CHECK_ON;
+    if (TRACING)
+    {
+      if (!cs->locked)
+        pthread_mutex_lock(&THR_LOCK_dbug);
+      DoPrefix(cs, _line_);
+      Indent(cs, cs->level);
+      (void) fprintf(cs->stack->out_file, ">%s\n", cs->func);
+      DbugFlush(cs);                       /* This does a unlock */
+    }
     break;
   case DISABLE_TRACE:
     cs->framep->level&= ~TRACE_ON;
@@ -1186,11 +1195,6 @@ void _db_enter_(const char *_func_, cons
   case DONT_TRACE:
     break;
   }
-#ifdef SAFEMALLOC
-  if (cs->stack->flags & SANITY_CHECK_ON)
-    if (_sanity(_file_,_line_))               /* Check of safemalloc */
-      cs->stack->flags &= ~SANITY_CHECK_ON;
-#endif
   errno=save_errno;
 }
 
@@ -1232,25 +1236,24 @@ void _db_return_(uint _line_, struct _db
   }
   else
   {
-#ifdef SAFEMALLOC
-    if (cs->stack->flags & SANITY_CHECK_ON)
-    {
-      if (_sanity(_stack_frame_->file,_line_))
-        cs->stack->flags &= ~SANITY_CHECK_ON;
-    }
-#endif
 #ifndef THREAD
     if (DoProfile(cs))
       (void) fprintf(cs->stack->prof_file, PROF_XFMT, Clock(), cs->func);
 #endif
-    if (TRACING && DoTrace(cs, 1) & DO_TRACE)
+    if (DoTrace(cs) & DO_TRACE)
     {
-      if (!cs->locked)
-        pthread_mutex_lock(&THR_LOCK_dbug);
-      DoPrefix(cs, _line_);
-      Indent(cs, cs->level);
-      (void) fprintf(cs->stack->out_file, "<%s\n", cs->func);
-      DbugFlush(cs);
+      if ((cs->stack->flags & SANITY_CHECK_ON) &&
+          _sanity(_stack_frame_->file,_line_))
+        cs->stack->flags &= ~SANITY_CHECK_ON;
+      if (TRACING)
+      {
+        if (!cs->locked)
+          pthread_mutex_lock(&THR_LOCK_dbug);
+        DoPrefix(cs, _line_);
+        Indent(cs, cs->level);
+        (void) fprintf(cs->stack->out_file, "<%s\n", cs->func);
+        DbugFlush(cs);
+      }
     }
   }
   /*
@@ -1726,28 +1729,24 @@ void _db_end_()
  *
  *      DoTrace    check to see if tracing is current enabled
  *
- *       tracing    is the value of TRACING to check if the tracing is enabled
- *                  or 1 to check if the function is enabled (in _db_keyword_)
- *
  *  DESCRIPTION
  *
- *      Checks to see if tracing is enabled based on whether the
- *      user has specified tracing, the maximum trace depth has
- *      not yet been reached, the current function is selected,
- *      and the current process is selected.
+ *      Checks to see if dbug in this function is enabled based on
+ *      whether the maximum trace depth has been reached, the current
+ *      function is selected, and the current process is selected.
  *
  */
 
-static int DoTrace(CODE_STATE *cs, int tracing)
+static int DoTrace(CODE_STATE *cs)
 {
   if ((cs->stack->maxdepth == 0 || cs->level <= cs->stack->maxdepth) &&
       InList(cs->stack->processes, cs->process) & (MATCHED|INCLUDE))
     switch(InList(cs->stack->functions, cs->func)) {
     case INCLUDE|SUBDIR:  return ENABLE_TRACE;
-    case INCLUDE:         return tracing ? DO_TRACE : DONT_TRACE;
+    case INCLUDE:         return DO_TRACE;
     case MATCHED|SUBDIR:
     case NOT_MATCHED|SUBDIR:
-    case MATCHED:         return tracing && framep_trace_flag(cs, cs->framep) ?
+    case MATCHED:         return framep_trace_flag(cs, cs->framep) ?
                                            DO_TRACE : DONT_TRACE;
     case EXCLUDE:
     case NOT_MATCHED:     return DONT_TRACE;
@@ -1818,7 +1817,7 @@ BOOLEAN _db_keyword_(CODE_STATE *cs, con
   get_code_state_if_not_set_or_return FALSE;
   strict=strict ? INCLUDE : INCLUDE|MATCHED;
 
-  return DEBUGGING && DoTrace(cs, 1) & DO_TRACE &&
+  return DEBUGGING && DoTrace(cs) & DO_TRACE &&
          InList(cs->stack->keywords, keyword) & strict;
 }
 

=== modified file 'mysql-test/include/maria_empty_logs.inc'
--- a/mysql-test/include/maria_empty_logs.inc	2008-06-26 09:32:22 +0000
+++ b/mysql-test/include/maria_empty_logs.inc	2008-12-05 14:08:09 +0000
@@ -13,7 +13,7 @@ append_file $MYSQLTEST_VARDIR/tmp/master
 wait-maria_empty_logs.inc
 EOF
 
---exec $MYSQLADMIN --no-defaults -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= shutdown 2>&1;
+--source include/mysqladmin_shutdown.inc
 
 if (!$mel_keep_control_file)
 {

=== added file 'mysql-test/include/mysqladmin_shutdown.inc'
--- a/mysql-test/include/mysqladmin_shutdown.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/mysqladmin_shutdown.inc	2008-12-05 14:08:09 +0000
@@ -0,0 +1,7 @@
+# Initiates a clean shutdown of the server and waits for its completion
+
+--exec $MYSQLADMIN --no-defaults -S $MASTER_MYSOCK -P $MASTER_MYPORT  -u root --password= shutdown 2>&1;
+
+# On Windows mysqladmin does not wait for shutdown to be finished,
+# so we have to monitor this with our connection:
+--source include/wait_until_disconnected.inc

=== modified file 'mysql-test/include/wait_until_connected_again.inc'
--- a/mysql-test/include/wait_until_connected_again.inc	2008-11-13 14:55:42 +0000
+++ b/mysql-test/include/wait_until_connected_again.inc	2008-12-09 13:11:48 +0000
@@ -2,6 +2,9 @@
 # Include this script to wait until the connection to the
 # server has been restored or timeout occurs.
 # You should have done --enable_reconnect first
+# When you change this file you may have to chance its cousin
+# wait_until_disconnected.inc
+
 --disable_result_log
 --disable_query_log
 let $counter= 600;

=== added file 'mysql-test/include/wait_until_disconnected.inc'
--- a/mysql-test/include/wait_until_disconnected.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/wait_until_disconnected.inc	2008-12-05 14:08:09 +0000
@@ -0,0 +1,24 @@
+#
+# Include this script after a shutdown to wait until the connection
+# to the server has been lost or timeout occurs.
+# When you change this file you may have to chance its cousin
+# wait_until_connected_again.inc
+
+--disable_result_log
+--disable_query_log
+let $counter= 5000;
+let $mysql_errno= 0;
+while (!$mysql_errno)
+{
+  --error 0,2002,2003,2006,1053
+  show status;
+
+  dec $counter;
+  if (!$counter)
+  {
+    --die Server failed to disconnect me
+  }
+  --sleep 0.1
+}
+--enable_query_log
+--enable_result_log

=== removed file 'mysql-test/include/wait_until_disconnected.inc'
--- a/mysql-test/include/wait_until_disconnected.inc	2008-11-03 17:51:36 +0000
+++ b/mysql-test/include/wait_until_disconnected.inc	1970-01-01 00:00:00 +0000
@@ -1,21 +0,0 @@
-#
-# Include this script to wait until the connection to the
-# server has been dropped
---disable_result_log
---disable_query_log
-let $counter= 500;
-let $mysql_errno= 9999;
-while (!$mysql_errno)
-{
-  --error 0,1053,2002,2006
-  show status;
-
-  dec $counter;
-  if (!$counter)
-  {
-    --die Server failed to dissapear
-  }
-  --sleep 0.1
-}
---enable_query_log
---enable_result_log

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2008-11-22 15:24:06 +0000
+++ b/mysql-test/mysql-test-run.pl	2008-12-09 13:11:48 +0000
@@ -4844,8 +4844,9 @@ sub gdb_arguments {
   else
   {
     # write init file for mysqld
-    mtr_tofile($gdb_init_file,
-	       "set args $str\n");
+    mtr_tofile($gdb_init_file, <<EOGDB );
+set args $str
+EOGDB
   }
 
   if ( $opt_manual_gdb )

=== added file 'mysql-test/suite/maria/r/maria-recovery3.result'
--- a/mysql-test/suite/maria/r/maria-recovery3.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/maria/r/maria-recovery3.result	2008-12-05 21:11:46 +0000
@@ -0,0 +1,29 @@
+set global maria_log_file_size=4294967295;
+drop database if exists mysqltest;
+create database mysqltest;
+use mysqltest;
+* shut down mysqld, removed logs, restarted it
+* TEST of Checkpoint between writing the commit log record and committing in trnman
+create table t1(a int primary key) engine=maria;
+insert into t1 values(1);
+flush table t1;
+* copied t1 for comparison
+set session debug="+d,maria_sleep_in_commit";
+insert into t1 values(2);
+set global maria_checkpoint_interval=1000;
+delete from t1 where a=2;
+SET SESSION debug="+d,maria_flush_whole_log,maria_crash";
+* crashing mysqld intentionally
+set global maria_checkpoint_interval=1;
+ERROR HY000: Lost connection to MySQL server during query
+* recovery happens
+check table t1 extended;
+Table	Op	Msg_type	Msg_text
+mysqltest.t1	check	status	OK
+* testing that checksum after recovery is as expected
+Checksum-check
+ok
+use mysqltest;
+drop table t1;
+drop database mysqltest_for_comparison;
+drop database mysqltest;

=== added file 'mysql-test/suite/maria/t/maria-recovery3-master.opt'
--- a/mysql-test/suite/maria/t/maria-recovery3-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/maria/t/maria-recovery3-master.opt	2008-12-05 21:11:46 +0000
@@ -0,0 +1 @@
+--skip-stack-trace --skip-core-file --loose-maria-log-dir-path=$MYSQLTEST_VARDIR/tmp

=== added file 'mysql-test/suite/maria/t/maria-recovery3.test'
--- a/mysql-test/suite/maria/t/maria-recovery3.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/maria/t/maria-recovery3.test	2008-12-05 21:11:46 +0000
@@ -0,0 +1,71 @@
+--source include/not_embedded.inc
+# Don't test this under valgrind, memory leaks will occur as we crash
+--source include/not_valgrind.inc
+# Binary must be compiled with debug for crash to occur
+--source include/have_debug.inc
+--source include/have_maria.inc
+
+set global maria_log_file_size=4294967295;
+let $MARIA_LOG=../tmp;
+
+--disable_warnings
+drop database if exists mysqltest;
+--enable_warnings
+create database mysqltest;
+let $mms_tname=t;
+
+# Include scripts can perform SQL. For it to not influence the main test
+# they use a separate connection. This way if they use a DDL it would
+# not autocommit in the main test.
+connect (admin, 127.0.0.1, root,,mysqltest,,);
+--enable_reconnect
+
+connection default;
+use mysqltest;
+--enable_reconnect
+
+let $mms_tables=1;
+let $mvr_restore_old_snapshot=0;
+let $mms_compare_physically=0;
+let $mvr_debug_option="+d,maria_flush_whole_log,maria_crash";
+let $mvr_crash_statement= set global maria_checkpoint_interval=1;
+
+-- source include/maria_empty_logs.inc
+
+# Test for BUG#41037 (recovery failure)
+--echo * TEST of Checkpoint between writing the commit log record and committing in trnman
+# we want recovery to use the tables as they were at time of crash
+let $mvr_restore_old_snapshot=0;
+# UNDO phase prevents physical comparison, normally,
+# so we'll only use checksums to compare.
+let $mms_compare_physically=0;
+let $mvr_crash_statement= set global maria_checkpoint_interval=1;
+create table t1(a int primary key) engine=maria;
+insert into t1 values(1);
+-- source include/maria_make_snapshot_for_comparison.inc
+set session debug="+d,maria_sleep_in_commit";
+send insert into t1 values(2);
+sleep 1;
+# Now the INSERT of 2 has written a commit record
+# but not yet called trnman_commit(), so for checkpoint it's not
+# committed.
+connection admin;
+set global maria_checkpoint_interval=1000; # force a checkpoint
+connection default;
+reap; # end of INSERT
+delete from t1 where a=2;
+# Bug was that: Recovery starts REDO scanning from too far: from
+# Checkpoint record which says INSERT is not committed, so
+# Recovery executes the INSERT's UNDO and finds no key to delete
+# (as DELETE already deleted it), fails.
+-- source include/maria_verify_recovery.inc
+drop table t1;
+
+# Note that even if machine is loaded and thus INSERT is committed
+# before checkpoint happens, test should still pass (though it won't
+# reproduce the conditions of the bug).
+
+# clean up everything
+let $mms_purpose=comparison;
+eval drop database mysqltest_for_$mms_purpose;
+drop database mysqltest;

=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc	2008-12-04 21:02:09 +0000
+++ b/storage/maria/ha_maria.cc	2008-12-09 13:11:48 +0000
@@ -2251,6 +2251,10 @@ int ha_maria::external_lock(THD *thd, in
         We always re-enable, don't rely on thd->transaction.on as it is
         sometimes reset to true after unlocking (see mysql_truncate() for a
         partitioned table based on Maria).
+        Note that we can come here without having an exclusive lock on the
+        table, for example in this case:
+        external_lock(F_(WR|RD)LCK); thr_lock() which fails due to lock
+        abortion; external_lock(F_UNLCK).
       */
       if (_ma_reenable_logging_for_table(file, TRUE))
         DBUG_RETURN(1);

=== modified file 'storage/maria/ma_bitmap.c'
--- a/storage/maria/ma_bitmap.c	2008-10-17 13:37:07 +0000
+++ b/storage/maria/ma_bitmap.c	2008-12-09 09:56:02 +0000
@@ -260,6 +260,7 @@ my_bool _ma_bitmap_init(MARIA_SHARE *sha
 my_bool _ma_bitmap_end(MARIA_SHARE *share)
 {
   my_bool res= _ma_bitmap_flush(share);
+  safe_mutex_assert_owner(&share->close_lock);
   pthread_mutex_destroy(&share->bitmap.bitmap_lock);
   pthread_cond_destroy(&share->bitmap.bitmap_cond);
   delete_dynamic(&share->bitmap.pinned_pages);

=== modified file 'storage/maria/ma_blockrec.c'
--- a/storage/maria/ma_blockrec.c	2008-10-14 15:18:14 +0000
+++ b/storage/maria/ma_blockrec.c	2008-12-09 09:56:02 +0000
@@ -453,7 +453,7 @@ my_bool _ma_once_end_block_record(MARIA_
   {
     /*
       We de-assign the id even though index has not been flushed, this is ok
-      as intern_lock serializes us with a Checkpoint looking at our share.
+      as close_lock serializes us with a Checkpoint looking at our share.
     */
     translog_deassign_id_from_share(share);
   }
@@ -5914,7 +5914,7 @@ my_bool write_hook_for_file_id(enum tran
                                TRN *trn
                                __attribute__ ((unused)),
                                MARIA_HA *tbl_info,
-                               LSN *lsn __attribute__ ((unused)),
+                               LSN *lsn,
                                void *hook_arg
                                __attribute__ ((unused)))
 {
@@ -5923,6 +5923,44 @@ my_bool write_hook_for_file_id(enum tran
   return 0;
 }
 
+
+/**
+   Updates transaction's rec_lsn when committing.
+
+   A transaction writes its commit record before being committed in trnman, so
+   if Checkpoint happens just between the COMMIT record log write and the
+   commit in trnman, it will record that transaction is not committed. Assume
+   the transaction (trn1) did an INSERT; after the checkpoint, a second
+   transaction (trn2) does a DELETE of what trn1 has inserted. Then crash,
+   Checkpoint record says that trn1 was not committed, and REDO phase starts
+   from Checkpoint record's LSN. So it will not find the COMMIT record of
+   trn1, will want to roll back trn1, which will fail because the row/key
+   which it wants to delete does not exist anymore.
+   To avoid this, Checkpoint needs to know that the REDO phase must start
+   before this COMMIT record, so transaction sets its rec_lsn to the COMMIT's
+   record LSN, and as Checkpoint reads the transaction's rec_lsn, Checkpoint
+   will know.
+
+   @note so after commit trn->rec_lsn is a "commit LSN", which could be of
+   use later.
+
+   @return Operation status, always 0 (success)
+*/
+
+my_bool write_hook_for_commit(enum translog_record_type type
+                              __attribute__ ((unused)),
+                              TRN *trn,
+                              MARIA_HA *tbl_info
+                              __attribute__ ((unused)),
+                              LSN *lsn,
+                              void *hook_arg
+                              __attribute__ ((unused)))
+{
+  trn->rec_lsn= *lsn;
+  return 0;
+}
+
+
 /***************************************************************************
   Applying of REDO log records
 ***************************************************************************/

=== modified file 'storage/maria/ma_blockrec.h'
--- a/storage/maria/ma_blockrec.h	2008-10-14 09:38:07 +0000
+++ b/storage/maria/ma_blockrec.h	2008-12-05 21:11:46 +0000
@@ -271,6 +271,9 @@ my_bool write_hook_for_undo_bulk_insert(
 my_bool write_hook_for_file_id(enum translog_record_type type,
                                TRN *trn, MARIA_HA *tbl_info, LSN *lsn,
                                void *hook_arg);
+my_bool write_hook_for_commit(enum translog_record_type type,
+                              TRN *trn, MARIA_HA *tbl_info, LSN *lsn,
+                              void *hook_arg);
 void _ma_block_get_status(void* param, my_bool concurrent_insert);
 void _ma_block_update_status(void *param);
 void _ma_block_restore_status(void *param);

=== modified file 'storage/maria/ma_checkpoint.c'
--- a/storage/maria/ma_checkpoint.c	2008-08-28 18:52:23 +0000
+++ b/storage/maria/ma_checkpoint.c	2008-12-09 09:56:02 +0000
@@ -784,10 +784,8 @@ static int collect_tables(LEX_STRING *st
         !(share->in_checkpoint & MARIA_CHECKPOINT_SEEN_IN_LOOP))
     {
       /*
-        Why we didn't take intern_lock above: table had in_checkpoint==0 so no
-        thread could set in_checkpoint. And no thread needs to know that we
-        are setting in_checkpoint, because only maria_close() needs it and
-        cannot run now as we hold THR_LOCK_maria.
+        Apart from us, only maria_close() reads/sets in_checkpoint but cannot
+        run now as we hold THR_LOCK_maria.
       */
       /*
         This table is relevant for checkpoint and not already seen. Mark it,
@@ -887,7 +885,10 @@ static int collect_tables(LEX_STRING *st
     my_bool ignore_share;
     if (!(share->in_checkpoint & MARIA_CHECKPOINT_LOOKS_AT_ME))
     {
-      /* No need for a mutex to read the above, only us can write this flag */
+      /*
+        No need for a mutex to read the above, only us can write *this* bit of
+        the in_checkpoint bitmap
+      */
       continue;
     }
     /**
@@ -956,6 +957,14 @@ static int collect_tables(LEX_STRING *st
 
     /* OS file descriptors are ints which we stored in 4 bytes */
     compile_time_assert(sizeof(int) <= 4);
+    /*
+      Protect against maria_close() (which does some memory freeing in
+      MARIA_FILE_BITMAP) with close_lock. intern_lock is not
+      sufficient as we, as well as maria_close(), are going to unlock
+      intern_lock in the middle of manipulating the table. Serializing us and
+      maria_close() should help avoid problems.
+    */
+    pthread_mutex_lock(&share->close_lock);
     pthread_mutex_lock(&share->intern_lock);
     /*
       Tables in a normal state have their two file descriptors open.
@@ -1045,6 +1054,20 @@ static int collect_tables(LEX_STRING *st
           each checkpoint if the table was once written and then not anymore.
         */
       }
+    }
+    /*
+      _ma_bitmap_flush_all() may wait, so don't keep intern_lock as
+      otherwise this would deadlock with allocate_and_write_block_record()
+      calling _ma_set_share_data_file_length()
+    */
+    pthread_mutex_unlock(&share->intern_lock);
+    
+    if (!ignore_share)
+    {
+      /*
+        share->bitmap is valid because it's destroyed under close_lock which
+        we hold.
+      */
       if (_ma_bitmap_flush_all(share))
       {
         sync_error= 1;
@@ -1057,23 +1080,28 @@ static int collect_tables(LEX_STRING *st
       Clean up any unused states.
       TODO: Only do this call if there has been # (10?) ended transactions
       since last call.
+      We had to release intern_lock to respect lock order with LOCK_trn_list.
     */
-    pthread_mutex_unlock(&share->intern_lock);
-    _ma_remove_not_visible_states_with_lock(share);
-    pthread_mutex_lock(&share->intern_lock);
+    _ma_remove_not_visible_states_with_lock(share, FALSE);
 
     if (share->in_checkpoint & MARIA_CHECKPOINT_SHOULD_FREE_ME)
     {
-      /* maria_close() left us to free the share */
-      pthread_mutex_unlock(&share->intern_lock);
+      /*
+        maria_close() left us free the share. When it run it set share->id
+        to 0. As it run before we locked close_lock, we should have seen this
+        and so this assertion should be true:
+      */
+      DBUG_ASSERT(ignore_share);
       pthread_mutex_destroy(&share->intern_lock);
+      pthread_mutex_unlock(&share->close_lock);
+      pthread_mutex_destroy(&share->close_lock);
       my_free((uchar *)share, MYF(0));
     }
     else
     {
       /* share goes back to normal state */
       share->in_checkpoint= 0;
-      pthread_mutex_unlock(&share->intern_lock);
+      pthread_mutex_unlock(&share->close_lock);
     }
 
     /*

=== modified file 'storage/maria/ma_close.c'
--- a/storage/maria/ma_close.c	2008-12-04 21:02:09 +0000
+++ b/storage/maria/ma_close.c	2008-12-09 13:11:48 +0000
@@ -46,6 +46,7 @@ int maria_close(register MARIA_HA *info)
     if (maria_lock_database(info,F_UNLCK))
       error=my_errno;
   }
+  pthread_mutex_lock(&share->close_lock);
   pthread_mutex_lock(&share->intern_lock);
 
   if (share->options & HA_OPTION_READ_ONLY_DATA)
@@ -124,22 +125,30 @@ int maria_close(register MARIA_HA *info)
     }
 #endif
     DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
-    if (share->in_checkpoint == MARIA_CHECKPOINT_LOOKS_AT_ME)
+    /*
+      We assign -1 because checkpoint does not need to flush (in case we
+      have concurrent checkpoint if no then we do not need it here also)
+    */
+    share->kfile.file= -1;
+
+    /*
+      Remember share->history for future opens
+
+      We have to unlock share->intern_lock then lock it after
+      LOCK_trn_list (trnman_lock()) to avoid dead locks.
+    */
+    pthread_mutex_unlock(&share->intern_lock);
+    _ma_remove_not_visible_states_with_lock(share, TRUE);
+    pthread_mutex_lock(&share->intern_lock);
+
+    if (share->in_checkpoint & MARIA_CHECKPOINT_LOOKS_AT_ME)
     {
-      share->kfile.file= -1; /* because Checkpoint does not need to flush */
       /* we cannot my_free() the share, Checkpoint would see a bad pointer */
       share->in_checkpoint|= MARIA_CHECKPOINT_SHOULD_FREE_ME;
     }
     else
       share_can_be_freed= TRUE;
 
-    /*
-      Remember share->history for future opens
-      Here we take share->intern_lock followed by trans_lock but this is
-      safe as no other thread one can use 'share' here.
-    */
-    share->state_history= _ma_remove_not_visible_states(share->state_history,
-                                                        1, 0);
     if (share->state_history)
     {
       MARIA_STATE_HISTORY_CLOSED *history;
@@ -160,10 +169,17 @@ int maria_close(register MARIA_HA *info)
   }
   pthread_mutex_unlock(&THR_LOCK_maria);
   pthread_mutex_unlock(&share->intern_lock);
+  pthread_mutex_unlock(&share->close_lock);
   if (share_can_be_freed)
   {
-    (void)(pthread_mutex_destroy(&share->intern_lock));
+    (void) pthread_mutex_destroy(&share->intern_lock);
+    (void) pthread_mutex_destroy(&share->close_lock);
     my_free((uchar *)share, MYF(0));
+    /*
+      If share cannot be freed, it's because checkpoint has previously
+      recorded to include this share in the checkpoint and so is soon going to
+      look at some of its content (share->in_checkpoint/id/last_version).
+    */
   }
   my_free(info->ftparser_param, MYF(MY_ALLOW_ZERO_PTR));
   if (info->dfile.file >= 0)

=== modified file 'storage/maria/ma_commit.c'
--- a/storage/maria/ma_commit.c	2008-10-09 20:03:54 +0000
+++ b/storage/maria/ma_commit.c	2008-12-05 21:11:46 +0000
@@ -33,6 +33,7 @@ int ma_commit(TRN *trn)
   LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS];
   DBUG_ENTER("ma_commit");
 
+  DBUG_ASSERT(trn->rec_lsn == LSN_IMPOSSIBLE);
   if (trn->undo_lsn == 0) /* no work done, rollback (cheaper than commit) */
     DBUG_RETURN(trnman_rollback_trn(trn));
   /*
@@ -61,8 +62,14 @@ int ma_commit(TRN *trn)
                              trn, NULL, 0,
                              sizeof(log_array)/sizeof(log_array[0]),
                              log_array, NULL, NULL) |
-        translog_flush(commit_lsn) |
-        trnman_commit_trn(trn));
+        translog_flush(commit_lsn));
+
+  DBUG_EXECUTE_IF("maria_sleep_in_commit",
+                  {
+                    DBUG_PRINT("info", ("maria_sleep_in_commit"));
+                    sleep(3);
+                  });
+  res|= trnman_commit_trn(trn);
 
 
   /*

=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c	2008-12-04 21:02:09 +0000
+++ b/storage/maria/ma_loghandler.c	2008-12-09 13:11:48 +0000
@@ -618,11 +618,11 @@ static LOG_DESC INIT_LOGREC_PREPARE_WITH
 
 static LOG_DESC INIT_LOGREC_COMMIT=
 {LOGRECTYPE_FIXEDLENGTH, 0, 0, NULL,
- NULL, NULL, 0, "commit", LOGREC_IS_GROUP_ITSELF, NULL,
+ write_hook_for_commit, NULL, 0, "commit", LOGREC_IS_GROUP_ITSELF, NULL,
  NULL};
 
 static LOG_DESC INIT_LOGREC_COMMIT_WITH_UNDO_PURGE=
-{LOGRECTYPE_PSEUDOFIXEDLENGTH, 5, 5, NULL, NULL, NULL, 1,
+{LOGRECTYPE_PSEUDOFIXEDLENGTH, 5, 5, NULL, write_hook_for_commit, NULL, 1,
  "commit_with_undo_purge", LOGREC_IS_GROUP_ITSELF, NULL, NULL};
 
 static LOG_DESC INIT_LOGREC_CHECKPOINT=
@@ -1404,18 +1404,21 @@ LSN translog_get_file_max_lsn_stored(uin
   SYNOPSIS
     translog_buffer_init()
     buffer               The buffer to initialize
+    num                  Number of this buffer
 
   RETURN
     0  OK
     1  Error
 */
 
-static my_bool translog_buffer_init(struct st_translog_buffer *buffer)
+static my_bool translog_buffer_init(struct st_translog_buffer *buffer, int num)
 {
   DBUG_ENTER("translog_buffer_init");
   buffer->prev_last_lsn= buffer->last_lsn= LSN_IMPOSSIBLE;
   DBUG_PRINT("info", ("last_lsn  and prev_last_lsn set to 0  buffer: 0x%lx",
                       (ulong) buffer));
+
+  buffer->buffer_no= (uint8) num;
   /* This Buffer File */
   buffer->file= NULL;
   buffer->overlay= 0;
@@ -1430,10 +1433,23 @@ static my_bool translog_buffer_init(stru
   buffer->copy_to_buffer_in_progress= 0;
   /* list of waiting buffer ready threads */
   buffer->waiting_flush= 0;
-  /* lock for the buffer. Current buffer also lock the handler */
+  /*
+    Buffers locked by fallowing mutex. As far as buffers create logical
+    circle (after last buffer goes first) it trigger false alarm of deadlock
+    detect system, so we remove check of deadlock for this buffers. In deed
+    all mutex locks concentrated around current buffer except flushing
+    thread (but it is only one thread). One thread can't take more then
+    2 buffer locks at once. So deadlock is impossible here.
+
+    To prevent false alarm of dead lock detection we switch dead lock
+    detection for one buffer in the middle of the buffers chain. Excluding
+    only one of eight buffers from deadlock detection hardly can hide other
+    possible problems which include this mutexes.
+  */
   if (my_pthread_mutex_init(&buffer->mutex, MY_MUTEX_INIT_FAST,
                             "translog_buffer->mutex",
-                            MYF_NO_DEADLOCK_DETECTION) ||
+                            (num == TRANSLOG_BUFFERS_NO - 2 ?
+                             MYF_NO_DEADLOCK_DETECTION : 0)) ||
       pthread_cond_init(&buffer->prev_sent_to_disk_cond, 0))
     DBUG_RETURN(1);
   buffer->is_closing_buffer= 0;
@@ -3555,9 +3571,8 @@ my_bool translog_init_with_table(const c
   /* Buffers for log writing */
   for (i= 0; i < TRANSLOG_BUFFERS_NO; i++)
   {
-    if (translog_buffer_init(log_descriptor.buffers + i))
+    if (translog_buffer_init(log_descriptor.buffers + i, i))
       goto err;
-    log_descriptor.buffers[i].buffer_no= (uint8) i;
     DBUG_PRINT("info", ("translog_buffer buffer #%u: 0x%lx",
                         i, (ulong) log_descriptor.buffers + i));
   }

=== modified file 'storage/maria/ma_open.c'
--- a/storage/maria/ma_open.c	2008-11-20 19:18:59 +0000
+++ b/storage/maria/ma_open.c	2008-12-09 13:11:48 +0000
@@ -809,7 +809,7 @@ MARIA_HA *maria_open(const char *name, i
         if (!(share->state_history= (MARIA_STATE_HISTORY *)
               my_malloc(sizeof(*share->state_history), MYF(MY_WME))))
           goto err;
-        share->state_history->trid= 0;          /* Visibly by all */
+        share->state_history->trid= 0;          /* Visible by all */
         share->state_history->state= share->state.state;
         share->state_history->next= 0;
       }
@@ -819,6 +819,7 @@ MARIA_HA *maria_open(const char *name, i
     pthread_mutex_init(&share->intern_lock, MY_MUTEX_INIT_FAST);
     pthread_mutex_init(&share->key_del_lock, MY_MUTEX_INIT_FAST);
     pthread_cond_init(&share->key_del_cond, 0);
+    pthread_mutex_init(&share->close_lock, MY_MUTEX_INIT_FAST);
     for (i=0; i<keys; i++)
       (void)(my_rwlock_init(&share->keyinfo[i].root_lock, NULL));
     (void)(my_rwlock_init(&share->mmap_lock, NULL));

=== modified file 'storage/maria/ma_recovery.c'
--- a/storage/maria/ma_recovery.c	2008-11-24 18:40:52 +0000
+++ b/storage/maria/ma_recovery.c	2008-12-09 13:11:48 +0000
@@ -555,8 +555,9 @@ static void new_transaction(uint16 sid, 
   char llbuf[22];
   all_active_trans[sid].long_trid= long_id;
   llstr(long_id, llbuf);
-  tprint(tracef, "Transaction long_trid %s short_trid %u starts\n",
-         llbuf, sid);
+  tprint(tracef, "Transaction long_trid %s short_trid %u starts,"
+         " undo_lsn (%lu,0x%lx) first_undo_lsn (%lu,0x%lx)\n",
+         llbuf, sid, LSN_IN_PARTS(undo_lsn), LSN_IN_PARTS(first_undo_lsn));
   all_active_trans[sid].undo_lsn= undo_lsn;
   all_active_trans[sid].first_undo_lsn= first_undo_lsn;
   set_if_bigger(max_long_trid, long_id);
@@ -2968,6 +2969,8 @@ static LSN parse_checkpoint_record(LSN l
   ptr= log_record_buffer.str;
   start_address= lsn_korr(ptr);
   ptr+= LSN_STORE_SIZE;
+  tprint(tracef, "Checkpoint record has start_horizon at (%lu,0x%lx)\n",
+         LSN_IN_PARTS(start_address));
 
   /* transactions */
   nb_active_transactions= uint2korr(ptr);
@@ -2983,6 +2986,9 @@ static LSN parse_checkpoint_record(LSN l
     line. It may make start_address slightly decrease (only by the time it
     takes to write one or a few rows, roughly).
   */
+  tprint(tracef, "Checkpoint record has min_rec_lsn of active transactions"
+         " at (%lu,0x%lx)\n",
+         LSN_IN_PARTS(minimum_rec_lsn_of_active_transactions));
   set_if_smaller(start_address, minimum_rec_lsn_of_active_transactions);
 
   for (i= 0; i < nb_active_transactions; i++)
@@ -3086,6 +3092,8 @@ static LSN parse_checkpoint_record(LSN l
   */
   start_address= checkpoint_start=
     translog_next_LSN(start_address, LSN_IMPOSSIBLE);
+  tprint(tracef, "Checkpoint record start_horizon now adjusted to"
+         " LSN (%lu,0x%lx)\n", LSN_IN_PARTS(start_address));
   if (checkpoint_start == LSN_IMPOSSIBLE)
   {
     /*
@@ -3095,6 +3103,8 @@ static LSN parse_checkpoint_record(LSN l
     return LSN_ERROR;
   }
   /* now, where the REDO phase should start reading log: */
+  tprint(tracef, "Checkpoint has min_rec_lsn of dirty pages at"
+         " LSN (%lu,0x%lx)\n", LSN_IN_PARTS(minimum_rec_lsn_of_dirty_pages));
   set_if_smaller(start_address, minimum_rec_lsn_of_dirty_pages);
   DBUG_PRINT("info",
              ("checkpoint_start: (%lu,0x%lx) start_address: (%lu,0x%lx)",
@@ -3266,6 +3276,8 @@ void _ma_tmp_disable_logging_for_table(M
 /**
    Re-enables logging for a table which had it temporarily disabled.
 
+   Only the thread which disabled logging is allowed to reenable it.
+
    @param  info            table
    @param  flush_pages     if function needs to flush pages first
 */

=== modified file 'storage/maria/ma_state.c'
--- a/storage/maria/ma_state.c	2008-12-02 22:02:52 +0000
+++ b/storage/maria/ma_state.c	2008-12-08 20:12:23 +0000
@@ -166,7 +166,6 @@ MARIA_STATE_HISTORY
 
   if (all && parent == &org_history->next)
   {
-    DBUG_ASSERT(trnman_is_locked == 0);
     /* There is only one state left. Delete this if it's visible for all */
     if (last_trid < trnman_get_min_trid())
     {
@@ -181,6 +180,11 @@ MARIA_STATE_HISTORY
 /**
    @brief Remove not used state history
 
+   @param share          Maria table information
+   @param all            1 if we should delete the first state if it's
+                         visible for all.  For the moment this is only used
+                         on close() of table.
+
    @notes
    share and trnman are not locked.
 
@@ -189,14 +193,19 @@ MARIA_STATE_HISTORY
    takes share->intern_lock.
 */
 
-void _ma_remove_not_visible_states_with_lock(MARIA_SHARE *share)
+void _ma_remove_not_visible_states_with_lock(MARIA_SHARE *share,
+                                             my_bool all)
 {
-  trnman_lock();
+  my_bool is_lock_trman;
+  if ((is_lock_trman= trman_is_inited()))
+    trnman_lock();
+
   pthread_mutex_lock(&share->intern_lock);
-  share->state_history=  _ma_remove_not_visible_states(share->state_history, 0,
-                                                       1);
+  share->state_history=  _ma_remove_not_visible_states(share->state_history,
+                                                       all, 1);
   pthread_mutex_unlock(&share->intern_lock);
-  trnman_unlock();
+  if (is_lock_trman)
+    trnman_unlock();
 }
 
 

=== modified file 'storage/maria/ma_state.h'
--- a/storage/maria/ma_state.h	2008-11-03 13:53:22 +0000
+++ b/storage/maria/ma_state.h	2008-12-08 20:09:59 +0000
@@ -78,6 +78,7 @@ my_bool _ma_trnman_end_trans_hook(TRN *t
 my_bool _ma_row_visible_always(MARIA_HA *info);
 my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info);
 my_bool _ma_row_visible_transactional_table(MARIA_HA *info);
-void _ma_remove_not_visible_states_with_lock(struct st_maria_share *share);
+void _ma_remove_not_visible_states_with_lock(struct st_maria_share *share,
+                                             my_bool all);
 void _ma_remove_table_from_trnman(struct st_maria_share *share, TRN *trn);
 void _ma_reset_history(struct st_maria_share *share);

=== modified file 'storage/maria/maria_def.h'
--- a/storage/maria/maria_def.h	2008-11-24 07:48:21 +0000
+++ b/storage/maria/maria_def.h	2008-12-09 09:56:02 +0000
@@ -353,7 +353,7 @@ typedef struct st_maria_share
   PAGECACHE_FILE kfile;			/* Shared keyfile */
   File data_file;			/* Shared data file */
   int mode;				/* mode of file on open */
-  uint reopen;				/* How many times reopened */
+  uint reopen;				/* How many times opened */
   uint in_trans;                        /* Number of references by trn */
   uint w_locks, r_locks, tot_locks;	/* Number of read/write locks */
   uint block_size;			/* block_size of keyfile & data file*/
@@ -362,7 +362,10 @@ typedef struct st_maria_share
   myf write_flag;
   enum data_file_type data_file_type;
   enum pagecache_page_type page_type;   /* value depending transactional */
-  uint8 in_checkpoint;               /**< if Checkpoint looking at table */
+  /**
+     if Checkpoint looking at table; protected by close_lock or THR_LOCK_maria
+  */
+  uint8 in_checkpoint;
   my_bool temporary;
   /* Below flag is needed to make log tables work with concurrent insert */
   my_bool is_log_table;
@@ -386,9 +389,20 @@ typedef struct st_maria_share
 #ifdef THREAD
   THR_LOCK lock;
   void (*lock_restore_status)(void *);
-  pthread_mutex_t intern_lock;		/* Locking for use with _locking */
+  /**
+    Protects kfile, dfile, most members of the state, state disk writes,
+    versioning information (like in_trans, state_history).
+    @todo find the exhaustive list.
+  */
+  pthread_mutex_t intern_lock;	
   pthread_mutex_t key_del_lock;
   pthread_cond_t  key_del_cond;
+  /**
+    _Always_ held while closing table; prevents checkpoint from looking at
+    structures freed during closure (like bitmap). If you need close_lock and
+    intern_lock, lock them in this order.
+  */
+  pthread_mutex_t close_lock;
 #endif
   my_off_t mmaped_length;
   uint nonmmaped_inserts;		/* counter of writing in

=== modified file 'storage/maria/trnman.c'
--- a/storage/maria/trnman.c	2008-11-20 14:11:00 +0000
+++ b/storage/maria/trnman.c	2008-12-08 20:12:23 +0000
@@ -261,6 +261,7 @@ TRN *trnman_new_trn(WT_THD *wt)
 {
   int res;
   TRN *trn;
+  union { TRN *trn; void *v; } tmp;
   DBUG_ENTER("trnman_new_trn");
 
   /*
@@ -276,19 +277,19 @@ TRN *trnman_new_trn(WT_THD *wt)
   pthread_mutex_lock(&LOCK_trn_list);
 
   /* Allocating a new TRN structure */
-  trn= pool;
+  tmp.trn= pool;
   /*
     Popping an unused TRN from the pool
     (ABA isn't possible, we're behind a mutex
   */
   my_atomic_rwlock_wrlock(&LOCK_pool);
-  while (trn && !my_atomic_casptr((void **)&pool, (void **)&trn,
-                                  (void *)trn->next))
+  while (tmp.trn && !my_atomic_casptr((void **)&pool, &tmp.v,
+                                  (void *)tmp.trn->next))
     /* no-op */;
   my_atomic_rwlock_wrunlock(&LOCK_pool);
 
   /* Nothing in the pool ? Allocate a new one */
-  if (!trn)
+  if (!(trn= tmp.trn))
   {
     /*
       trn should be completely initalized at create time to allow
@@ -359,7 +360,7 @@ TRN *trnman_new_trn(WT_THD *wt)
     return 0;
   }
 
-  DBUG_PRINT("exit", ("trn: x%lx  trid: 0x%lu",
+  DBUG_PRINT("exit", ("trn: 0x%lx  trid: 0x%lu",
                       (ulong) trn, (ulong) trn->trid));
 
   DBUG_RETURN(trn);
@@ -385,11 +386,12 @@ TRN *trnman_new_trn(WT_THD *wt)
 my_bool trnman_end_trn(TRN *trn, my_bool commit)
 {
   int res= 1;
+  uint16 cached_short_id= trn->short_id; /* we have to cache it, see below */
   TRN *free_me= 0;
   LF_PINS *pins= trn->pins;
   DBUG_ENTER("trnman_end_trn");
+  DBUG_PRINT("enter", ("trn=0x%lx commit=%d", (ulong) trn, commit));
 
-  DBUG_ASSERT(trn->rec_lsn == 0);
   /* if a rollback, all UNDO records should have been executed */
   DBUG_ASSERT(commit || trn->undo_lsn == 0);
   DBUG_PRINT("info", ("pthread_mutex_lock LOCK_trn_list"));
@@ -454,11 +456,17 @@ my_bool trnman_end_trn(TRN *trn, my_bool
     res= -1;
   trnman_active_transactions--;
 
+  DBUG_PRINT("info", ("pthread_mutex_unlock LOCK_trn_list"));
   pthread_mutex_unlock(&LOCK_trn_list);
 
-  /* the rest is done outside of a critical section */
+  /*
+    the rest is done outside of a critical section
+
+    note that we don't own trn anymore, it may be in a shared list now.
+    Thus, we cannot dereference it, and must use cached_short_id below.
+  */
   my_atomic_rwlock_rdlock(&LOCK_short_trid_to_trn);
-  my_atomic_storeptr((void **)&short_trid_to_active_trn[trn->short_id], 0);
+  my_atomic_storeptr((void **)&short_trid_to_active_trn[cached_short_id], 0);
   my_atomic_rwlock_rdunlock(&LOCK_short_trid_to_trn);
 
   /*
@@ -503,7 +511,6 @@ void trnman_free_trn(TRN *trn)
   */
   union { TRN *trn; void *v; } tmp;
 
-
   pthread_mutex_lock(&trn->state_lock);
   trn->short_id= 0;
   pthread_mutex_unlock(&trn->state_lock);
@@ -874,6 +881,7 @@ my_bool trnman_exists_active_transaction
 
   if (!trnman_is_locked)
     pthread_mutex_lock(&LOCK_trn_list);
+  safe_mutex_assert_owner(&LOCK_trn_list);
   for (trn= active_list_min.next; trn != &active_list_max; trn= trn->next)
   {
     if (trn->trid > min_id && trn->trid < max_id)
@@ -897,6 +905,7 @@ void trnman_lock()
   pthread_mutex_lock(&LOCK_trn_list);
 }
 
+
 /**
    unlock transaction list
 */
@@ -905,3 +914,13 @@ void trnman_unlock()
 {
   pthread_mutex_unlock(&LOCK_trn_list);
 }
+
+
+/**
+  Is trman initialized
+*/
+
+my_bool trman_is_inited()
+{
+  return (short_trid_to_active_trn != NULL);
+}

=== modified file 'storage/maria/trnman_public.h'
--- a/storage/maria/trnman_public.h	2008-08-07 20:57:25 +0000
+++ b/storage/maria/trnman_public.h	2008-12-08 20:09:59 +0000
@@ -69,5 +69,6 @@ my_bool trnman_exists_active_transaction
 #define transid_korr(P) uint6korr(P)
 void trnman_lock();
 void trnman_unlock();
+my_bool trman_is_inited();
 C_MODE_END
 #endif

Thread
bzr commit into mysql-6.0 branch (guilhem:2927) Guilhem Bichot9 Dec