List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:March 21 2011 3:56pm
Subject:bzr commit into mysql-trunk branch (alfranio.correia:3773) WL#4832
View as plain text  
#At file:///home/acorreia/workspace.oracle/repository.mysql/bzrwork/wl-4832/mysql-trunk/ based on revid:alfranio.correia@stripped

 3773 Alfranio Correia	2011-03-21
      WL#4832
      
      Refactored the code to make the Log events to go through a cache before
      being written to the binary log. In particular, after the WL#2687 only
      Query Log Events with DDLS, BEGIN, COMMIT and ROLLBACK, Incident Events
      and Rotate Events were written directly to the binary log without
      going through a cache.
      
      After this WL, only Incident Events and Rotate Events are still written
      directly to the binary log.
     @ mysql-test/extra/binlog_tests/binlog_cache_stat.test
        Updated test case because DDLs go through the stmt-cache before being flushed.
     @ mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test
        Updated test case because DDLs go through the stmt-cache before being flushed.
     @ mysql-test/r/read_only_innodb.result
        Fixed problem with BUG#11763126.
     @ mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result
        Updated test case because DDLs go through the stmt-cache before being flushed.
     @ mysql-test/suite/binlog/r/binlog_row_cache_stat.result
        Updated test case because DDLs go through the stmt-cache before being flushed.
     @ mysql-test/suite/binlog/r/binlog_stm_cache_stat.result
        Updated test case because DDLs go through the stmt-cache before being flushed.
     @ mysql-test/suite/rpl/r/rpl_crash_safe_master.result
        The debug option was set before calling CREATE TABLE t2 causing an unexpected crash.
        This started happening because the CREATE TABLE now goes to the cache where the
        debug option causes a suicide.
     @ mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result
        Updated test case because DDLs go through the stmt-cache before being flushed.
     @ mysql-test/suite/rpl/t/rpl_crash_safe_master.test
        The debug option was set before calling CREATE TABLE t2 causing an unexpected crash.
        This started happening because the CREATE TABLE now goes to the cache where the
        debug option causes a suicide.
     @ sql/binlog.cc
        The following changes were made:
        
          . "BEGIN" is appended to either the trx- or stmt-cache when a transaction begins.
               
         
          . "COMMIT/ROLLBACK" is appened to either the trx- or stmt-cache when a transaction ends.
                
          . DDLs go through the stmt-cache but are immediately written to the binary.
                
          . The code that decides which cache should be used was refactored and
          simplified.
     @ sql/binlog.h
        use_trans_cache was merged into Query_log_event::Query_log_event and
        write_incident(Incident_log_event *ev, bool lock) was created.
     @ sql/log_event.cc
        The routine that decides which cache should be used was improved by
        merging code from the binlog.cc in order to ease maintenance and
        improve supportability.
     @ sql/log_event.h
        Created two different variables to denoate when a change should go
        through a cache or not and when it should be written to the binary
        log.
                
        The first variable, event_cache_type, may assume:
                
          . EVENT_NO_CACHE
          . EVENT_STMT_CACHE
          . EVENT_TRANSACTIONAL_CACHE
                
        The variable, event_logging_type, may assume:
                
          . EVENT_NORMAL_LOGGING
          . EVENT_IMMEDIATE_LOGGING
                
        Any event that does not go through a cache, such as an
        Incident or a Rotate event, is tagged as
                
          . EVENT_NO_CACHE and EVENT_IMMEDIATE_LOGGING
        
        Query Log Events go through a cache and may be immediately written to the
        binary log or written to it upon commit/rollback. In particular,
        
          . DDLS are tagged as EVENT_STMT_CACHE and EVENT_IMMEDIATE_LOGGING
        
        The remaining queries and events are tagged as:
        
          . EVENT_STMT_CACHE or EVENT_TRANSACTIONAL_CACHE and
            EVENT_NORMAL_LOGGING
        
        Changed 
        
          . use_trans_cache to is_using_trans_cache
          . use_cache to is_using_stmt_cache
          . used_direct_logging to is_using_immediate_logging
        
        in order to improve readability.
     @ sql/log_event_old.cc
        Changed use_trans_cache to is_using_trans_cache to improve readability.
     @ sql/rpl_injector.cc
        When an incident event is logged rotation is automatically forced.
     @ sql/sql_class.h
        Removed these member functions from the THD as they are now local to
        the MYSQL_BIN_LOG after its improvement.
     @ sql/sql_insert.cc
        Removed this unecessary code after improving MYSQL_BIN_LOG as
        an optimized version of binlog_start_trans_and_stmt is now
        called for each event if RBR is in use.
     @ sql/sql_parse.cc
        When an incident event is logged rotation is automatically forced.

    modified:
      mysql-test/extra/binlog_tests/binlog_cache_stat.test
      mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test
      mysql-test/r/read_only_innodb.result
      mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result
      mysql-test/suite/binlog/r/binlog_row_cache_stat.result
      mysql-test/suite/binlog/r/binlog_stm_cache_stat.result
      mysql-test/suite/rpl/r/rpl_crash_safe_master.result
      mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result
      mysql-test/suite/rpl/t/rpl_crash_safe_master.test
      sql/binlog.cc
      sql/binlog.h
      sql/log_event.cc
      sql/log_event.h
      sql/log_event_old.cc
      sql/rpl_injector.cc
      sql/sql_class.h
      sql/sql_insert.cc
      sql/sql_parse.cc
=== modified file 'mysql-test/extra/binlog_tests/binlog_cache_stat.test'
--- a/mysql-test/extra/binlog_tests/binlog_cache_stat.test	2010-11-05 17:42:37 +0000
+++ b/mysql-test/extra/binlog_tests/binlog_cache_stat.test	2011-03-21 15:56:26 +0000
@@ -20,13 +20,13 @@ create table t2 (a int) engine=myisam;
 #
 --echo **** Preparing the enviroment to check commit and its effect on status variables.
 --echo **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 let $exp_cache= 0;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 0;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -39,7 +39,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 
 --echo **** Transactional changes which are long enough so they will be flushed to disk...
 --echo **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 let $1=2000;
 disable_query_log;
 begin;
@@ -54,7 +54,7 @@ let $exp_cache= 1;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -68,7 +68,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Transactional changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 commit;
@@ -76,7 +76,7 @@ let $exp_cache= 2;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -90,7 +90,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Non-Transactional changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 commit;
@@ -98,7 +98,7 @@ let $exp_cache= 2;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 1;
+let $exp_stmt_cache= 2;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -112,7 +112,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Mixed changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
@@ -121,7 +121,7 @@ let $exp_cache= 3;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 2;
+let $exp_stmt_cache= 3;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -137,13 +137,13 @@ if (`SELECT $got_cache <> $exp_cache ||
 #
 --echo **** Preparing the enviroment to check abort and its effect on the status variables.
 --echo **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 let $exp_cache= 0;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 0;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -156,7 +156,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 
 --echo **** Transactional changes which are long enough so they will be flushed to disk...
 --echo **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 let $1=2000;
 disable_query_log;
 begin;
@@ -171,7 +171,7 @@ let $exp_cache= 1;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -185,7 +185,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Transactional changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 rollback;
@@ -193,7 +193,7 @@ let $exp_cache= 2;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 0;
+let $exp_stmt_cache= 1;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -207,7 +207,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Non-Transactional changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 rollback;
@@ -215,7 +215,7 @@ let $exp_cache= 2;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 1;
+let $exp_stmt_cache= 2;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);
@@ -229,7 +229,7 @@ if (`SELECT $got_cache <> $exp_cache ||
 --echo **** Mixed changes which should not be flushed to disk and so should not
 --echo **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 --echo **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
---echo **** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+--echo **** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
@@ -238,7 +238,7 @@ let $exp_cache= 3;
 let $got_cache= query_get_value(show status like "binlog_cache_use", Value, 1);
 let $exp_disk= 1;
 let $got_disk= query_get_value(show status like "binlog_cache_disk_use", Value, 1);
-let $exp_stmt_cache= 2;
+let $exp_stmt_cache= 3;
 let $got_stmt_cache= query_get_value(show status like "binlog_stmt_cache_use", Value, 1);
 let $exp_stmt_disk= 0;
 let $got_stmt_disk= query_get_value(show status like "binlog_stmt_cache_disk_use", Value, 1);

=== modified file 'mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test'
--- a/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test	2011-02-23 20:01:27 +0000
+++ b/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test	2011-03-21 15:56:26 +0000
@@ -423,10 +423,6 @@ COMMIT;
 
 --connection slave
 --let $slave_sql_errno= 1197
-if (`SELECT @@binlog_format = 'ROW'`)
-{
-  --let $slave_sql_errno= 1534
-}
 source include/wait_for_slave_sql_error.inc;
 
 SELECT count(*) FROM t1;

=== modified file 'mysql-test/r/read_only_innodb.result'
--- a/mysql-test/r/read_only_innodb.result	2011-03-16 16:41:46 +0000
+++ b/mysql-test/r/read_only_innodb.result	2011-03-21 15:56:26 +0000
@@ -97,7 +97,7 @@ a
 2
 ROLLBACK;
 Warnings:
-Warning	1726	The creation of some temporary tables could not be rolled back.
+Warning	1732	The creation of some temporary tables could not be rolled back.
 SELECT * FROM temp;
 a
 DROP TABLE temp;

=== modified file 'mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result	2010-11-05 17:42:37 +0000
+++ b/mysql-test/suite/binlog/r/binlog_mixed_cache_stat.result	2011-03-21 15:56:26 +0000
@@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
 create table t2 (a int) engine=myisam;
 **** Preparing the enviroment to check commit and its effect on status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 commit;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 commit;
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
 commit;
 **** Preparing the enviroment to check abort and its effect on the status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 rollback;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 rollback;
@@ -56,7 +56,7 @@ Warning	1196	Some non-transactional chan
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );

