List:Commits« Previous MessageNext Message »
From:Luís Soares Date:May 13 2011 1:45pm
Subject:Re: bzr commit into mysql-trunk-mtr branch (alfranio.correia:3080)
WL#4832
View as plain text  
Alfranio,

Following my previous comments (http://lists.mysql.com/commits/134932),
I have nothing else to point out. Patch looks OK. Thanks for considering
my suggestion and for doing this work.

Regards,
Luís

On 05/12/2011 10:51 PM, Alfranio Correia wrote:
> #At
> file:///home/acorreia/workspace.oracle/repository.mysql/bzrwork/wl-4832/mysql-trunk/ based
> on revid:alfranio.correia@stripped
>
>   3080 Alfranio Correia	2011-05-12
>        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/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/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-05-12 21:51:20 +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-05-12 21:51:20
> +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/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-05-12 21:51:20
> +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-05-12 21:51:20
> +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-05-12 21:51:20
> +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-05-05 09:58:48 +0000
> +++ b/mysql-test/suite/rpl/r/rpl_crash_safe_master.result	2011-05-12 21:51:20 +0000
> @@ -69,7 +69,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));
> @@ -95,6 +94,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
> @@ -110,8 +110,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-05-12 21:51:20
> +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-05-05 09:58:48 +0000
> +++ b/mysql-test/suite/rpl/t/rpl_crash_safe_master.test	2011-05-12 21:51:20 +0000
> @@ -168,7 +168,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)
> @@ -178,6 +177,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;
> @@ -199,12 +199,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-05-12 17:29:19 +0000
> +++ b/sql/binlog.cc	2011-05-12 21:51:20 +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()
>     {
> @@ -116,11 +124,16 @@ public:
>       incident= TRUE;
>     }
>
> -  bool has_incident(void)
> +  bool has_incident(void) const
>     {
>       return(incident);
>     }
>
> +  bool is_trx_cache() const
> +  {
> +    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()
>     {
> @@ -254,7 +250,7 @@ public:
>       binlog_cache_data::reset();
>     }
>
> -  bool cannot_rollback()
> +  bool cannot_rollback() const
>     {
>       return m_cannot_rollback;
>     }
> @@ -269,9 +265,9 @@ public:
>       return my_b_tell(&cache_log);
>     }
>
> -  my_off_t get_prev_position()
> +  my_off_t get_prev_position() const
>     {
> -     return(before_stmt_pos);
> +     return before_stmt_pos;
>     }
>
>     void set_prev_position(my_off_t pos)
> @@ -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()
>     {
> @@ -337,7 +335,7 @@ public:
>       trx_cache.set_cannot_rollback();
>     }
>
> -  bool trx_cache_cannot_rollback()
> +  bool trx_cache_cannot_rollback() const
>     {
>       return trx_cache.cannot_rollback();
>     }
> @@ -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,10 @@ 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);
> +  return binlog_flush_cache(thd, cache_data,&end_evt);
>   }
>
>   /**
> @@ -622,8 +623,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 +643,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 +670,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);
>   }
>
> @@ -1148,33 +1143,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.
> @@ -3532,7 +3500,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())
>     {
> @@ -3569,7 +3537,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()));
>
> @@ -3615,7 +3583,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);
>     }
>
> @@ -3627,7 +3595,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);
>
>     /*
> @@ -3652,28 +3620,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()));
>
>       /*
> @@ -3688,16 +3643,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;
>           }
> @@ -3708,14 +3658,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;
>           }
> @@ -3737,7 +3689,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;
>             }
> @@ -3763,25 +3716,12 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
>       error= 0;
>
>   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)
> @@ -4134,7 +4074,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");
> @@ -4142,40 +4093,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.
> @@ -4185,8 +4157,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);
> @@ -4200,14 +4171,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)))
> @@ -4220,9 +4183,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;
>
> @@ -4256,7 +4216,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++;
> @@ -4757,25 +4717,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.
> @@ -4790,55 +4745,89 @@ 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()
> +  Note however that IMMEDIATE_LOGGING implies that the statement is
> +  written without BEGIN/COMMIT.
> +
> +  @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.
> @@ -4875,14 +4864,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())
>     {
> @@ -4926,7 +4914,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();
>     }
> @@ -4946,16 +4934,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);
>   }
> @@ -5379,13 +5364,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-05-12 17:29:19 +0000
> +++ b/sql/binlog.h	2011-05-12 21:51:20 +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 trans_cannot_safely_rollback(const THD* thd);
>
> === modified file 'sql/log_event.cc'
> --- a/sql/log_event.cc	2011-05-12 17:29:19 +0000
> +++ b/sql/log_event.cc	2011-05-12 21:51:20 +0000
> @@ -678,18 +678,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;
>   }
>
>   /**
> @@ -699,9 +697,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;
>     /*
> @@ -720,8 +720,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;
> @@ -904,18 +906,20 @@ 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;
> +  else
> +    ret= FALSE;
>
>     /*
>       FD calls the methods before data_written has been calculated.
> @@ -955,7 +959,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);
>   }
> @@ -2681,29 +2685,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),
> @@ -2781,62 +2789,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));
>   }
> @@ -4828,7 +4920,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),
> @@ -5473,9 +5567,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];
> @@ -5483,7 +5577,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)
> @@ -6839,7 +6934,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)
>   {
>   }
> @@ -7006,7 +7105,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
> @@ -7102,7 +7205,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
> @@ -7318,9 +7425,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)
> @@ -7595,8 +7702,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),
> @@ -8518,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-22 11:44:40 +0000
> +++ b/sql/log_event.h	2011-05-12 21:51:20 +0000
> @@ -926,9 +926,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
> @@ -943,15 +944,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
> @@ -1002,12 +1023,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.
> @@ -1015,14 +1030,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
> @@ -1063,7 +1092,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
> @@ -1137,17 +1169,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);
> @@ -1774,7 +1806,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);
> @@ -2365,9 +2398,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 */
> @@ -2442,9 +2476,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 */
> @@ -2488,8 +2523,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 */
> @@ -2542,11 +2581,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);
> @@ -2986,7 +3028,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);
> @@ -4006,18 +4048,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));
> @@ -4031,7 +4075,6 @@ public:
>       }
>       strmake(m_message.str, msg.str, msg.length);
>       m_message.length= msg.length;
> -    set_direct_logging();
>       DBUG_VOID_RETURN;
>     }
>   #endif
> @@ -4089,7 +4132,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-05-12 21:51:20 +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-05-12 21:51:20 +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-05-12 17:29:19 +0000
> +++ b/sql/sql_class.h	2011-05-12 21:51:20 +0000
> @@ -1851,8 +1851,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-05-12 17:29:19 +0000
> +++ b/sql/sql_insert.cc	2011-05-12 21:51:20 +0000
> @@ -3895,19 +3895,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-05-12 17:29:19 +0000
> +++ b/sql/sql_parse.cc	2011-05-12 21:51:20 +0000
> @@ -2929,8 +2929,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;
>
>
>
>
>

Thread
bzr commit into mysql-trunk-mtr branch (alfranio.correia:3080) WL#4832Alfranio Correia12 May
  • Re: bzr commit into mysql-trunk-mtr branch (alfranio.correia:3080)WL#4832Luís Soares13 May