List:Commits« Previous MessageNext Message »
From:Luís Soares Date:March 15 2011 7:03pm
Subject:Re: bzr commit into mysql-trunk branch (alfranio.correia:3564) WL#4832
View as plain text  
Hi Alfranio,

   Nice Work. I'll need a patch that I can apply before conducting my
   final review. I tried to apply Libing's latest patch from
   BUG#11763471 before applying yours, but that did not work out
   (conflicts and once resolved bzr would still say that it needed some
   other revision while merging the patch from WL#4832).

   In any case, I have some comments already, please find them below.

STATUS
------

   Not approved.

REQUIRED CHANGES
----------------

   RC1. The patch does not apply to a latest mysql-trunk. When I try to
        merge the bundle I get a message stating that the tree does not
        have all the required revisions in it.

   RC2. @@ -189,6 +195,12 @@ protected:

        About the comment... does it mean that the cache will only
        stores *only* transactional or non-transactional updates? Or
        that the cache can have both types of updates?


   RC3. @@ -918,8 +922,8 @@ my_bool Log_event::need_checksum()

        Would you please rewrite that "ret= ..." assignement ?
        I get a hard time following what's going on there...

   RC4. @@ -1131,16 +1158,29 @@ public:

        Perhaps I would unfold set_cache to:

        - use_trans_cache()
        - use_stmt_cache()
        - use_no_cache()             <--- you already have this one

        I would rename:

        - use_trans_cache() --> is_using_trans_cache()
        - use_stmt_cache() --> is_using_stmt_cache()
        - use_immediate_logging() --> is_using_immediate_logging()

        Why ? Because use_ and set_ make everything a bit
        ambiguous. One can, for instance, thing that use_* is a setter...

        I think my suggestions make the code easier to read.


   RC5. @@ -3895,23 +3895,9 @@ select_create::prepare(List<Item> &value

        Please, remove the empty lines you've added. There may be other
        places in the patch to fix.

   RC6. In the commit message you have:

        "DDLs go through the stmt-cache but a immediately written to the binary."

        and then:

        "Any Query event that requests an immediate logging such as
         DDLs are tagged as EVENT_IMMEDIATE_LOGGING and EVENT_NO_CACHE"

        and finally:

         "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"

        This is ambiguous, do DDLs go through the STMT-cache or not?


   RC7. @@ -565,10 +586,15 @@ static inline int

        Please improve the comment, I find it hard to follow.

        Also, if we are forcing (which is not entirely clear), why not
        use a constant instead, e.g., end_evt.set_cache(FALSE) .

        But then again, why not rename the set_cache to
        set_stmt_cache(), or even better use_stmt_cache(). See also
        comment on RC4.

        The very same comment applies to hunks:
        @@ -583,10 +609,15 @@ binlog_commit_flush_stmt_cache(THD *thd,
        @@ -601,10 +632,15 @@ binlog_commit_flush_trx_cache(THD *thd,

   RC8. In some cases, I think you could use the initializer list, see:

        @@ -2358,9 +2399,12 @@ public:
        @@ -2435,9 +2479,12 @@ class Rand_log_event: public Log_event
        @@ -2535,11 +2582,15 @@ public:

REQUESTS
--------

   R1. Would be nice to have a block diagram/workflow of the events
       logging lifecycle, would that be too much to ask for? ;)

SUGGESTIONS
-----------
  n/a

DETAILS
-------
  n/a



On 02/04/2011 02:17 PM, Alfranio Correia wrote:
> #At
> file:///home/acorreia/workspace.oracle/repository.mysql/bzrwork/wl-4832/mysql-trunk/ based
> on revid:alfranio.correia@stripped
>
>   3564 Alfranio Correia	2011-02-04
>        WL#4832
>       @ 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_row_binlog_max_cache_size.result
>          Updated test case because DDLs go through the stmt-cache before being
> flushed.
>       @ 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 a immediately written to the binary.
>
>          . Simplified the logic that decides which cache should be used.
>
>          . Merged binlog_start_trans_and_stmt() and binlog_set_stmt_begin().
>       @ sql/binlog.h
>          use_trans_cache was merged into Query_log_event::Query_log_event and
>          created write_incident(Incident_log_event *ev, bool lock).
>       @ sql/log_event.cc
>          Any Query event that requests an immediate logging such as DDLs are
>          tagged as EVENT_IMMEDIATE_LOGGING and EVENT_NO_CACHE. Other statements
>          are tagged as EVENT_NORMAL_LOGGING.
>
>          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
>       @ sql/rpl_injector.cc
>          When an incident event is logged rotation is automatically forced.
>       @ sql/sql_class.h
>          Removed this classes 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 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_row_binlog_max_cache_size.result
>        sql/binlog.cc
>        sql/binlog.h
>        sql/log_event.cc
>        sql/log_event.h
>        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-02-04 14:17:40 +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	2010-12-19 17:22:30
> +0000
> +++ b/mysql-test/extra/rpl_tests/rpl_binlog_max_cache_size.test	2011-02-04 14:17:40
> +0000
> @@ -422,10 +422,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-02-04 14:17:40
> +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-02-04 14:17:40
> +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-02-04 14:17:40
> +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_row_binlog_max_cache_size.result'
> --- a/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result	2010-12-19 17:22:30
> +0000
> +++ b/mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result	2011-02-04 14:17:40
> +0000
> @@ -149,7 +149,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 'sql/binlog.cc'
> --- a/sql/binlog.cc	2011-01-05 05:21:07 +0000
> +++ b/sql/binlog.cc	2011-02-04 14:17:40 +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,7 +86,7 @@ class binlog_cache_data
>   {
>   public:
>
> -  binlog_cache_data(): m_pending(0),
> +  binlog_cache_data(): is_transactional(FALSE), m_pending(0),
>     incident(FALSE), saved_max_binlog_cache_size(0), ptr_binlog_cache_use(0),
>     ptr_binlog_cache_disk_use(0)
>     { }
> @@ -121,6 +122,11 @@ public:
>       return(incident);
>     }
>
> +  bool has_trans_updates()
> +  {
> +    return(is_transactional);
> +  }
> +
>     virtual void reset()
>     {
>       compute_statistics();
> @@ -189,6 +195,12 @@ protected:
>       cache_log.end_of_file= saved_max_binlog_cache_size;
>     }
>
> +  /*
> +    Defines if the cache stores transactional or non-transactional
> +    updates.
> +  */
> +  bool is_transactional;
> +
>   private:
>     /*
>       Pending binrows event. This event is the event where the rows are currently
> @@ -245,7 +257,9 @@ class binlog_trx_cache_data : public bin
>   public:
>     binlog_trx_cache_data() : m_cannot_rollback(FALSE),
>     before_stmt_pos(MY_OFF_T_UNDEF)
> -  {}
> +  {
> +    is_transactional= TRUE;
> +  }
>
>     void reset()
>     {
> @@ -303,6 +317,9 @@ 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 {
> @@ -434,8 +451,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,12 +482,12 @@ 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=
>       (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton);
>     cache_mngr->trx_cache.restore_savepoint(pos);
> +
>     DBUG_VOID_RETURN;
>   }
>
> @@ -516,23 +531,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->use_trans_cache()&& 
> cache_data->has_trans_updates()) ||
> +              (!end_evt->use_trans_cache()&& 
> !cache_data->has_trans_updates()));
> +
>     if (!cache_data->empty())
>     {
> -    if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional))
> +    if (thd->binlog_flush_pending_rows_event(TRUE,
> cache_data->has_trans_updates()))
> +      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 +562,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 +586,15 @@ 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->has_trans_updates(), FALSE, TRUE, 0);
> +  /*
> +    Force the use of the stmt-cache because the current statement may
> +    be something that makes Query_log_event to choose another cache.
> +  */
> +  end_evt.set_cache(cache_data->has_trans_updates());
> +  return (binlog_flush_cache(thd, cache_data,&end_evt));
>   }
>
>   /**
> @@ -583,10 +609,15 @@ 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->has_trans_updates(), FALSE, TRUE, 0);
> +  /*
> +    Force the use of the trx-cache because the current statement may
> +    be something that makes Query_log_event to choose another cache.
> +  */
> +  end_evt.set_cache(cache_data->has_trans_updates());
> +  return (binlog_flush_cache(thd, cache_data,&end_evt));
>   }
>
>   /**
> @@ -601,10 +632,15 @@ 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->has_trans_updates(), FALSE, TRUE, 0);
> +  /*
> +    Force the use of the trx-cache because the current statement may
> +    be something that makes Query_log_event to choose another cache.
> +  */
> +  end_evt.set_cache(cache_data->has_trans_updates());
> +  return (binlog_flush_cache(thd, cache_data,&end_evt));
>   }
>
>   /**
> @@ -622,8 +658,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 +678,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 +705,7 @@ binlog_truncate_trx_cache(THD *thd, binl
>     else
>       cache_mngr->trx_cache.restore_prev_position();
>
> -  DBUG_ASSERT(thd->binlog_get_pending_rows_event(is_transactional) == NULL);
> +  DBUG_ASSERT(thd->binlog_get_pending_rows_event(TRUE) == NULL);
>     DBUG_RETURN(error);
>   }
>
> @@ -1102,33 +1132,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.
> @@ -3199,7 +3202,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())
>     {
> @@ -3236,7 +3239,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()));
>
> @@ -3318,30 +3321,16 @@ 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->use_trans_cache() ||
> event_info->use_stmt_cache());
> +
> +    binlog_start_trans_and_stmt(thd, event_info);
>
> -      thd->binlog_start_trans_and_stmt();
> -    }
> +    bool is_trans_cache= event_info->use_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()));
> -
>       /*
>          No check for auto events flag here - this write method should
>          never be called if auto-events are enabled.
> @@ -3354,16 +3343,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;
>           }
> @@ -3374,14 +3358,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;
>           }
> @@ -3403,7 +3389,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;
>             }
> @@ -3420,28 +3407,18 @@ bool MYSQL_BIN_LOG::write(Log_event *eve
>
>       error= 0;
>
> +    /*
> +      Checks if a non-transactional event was written to a trx-cache.
> +    */
>       if (is_trans_cache&&  stmt_cannot_safely_rollback(thd))
>         cache_mngr->set_trx_cache_cannot_rollback();
>   err:
> -    if (event_info->use_direct_logging())
> +    if (event_info->use_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)
> @@ -3791,7 +3768,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");
> @@ -3799,40 +3787,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.
> @@ -3842,8 +3851,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);
> @@ -3857,14 +3865,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)))
> @@ -3877,9 +3877,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;
>
> @@ -3913,7 +3910,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++;
> @@ -4322,17 +4319,12 @@ int THD::binlog_setup_trx_data()
>     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.
> @@ -4347,55 +4339,86 @@ int THD::binlog_setup_trx_data()
>         we should use the first. This means that calls to this function
>         can be used to start the statement before the first table map
>         event, to include some extra events.
> - */
>
> -void
> -THD::binlog_start_trans_and_stmt()
> +  @param thd         Thread variable
> +  @param start_event The first event requested to be written into the
> +                     binary log
> + */
> +inline void binlog_start_trans_and_stmt(THD *thd, Log_event *start_event)
>   {
> -  binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this,
> binlog_hton);
>     DBUG_ENTER("binlog_start_trans_and_stmt");
> -  DBUG_PRINT("enter", ("cache_mngr: %p 
> cache_mngr->trx_cache.get_prev_position(): %lu",
> -                       cache_mngr,
> -                       (cache_mngr ? (ulong)
> cache_mngr->trx_cache.get_prev_position() :
> -                        (ulong) 0)));
> -
> -  if (cache_mngr == NULL ||
> -      cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF)
> -  {
> -    this->binlog_set_stmt_begin();
> -    if (in_multi_stmt_transaction_mode())
> -      trans_register_ha(this, TRUE, binlog_hton);
> -    trans_register_ha(this, FALSE, binlog_hton);
> +
> +  /*
> +    Initialize the cache manager if this was not done yet.
> +  */
> +  if (thd_get_ha_data(thd, binlog_hton) == NULL)
> +    thd->binlog_setup_trx_data();
> +
> +  /*
> +    If the event is requesting immediatly logging, there is no need to go
> +    further and set savepoint and register callbacks.
> +  */
> +  if (start_event->use_immediate_logging())
> +    DBUG_VOID_RETURN;
> +
> +  /*
> +    Retrieve the appropriated cache.
> +  */
> +  bool is_transactional= start_event->use_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);
> +    qinfo.set_cache(is_transactional);
> +    qinfo.write(file);
> +  }
>
> +  DBUG_VOID_RETURN;
> +}
>
>   /**
>     This function writes a table map to the binary log.
> @@ -4432,14 +4455,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())
>     {
> @@ -4483,7 +4505,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();
>     }
> @@ -4503,16 +4525,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);
>   }
> @@ -4936,13 +4955,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-01-05 05:21:07 +0000
> +++ b/sql/binlog.h	2011-02-04 14:17:40 +0000
> @@ -198,12 +198,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);
> @@ -284,7 +285,6 @@ extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG
>
>   bool trans_has_updated_trans_table(const THD* thd);
>   bool stmt_has_updated_trans_table(const THD *thd);
> -bool use_trans_cache(const THD* thd, bool is_transactional);
>   bool ending_trans(THD* thd, const bool all);
>   bool ending_single_stmt_trans(THD* thd, const bool all);
>   bool stmt_cannot_safely_rollback(const THD* thd);
>
> === modified file 'sql/log_event.cc'
> --- a/sql/log_event.cc	2011-01-28 14:49:41 +0000
> +++ b/sql/log_event.cc	2011-02-04 14:17:40 +0000
> @@ -684,16 +684,18 @@ const char* Log_event::get_type_str()
>   #ifndef MYSQL_CLIENT
>   Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans)
>     :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(EVENT_INVALID_CACHE),
> +  event_logging_type(EVENT_INVALID_LOGGING),
> +  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;
> +    event_cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
>     else
> -    cache_type= Log_event::EVENT_STMT_CACHE;
> +    event_cache_type= Log_event::EVENT_STMT_CACHE;
> +  event_logging_type= Log_event::EVENT_NORMAL_LOGGING;
>   }
>
>   /**
> @@ -724,8 +726,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;
> @@ -918,8 +922,8 @@ my_bool Log_event::need_checksum()
>     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;
> +     (event_cache_type == Log_event::EVENT_NO_CACHE))?
> +    binlog_checksum_options : FALSE;
>
>     /*
>       FD calls the methods before data_written has been calculated.
> @@ -959,7 +963,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);
>   }
> @@ -2688,23 +2692,20 @@ 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 an event for binlogging.
> +
> +  @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  There is a modified transactional table
> +  @param immediate    Should be flushed immediately
> +  @param suppress_use Suppress the generation of 'USE' statements
> +  @param errcode      The error code of the query
>   */
>   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)
>
>     :Log_event(thd_arg,
>                (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
> @@ -2804,7 +2805,8 @@ Query_log_event::Query_log_event(THD* th
>       Note that a cache will not be used if the parameter direct is TRUE.
>     */
>     bool trx_cache= FALSE;
> -  cache_type= Log_event::EVENT_INVALID_CACHE;
> +  event_cache_type= Log_event::EVENT_INVALID_CACHE;
> +  event_logging_type= Log_event::EVENT_INVALID_LOGGING;
>
>     switch (lex->sql_command)
>     {
> @@ -2831,19 +2833,29 @@ Query_log_event::Query_log_event(THD* th
>         break;
>     }
>
> -  if (!use_cache || direct)
> +  if (!use_cache || immediate)
>     {
> -    cache_type= Log_event::EVENT_NO_CACHE;
> +    event_logging_type= Log_event::EVENT_IMMEDIATE_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;
> +                                          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
> -    cache_type= Log_event::EVENT_STMT_CACHE;
> -  DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE);
> +  {
> +    event_logging_type= Log_event::EVENT_NORMAL_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));
>   }
> @@ -5489,7 +5501,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)
> @@ -7326,9 +7339,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)
>
> === modified file 'sql/log_event.h'
> --- a/sql/log_event.h	2011-01-11 05:13:23 +0000
> +++ b/sql/log_event.h	2011-02-04 14:17:40 +0000
> @@ -920,9 +920,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
> @@ -937,15 +938,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
> @@ -996,22 +1017,28 @@ 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.
>     */
>     ulong slave_exec_mode;
>
> +  /*
> +    Defines the type of the cache, if any, where the event will be
> +    stored before being flushed to disk.
> +  */
> +  uint16 event_cache_type;
> +
> +  /*
> +    Defines when information, i.e. event or cache will be stored into
> +    disk.
> +  */
> +  uint16 event_logging_type;
>     /**
>       Placeholder for event checksum while writing to binlog.
>      */
>     ha_checksum crc;
> +
>   #ifdef MYSQL_SERVER
>     THD* thd;
>
> @@ -1131,16 +1158,29 @@ 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; }
>     inline bool use_trans_cache() const
> -  {
> -    return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE);
> +  {
> +    return (event_cache_type == EVENT_TRANSACTIONAL_CACHE);
>     }
> -  inline void set_direct_logging()
> +  inline bool use_stmt_cache() const
>     {
> -    cache_type = Log_event::EVENT_NO_CACHE;
> +    return(event_cache_type == EVENT_STMT_CACHE);
>     }
> -  inline bool use_direct_logging()
> +  inline bool use_immediate_logging() const
>     {
> -    return (cache_type == Log_event::EVENT_NO_CACHE);
> +    return(event_logging_type == EVENT_IMMEDIATE_LOGGING);
> +  }
> +  inline void set_cache(bool is_transactional)
> +  {
> +    event_logging_type= EVENT_NORMAL_LOGGING;
> +    if (is_transactional)
> +      event_cache_type= EVENT_TRANSACTIONAL_CACHE;
> +    else
> +      event_cache_type= EVENT_STMT_CACHE;
> +  }
> +  inline void set_no_cache()
> +  {
> +    event_logging_type= EVENT_IMMEDIATE_LOGGING;
> +    event_cache_type = EVENT_NO_CACHE;
>     }
>     Log_event(const char* buf, const Format_description_log_event
>               *description_event);
> @@ -1767,7 +1807,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);
>     const char* get_db() { return db; }
>   #ifdef HAVE_REPLICATION
>     void pack_info(Protocol* protocol);
> @@ -2358,9 +2399,12 @@ public:
>
>   #ifdef MYSQL_SERVER
>     Intvar_log_event(THD* thd_arg, uchar type_arg, ulonglong val_arg,
> -                   uint16 cache_type_arg)
> +                   uint16 cache_type_arg, uint16 logging_type_arg)
>       :Log_event(thd_arg, 0, 0), val(val_arg), type(type_arg)
> -  { cache_type= cache_type_arg; }
> +  {
> +    event_cache_type= cache_type_arg;
> +    event_logging_type= logging_type_arg;
> +  }
>   #ifdef HAVE_REPLICATION
>     void pack_info(Protocol* protocol);
>   #endif /* HAVE_REPLICATION */
> @@ -2435,9 +2479,12 @@ 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)
> +                 uint16 cache_type_arg, uint16 logging_type_arg)
>       :Log_event(thd_arg, 0, 0), seed1(seed1_arg), seed2(seed2_arg)
> -    { cache_type= cache_type_arg; }
> +    {
> +      event_cache_type= cache_type_arg;
> +      event_logging_type= logging_type_arg;
> +    }
>   #ifdef HAVE_REPLICATION
>     void pack_info(Protocol* protocol);
>   #endif /* HAVE_REPLICATION */
> @@ -2482,7 +2529,7 @@ class Xid_log_event: public Log_event
>
>   #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; }
> +  { }
>   #ifdef HAVE_REPLICATION
>     void pack_info(Protocol* protocol);
>   #endif /* HAVE_REPLICATION */
> @@ -2535,11 +2582,15 @@ 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)
> +                     uint16 cache_type_arg, uint16 logging_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; }
> +    {
> +      is_null= !val;
> +      event_cache_type= cache_type_arg;
> +      event_logging_type= logging_type_arg;
> +    }
>     void pack_info(Protocol* protocol);
>   #else
>     void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
> @@ -2979,7 +3030,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);
> @@ -4005,7 +4056,8 @@ public:
>       DBUG_PRINT("enter", ("m_incident: %d", m_incident));
>       m_message.str= NULL;                    /* Just as a precaution */
>       m_message.length= 0;
> -    set_direct_logging();
> +    event_cache_type= Log_event::EVENT_NO_CACHE;
> +    event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
>       DBUG_VOID_RETURN;
>     }
>
> @@ -4024,7 +4076,8 @@ public:
>       }
>       strmake(m_message.str, msg.str, msg.length);
>       m_message.length= msg.length;
> -    set_direct_logging();
> +    event_cache_type= Log_event::EVENT_NO_CACHE;
> +    event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
>       DBUG_VOID_RETURN;
>     }
>   #endif
>
> === modified file 'sql/rpl_injector.cc'
> --- a/sql/rpl_injector.cc	2010-12-10 16:55:50 +0000
> +++ b/sql/rpl_injector.cc	2011-02-04 14:17:40 +0000
> @@ -242,15 +242,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-01-28 14:49:41 +0000
> +++ b/sql/sql_class.h	2011-02-04 14:17:40 +0000
> @@ -1642,8 +1642,6 @@ public:
>     /*
>       Public interface to write RBR events to the binlog
>     */
> -  void binlog_start_trans_and_stmt();
> -  void binlog_set_stmt_begin();
>     int binlog_write_table_map(TABLE *table, bool is_transactional,
>                                bool binlog_rows_query);
>     int binlog_write_row(TABLE* table, bool is_transactional,
>
> === modified file 'sql/sql_insert.cc'
> --- a/sql/sql_insert.cc	2011-01-28 14:49:41 +0000
> +++ b/sql/sql_insert.cc	2011-02-04 14:17:40 +0000
> @@ -3895,23 +3895,9 @@ select_create::prepare(List<Item>  &value
>
>     MY_HOOKS hooks(this, create_table, select_tables);
>     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););
>
>     if (!(table= create_table_from_items(thd, create_info, create_table,
>
> === modified file 'sql/sql_parse.cc'
> --- a/sql/sql_parse.cc	2011-01-28 14:49:41 +0000
> +++ b/sql/sql_parse.cc	2011-02-04 14:17:40 +0000
> @@ -2816,8 +2816,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 branch (alfranio.correia:3564) WL#4832Alfranio Correia4 Feb
  • Re: bzr commit into mysql-trunk branch (alfranio.correia:3564) WL#4832Mats Kindahl10 Mar
    • Re: bzr commit into mysql-trunk branch (alfranio.correia:3564) WL#4832Alfranio Correia10 Mar
      • Re: bzr commit into mysql-trunk branch (alfranio.correia:3564) WL#4832Mats Kindahl10 Mar
  • Re: bzr commit into mysql-trunk branch (alfranio.correia:3564) WL#4832Luís Soares15 Mar
    • Re: bzr commit into mysql-trunk branch (alfranio.correia:3564) WL#4832Alfranio Correia17 Mar