=== modified file 'mysql-test/suite/binlog/r/binlog_row_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_row_cache_stat.result	2010-11-05 17:42:37 +0000
+++ b/mysql-test/suite/binlog/r/binlog_row_cache_stat.result	2011-03-21 15:56:26 +0000
@@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
 create table t2 (a int) engine=myisam;
 **** Preparing the enviroment to check commit and its effect on status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 commit;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 commit;
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
 commit;
 **** Preparing the enviroment to check abort and its effect on the status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 rollback;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 rollback;
@@ -56,7 +56,7 @@ Warning	1196	Some non-transactional chan
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );

=== modified file 'mysql-test/suite/binlog/r/binlog_stm_cache_stat.result'
--- a/mysql-test/suite/binlog/r/binlog_stm_cache_stat.result	2010-11-05 17:42:37 +0000
+++ b/mysql-test/suite/binlog/r/binlog_stm_cache_stat.result	2011-03-21 15:56:26 +0000
@@ -3,51 +3,51 @@ create table t1 (a int) engine=innodb;
 create table t2 (a int) engine=myisam;
 **** Preparing the enviroment to check commit and its effect on status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 commit;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 commit;
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );
 commit;
 **** Preparing the enviroment to check abort and its effect on the status variables.
 **** Expected: binlog_cache_use = 0, binlog_cache_disk_use = 0.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 flush status;
 **** Transactional changes which are long enough so they will be flushed to disk...
 **** Expected: binlog_cache_use = 1, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 **** Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 rollback;
 **** Non-Transactional changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 2, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 1, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t2 values( 1 );
 rollback;
@@ -56,7 +56,7 @@ Warning	1196	Some non-transactional chan
 **** Mixed changes which should not be flushed to disk and so should not
 **** increase either binlog_cache_disk_use or binlog_stmt_cache_disk_use.
 **** Expected: binlog_cache_use = 3, binlog_cache_disk_use = 1.
-**** Expected: binlog_stmt_cache_use = 2, binlog_stmt_cache_disk_use = 0.
+**** Expected: binlog_stmt_cache_use = 3, binlog_stmt_cache_disk_use = 0.
 begin;
 insert into t1 values( 1 );
 insert into t2 values( 1 );

=== modified file 'mysql-test/suite/rpl/r/rpl_crash_safe_master.result'
--- a/mysql-test/suite/rpl/r/rpl_crash_safe_master.result	2011-01-13 03:14:52 +0000
+++ b/mysql-test/suite/rpl/r/rpl_crash_safe_master.result	2011-03-21 15:56:26 +0000
@@ -65,7 +65,6 @@ include/stop_slave.inc
 CREATE TABLE t1(a LONGBLOB) ENGINE=INNODB;
 # Test case3: Set DEBUG POINT in the middle of binlog to
 #             make the master crash for transaction.
-SET SESSION debug="d,half_binlogged_transaction";
 BEGIN;
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
@@ -91,6 +90,7 @@ INSERT INTO t1 (a) VALUES (REPEAT('a',61
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
 INSERT INTO t1 (a) VALUES (REPEAT('a',6144));
+SET SESSION debug="d,half_binlogged_transaction";
 COMMIT;
 ERROR HY000: Lost connection to MySQL server during query
 # Restart the master server
@@ -106,8 +106,8 @@ COUNT(*)
 0
 # Test case4: Set DEBUG POINT in the middle of binlog to
 #             make the master crash for non-transaction.
-SET SESSION debug="d,half_binlogged_transaction";
 CREATE TABLE t2(a LONGBLOB) ENGINE=MYISAM;
+SET SESSION debug="d,half_binlogged_transaction";
 INSERT INTO t2 (a) VALUES (REPEAT('a',16384));
 ERROR HY000: Lost connection to MySQL server during query
 # Restart the master server

=== modified file 'mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result'
--- a/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result	2011-02-23 20:01:27 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result	2011-03-21 15:56:26 +0000
@@ -150,7 +150,7 @@ SET GLOBAL binlog_stmt_cache_size= ORIGI
 BEGIN;
 Repeat statement 'INSERT INTO t1 VALUES($n, repeat("a", 32))' 128 times
 COMMIT;
-include/wait_for_slave_sql_error.inc [errno=1534]
+include/wait_for_slave_sql_error.inc [errno=1197]
 SELECT count(*) FROM t1;
 count(*)
 0

=== modified file 'mysql-test/suite/rpl/t/rpl_crash_safe_master.test'
--- a/mysql-test/suite/rpl/t/rpl_crash_safe_master.test	2011-02-15 08:25:14 +0000
+++ b/mysql-test/suite/rpl/t/rpl_crash_safe_master.test	2011-03-21 15:56:26 +0000
@@ -135,7 +135,6 @@ CREATE TABLE t1(a LONGBLOB) ENGINE=INNOD
 
 -- echo # Test case3: Set DEBUG POINT in the middle of binlog to
 -- echo #             make the master crash for transaction.
-SET SESSION debug="d,half_binlogged_transaction";
 BEGIN;
 let $rows= 24;
 WHILE($rows)
@@ -145,6 +144,7 @@ WHILE($rows)
 }
 # Write file to make mysql-test-run.pl expect crash and restart
 -- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+SET SESSION debug="d,half_binlogged_transaction";
 # Run the crashing query
 -- error 2013
 COMMIT;
@@ -166,12 +166,12 @@ SELECT COUNT(*) FROM t1;
 
 -- echo # Test case4: Set DEBUG POINT in the middle of binlog to
 -- echo #             make the master crash for non-transaction.
-SET SESSION debug="d,half_binlogged_transaction";
-# Write file to make mysql-test-run.pl expect crash and restart
--- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
 -- let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1)
 -- let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
 CREATE TABLE t2(a LONGBLOB) ENGINE=MYISAM;
+# Write file to make mysql-test-run.pl expect crash and restart
+-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+SET SESSION debug="d,half_binlogged_transaction";
 -- error 2013
 INSERT INTO t2 (a) VALUES (REPEAT('a',16384));
 

=== modified file 'sql/binlog.cc'
--- a/sql/binlog.cc	2011-03-16 16:41:46 +0000
+++ b/sql/binlog.cc	2011-03-21 15:56:26 +0000
@@ -35,6 +35,7 @@ const char *log_bin_basename= 0;
 MYSQL_BIN_LOG mysql_bin_log(&sync_binlog_period);
 
 static int binlog_init(void *p);
+static void binlog_start_trans_and_stmt(THD *thd, Log_event *start_event);
 static int binlog_close_connection(handlerton *hton, THD *thd);
 static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv);
 static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv);
@@ -85,10 +86,17 @@ class binlog_cache_data
 {
 public:
 
-  binlog_cache_data(): m_pending(0),
-  incident(FALSE), saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0),
-  ptr_binlog_cache_disk_use(0)
-  { }
+  binlog_cache_data(bool trx_cache_arg,
+                    ulong max_binlog_cache_size_arg,
+                    ulong *ptr_binlog_cache_use_arg,
+                    ulong *ptr_binlog_cache_disk_use_arg)
+  : trx_cache(trx_cache_arg), m_pending(0), incident(FALSE),
+  saved_max_binlog_cache_size(max_binlog_cache_size_arg),
+  ptr_binlog_cache_use(ptr_binlog_cache_use_arg),
+  ptr_binlog_cache_disk_use(ptr_binlog_cache_disk_use_arg)
+  {
+    cache_log.end_of_file= saved_max_binlog_cache_size;
+  }
   
   virtual ~binlog_cache_data()
   {
@@ -121,6 +129,11 @@ public:
     return(incident);
   }
 
+  bool is_trx_cache()
+  {
+    return trx_cache;
+  }
+
   virtual void reset()
   {
     compute_statistics();
@@ -137,36 +150,6 @@ public:
     DBUG_ASSERT(empty());
   }
 
-  void set_binlog_cache_info(ulong param_max_binlog_cache_size,
-                             ulong *param_ptr_binlog_cache_use,
-                             ulong *param_ptr_binlog_cache_disk_use)
-  {
-    /*
-      The assertions guarantee that the set_binlog_cache_info is
-      called just once and information passed as parameters are
-      never zero.
-
-      This is done while calling the constructor binlog_cache_mngr.
-      We cannot set informaton in the constructor binlog_cache_data
-      because the space for binlog_cache_mngr is allocated through
-      a placement new.
-
-      In the future, we can refactor this and change it to avoid
-      the set_binlog_info. 
-    */
-    DBUG_ASSERT(saved_max_binlog_cache_size == 0 &&
-                param_max_binlog_cache_size != 0 &&
-                ptr_binlog_cache_use == 0 &&
-                param_ptr_binlog_cache_use != 0 &&
-                ptr_binlog_cache_disk_use == 0 &&
-                param_ptr_binlog_cache_disk_use != 0);
-
-    saved_max_binlog_cache_size= param_max_binlog_cache_size;
-    ptr_binlog_cache_use= param_ptr_binlog_cache_use;
-    ptr_binlog_cache_disk_use= param_ptr_binlog_cache_disk_use;
-    cache_log.end_of_file= saved_max_binlog_cache_size;
-  }
-
   /*
     Cache to store data before copying it to the binary log.
   */
@@ -189,6 +172,12 @@ protected:
     cache_log.end_of_file= saved_max_binlog_cache_size;
   }
 
+  /*
+    Defines if this is either a trx-cache or stmt-cache, respectively, a
+    transactional or non-transactional cache.
+  */
+  bool trx_cache;
+
 private:
   /*
     Pending binrows event. This event is the event where the rows are currently
@@ -243,9 +232,16 @@ private:
 class binlog_trx_cache_data : public binlog_cache_data
 {
 public:
-  binlog_trx_cache_data() : m_cannot_rollback(FALSE),
-  before_stmt_pos(MY_OFF_T_UNDEF)
-  {}
+  binlog_trx_cache_data(bool trx_cache_arg,
+                        ulong max_binlog_cache_size_arg,
+                        ulong *ptr_binlog_cache_use_arg,
+                        ulong *ptr_binlog_cache_disk_use_arg)
+  : binlog_cache_data(trx_cache_arg,
+                      max_binlog_cache_size_arg,
+                      ptr_binlog_cache_use_arg,
+                      ptr_binlog_cache_disk_use_arg),
+    m_cannot_rollback(FALSE), before_stmt_pos(MY_OFF_T_UNDEF)
+  {   }
 
   void reset()
   {
@@ -303,24 +299,26 @@ private:
     Binlog position before the start of the current statement.
   */
   my_off_t before_stmt_pos;
+
+  binlog_trx_cache_data& operator=(const binlog_trx_cache_data& info);
+  binlog_trx_cache_data(const binlog_trx_cache_data& info);
 };
 
 class binlog_cache_mngr {
 public:
-  binlog_cache_mngr(ulong param_max_binlog_stmt_cache_size,
-                    ulong param_max_binlog_cache_size,
-                    ulong *param_ptr_binlog_stmt_cache_use,
-                    ulong *param_ptr_binlog_stmt_cache_disk_use,
-                    ulong *param_ptr_binlog_cache_use,
-                    ulong *param_ptr_binlog_cache_disk_use)
-  {
-    stmt_cache.set_binlog_cache_info(param_max_binlog_stmt_cache_size,
-                                     param_ptr_binlog_stmt_cache_use,
-                                     param_ptr_binlog_stmt_cache_disk_use);
-    trx_cache.set_binlog_cache_info(param_max_binlog_cache_size,
-                                    param_ptr_binlog_cache_use,
-                                    param_ptr_binlog_cache_disk_use);
-  }
+  binlog_cache_mngr(ulong max_binlog_stmt_cache_size_arg,
+                    ulong *ptr_binlog_stmt_cache_use_arg,
+                    ulong *ptr_binlog_stmt_cache_disk_use_arg,
+                    ulong max_binlog_cache_size_arg,
+                    ulong *ptr_binlog_cache_use_arg,
+                    ulong *ptr_binlog_cache_disk_use_arg)
+  : stmt_cache(FALSE, max_binlog_stmt_cache_size_arg,
+               ptr_binlog_stmt_cache_use_arg,
+               ptr_binlog_stmt_cache_disk_use_arg),
+    trx_cache(TRUE, max_binlog_cache_size_arg,
+              ptr_binlog_cache_use_arg,
+              ptr_binlog_cache_disk_use_arg)
+  {  }
 
   void reset_stmt_cache()
   {
@@ -434,8 +432,6 @@ binlog_trans_log_savepos(THD *thd, my_of
 {
   DBUG_ENTER("binlog_trans_log_savepos");
   DBUG_ASSERT(pos != NULL);
-  if (thd_get_ha_data(thd, binlog_hton) == NULL)
-    thd->binlog_setup_trx_data();
   binlog_cache_mngr *const cache_mngr=
     (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
   DBUG_ASSERT(mysql_bin_log.is_open());
@@ -467,7 +463,6 @@ binlog_trans_log_truncate(THD *thd, my_o
   DBUG_PRINT("enter", ("pos: %lu", (ulong) pos));
 
   DBUG_ASSERT(thd_get_ha_data(thd, binlog_hton) != NULL);
-  /* Only true if binlog_trans_log_savepos() wasn't called before */
   DBUG_ASSERT(pos != ~(my_off_t) 0);
 
   binlog_cache_mngr *const cache_mngr=
@@ -516,23 +511,27 @@ static int binlog_close_connection(handl
   @param thd                The thread whose transaction should be flushed
   @param cache_data         Pointer to the cache
   @param end_ev             The end event either commit/rollback
-  @param is_transactional   The type of the cache: transactional or
-                            non-transactional
 
   @return
     nonzero if an error pops up when flushing the cache.
 */
 static inline int
-binlog_flush_cache(THD *thd, binlog_cache_data* cache_data, Log_event *end_evt,
-                   bool is_transactional)
+binlog_flush_cache(THD *thd, binlog_cache_data* cache_data, Log_event *end_evt)
 {
   DBUG_ENTER("binlog_flush_cache");
   int error= 0;
 
+  DBUG_ASSERT((end_evt->is_using_trans_cache() && cache_data->is_trx_cache()) ||
+              (!end_evt->is_using_trans_cache() && !cache_data->is_trx_cache()));
+
   if (!cache_data->empty())
   {
-    if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
+    if (thd->binlog_flush_pending_rows_event(TRUE, cache_data->is_trx_cache()))
       DBUG_RETURN(1);
+
+    if (end_evt->write(&cache_data->cache_log))
+      DBUG_RETURN(1);
+ 
     /*
       Doing a commit or a rollback including non-transactional tables,
       i.e., ending a transaction where we might write the transaction
@@ -543,8 +542,10 @@ binlog_flush_cache(THD *thd, binlog_cach
       were, we would have to ensure that we're not ending a statement
       inside a stored function.
     */
-    error= mysql_bin_log.write(thd, &cache_data->cache_log, end_evt,
-                               cache_data->has_incident());
+    bool prepared= (end_evt->get_type_code() == XID_EVENT);
+    error= mysql_bin_log.write(thd, &cache_data->cache_log,
+                               cache_data->has_incident(),
+                               prepared);
   }
   cache_data->reset();
 
@@ -565,10 +566,10 @@ static inline int
 binlog_commit_flush_stmt_cache(THD *thd,
                                binlog_cache_mngr *cache_mngr)
 {
+  binlog_cache_data* cache_data= &cache_mngr->stmt_cache;
   Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
-                          FALSE, TRUE, TRUE, 0);
-  return (binlog_flush_cache(thd, &cache_mngr->stmt_cache, &end_evt,
-                             FALSE));
+                          cache_data->is_trx_cache(), FALSE, TRUE, 0, TRUE);
+  return binlog_flush_cache(thd, cache_data, &end_evt);
 }
 
 /**
@@ -583,10 +584,10 @@ binlog_commit_flush_stmt_cache(THD *thd,
 static inline int
 binlog_commit_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
 {
+  binlog_cache_data* cache_data= &cache_mngr->trx_cache;
   Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"),
-                          TRUE, TRUE, TRUE, 0);
-  return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-                             TRUE));
+                          cache_data->is_trx_cache(), FALSE, TRUE, 0, TRUE);
+  return binlog_flush_cache(thd, cache_data, &end_evt);
 }
 
 /**
@@ -601,10 +602,14 @@ binlog_commit_flush_trx_cache(THD *thd,
 static inline int
 binlog_rollback_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr)
 {
+  binlog_cache_data* cache_data= &cache_mngr->trx_cache;
   Query_log_event end_evt(thd, STRING_WITH_LEN("ROLLBACK"),
-                          TRUE, TRUE, TRUE, 0);
-  return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-                             TRUE));
+                          cache_data->is_trx_cache(), FALSE, TRUE, 0, TRUE);
+  /*
+    Force the use of the trx-cache because the current statement may
+    be something that makes Query_log_event to choose another cache.
+  */
+  return binlog_flush_cache(thd, cache_data, &end_evt);
 }
 
 /**
@@ -622,8 +627,7 @@ binlog_commit_flush_trx_cache(THD *thd,
                               my_xid xid)
 {
   Xid_log_event end_evt(thd, xid);
-  return (binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt,
-                             TRUE));
+  return binlog_flush_cache(thd, &cache_mngr->trx_cache, &end_evt);
 }
 
 /**
@@ -643,18 +647,13 @@ binlog_truncate_trx_cache(THD *thd, binl
 {
   DBUG_ENTER("binlog_truncate_trx_cache");
   int error=0;
-  /*
-    This function handles transactional changes and as such this flag
-    equals to true.
-  */
-  bool const is_transactional= TRUE;
 
   DBUG_PRINT("info", ("thd->options={ %s %s}, transaction: %s",
                       FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT),
                       FLAGSTR(thd->variables.option_bits, OPTION_BEGIN),
                       all ? "all" : "stmt"));
 
-  thd->binlog_remove_pending_rows_event(TRUE, is_transactional);
+  thd->binlog_remove_pending_rows_event(TRUE, TRUE);
   /*
     If rolling back an entire transaction or a single statement not
     inside a transaction, we reset the transaction cache.
@@ -675,7 +674,7 @@ binlog_truncate_trx_cache(THD *thd, binl
   else
     cache_mngr->trx_cache.restore_prev_position();
 
-  DBUG_ASSERT(thd->binlog_get_pending_rows_event(is_transactional) == NULL);
+  DBUG_ASSERT(thd->binlog_get_pending_rows_event(TRUE) == NULL);
   DBUG_RETURN(error);
 }
 
@@ -1102,33 +1101,6 @@ stmt_has_updated_trans_table(const THD *
   return (FALSE);
 }
 
-/** 
-  This function checks if either a trx-cache or a non-trx-cache should
-  be used. If @c bin_log_direct_non_trans_update is active or the format
-  is either MIXED or ROW, the cache to be used depends on the flag @c
-  is_transactional. 
-
-  On the other hand, if binlog_format is STMT or direct option is
-  OFF, the trx-cache should be used if and only if the statement is
-  transactional or the trx-cache is not empty. Otherwise, the
-  non-trx-cache should be used.
-
-  @param thd              The client thread.
-  @param is_transactional The changes are related to a trx-table.
-  @return
-    @c true if a trx-cache should be used, @c false otherwise.
-*/
-bool use_trans_cache(const THD* thd, bool is_transactional)
-{
-  binlog_cache_mngr *const cache_mngr=
-    (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
-
-  return
-    ((thd->is_current_stmt_binlog_format_row() ||
-     thd->variables.binlog_direct_non_trans_update) ? is_transactional :
-     (is_transactional || !cache_mngr->trx_cache.empty()));
-}
-
 /**
   This function checks if a transaction, either a multi-statement
   or a single statement transaction is about to commit or not.
@@ -3471,7 +3443,7 @@ MYSQL_BIN_LOG::remove_pending_rows_event
   DBUG_ASSERT(cache_mngr);
 
   binlog_cache_data *cache_data=
-    cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional));
+    cache_mngr->get_binlog_cache_data(is_transactional);
 
   if (Rows_log_event* pending= cache_data->pending())
   {
@@ -3508,7 +3480,7 @@ MYSQL_BIN_LOG::flush_and_set_pending_row
   DBUG_ASSERT(cache_mngr);
 
   binlog_cache_data *cache_data=
-    cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional));
+    cache_mngr->get_binlog_cache_data(is_transactional);
 
   DBUG_PRINT("info", ("cache_mngr->pending(): 0x%lx", (long) cache_data->pending()));
 
@@ -3554,7 +3526,7 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
     */
     thd->binlog_evt_union.unioned_events= TRUE;
     thd->binlog_evt_union.unioned_events_trans |=
-      event_info->use_trans_cache();
+      event_info->is_using_trans_cache();
     DBUG_RETURN(0);
   }
 
@@ -3566,7 +3538,7 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
   bool const end_stmt=
     thd->locked_tables_mode && thd->lex->requires_prelocking();
   if (thd->binlog_flush_pending_rows_event(end_stmt,
-                                           event_info->use_trans_cache()))
+                                           event_info->is_using_trans_cache()))
     DBUG_RETURN(error);
 
   /*
@@ -3591,28 +3563,15 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
       DBUG_RETURN(0);
 #endif /* HAVE_REPLICATION */
 
-    IO_CACHE *file= NULL;
-    binlog_cache_mngr *cache_mngr= NULL;
-    binlog_cache_data *cache_data= 0;
-    bool is_trans_cache= FALSE;
-
-    if (event_info->use_direct_logging())
-    {
-      file= &log_file;
-      mysql_mutex_lock(&LOCK_log);
-    }
-    else
-    {
-      if (thd->binlog_setup_trx_data())
-        goto err;
-
-      cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
-      is_trans_cache= use_trans_cache(thd, event_info->use_trans_cache());
-      file= cache_mngr->get_binlog_cache_log(is_trans_cache);
-      cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
+    DBUG_ASSERT(event_info->is_using_trans_cache() || event_info->is_using_stmt_cache());
+    
+    binlog_start_trans_and_stmt(thd, event_info);
 
-      thd->binlog_start_trans_and_stmt();
-    }
+    bool is_trans_cache= event_info->is_using_trans_cache();
+    binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+    IO_CACHE *file= cache_mngr->get_binlog_cache_log(is_trans_cache);
+    binlog_cache_data *cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache);
+    
     DBUG_PRINT("info",("event type: %d",event_info->get_type_code()));
 
     /*
@@ -3627,16 +3586,11 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
     {
       if (!thd->is_current_stmt_binlog_format_row())
       {
-        /* three possibility for cache_type at this point */
-        DBUG_ASSERT(event_info->cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE ||
-                    event_info->cache_type == Log_event::EVENT_STMT_CACHE ||
-                    event_info->cache_type == Log_event::EVENT_NO_CACHE);
- 
         if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
         {
           Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
                              thd->first_successful_insert_id_in_prev_stmt_for_binlog,
-                             event_info->cache_type);
+                             event_info->event_cache_type, event_info->event_logging_type);
           if (e.write(file))
             goto err;
         }
@@ -3647,14 +3601,16 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
                              nb_elements()));
           Intvar_log_event e(thd, (uchar) INSERT_ID_EVENT,
                              thd->auto_inc_intervals_in_cur_stmt_for_binlog.
-                             minimum(), event_info->cache_type);
+                             minimum(), event_info->event_cache_type,
+                             event_info->event_logging_type);
           if (e.write(file))
             goto err;
         }
         if (thd->rand_used)
         {
           Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2,
-                           event_info->cache_type);
+                           event_info->event_cache_type,
+                           event_info->event_logging_type);
           if (e.write(file))
             goto err;
         }
@@ -3676,7 +3632,8 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
                                  user_var_event->length,
                                  user_var_event->type,
                                  user_var_event->charset_number, flags,
-                                 event_info->cache_type);
+                                 event_info->event_cache_type,
+                                 event_info->event_logging_type);
             if (e.write(file))
               goto err;
           }
@@ -3693,28 +3650,18 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
 
     error= 0;
 
+    /*
+      Checks if a non-transactional event was written to a trx-cache.
+    */
     if (is_trans_cache && stmt_cannot_safely_rollback(thd))
       cache_mngr->set_trx_cache_cannot_rollback();
 err:
-    if (event_info->use_direct_logging())
+    if (event_info->is_using_immediate_logging())
     {
-      if (!error)
-      {
-        bool synced;
-        if ((error= flush_and_sync(&synced)))
-          goto unlock;
-
-        if ((error= RUN_HOOK(binlog_storage, after_flush,
-                 (thd, log_file_name, file->pos_in_file, synced))))
-        {
-          sql_print_error("Failed to run 'after_flush' hooks");
-          goto unlock;
-        }
-        signal_update();
-        rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
-      }
-unlock:
-      mysql_mutex_unlock(&LOCK_log);
+      error |= mysql_bin_log.write(thd, &cache_data->cache_log,
+                                   cache_data->has_incident(),
+                                   FALSE);
+      cache_data->reset();
     }
 
     if (error)
@@ -4067,7 +4014,18 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE
   return 0;                                     // All OK
 }
 
-bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
+/**
+  Writes an incident event to the binary log.
+
+  @param ev   Incident event to be written
+  @param lock If the binary lock should be locked or not
+
+  @retval
+    0    error
+  @retval
+    1    success
+*/
+bool MYSQL_BIN_LOG::write_incident(Incident_log_event *ev, bool lock)
 {
   uint error= 0;
   DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
@@ -4075,40 +4033,61 @@ bool MYSQL_BIN_LOG::write_incident(THD *
   if (!is_open())
     DBUG_RETURN(error);
 
-  LEX_STRING const write_error_msg=
-    { C_STRING_WITH_LEN("error writing to the binary log") };
-  Incident incident= INCIDENT_LOST_EVENTS;
-  Incident_log_event ev(thd, incident, write_error_msg);
   if (lock)
     mysql_mutex_lock(&LOCK_log);
-  error= ev.write(&log_file);
+
+  error= ev->write(&log_file);
+
   if (lock)
   {
     if (!error && !(error= flush_and_sync(0)))
     {
       signal_update();
-      error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED);
+      error= rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED |
+                              RP_FORCE_ROTATE);
     }
     mysql_mutex_unlock(&LOCK_log);
   }
+
   DBUG_RETURN(error);
 }
 
 /**
+  Creates an incident event and writes it to the binary log.
+
+  @param thd  Thread variable
+  @param ev   Incident event to be written
+  @param lock If the binary lock should be locked or not
+
+  @retval
+    0    error
+  @retval
+    1    success
+*/
+bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock)
+{
+  DBUG_ENTER("MYSQL_BIN_LOG::write_incident");
+
+  if (!is_open())
+    DBUG_RETURN(0);
+
+  LEX_STRING const write_error_msg=
+    { C_STRING_WITH_LEN("error writing to the binary log") };
+  Incident incident= INCIDENT_LOST_EVENTS;
+  Incident_log_event ev(thd, incident, write_error_msg);
+
+  DBUG_RETURN(write_incident(&ev, lock));
+}
+
+/**
   Write a cached log entry to the binary log.
-  - To support transaction over replication, we wrap the transaction
-  with BEGIN/COMMIT or BEGIN/ROLLBACK in the binary log.
-  We want to write a BEGIN/ROLLBACK block when a non-transactional table
-  was updated in a transaction which was rolled back. This is to ensure
-  that the same updates are run on the slave.
 
-  @param thd
+  @param thd            Thread variable
   @param cache		The cache to copy to the binlog
-  @param commit_event   The commit event to print after writing the
-                        contents of the cache.
   @param incident       Defines if an incident event should be created to
                         notify that some non-transactional changes did
                         not get into the binlog.
+  @param prepared       Defines if a transaction is part of a 2-PC.
 
   @note
     We only come here if there is something in the cache.
@@ -4118,8 +4097,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *
     'cache' needs to be reinitialized after this functions returns.
 */
 
-bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event,
-                          bool incident)
+bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, bool incident, bool prepared)
 {
   DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)");
   mysql_mutex_lock(&LOCK_log);
@@ -4133,14 +4111,6 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
      */
     if (my_b_tell(cache) > 0)
     {
-      /*
-        Log "BEGIN" at the beginning of every transaction.  Here, a
-        transaction is either a BEGIN..COMMIT block or a single
-        statement in autocommit mode.
-      */
-      Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, TRUE, TRUE, 0);
-      if (qinfo.write(&log_file))
-        goto err;
       DBUG_EXECUTE_IF("crash_before_writing_xid",
                       {
                         if ((write_error= write_cache(cache, false, true)))
@@ -4153,9 +4123,6 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
       if ((write_error= write_cache(cache, false, false)))
         goto err;
 
-      if (commit_event && commit_event->write(&log_file))
-        goto err;
-
       if (incident && write_incident(thd, FALSE))
         goto err;
 
@@ -4189,7 +4156,7 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_C
       If the commit_event is not Xid_log_event (then it's a Query_log_event)
       rotate binlog, if necessary.
     */
-    if (commit_event && commit_event->get_type_code() == XID_EVENT)
+    if (prepared)
     {
       mysql_mutex_lock(&LOCK_prep_xids);
       prepared_xids++;
@@ -4687,25 +4654,20 @@ int THD::binlog_setup_trx_data()
 
   cache_mngr= new (thd_get_ha_data(this, binlog_hton))
               binlog_cache_mngr(max_binlog_stmt_cache_size,
-                                max_binlog_cache_size,
                                 &binlog_stmt_cache_use,
                                 &binlog_stmt_cache_disk_use,
+                                max_binlog_cache_size,
                                 &binlog_cache_use,
                                 &binlog_cache_disk_use);
   DBUG_RETURN(0);
 }
 
-/*
+/**
   Function to start a statement and optionally a transaction for the
   binary log.
 
-  SYNOPSIS
-    binlog_start_trans_and_stmt()
-
-  DESCRIPTION
-
-    This function does three things:
-    - Start a transaction if not in autocommit mode or if a BEGIN
+  This function does three things:
+    - Starts a transaction if not in autocommit mode or if a BEGIN
       statement has been seen.
 
     - Start a statement transaction to allow us to truncate the cache.
@@ -4720,55 +4682,86 @@ int THD::binlog_setup_trx_data()
       we should use the first. This means that calls to this function
       can be used to start the statement before the first table map
       event, to include some extra events.
- */
 
-void
-THD::binlog_start_trans_and_stmt()
+  @param thd         Thread variable
+  @param start_event The first event requested to be written into the
+                     binary log
+ */
+inline void binlog_start_trans_and_stmt(THD *thd, Log_event *start_event)
 {
-  binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
   DBUG_ENTER("binlog_start_trans_and_stmt");
-  DBUG_PRINT("enter", ("cache_mngr: %p  cache_mngr->trx_cache.get_prev_position(): %lu",
-                       cache_mngr,
-                       (cache_mngr ? (ulong) cache_mngr->trx_cache.get_prev_position() :
-                        (ulong) 0)));
-
-  if (cache_mngr == NULL ||
-      cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
-  {
-    this->binlog_set_stmt_begin();
-    if (in_multi_stmt_transaction_mode())
-      trans_register_ha(this, TRUE, binlog_hton);
-    trans_register_ha(this, FALSE, binlog_hton);
+ 
+  /*
+    Initialize the cache manager if this was not done yet.
+  */ 
+  if (thd_get_ha_data(thd, binlog_hton) == NULL)
+    thd->binlog_setup_trx_data();
+
+  /*
+    If the event is requesting immediatly logging, there is no need to go
+    further and set savepoint and register callbacks.
+  */ 
+  if (start_event->is_using_immediate_logging())
+    DBUG_VOID_RETURN;
+
+  /*
+    Retrieve the appropriated cache.
+  */
+  bool is_transactional= start_event->is_using_trans_cache();
+  binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
+  binlog_cache_data *cache= cache_mngr->get_binlog_cache_data(is_transactional);
+ 
+  /*
+    If this is the first call to this funciton while processing a statement,
+    the transactional cache does not have a savepoint defined. So, in what
+    follows:
+      . an implicit savepoint is defined;
+      . callbacks are registered;
+      . binary log is set as read/write.
+
+    The savepoint allows for truncating the trx-cache transactional changes
+    fail. Callbacks are necessary to flush caches upon committing or rolling
+    back a statement or a transaction. However, notifications do not happen
+    if the binary log is set as read/write.
+  */
+  if (cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
+  {
     /*
-      Mark statement transaction as read/write. We never start
-      a binary log transaction and keep it read-only,
-      therefore it's best to mark the transaction read/write just
-      at the same time we start it.
-      Not necessary to mark the normal transaction read/write
-      since the statement-level flag will be propagated automatically
-      inside ha_commit_trans.
+      Set an implicit savepoint in order to be able to truncate a trx-cache.
     */
-    ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
-  }
-  DBUG_VOID_RETURN;
-}
+    my_off_t pos= 0;
+    binlog_trans_log_savepos(thd, &pos);
+    cache_mngr->trx_cache.set_prev_position(pos);
 
-void THD::binlog_set_stmt_begin() {
-  binlog_cache_mngr *cache_mngr=
-    (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
+    /*
+      Set callbacks in order to be able to call commmit or rollback.
+    */
+    if (thd->in_multi_stmt_transaction_mode())
+      trans_register_ha(thd, TRUE, binlog_hton);
+    trans_register_ha(thd, FALSE, binlog_hton);
+
+    /*
+      Set the binary log as read/write otherwise callbacks are not called.
+    */
+    thd->ha_data[binlog_hton->slot].ha_info[0].set_trx_read_write();
+  }
 
   /*
-    The call to binlog_trans_log_savepos() might create the cache_mngr
-    structure, if it didn't exist before, so we save the position
-    into an auto variable and then write it into the transaction
-    data for the binary log (i.e., cache_mngr).
-  */
-  my_off_t pos= 0;
-  binlog_trans_log_savepos(this, &pos);
-  cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
-  cache_mngr->trx_cache.set_prev_position(pos);
-}
+    If the cache is empty log "BEGIN" at the beginning of every transaction.
+    Here, a transaction is either a BEGIN..COMMIT/ROLLBACK block or a single
+    statement in autocommit mode.
+  */
+  if (cache->empty())
+  {
+    IO_CACHE *file=
+      cache_mngr->get_binlog_cache_log(is_transactional);
+    Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"),
+                          is_transactional, FALSE, TRUE, 0, TRUE);
+    qinfo.write(file);
+  }
 
+  DBUG_VOID_RETURN;
+}
 
 /**
   This function writes a table map to the binary log. 
@@ -4805,14 +4798,13 @@ int THD::binlog_write_table_map(TABLE *t
   Table_map_log_event
     the_event(this, table, table->s->table_map_id, is_transactional);
 
-  if (binlog_table_maps == 0)
-    binlog_start_trans_and_stmt();
+  binlog_start_trans_and_stmt(this, &the_event);
 
   binlog_cache_mngr *const cache_mngr=
     (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
 
   IO_CACHE *file=
-    cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional));
+    cache_mngr->get_binlog_cache_log(is_transactional);
 
   if (binlog_rows_query && this->query())
   {
@@ -4856,7 +4848,7 @@ THD::binlog_get_pending_rows_event(bool
   if (cache_mngr)
   {
     binlog_cache_data *cache_data=
-      cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional));
+      cache_mngr->get_binlog_cache_data(is_transactional);
 
     rows= cache_data->pending();
   }
@@ -4876,16 +4868,13 @@ THD::binlog_get_pending_rows_event(bool
 void
 THD::binlog_set_pending_rows_event(Rows_log_event* ev, bool is_transactional)
 {
-  if (thd_get_ha_data(this, binlog_hton) == NULL)
-    binlog_setup_trx_data();
-
   binlog_cache_mngr *const cache_mngr=
     (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton);
 
   DBUG_ASSERT(cache_mngr);
 
   binlog_cache_data *cache_data=
-    cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional));
+    cache_mngr->get_binlog_cache_data(is_transactional);
 
   cache_data->set_pending(ev);
 }
@@ -5309,13 +5298,6 @@ THD::binlog_prepare_pending_rows_event(T
   /* Fetch the type code for the RowsEventT template parameter */
   int const type_code= RowsEventT::TYPE_CODE;
 
-  /*
-    There is no good place to set up the transactional data, so we
-    have to do it here.
-  */
-  if (binlog_setup_trx_data())
-    DBUG_RETURN(NULL);
-
   Rows_log_event* pending= binlog_get_pending_rows_event(is_transactional);
 
   if (unlikely(pending && !pending->is_valid()))

=== modified file 'sql/binlog.h'
--- a/sql/binlog.h	2011-03-16 16:41:46 +0000
+++ b/sql/binlog.h	2011-03-21 15:56:26 +0000
@@ -229,12 +229,13 @@ public:
   int new_file();
 
   bool write(Log_event* event_info); // binary log write
-  bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident);
-
-  bool write_incident(THD *thd, bool lock);
+  bool write(THD *thd, IO_CACHE *cache, bool incident, bool prepared);
   int  write_cache(IO_CACHE *cache, bool lock_log, bool flush_and_sync);
+
   void set_write_error(THD *thd, bool is_transactional);
   bool check_write_error(THD *thd);
+  bool write_incident(THD *thd, bool lock);
+  bool write_incident(Incident_log_event *ev, bool lock);
 
   void start_union_events(THD *thd, query_id_t query_id_param);
   void stop_union_events(THD *thd);
@@ -320,7 +321,6 @@ extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG
 
 bool trans_has_updated_trans_table(const THD* thd);
 bool stmt_has_updated_trans_table(const THD *thd);
-bool use_trans_cache(const THD* thd, bool is_transactional);
 bool ending_trans(THD* thd, const bool all);
 bool ending_single_stmt_trans(THD* thd, const bool all);
 bool stmt_cannot_safely_rollback(const THD* thd);

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2011-03-16 16:41:46 +0000
+++ b/sql/log_event.cc	2011-03-21 15:56:26 +0000
@@ -682,18 +682,16 @@ const char* Log_event::get_type_str()
 */
 
 #ifndef MYSQL_CLIENT
-Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
+Log_event::Log_event(THD* thd_arg, uint16 flags_arg,
+                     enum_event_cache_type cache_type_arg,
+                     enum_event_logging_type logging_type_arg)
   :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg),
-   cache_type(Log_event::EVENT_INVALID_CACHE), crc(0), thd(thd_arg),
-   checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
+  event_cache_type(cache_type_arg),
+  event_logging_type(logging_type_arg),
+  crc(0), thd(thd_arg), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
 {
   server_id=	thd->server_id;
   when=		thd->start_time;
-
-  if (using_trans)
-    cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
-  else
-    cache_type= Log_event::EVENT_STMT_CACHE;
 }
 
 /**
@@ -703,9 +701,11 @@ Log_event::Log_event(THD* thd_arg, uint1
   the binlog but we have no THD, so we need this minimal constructor).
 */
 
-Log_event::Log_event()
-  :temp_buf(0), exec_time(0), flags(0),  crc(0), thd(0),
-   checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
+Log_event::Log_event(enum_event_cache_type cache_type_arg,
+                     enum_event_logging_type logging_type_arg)
+  :temp_buf(0), exec_time(0), flags(0), event_cache_type(cache_type_arg),
+  event_logging_type(logging_type_arg), crc(0), thd(0),
+  checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
 {
   server_id=	::server_id;
   /*
@@ -724,8 +724,10 @@ Log_event::Log_event()
 
 Log_event::Log_event(const char* buf,
                      const Format_description_log_event* description_event)
-  :temp_buf(0), exec_time(0), cache_type(Log_event::EVENT_INVALID_CACHE),
-    crc(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
+  :temp_buf(0), exec_time(0),
+  event_cache_type(EVENT_INVALID_CACHE),
+  event_logging_type(EVENT_INVALID_LOGGING),
+  crc(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
 {
 #ifndef MYSQL_CLIENT
   thd = 0;
@@ -908,18 +910,19 @@ void Log_event::init_show_field_list(Lis
 my_bool Log_event::need_checksum()
 {
   DBUG_ENTER("Log_event::need_checksum");
-  my_bool ret;
+  my_bool ret= FALSE;
   /* 
      few callers of Log_event::write 
      (incl FD::write, FD constructing code on the slave side, Rotate relay log
      and Stop event) 
      provides their checksum alg preference through Log_event::checksum_alg.
   */
-  ret= (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF) ?
-    (checksum_alg != BINLOG_CHECKSUM_ALG_OFF) :
-    ((binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF) &&
-     (cache_type == Log_event::EVENT_NO_CACHE))? binlog_checksum_options :
-    FALSE;
+  if (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF)
+    ret= (checksum_alg != BINLOG_CHECKSUM_ALG_OFF);
+  else
+  if (binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF &&
+      event_cache_type == Log_event::EVENT_NO_CACHE)
+    ret= binlog_checksum_options;
 
   /*
     FD calls the methods before data_written has been calculated.
@@ -959,7 +962,7 @@ my_bool Log_event::need_checksum()
   DBUG_ASSERT(((get_type_code() != ROTATE_EVENT &&
                 get_type_code() != STOP_EVENT) ||
                get_type_code() != FORMAT_DESCRIPTION_EVENT) ||
-              cache_type == Log_event::EVENT_NO_CACHE);
+              event_cache_type == Log_event::EVENT_NO_CACHE);
 
   DBUG_RETURN(ret);
 }
@@ -2685,29 +2688,33 @@ Query_log_event::Query_log_event()
 }
 
 
-/*
-  SYNOPSIS
-    Query_log_event::Query_log_event()
-      thd_arg           - thread handle
-      query_arg         - array of char representing the query
-      query_length      - size of the  `query_arg' array
-      using_trans       - there is a modified transactional table
-      suppress_use      - suppress the generation of 'USE' statements
-      errcode           - the error code of the query
-      
-  DESCRIPTION
-  Creates an event for binlogging
-  The value for `errcode' should be supplied by caller.
+/**
+  Creates a Query Log Event.
+
+  @param thd_arg      Thread handle
+  @param query_arg    Array of char representing the query
+  @param query_length Size of the 'query_arg' array
+  @param using_trans  Indicates that there are transactional changes.
+  @param immediate    After being written to the binary log, the event
+                      must be flushed immediately. This indirectly implies
+                      the stmt-cache.
+  @param suppress_use Suppress the generation of 'USE' statements
+  @param errcode      The error code of the query
+  @param ignore       Ignore user's statement, i.e. lex information, while
+                      deciding which cache must be used.
 */
 Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
 				 ulong query_length, bool using_trans,
-				 bool direct, bool suppress_use, int errcode)
+				 bool immediate, bool suppress_use,
+                                 int errcode, bool ignore_cmd_internals)
 
   :Log_event(thd_arg,
              (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
               0) |
              (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
-	     using_trans),
+	     using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                          Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
    data_buf(0), query(query_arg), catalog(thd_arg->catalog),
    db(thd_arg->db), q_len((uint32) query_length),
    thread_id(thd_arg->thread_id),
@@ -2785,62 +2792,146 @@ Query_log_event::Query_log_event(THD* th
   else
     time_zone_len= 0;
 
-  LEX *lex= thd->lex;
   /*
-    Defines that the statement will be written directly to the binary log
-    without being wrapped by a BEGIN...COMMIT. Otherwise, the statement
-    will be written to either the trx-cache or stmt-cache.
+    In what follows, we define in which cache, trx-cache or stmt-cache,
+    this Query Log Event will be written to.
 
-    Note that a cache will not be used if the parameter direct is TRUE.
+    If ignore_cmd_internals is defined, we rely on the is_trans flag to
+    choose the cache and this is done in the base class Log_event. False
+    means that the stmt-cache will be used and upon statement commit/rollback
+    the cache will be flushed to disk. True means that the trx-cache will
+    be used and upon transaction commit/rollback the cache will be flushed
+    to disk.
+
+    If set immediate cache is defined, for convenience, we automatically
+    use the stmt-cache. This mean that the statement will be written
+    to the stmt-cache and immediately flushed to disk without waiting
+    for a commit/rollback notification.
+
+    For example, the cluster/ndb captures a request to execute a DDL
+    statement and synchronously propagate it to all available MySQL
+    servers. Unfortunately, the current protocol assumes that the
+    generated events are immediately written to diks and does not check
+    for commit/rollback.
+
+    Upon dropping a connection, DDLs (i.e. DROP TEMPORARY TABLE) are
+    generated and in this case the statements have the immediate flag
+    set because there is no commit/rollback.
+
+    If the immediate flag is not set, the decision on the cache is based
+    on the current statement and the flag is_trans, which indicates if
+    a transactional engine was updated. 
+
+    Statements are classifed as row producers (i.e. can_generate_row_events())
+    or non-row producers. Non-row producers, DDL in general, are treated
+    as the immediate flag was set and for convenience are written to the
+    stmt-cache and immediately flushed to disk. 
+
+    Row producers are handled in general according to the is_trans flag.
+    False means that the stmt-cache will be used and upon statement
+    commit/rollback the cache will be flushed to disk. True means that the
+    trx-cache will be used and upon transaction commit/rollback the cache
+    will be flushed to disk.
+
+    Unfortunately, there are exceptions to this non-row and row producer
+    rules:
+
+      . The SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT does not
+        have the flag is_trans set because there is no updated engine but
+        must be written to the trx-cache.
+
+      . SET does not have the flag is_trans set but, if auto-commit is off,
+        must be written to the trx-cache.
+
+      . CREATE TABLE is classfied as non-row producer but CREATE TEMPORARY
+        must be handled as row producer.
+
+      . DROP TABLE is classfied as non-row producer but DROP TEMPORARY
+        must be handled as row producer.
+
+    Finally, some statements that does not have the flag is_trans set may
+    be written to the trx-cache based on the following criteria:
+
+      . updated both a transactional and a non-transactional engine (i.e.
+        stmt_has_updated_trans_table()).
+
+      . accessed both a transactional and a non-transactional engine and
+        is classified as unsafe (i.e. is_mixed_stmt_unsafe()).
+
+      . is executed within a transaction and previously a transactional
+        engine was updated and the flag binlog_direct_non_trans_update
+        is set.
   */
-  bool use_cache= FALSE;
-  /*
-    TRUE defines that the trx-cache must be used and by consequence the
-    use_cache is TRUE.
+  if (ignore_cmd_internals)
+    return;
 
-    Note that a cache will not be used if the parameter direct is TRUE.
+  /*
+    TRUE defines that the trx-cache must be used.
   */
-  bool trx_cache= FALSE;
-  cache_type= Log_event::EVENT_INVALID_CACHE;
-
-  switch (lex->sql_command)
+  bool cmd_can_generate_row_events= FALSE;
+  /*
+    TRUE defines that the trx-cache must be used.
+  */
+  bool cmd_must_go_to_trx_cache= FALSE;
+   
+  LEX *lex= thd->lex;
+  if (!immediate)
   {
-    case SQLCOM_DROP_TABLE:
-      use_cache= (lex->drop_temporary && thd->in_multi_stmt_transaction_mode());
-    break;
-
-    case SQLCOM_CREATE_TABLE:
-      trx_cache= (lex->select_lex.item_list.elements &&
-                  thd->is_current_stmt_binlog_format_row());
-      use_cache= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
-                   thd->in_multi_stmt_transaction_mode()) || trx_cache;
-      break;
-    case SQLCOM_SET_OPTION:
-      use_cache= trx_cache= (lex->autocommit ? FALSE : TRUE);
-      break;
-    case SQLCOM_RELEASE_SAVEPOINT:
-    case SQLCOM_ROLLBACK_TO_SAVEPOINT:
-    case SQLCOM_SAVEPOINT:
-      use_cache= trx_cache= TRUE;
-      break;
-    default:
-      use_cache= sqlcom_can_generate_row_events(thd);
-      break;
+    switch (lex->sql_command)
+    {
+      case SQLCOM_DROP_TABLE:
+        cmd_can_generate_row_events= lex->drop_temporary &&
+                                     thd->in_multi_stmt_transaction_mode();
+      break;
+      case SQLCOM_CREATE_TABLE:
+        cmd_must_go_to_trx_cache= lex->select_lex.item_list.elements &&
+                                  thd->is_current_stmt_binlog_format_row();
+        cmd_can_generate_row_events= 
+          ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
+            thd->in_multi_stmt_transaction_mode()) || cmd_must_go_to_trx_cache;
+        break;
+      case SQLCOM_SET_OPTION:
+        cmd_can_generate_row_events= cmd_must_go_to_trx_cache=
+          (lex->autocommit ? FALSE : TRUE);
+        break;
+      case SQLCOM_RELEASE_SAVEPOINT:
+      case SQLCOM_ROLLBACK_TO_SAVEPOINT:
+      case SQLCOM_SAVEPOINT:
+        cmd_can_generate_row_events= cmd_must_go_to_trx_cache= TRUE;
+        break;
+      default:
+        cmd_can_generate_row_events= sqlcom_can_generate_row_events(thd);
+        break;
+    }
   }
-
-  if (!use_cache || direct)
+  
+  if (cmd_can_generate_row_events)
   {
-    cache_type= Log_event::EVENT_NO_CACHE;
+    cmd_must_go_to_trx_cache= cmd_must_go_to_trx_cache || using_trans;
+    if (cmd_must_go_to_trx_cache || stmt_has_updated_trans_table(thd) ||
+        thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
+                                       thd->variables.binlog_direct_non_trans_update,
+                                       trans_has_updated_trans_table(thd),
+                                       thd->tx_isolation) ||
+        (!thd->variables.binlog_direct_non_trans_update && trans_has_updated_trans_table(thd)))
+    {
+      event_logging_type= Log_event::EVENT_NORMAL_LOGGING; 
+      event_cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
+    }
+    else
+    {
+      event_logging_type= Log_event::EVENT_NORMAL_LOGGING; 
+      event_cache_type= Log_event::EVENT_STMT_CACHE;
+    }
   }
-  else if (using_trans || trx_cache || stmt_has_updated_trans_table(thd) ||
-           thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
-                                          thd->variables.binlog_direct_non_trans_update,
-                                          trans_has_updated_trans_table(thd),
-                                          thd->tx_isolation))
-    cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
   else
-    cache_type= Log_event::EVENT_STMT_CACHE;
-  DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE);
+  {
+    event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
+    event_cache_type= Log_event::EVENT_STMT_CACHE;
+  }
+
+  DBUG_ASSERT(event_cache_type != Log_event::EVENT_INVALID_CACHE);
+  DBUG_ASSERT(event_logging_type != Log_event::EVENT_INVALID_LOGGING);
   DBUG_PRINT("info",("Query_log_event has flags2: %lu  sql_mode: %llu",
                      (ulong) flags2, sql_mode));
 }
@@ -4832,7 +4923,9 @@ Load_log_event::Load_log_event(THD *thd_
 			       bool ignore, bool using_trans)
   :Log_event(thd_arg,
              thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0,
-             using_trans),
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
    thread_id(thd_arg->thread_id),
    slave_proxy_id(thd_arg->variables.pseudo_thread_id),
    num_fields(0),fields(0),
@@ -5476,9 +5569,9 @@ void Rotate_log_event::print(FILE* file,
 Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg,
                                    uint ident_len_arg, ulonglong pos_arg,
                                    uint flags_arg)
-  :Log_event(), new_log_ident(new_log_ident_arg),
-   pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
-                          (uint) strlen(new_log_ident_arg)), flags(flags_arg)
+  :Log_event(Log_event::EVENT_NO_CACHE, Log_event::EVENT_IMMEDIATE_LOGGING),
+   new_log_ident(new_log_ident_arg), pos(pos_arg),ident_len(ident_len_arg ?
+   ident_len_arg : (uint) strlen(new_log_ident_arg)), flags(flags_arg)
 {
 #ifndef DBUG_OFF
   char buff[22];
@@ -5486,7 +5579,8 @@ Rotate_log_event::Rotate_log_event(const
   DBUG_PRINT("enter",("new_log_ident: %s  pos: %s  flags: %lu", new_log_ident_arg,
                       llstr(pos_arg, buff), (ulong) flags));
 #endif
-  cache_type= EVENT_NO_CACHE;
+  event_cache_type= EVENT_NO_CACHE;
+  event_logging_type= EVENT_IMMEDIATE_LOGGING;
   if (flags & DUP_NAME)
     new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME));
   if (flags & RELAY_LOG)
@@ -6843,7 +6937,11 @@ Append_block_log_event::Append_block_log
 					       uchar *block_arg,
 					       uint block_len_arg,
 					       bool using_trans)
-  :Log_event(thd_arg,0, using_trans), block(block_arg),
+  :Log_event(thd_arg, 0,
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
+   block(block_arg),
    block_len(block_len_arg), file_id(thd_arg->file_id), db(db_arg)
 {
 }
@@ -7011,7 +7109,11 @@ err:
 #ifndef MYSQL_CLIENT
 Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char* db_arg,
 					     bool using_trans)
-  :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id), db(db_arg)
+  :Log_event(thd_arg, 0, 
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
+  file_id(thd_arg->file_id), db(db_arg)
 {
 }
 #endif
@@ -7107,7 +7209,11 @@ int Delete_file_log_event::do_apply_even
 Execute_load_log_event::Execute_load_log_event(THD *thd_arg,
                                                const char* db_arg,
 					       bool using_trans)
-  :Log_event(thd_arg, 0, using_trans), file_id(thd_arg->file_id), db(db_arg)
+  :Log_event(thd_arg, 0,
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
+  file_id(thd_arg->file_id), db(db_arg)
 {
 }
 #endif
@@ -7323,9 +7429,9 @@ Execute_load_query_log_event(THD *thd_ar
                              ulong query_length_arg, uint fn_pos_start_arg,
                              uint fn_pos_end_arg,
                              enum_load_dup_handling dup_handling_arg,
-                             bool using_trans, bool direct, bool suppress_use,
+                             bool using_trans, bool immediate, bool suppress_use,
                              int errcode):
-  Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, direct,
+  Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, immediate,
                   suppress_use, errcode),
   file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
   fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
@@ -7600,8 +7706,11 @@ const char *sql_ex_info::init(const char
 
 #ifndef MYSQL_CLIENT
 Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid,
-                               MY_BITMAP const *cols, bool is_transactional)
-  : Log_event(thd_arg, 0, is_transactional),
+                               MY_BITMAP const *cols, bool using_trans)
+  : Log_event(thd_arg, 0,
+             using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                           Log_event::EVENT_STMT_CACHE,
+             Log_event::EVENT_NORMAL_LOGGING),
     m_row_count(0),
     m_table(tbl_arg),
     m_table_id(tid),
@@ -8519,8 +8628,11 @@ int Table_map_log_event::save_field_meta
  */
 #if !defined(MYSQL_CLIENT)
 Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid,
-                                         bool is_transactional)
-  : Log_event(thd, 0, is_transactional),
+                                         bool using_trans)
+  : Log_event(thd, 0,
+              using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                            Log_event::EVENT_STMT_CACHE,
+              Log_event::EVENT_NORMAL_LOGGING),
     m_table(tbl),
     m_dbnam(tbl->s->db.str),
     m_dblen(m_dbnam ? tbl->s->db.length : 0),

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2011-03-14 17:55:26 +0000
+++ b/sql/log_event.h	2011-03-21 15:56:26 +0000
@@ -930,9 +930,10 @@ public:
     EVENT_SKIP_COUNT
   };
 
+protected:
   enum enum_event_cache_type 
   {
-    EVENT_INVALID_CACHE,
+    EVENT_INVALID_CACHE= 0,
     /* 
       If possible the event should use a non-transactional cache before
       being flushed to the binary log. This means that it must be flushed
@@ -947,15 +948,35 @@ public:
     EVENT_TRANSACTIONAL_CACHE,
     /* 
       The event must be written directly to the binary log without going
-      through a cache.
+      through any cache.
     */
     EVENT_NO_CACHE,
-    /**
+    /*
        If there is a need for different types, introduce them before this.
     */
     EVENT_CACHE_COUNT
   };
 
+  enum enum_event_logging_type
+  {
+    EVENT_INVALID_LOGGING= 0,
+    /*
+      The event must be written to a cache and upon commit or rollback
+      written to the binary log.
+    */
+    EVENT_NORMAL_LOGGING,
+    /*
+      The event must be written to an empty cache and immediatly written
+      to the binary log without waiting for any other event.
+    */
+    EVENT_IMMEDIATE_LOGGING,
+    /*
+       If there is a need for different types, introduce them before this.
+    */
+    EVENT_CACHE_LOGGING_COUNT
+  };
+
+public:
   /*
     The following type definition is to be used whenever data is placed 
     and manipulated in a common buffer. Use this typedef for buffers
@@ -1006,12 +1027,6 @@ public:
   */
   uint16 flags;
   
-  /*
-    Defines the type of the cache, if any, where the event will be
-    stored before being flushed to disk.
-  */
-  uint16 cache_type;
-
   /**
     A storage to cache the global system variable's value.
     Handling of a separate event will be governed its member.
@@ -1019,14 +1034,28 @@ public:
   ulong slave_exec_mode;
 
   /**
+    Defines the type of the cache, if any, where the event will be
+    stored before being flushed to disk.
+  */
+  enum_event_cache_type event_cache_type;
+
+  /**
+    Defines when information, i.e. event or cache, will be flushed
+    to disk.
+  */
+  enum_event_logging_type event_logging_type;
+  /**
     Placeholder for event checksum while writing to binlog.
    */
   ha_checksum crc;
 #ifdef MYSQL_SERVER
   THD* thd;
 
-  Log_event();
-  Log_event(THD* thd_arg, uint16 flags_arg, bool is_transactional);
+  Log_event(enum_event_cache_type cache_type_arg= EVENT_INVALID_CACHE,
+            enum_event_logging_type logging_type_arg= EVENT_INVALID_LOGGING);
+  Log_event(THD* thd_arg, uint16 flags_arg,
+            enum_event_cache_type cache_type_arg,
+            enum_event_logging_type logging_type_arg);
   /*
     read_log_event() functions read an event from a binlog or relay
     log; used by SHOW BINLOG EVENTS, the binlog_dump thread on the
@@ -1067,7 +1096,10 @@ public:
     return thd ? thd->db : 0;
   }
 #else
-  Log_event() : temp_buf(0) {}
+  Log_event(enum_event_cache_type cache_type_arg= EVENT_INVALID_CACHE,
+            enum_event_logging_type logging_type_arg= EVENT_INVALID_LOGGING)
+  : temp_buf(0), event_cache_type(cache_type_arg),
+  event_logging_type(logging_type_arg) { }
     /* avoid having to link mysqlbinlog against libpthread */
   static Log_event* read_log_event(IO_CACHE* file,
                                    const Format_description_log_event
@@ -1141,17 +1173,17 @@ public:
   bool is_relay_log_event() const { return flags & LOG_EVENT_RELAY_LOG_F; }
   bool is_ignorable_event() const { return flags & LOG_EVENT_IGNORABLE_F; }
   bool is_no_filter_event() const { return flags & LOG_EVENT_NO_FILTER_F; }
-  inline bool use_trans_cache() const
-  { 
-    return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE);
+  inline bool is_using_trans_cache() const
+  {
+    return (event_cache_type == EVENT_TRANSACTIONAL_CACHE);
   }
-  inline void set_direct_logging()
+  inline bool is_using_stmt_cache() const
   {
-    cache_type = Log_event::EVENT_NO_CACHE;
+    return(event_cache_type == EVENT_STMT_CACHE);
   }
-  inline bool use_direct_logging()
+  inline bool is_using_immediate_logging() const
   {
-    return (cache_type == Log_event::EVENT_NO_CACHE);
+    return(event_logging_type == EVENT_IMMEDIATE_LOGGING);
   }
   Log_event(const char* buf, const Format_description_log_event
             *description_event);
@@ -1778,7 +1810,8 @@ public:
 #ifdef MYSQL_SERVER
 
   Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
-                  bool using_trans, bool direct, bool suppress_use, int error);
+                  bool using_trans, bool immediate, bool suppress_use,
+                  int error, bool ignore_command= FALSE);
   const char* get_db() { return db; }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
@@ -2369,9 +2402,10 @@ public:
 
 #ifdef MYSQL_SERVER
   Intvar_log_event(THD* thd_arg, uchar type_arg, ulonglong val_arg,
-                   uint16 cache_type_arg)
-    :Log_event(thd_arg, 0, 0), val(val_arg), type(type_arg)
-  { cache_type= cache_type_arg; }
+                   enum_event_cache_type cache_type_arg,
+                   enum_event_logging_type logging_type_arg)
+    :Log_event(thd_arg, 0, cache_type_arg, logging_type_arg),
+    val(val_arg), type(type_arg) { }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
 #endif /* HAVE_REPLICATION */
@@ -2446,9 +2480,10 @@ class Rand_log_event: public Log_event
 
 #ifdef MYSQL_SERVER
   Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg,
-                 uint16 cache_type_arg)
-    :Log_event(thd_arg, 0, 0), seed1(seed1_arg), seed2(seed2_arg)
-    { cache_type= cache_type_arg; }
+                 enum_event_cache_type cache_type_arg,
+                 enum_event_logging_type logging_type_arg)
+    :Log_event(thd_arg, 0, cache_type_arg, logging_type_arg),
+    seed1(seed1_arg), seed2(seed2_arg) { }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
 #endif /* HAVE_REPLICATION */
@@ -2492,8 +2527,12 @@ class Xid_log_event: public Log_event
    my_xid xid;
 
 #ifdef MYSQL_SERVER
-  Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg, 0, TRUE), xid(x)
-  { cache_type= EVENT_NO_CACHE; }
+  Xid_log_event(THD* thd_arg, my_xid x)
+  : Log_event(thd_arg, 0, 
+              Log_event::EVENT_TRANSACTIONAL_CACHE,
+              Log_event::EVENT_NORMAL_LOGGING),
+  xid(x)
+  { }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
 #endif /* HAVE_REPLICATION */
@@ -2546,11 +2585,14 @@ public:
   User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
                      char *val_arg, ulong val_len_arg, Item_result type_arg,
 		     uint charset_number_arg, uchar flags_arg,
-                     uint16 cache_type_arg)
-    :Log_event(thd_arg, 0, 0), name(name_arg), name_len(name_len_arg), val(val_arg),
-     val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg),
-     flags(flags_arg)
-    { is_null= !val; cache_type= cache_type_arg; }
+                     enum_event_cache_type cache_type_arg,
+                     enum_event_logging_type logging_type_arg)
+    :Log_event(thd_arg, 0, cache_type_arg, logging_type_arg), name(name_arg),
+     name_len(name_len_arg), val(val_arg), val_len(val_len_arg), type(type_arg),
+     charset_number(charset_number_arg), flags(flags_arg)
+    { 
+      is_null= !val;
+    }
   void pack_info(Protocol* protocol);
 #else
   void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
@@ -2990,7 +3032,7 @@ public:
                                ulong query_length, uint fn_pos_start_arg,
                                uint fn_pos_end_arg,
                                enum_load_dup_handling dup_handling_arg,
-                               bool using_trans, bool direct,
+                               bool using_trans, bool immediate,
                                bool suppress_use, int errcode);
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
@@ -4010,18 +4052,20 @@ class Incident_log_event : public Log_ev
 public:
 #ifdef MYSQL_SERVER
   Incident_log_event(THD *thd_arg, Incident incident)
-    : Log_event(thd_arg, LOG_EVENT_NO_FILTER_F, FALSE), m_incident(incident)
+    : Log_event(thd_arg, LOG_EVENT_NO_FILTER_F, Log_event::EVENT_NO_CACHE,
+                Log_event::EVENT_IMMEDIATE_LOGGING), m_incident(incident)
   {
     DBUG_ENTER("Incident_log_event::Incident_log_event");
     DBUG_PRINT("enter", ("m_incident: %d", m_incident));
     m_message.str= NULL;                    /* Just as a precaution */
     m_message.length= 0;
-    set_direct_logging();
     DBUG_VOID_RETURN;
   }
 
   Incident_log_event(THD *thd_arg, Incident incident, LEX_STRING const msg)
-    : Log_event(thd_arg, LOG_EVENT_NO_FILTER_F, FALSE), m_incident(incident)
+    : Log_event(thd_arg, LOG_EVENT_NO_FILTER_F,
+                Log_event::EVENT_NO_CACHE,
+                Log_event::EVENT_IMMEDIATE_LOGGING), m_incident(incident)
   {
     DBUG_ENTER("Incident_log_event::Incident_log_event");
     DBUG_PRINT("enter", ("m_incident: %d", m_incident));
@@ -4035,7 +4079,6 @@ public:
     }
     strmake(m_message.str, msg.str, msg.length);
     m_message.length= msg.length;
-    set_direct_logging();
     DBUG_VOID_RETURN;
   }
 #endif
@@ -4093,7 +4136,9 @@ class Ignorable_log_event : public Log_e
 public:
 #ifndef MYSQL_CLIENT
   Ignorable_log_event(THD *thd_arg)
-      : Log_event(thd_arg, LOG_EVENT_IGNORABLE_F, FALSE)
+      : Log_event(thd_arg, LOG_EVENT_IGNORABLE_F, 
+                  Log_event::EVENT_STMT_CACHE,
+                  Log_event::EVENT_NORMAL_LOGGING)
   {
     DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
     DBUG_VOID_RETURN;

=== modified file 'sql/log_event_old.cc'
--- a/sql/log_event_old.cc	2010-11-01 05:40:27 +0000
+++ b/sql/log_event_old.cc	2011-03-21 15:56:26 +0000
@@ -1230,8 +1230,11 @@ int Update_rows_log_event_old::do_exec_r
 #ifndef MYSQL_CLIENT
 Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid,
                                        MY_BITMAP const *cols,
-                                       bool is_transactional)
-  : Log_event(thd_arg, 0, is_transactional),
+                                       bool using_trans)
+  : Log_event(thd_arg, 0,
+              using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
+                            Log_event::EVENT_STMT_CACHE,
+              Log_event::EVENT_NORMAL_LOGGING),
     m_row_count(0),
     m_table(tbl_arg),
     m_table_id(tid),
@@ -1746,7 +1749,7 @@ int Old_rows_log_event::do_apply_event(R
     last_event_start_time here instead.
   */
   if (table && (table->s->primary_key == MAX_KEY) &&
-      !use_trans_cache() && get_flags(STMT_END_F) == RLE_NO_FLAGS)
+      !is_using_trans_cache() && get_flags(STMT_END_F) == RLE_NO_FLAGS)
   {
     /*
       ------------ Temporary fix until WL#2975 is implemented ---------

=== modified file 'sql/rpl_injector.cc'
--- a/sql/rpl_injector.cc	2011-02-01 08:51:58 +0000
+++ b/sql/rpl_injector.cc	2011-03-21 15:56:26 +0000
@@ -256,15 +256,11 @@ void injector::new_trans(THD *thd, injec
 int injector::record_incident(THD *thd, Incident incident)
 {
   Incident_log_event ev(thd, incident);
-  if (int error= mysql_bin_log.write(&ev))
-    return error;
-  return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+  return mysql_bin_log.write_incident(&ev, TRUE);
 }
 
 int injector::record_incident(THD *thd, Incident incident, LEX_STRING const message)
 {
   Incident_log_event ev(thd, incident, message);
-  if (int error= mysql_bin_log.write(&ev))
-    return error;
-  return mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE);
+  return mysql_bin_log.write_incident(&ev, TRUE);
 }

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-03-16 16:41:46 +0000
+++ b/sql/sql_class.h	2011-03-21 15:56:26 +0000
@@ -1642,8 +1642,6 @@ public:
   /*
     Public interface to write RBR events to the binlog
   */
-  void binlog_start_trans_and_stmt();
-  void binlog_set_stmt_begin();
   int binlog_write_table_map(TABLE *table, bool is_transactional,
                              bool binlog_rows_query);
   int binlog_write_row(TABLE* table, bool is_transactional,

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2011-03-16 16:41:46 +0000
+++ b/sql/sql_insert.cc	2011-03-21 15:56:26 +0000
@@ -3897,19 +3897,6 @@ select_create::prepare(List<Item> &value
   hook_ptr= &hooks;
 
   unit= u;
-
-  /*
-    Start a statement transaction before the create if we are using
-    row-based replication for the statement.  If we are creating a
-    temporary table, we need to start a statement transaction.
-  */
-  if ((thd->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) == 0 &&
-      thd->is_current_stmt_binlog_format_row() &&
-      mysql_bin_log.is_open())
-  {
-    thd->binlog_start_trans_and_stmt();
-  }
-
   DBUG_ASSERT(create_table->table == NULL);
 
   DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000););

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-03-16 16:41:46 +0000
+++ b/sql/sql_parse.cc	2011-03-21 15:56:26 +0000
@@ -2817,8 +2817,7 @@ end_with_restore_list:
       if (incident)
       {
         Incident_log_event ev(thd, incident);
-        (void) mysql_bin_log.write(&ev);        /* error is ignored */
-        if (mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE))
+        if (mysql_bin_log.write_incident(&ev, TRUE))
         {
           res= 1;
           break;


Attachment: [text/bzr-bundle] bzr/alfranio.correia@oracle.com-20110321155626-5u501mmuhf3vgo25.bundle
Thread
bzr commit into mysql-trunk branch (alfranio.correia:3773) WL#4832Alfranio Correia21 Mar
  • Re: bzr commit into mysql-trunk branch (alfranio.correia:3773) WL#4832Mats Kindahl28 Mar
    • Re: bzr commit into mysql-trunk branch (alfranio.correia:3773) WL#4832Alfranio Correia29 Mar
  • Re: bzr commit into mysql-trunk branch (alfranio.correia:3773) WL#4832Luís Soares7 Apr
    • Re: bzr commit into mysql-trunk branch (alfranio.correia:3773) WL#4832Alfranio Correia7 Apr
      • Re: bzr commit into mysql-trunk branch (alfranio.correia:3773) WL#4832Luís Soares7 Apr