]> git.pld-linux.org Git - packages/mysql.git/commitdiff
- update patches auto/th/mysql-5_1_35-2 auto/ti/mysql-5_1_35-2
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Fri, 19 Jun 2009 21:40:45 +0000 (21:40 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    mysql-acc-pslist.patch -> 1.5
    mysql-innodb_rw_lock.patch -> 1.2
    mysql-microslow.patch -> 1.2
    mysql-split_buf_pool_mutex_fixed_optimistic_safe.patch -> 1.2
    mysql-userstats.patch -> 1.5
    mysql.spec -> 1.453

mysql-acc-pslist.patch
mysql-innodb_rw_lock.patch [new file with mode: 0644]
mysql-microslow.patch
mysql-split_buf_pool_mutex_fixed_optimistic_safe.patch [new file with mode: 0644]
mysql-userstats.patch
mysql.spec

index 56daca3a7fb0f2dcc082a97084f201423e660a93..f447f4ff7b36099d6405f22034dd841f7ca48673 100644 (file)
@@ -1,6 +1,6 @@
-diff -r 174803e7e869 mysql-test/r/create.result
---- a/mysql-test/r/create.result       Thu Sep 04 12:17:56 2008 -0700
-+++ b/mysql-test/r/create.result       Thu Sep 04 12:20:19 2008 -0700
+diff -r 1a59073d658d mysql-test/r/create.result
+--- a/mysql-test/r/create.result       Sat Sep 13 17:31:30 2008 -0700
++++ b/mysql-test/r/create.result       Sat Sep 13 17:31:40 2008 -0700
 @@ -1720,7 +1720,8 @@
    `COMMAND` varchar(16) NOT NULL DEFAULT '',
    `TIME` bigint(7) NOT NULL DEFAULT '0',
@@ -21,19 +21,9 @@ diff -r 174803e7e869 mysql-test/r/create.result
  ) ENGINE=MyISAM DEFAULT CHARSET=utf8
  drop table t1;
  create table t1 like information_schema.character_sets;
-diff -r 174803e7e869 patch_info/acc-pslist.info
---- /dev/null  Thu Jan 01 00:00:00 1970 +0000
-+++ b/patch_info/acc-pslist.info       Thu Sep 04 12:20:19 2008 -0700
-@@ -0,0 +1,6 @@
-+File=acc-pslist.patch
-+Name=Milliseconds in PROCESSLIST
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-diff -r 174803e7e869 sql/sql_show.cc
---- a/sql/sql_show.cc  Thu Sep 04 12:17:56 2008 -0700
-+++ b/sql/sql_show.cc  Thu Sep 04 12:20:19 2008 -0700
+diff -r 1a59073d658d sql/sql_show.cc
+--- a/sql/sql_show.cc  Sat Sep 13 17:31:30 2008 -0700
++++ b/sql/sql_show.cc  Sat Sep 13 17:31:40 2008 -0700
 @@ -1803,7 +1803,7 @@
    TABLE *table= tables->table;
    CHARSET_INFO *cs= system_charset_info;
@@ -43,7 +33,7 @@ diff -r 174803e7e869 sql/sql_show.cc
    DBUG_ENTER("fill_process_list");
  
    user= thd->security_ctx->master_access & PROCESS_ACL ?
-@@ -1861,8 +1861,8 @@
+@@ -1873,8 +1873,8 @@
          table->field[4]->store(command_name[tmp->command].str,
                                 command_name[tmp->command].length, cs);
        /* MYSQL_TIME */
@@ -70,7 +60,7 @@ diff -r 174803e7e869 sql/sql_show.cc
      }
    }
  
-@@ -5532,7 +5536,7 @@
+@@ -5531,7 +5535,7 @@
      into it two numbers, based on modulus of base-10 numbers.  In the ones
      position is the number of decimals.  Tens position is unused.  In the
      hundreds and thousands position is a two-digit decimal number representing
@@ -79,7 +69,7 @@ diff -r 174803e7e869 sql/sql_show.cc
      0<decimals<10 and 0<=length<100 .
  
    @param
-@@ -6540,6 +6544,8 @@
+@@ -6539,6 +6543,8 @@
    {"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
    {"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
     SKIP_OPEN_TABLE},
diff --git a/mysql-innodb_rw_lock.patch b/mysql-innodb_rw_lock.patch
new file mode 100644 (file)
index 0000000..f4a33fb
--- /dev/null
@@ -0,0 +1,1309 @@
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.h mysql-5.1.29-rc/storage/innobase/include/sync0rw.h
+--- mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.h    2008-10-12 06:54:14.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/sync0rw.h 2008-11-17 15:34:00.000000000 +0900
+@@ -328,7 +328,17 @@
+ Accessor functions for rw lock. */
+ UNIV_INLINE
+ ulint
+-rw_lock_get_waiters(
++rw_lock_get_s_waiters(
++/*==================*/
++      rw_lock_t*      lock);
++UNIV_INLINE
++ulint
++rw_lock_get_x_waiters(
++/*==================*/
++      rw_lock_t*      lock);
++UNIV_INLINE
++ulint
++rw_lock_get_wx_waiters(
+ /*================*/
+       rw_lock_t*      lock);
+ UNIV_INLINE
+@@ -412,6 +422,11 @@
+       rw_lock_debug_t*        info);  /* in: debug struct */
+ #endif /* UNIV_SYNC_DEBUG */
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++/* This value means NOT_LOCKED */
++#define RW_LOCK_BIAS          0x00100000
++#endif
++
+ /* NOTE! The structure appears here only for the compiler to know its size.
+ Do not use its fields directly! The structure used in the spin lock
+ implementation of a read-write lock. Several threads may have a shared lock
+@@ -421,9 +436,9 @@
+ field. Then no new readers are allowed in. */
+ struct rw_lock_struct {
+-      os_event_t      event;  /* Used by sync0arr.c for thread queueing */
+-
+-#ifdef __WIN__
++                      /* Used by sync0arr.c for thread queueing */
++      os_event_t      s_event;        /* Used for s_lock */
++      os_event_t      x_event;        /* Used for x_lock */
+       os_event_t      wait_ex_event;  /* This windows specific event is
+                               used by the thread which has set the
+                               lock state to RW_LOCK_WAIT_EX. The
+@@ -431,30 +446,34 @@
+                               thread will be the next one to proceed
+                               once the current the event gets
+                               signalled. See LEMMA 2 in sync0sync.c */
++
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      volatile lint   lock_word;      /* Used by using atomic builtin */
+ #endif
+-      ulint   reader_count;   /* Number of readers who have locked this
++      volatile ulint  reader_count;   /* Number of readers who have locked this
+                               lock in the shared mode */
+-      ulint   writer;         /* This field is set to RW_LOCK_EX if there
++      volatile ulint  writer;         /* This field is set to RW_LOCK_EX if there
+                               is a writer owning the lock (in exclusive
+                               mode), RW_LOCK_WAIT_EX if a writer is
+                               queueing for the lock, and
+                               RW_LOCK_NOT_LOCKED, otherwise. */
+-      os_thread_id_t  writer_thread;
++      volatile os_thread_id_t writer_thread;
+                               /* Thread id of a possible writer thread */
+-      ulint   writer_count;   /* Number of times the same thread has
++      volatile ulint  writer_count;   /* Number of times the same thread has
+                               recursively locked the lock in the exclusive
+                               mode */
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_t mutex;          /* The mutex protecting rw_lock_struct */
++#endif
+       ulint   pass;           /* Default value 0. This is set to some
+                               value != 0 given by the caller of an x-lock
+                               operation, if the x-lock is to be passed to
+                               another thread to unlock (which happens in
+                               asynchronous i/o). */
+-      ulint   waiters;        /* This ulint is set to 1 if there are
+-                              waiters (readers or writers) in the global
+-                              wait array, waiting for this rw_lock.
+-                              Otherwise, == 0. */
++      volatile ulint  s_waiters;      /* 1: there are waiters (s_lock) */
++      volatile ulint  x_waiters;      /* 1: there are waiters (x_lock) */
++      volatile ulint  wait_ex_waiters;        /* 1: there are waiters (wait_ex) */
+       UT_LIST_NODE_T(rw_lock_t) list;
+                               /* All allocated rw locks are put into a
+                               list */
+@@ -467,7 +486,7 @@
+       const char*     cfile_name;/* File name where lock created */
+       const char*     last_s_file_name;/* File name where last s-locked */
+       const char*     last_x_file_name;/* File name where last x-locked */
+-      ibool           writer_is_wait_ex;
++      volatile ibool          writer_is_wait_ex;
+                               /* This is TRUE if the writer field is
+                               RW_LOCK_WAIT_EX; this field is located far
+                               from the memory update hotspot fields which
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.ic mysql-5.1.29-rc/storage/innobase/include/sync0rw.ic
+--- mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.ic   2008-10-12 06:54:14.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/sync0rw.ic        2008-11-17 16:07:32.000000000 +0900
+@@ -47,20 +47,52 @@
+ Accessor functions for rw lock. */
+ UNIV_INLINE
+ ulint
+-rw_lock_get_waiters(
++rw_lock_get_s_waiters(
+ /*================*/
+       rw_lock_t*      lock)
+ {
+-      return(lock->waiters);
++      return(lock->s_waiters);
+ }
+ UNIV_INLINE
+-void
+-rw_lock_set_waiters(
++ulint
++rw_lock_get_x_waiters(
++/*================*/
++      rw_lock_t*      lock)
++{
++      return(lock->x_waiters);
++}
++UNIV_INLINE
++ulint
++rw_lock_get_wx_waiters(
+ /*================*/
++      rw_lock_t*      lock)
++{
++      return(lock->wait_ex_waiters);
++}
++UNIV_INLINE
++void
++rw_lock_set_s_waiters(
++      rw_lock_t*      lock,
++      ulint           flag)
++{
++      lock->s_waiters = flag;
++}
++UNIV_INLINE
++void
++rw_lock_set_x_waiters(
+       rw_lock_t*      lock,
+       ulint           flag)
+ {
+-      lock->waiters = flag;
++      lock->x_waiters = flag;
++}
++UNIV_INLINE
++void
++rw_lock_set_wx_waiters(
++/*================*/
++      rw_lock_t*      lock,
++      ulint           flag)
++{
++      lock->wait_ex_waiters = flag;
+ }
+ UNIV_INLINE
+ ulint
+@@ -68,7 +100,19 @@
+ /*===============*/
+       rw_lock_t*      lock)
+ {
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if (lock->writer == RW_LOCK_NOT_LOCKED) {
++              return(RW_LOCK_NOT_LOCKED);
++      }
++
++      if (lock->writer_is_wait_ex) {
++              return(RW_LOCK_WAIT_EX);
++      } else {
++              return(RW_LOCK_EX);
++      }
++#else
+       return(lock->writer);
++#endif
+ }
+ UNIV_INLINE
+ void
+@@ -96,6 +140,7 @@
+ {
+       lock->reader_count = count;
+ }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ UNIV_INLINE
+ mutex_t*
+ rw_lock_get_mutex(
+@@ -104,6 +149,7 @@
+ {
+       return(&(lock->mutex));
+ }
++#endif
+ /**********************************************************************
+ Returns the value of writer_count for the lock. Does not reserve the lock
+@@ -133,13 +179,27 @@
+       const char*     file_name, /* in: file name where lock requested */
+       ulint           line)   /* in: line where requested */
+ {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       ut_ad(mutex_own(rw_lock_get_mutex(lock)));
++#endif
+       /* Check if the writer field is free */
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if (UNIV_LIKELY(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)) {
++              /* try s-lock */
++              if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
++                      /* fail */
++                      __sync_fetch_and_add(&(lock->lock_word),1);
++                      return(FALSE);  /* locking did not succeed */
++              }
++              /* success */
++              __sync_fetch_and_add(&(lock->reader_count),1);
++#else
+       if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
+               /* Set the shared lock by incrementing the reader count */
+               lock->reader_count++;
++#endif
+ #ifdef UNIV_SYNC_DEBUG
+               rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
+@@ -166,11 +226,15 @@
+       const char*     file_name,      /* in: file name where requested */
+       ulint           line)           /* in: line where lock requested */
+ {
+-      ut_ad(lock->writer == RW_LOCK_NOT_LOCKED);
++      ut_ad(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
+       ut_ad(rw_lock_get_reader_count(lock) == 0);
+       /* Set the shared lock by incrementing the reader count */
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      __sync_fetch_and_add(&(lock->reader_count),1);
++#else
+       lock->reader_count++;
++#endif
+       lock->last_s_file_name = file_name;
+       lock->last_s_line = line;
+@@ -198,7 +262,11 @@
+       rw_lock_set_writer(lock, RW_LOCK_EX);
+       lock->writer_thread = os_thread_get_curr_id();
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      __sync_fetch_and_add(&(lock->writer_count),1);
++#else
+       lock->writer_count++;
++#endif
+       lock->pass = 0;
+       lock->last_x_file_name = file_name;
+@@ -240,15 +308,21 @@
+       ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+ #endif /* UNIV_SYNC_DEBUG */
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_enter(rw_lock_get_mutex(lock));
++#endif
+       if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+               mutex_exit(rw_lock_get_mutex(lock));
++#endif
+               return; /* Success */
+       } else {
+               /* Did not succeed, try spin wait */
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+               mutex_exit(rw_lock_get_mutex(lock));
++#endif
+               rw_lock_s_lock_spin(lock, pass, file_name, line);
+@@ -271,11 +345,23 @@
+ {
+       ibool   success = FALSE;
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
++              /* try s-lock */
++              if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
++                      /* fail */
++                      __sync_fetch_and_add(&(lock->lock_word),1);
++                      return(FALSE);  /* locking did not succeed */
++              }
++              /* success */
++              __sync_fetch_and_add(&(lock->reader_count),1);
++#else
+       mutex_enter(rw_lock_get_mutex(lock));
+       if (lock->writer == RW_LOCK_NOT_LOCKED) {
+               /* Set the shared lock by incrementing the reader count */
+               lock->reader_count++;
++#endif
+ #ifdef UNIV_SYNC_DEBUG
+               rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
+@@ -288,7 +374,9 @@
+               success = TRUE;
+       }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_exit(rw_lock_get_mutex(lock));
++#endif
+       return(success);
+ }
+@@ -308,6 +396,55 @@
+ {
+       ibool           success         = FALSE;
+       os_thread_id_t  curr_thread     = os_thread_get_curr_id();
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if ((lock->lock_word == RW_LOCK_BIAS)
++                      && rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
++              /* try x-lock */
++              if(__sync_sub_and_fetch(&(lock->lock_word),
++                              RW_LOCK_BIAS) == 0) {
++                      /* success */
++                      /* try to lock writer */
++                      if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
++                                      == RW_LOCK_NOT_LOCKED) {
++                              /* success */
++                              lock->writer_thread = curr_thread;
++                              lock->pass = 0;
++                              lock->writer_is_wait_ex = FALSE;
++                              /* next function may work as memory barrier */
++                      relock:
++                              __sync_fetch_and_add(&(lock->writer_count),1);
++
++#ifdef UNIV_SYNC_DEBUG
++                              rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
++#endif
++
++                              lock->last_x_file_name = file_name;
++                              lock->last_x_line = line;
++
++                              ut_ad(rw_lock_validate(lock));
++
++                              return(TRUE);
++                      } else {
++                              /* x-unlock */
++                              __sync_fetch_and_add(&(lock->lock_word),
++                                      RW_LOCK_BIAS);
++                      }
++              } else {
++                      /* fail (x-lock) */
++                      __sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
++              }
++      }
++
++      if (lock->pass == 0
++                      && os_thread_eq(lock->writer_thread, curr_thread)
++                      && rw_lock_get_writer(lock) == RW_LOCK_EX) {
++              goto relock;
++      }
++
++      ut_ad(rw_lock_validate(lock));
++
++      return(FALSE);
++#else
+       mutex_enter(rw_lock_get_mutex(lock));
+       if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
+@@ -338,6 +475,7 @@
+       ut_ad(rw_lock_validate(lock));
+       return(success);
++#endif
+ }
+ /**********************************************************************
+@@ -353,16 +491,33 @@
+ #endif
+       )
+ {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_t*        mutex   = &(lock->mutex);
+-      ibool           sg      = FALSE;
++#endif
++      ibool           x_sg    = FALSE;
++      ibool           wx_sg   = FALSE;
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      ibool           last    = FALSE;
++#endif
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       /* Acquire the mutex protecting the rw-lock fields */
+       mutex_enter(mutex);
++#endif
+       /* Reset the shared lock by decrementing the reader count */
+       ut_a(lock->reader_count > 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      /* unlock lock_word */
++      __sync_fetch_and_add(&(lock->lock_word),1);
++
++      if(__sync_sub_and_fetch(&(lock->reader_count),1) == 0) {
++              last = TRUE;
++      }
++#else
+       lock->reader_count--;
++#endif
+ #ifdef UNIV_SYNC_DEBUG
+       rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
+@@ -371,20 +526,36 @@
+       /* If there may be waiters and this was the last s-lock,
+       signal the object */
+-      if (UNIV_UNLIKELY(lock->waiters)
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if (UNIV_UNLIKELY(last && lock->wait_ex_waiters)) {
++#else
++      if (UNIV_UNLIKELY(lock->wait_ex_waiters)
+           && lock->reader_count == 0) {
+-              sg = TRUE;
++#endif
++              wx_sg = TRUE;
+-              rw_lock_set_waiters(lock, 0);
++              rw_lock_set_wx_waiters(lock, 0);
+       }
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      else if (UNIV_UNLIKELY(last && lock->x_waiters)) {
++#else
++      else if (UNIV_UNLIKELY(lock->x_waiters)
++               && lock->reader_count == 0) {
++#endif
++              x_sg = TRUE;
++              rw_lock_set_x_waiters(lock, 0);
++      }
++
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_exit(mutex);
++#endif
+-      if (UNIV_UNLIKELY(sg)) {
+-#ifdef __WIN__
++      if (UNIV_UNLIKELY(wx_sg)) {
+               os_event_set(lock->wait_ex_event);
+-#endif
+-              os_event_set(lock->event);
++              sync_array_object_signalled(sync_primary_wait_array);
++      } else if (UNIV_UNLIKELY(x_sg)) {
++              os_event_set(lock->x_event);
+               sync_array_object_signalled(sync_primary_wait_array);
+       }
+@@ -408,13 +579,19 @@
+       ut_ad(lock->reader_count > 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      __sync_sub_and_fetch(&(lock->reader_count),1);
++#else
+       lock->reader_count--;
++#endif
+ #ifdef UNIV_SYNC_DEBUG
+       rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED);
+ #endif
+-      ut_ad(!lock->waiters);
++      ut_ad(!lock->s_waiters);
++      ut_ad(!lock->x_waiters);
++      ut_ad(!lock->wait_ex_waiters);
+       ut_ad(rw_lock_validate(lock));
+ #ifdef UNIV_SYNC_PERF_STAT
+       rw_s_exit_count++;
+@@ -434,41 +611,81 @@
+ #endif
+       )
+ {
+-      ibool   sg      = FALSE;
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      ibool   last    = FALSE;
++#endif
++      ibool   s_sg    = FALSE;
++      ibool   x_sg    = FALSE;
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       /* Acquire the mutex protecting the rw-lock fields */
+       mutex_enter(&(lock->mutex));
++#endif
+       /* Reset the exclusive lock if this thread no longer has an x-mode
+       lock */
+       ut_ad(lock->writer_count > 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
++              last = TRUE;
++      }
++
++      if (last) {
++              /* unlock lock_word */
++              __sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
++
++              /* FIXME: It is a value of bad manners for pthread.
++                        But we shouldn't keep an ID of not-owner. */
++              lock->writer_thread = -1;
++
++              /* atomic operation may be safer about memory order. */
++              rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
++              __sync_synchronize();
++      }
++#else
+       lock->writer_count--;
+       if (lock->writer_count == 0) {
+               rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
+       }
++#endif
+ #ifdef UNIV_SYNC_DEBUG
+       rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX);
+ #endif
+       /* If there may be waiters, signal the lock */
+-      if (UNIV_UNLIKELY(lock->waiters)
+-          && lock->writer_count == 0) {
+-
+-              sg = TRUE;
+-              rw_lock_set_waiters(lock, 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if (last) {
++#else
++      if (lock->writer_count == 0) {
++#endif
++              if(lock->s_waiters){
++                      s_sg = TRUE;
++                      rw_lock_set_s_waiters(lock, 0);
++              }
++              if(lock->x_waiters){
++                      x_sg = TRUE;
++                      rw_lock_set_x_waiters(lock, 0);
++              }
+       }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_exit(&(lock->mutex));
++#endif
+-      if (UNIV_UNLIKELY(sg)) {
++      if (UNIV_UNLIKELY(s_sg)) {
++              os_event_set(lock->s_event);
++              sync_array_object_signalled(sync_primary_wait_array);
++      }
++      if (UNIV_UNLIKELY(x_sg)) {
+ #ifdef __WIN__
++              /* I doubt the necessity of it. */
+               os_event_set(lock->wait_ex_event);
+ #endif
+-              os_event_set(lock->event);
++              os_event_set(lock->x_event);
+               sync_array_object_signalled(sync_primary_wait_array);
+       }
+@@ -493,9 +710,13 @@
+       ut_ad(lock->writer_count > 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
++#else
+       lock->writer_count--;
+       if (lock->writer_count == 0) {
++#endif
+               rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
+       }
+@@ -503,7 +724,9 @@
+       rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
+ #endif
+-      ut_ad(!lock->waiters);
++      ut_ad(!lock->s_waiters);
++      ut_ad(!lock->x_waiters);
++      ut_ad(!lock->wait_ex_waiters);
+       ut_ad(rw_lock_validate(lock));
+ #ifdef UNIV_SYNC_PERF_STAT
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/sync/sync0arr.c mysql-5.1.29-rc/storage/innobase/sync/sync0arr.c
+--- mysql-5.1.29-rc_orig/storage/innobase/sync/sync0arr.c      2008-10-12 06:54:15.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/sync/sync0arr.c   2008-11-17 16:17:39.000000000 +0900
+@@ -307,13 +307,13 @@
+ {
+       if (type == SYNC_MUTEX) {
+               return(os_event_reset(((mutex_t *) object)->event));
+-#ifdef __WIN__
+       } else if (type == RW_LOCK_WAIT_EX) {
+               return(os_event_reset(
+                      ((rw_lock_t *) object)->wait_ex_event));
+-#endif
+-      } else {
+-              return(os_event_reset(((rw_lock_t *) object)->event));
++      } else if (type == RW_LOCK_SHARED) {
++              return(os_event_reset(((rw_lock_t *) object)->s_event));
++      } else { /* RW_LOCK_EX */
++              return(os_event_reset(((rw_lock_t *) object)->x_event));
+       }
+ }
+@@ -413,15 +413,12 @@
+       if (cell->request_type == SYNC_MUTEX) {
+               event = ((mutex_t*) cell->wait_object)->event;
+-#ifdef __WIN__
+-      /* On windows if the thread about to wait is the one which
+-      has set the state of the rw_lock to RW_LOCK_WAIT_EX, then
+-      it waits on a special event i.e.: wait_ex_event. */
+       } else if (cell->request_type == RW_LOCK_WAIT_EX) {
+               event = ((rw_lock_t*) cell->wait_object)->wait_ex_event;
+-#endif
++      } else if (cell->request_type == RW_LOCK_SHARED) {
++              event = ((rw_lock_t*) cell->wait_object)->s_event;
+       } else {
+-              event = ((rw_lock_t*) cell->wait_object)->event;
++              event = ((rw_lock_t*) cell->wait_object)->x_event;
+       }
+               cell->waiting = TRUE;
+@@ -462,6 +459,7 @@
+       mutex_t*        mutex;
+       rw_lock_t*      rwlock;
+       ulint           type;
++      ulint           writer;
+       type = cell->request_type;
+@@ -491,12 +489,10 @@
+                       (ulong) mutex->waiters);
+       } else if (type == RW_LOCK_EX
+-#ifdef __WIN__
+                  || type == RW_LOCK_WAIT_EX
+-#endif
+                  || type == RW_LOCK_SHARED) {
+-              fputs(type == RW_LOCK_EX ? "X-lock on" : "S-lock on", file);
++              fputs(type == RW_LOCK_SHARED ? "S-lock on" : "X-lock on", file);
+               rwlock = cell->old_wait_rw_lock;
+@@ -504,22 +500,24 @@
+                       " RW-latch at %p created in file %s line %lu\n",
+                       (void*) rwlock, rwlock->cfile_name,
+                       (ulong) rwlock->cline);
+-              if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
++              writer = rw_lock_get_writer(rwlock);
++              if (writer != RW_LOCK_NOT_LOCKED) {
+                       fprintf(file,
+                               "a writer (thread id %lu) has"
+                               " reserved it in mode %s",
+                               (ulong) os_thread_pf(rwlock->writer_thread),
+-                              rwlock->writer == RW_LOCK_EX
++                              writer == RW_LOCK_EX
+                               ? " exclusive\n"
+                               : " wait exclusive\n");
+               }
+               fprintf(file,
+-                      "number of readers %lu, waiters flag %lu\n"
++                      "number of readers %lu, s_waiters flag %lu, x_waiters flag %lu\n"
+                       "Last time read locked in file %s line %lu\n"
+                       "Last time write locked in file %s line %lu\n",
+                       (ulong) rwlock->reader_count,
+-                      (ulong) rwlock->waiters,
++                      (ulong) rwlock->s_waiters,
++                      (ulong) (rwlock->x_waiters || rwlock->wait_ex_waiters),
+                       rwlock->last_s_file_name,
+                       (ulong) rwlock->last_s_line,
+                       rwlock->last_x_file_name,
+@@ -844,11 +842,15 @@
+ /*========================*/
+       sync_array_t*   arr)    /* in: wait array */
+ {
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      __sync_fetch_and_add(&(arr->sg_count),1);
++#else
+       sync_array_enter(arr);
+       arr->sg_count++;
+       sync_array_exit(arr);
++#endif
+ }
+ /**************************************************************************
+@@ -889,19 +891,23 @@
+                                       mutex = cell->wait_object;
+                                       os_event_set(mutex->event);
+-#ifdef __WIN__
+                               } else if (cell->request_type
+                                          == RW_LOCK_WAIT_EX) {
+                                       rw_lock_t*      lock;
+                                       lock = cell->wait_object;
+                                       os_event_set(lock->wait_ex_event);
+-#endif
+-                              } else {
++                              } else if (cell->request_type
++                                         == RW_LOCK_SHARED) {
+                                       rw_lock_t*      lock;
+                                       lock = cell->wait_object;
+-                                      os_event_set(lock->event);
++                                      os_event_set(lock->s_event);
++                              } else {
++                                      rw_lock_t*      lock;
++
++                                      lock = cell->wait_object;
++                                      os_event_set(lock->x_event);
+                               }
+                       }
+               }
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/sync/sync0rw.c mysql-5.1.29-rc/storage/innobase/sync/sync0rw.c
+--- mysql-5.1.29-rc_orig/storage/innobase/sync/sync0rw.c       2008-10-12 06:54:15.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/sync/sync0rw.c    2008-11-17 17:43:45.000000000 +0900
+@@ -119,6 +119,7 @@
+       /* If this is the very first time a synchronization object is
+       created, then the following call initializes the sync system. */
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
+       lock->mutex.cfile_name = cfile_name;
+@@ -128,8 +129,14 @@
+       lock->mutex.cmutex_name = cmutex_name;
+       lock->mutex.mutex_type = 1;
+ #endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
++#endif /* !HAVE_GCC_ATOMIC_BUILTINS */
+-      rw_lock_set_waiters(lock, 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      lock->lock_word = RW_LOCK_BIAS;
++#endif
++      rw_lock_set_s_waiters(lock, 0);
++      rw_lock_set_x_waiters(lock, 0);
++      rw_lock_set_wx_waiters(lock, 0);
+       rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
+       lock->writer_count = 0;
+       rw_lock_set_reader_count(lock, 0);
+@@ -151,11 +158,9 @@
+       lock->last_x_file_name = "not yet reserved";
+       lock->last_s_line = 0;
+       lock->last_x_line = 0;
+-      lock->event = os_event_create(NULL);
+-
+-#ifdef __WIN__
++      lock->s_event = os_event_create(NULL);
++      lock->x_event = os_event_create(NULL);
+       lock->wait_ex_event = os_event_create(NULL);
+-#endif
+       mutex_enter(&rw_lock_list_mutex);
+@@ -181,19 +186,21 @@
+ {
+       ut_ad(rw_lock_validate(lock));
+       ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
+-      ut_a(rw_lock_get_waiters(lock) == 0);
++      ut_a(rw_lock_get_s_waiters(lock) == 0);
++      ut_a(rw_lock_get_x_waiters(lock) == 0);
++      ut_a(rw_lock_get_wx_waiters(lock) == 0);
+       ut_a(rw_lock_get_reader_count(lock) == 0);
+       lock->magic_n = 0;
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_free(rw_lock_get_mutex(lock));
++#endif
+       mutex_enter(&rw_lock_list_mutex);
+-      os_event_free(lock->event);
+-
+-#ifdef __WIN__
++      os_event_free(lock->s_event);
++      os_event_free(lock->x_event);
+       os_event_free(lock->wait_ex_event);
+-#endif
+       if (UT_LIST_GET_PREV(list, lock)) {
+               ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
+@@ -212,6 +219,8 @@
+ Checks that the rw-lock has been initialized and that there are no
+ simultaneous shared and exclusive locks. */
++/* MEMO: If HAVE_GCC_ATOMIC_BUILTINS, we should use this function statically. */
++
+ ibool
+ rw_lock_validate(
+ /*=============*/
+@@ -219,7 +228,9 @@
+ {
+       ut_a(lock);
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_enter(rw_lock_get_mutex(lock));
++#endif
+       ut_a(lock->magic_n == RW_LOCK_MAGIC_N);
+       ut_a((rw_lock_get_reader_count(lock) == 0)
+@@ -227,11 +238,17 @@
+       ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX)
+            || (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
+            || (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED));
+-      ut_a((rw_lock_get_waiters(lock) == 0)
+-           || (rw_lock_get_waiters(lock) == 1));
++      ut_a((rw_lock_get_s_waiters(lock) == 0)
++           || (rw_lock_get_s_waiters(lock) == 1));
++      ut_a((rw_lock_get_x_waiters(lock) == 0)
++           || (rw_lock_get_x_waiters(lock) == 1));
++      ut_a((rw_lock_get_wx_waiters(lock) == 0)
++           || (rw_lock_get_wx_waiters(lock) == 1));
+       ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_exit(rw_lock_get_mutex(lock));
++#endif
+       return(TRUE);
+ }
+@@ -258,13 +275,14 @@
+       ut_ad(rw_lock_validate(lock));
+ lock_loop:
++      i = 0;
++spin_loop:
+       rw_s_spin_wait_count++;
+       /* Spin waiting for the writer field to become free */
+-      i = 0;
+-      while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
+-             && i < SYNC_SPIN_ROUNDS) {
++      while (i < SYNC_SPIN_ROUNDS
++             && rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) {
+               if (srv_spin_wait_delay) {
+                       ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
+               }
+@@ -285,15 +303,27 @@
+                       lock->cfile_name, (ulong) lock->cline, (ulong) i);
+       }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_enter(rw_lock_get_mutex(lock));
++#endif
+       /* We try once again to obtain the lock */
+       if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+               mutex_exit(rw_lock_get_mutex(lock));
++#endif
+               return; /* Success */
+       } else {
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++              /* like sync0sync.c doing */
++              i++;
++
++              if (i < SYNC_SPIN_ROUNDS) {
++                      goto spin_loop;
++              }
++#endif
+               /* If we get here, locking did not succeed, we may
+               suspend the thread to wait in the wait array */
+@@ -304,9 +334,19 @@
+                                       file_name, line,
+                                       &index);
+-              rw_lock_set_waiters(lock, 1);
++              rw_lock_set_s_waiters(lock, 1);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++              /* like sync0sync.c doing */
++              for (i = 0; i < 4; i++) {
++                      if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
++                              sync_array_free_cell(sync_primary_wait_array, index);
++                              return; /* Success */
++                      }
++              }
++#else
+               mutex_exit(rw_lock_get_mutex(lock));
++#endif
+               if (srv_print_latch_waits) {
+                       fprintf(stderr,
+@@ -343,13 +383,19 @@
+ {
+       ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_enter(&(lock->mutex));
++#endif
+       lock->writer_thread = os_thread_get_curr_id();
+       lock->pass = 0;
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_exit(&(lock->mutex));
++#else
++      __sync_synchronize();
++#endif
+ }
+ /**********************************************************************
+@@ -367,6 +413,89 @@
+       const char*     file_name,/* in: file name where lock requested */
+       ulint           line)   /* in: line where requested */
+ {
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      os_thread_id_t  curr_thread     = os_thread_get_curr_id();
++
++      /* try to lock writer */
++      if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
++                      == RW_LOCK_NOT_LOCKED) {
++              /* success */
++              /* obtain RW_LOCK_WAIT_EX right */
++              lock->writer_thread = curr_thread;
++              lock->pass = pass;
++              lock->writer_is_wait_ex = TRUE;
++              /* atomic operation may be safer about memory order. */
++              __sync_synchronize();
++#ifdef UNIV_SYNC_DEBUG
++              rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
++                                      file_name, line);
++#endif
++      }
++
++      if (!os_thread_eq(lock->writer_thread, curr_thread)) {
++              return(RW_LOCK_NOT_LOCKED);
++      }
++
++      switch(rw_lock_get_writer(lock)) {
++          case RW_LOCK_WAIT_EX:
++              /* have right to try x-lock */
++              if (lock->lock_word == RW_LOCK_BIAS) {
++                      /* try x-lock */
++                      if(__sync_sub_and_fetch(&(lock->lock_word),
++                                      RW_LOCK_BIAS) == 0) {
++                              /* success */
++                              lock->pass = pass;
++                              lock->writer_is_wait_ex = FALSE;
++                              __sync_fetch_and_add(&(lock->writer_count),1);
++
++#ifdef UNIV_SYNC_DEBUG
++                              rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX);
++                              rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
++                                                      file_name, line);
++#endif
++
++                              lock->last_x_file_name = file_name;
++                              lock->last_x_line = line;
++
++                              /* Locking succeeded, we may return */
++                              return(RW_LOCK_EX);
++                      } else {
++                              /* fail */
++                              __sync_fetch_and_add(&(lock->lock_word),
++                                      RW_LOCK_BIAS);
++                      }
++              }
++              /* There are readers, we have to wait */
++              return(RW_LOCK_WAIT_EX);
++
++              break;
++
++          case RW_LOCK_EX:
++              /* already have x-lock */
++              if ((lock->pass == 0)&&(pass == 0)) {
++                      __sync_fetch_and_add(&(lock->writer_count),1);
++
++#ifdef UNIV_SYNC_DEBUG
++                      rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name,
++                                              line);
++#endif
++
++                      lock->last_x_file_name = file_name;
++                      lock->last_x_line = line;
++
++                      /* Locking succeeded, we may return */
++                      return(RW_LOCK_EX);
++              }
++
++              return(RW_LOCK_NOT_LOCKED);
++
++              break;
++
++          default: /* ??? */
++              return(RW_LOCK_NOT_LOCKED);
++      }
++#else /* HAVE_GCC_ATOMIC_BUILTINS */
++
+       ut_ad(mutex_own(rw_lock_get_mutex(lock)));
+       if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
+@@ -447,6 +576,7 @@
+               /* Locking succeeded, we may return */
+               return(RW_LOCK_EX);
+       }
++#endif /* HAVE_GCC_ATOMIC_BUILTINS */
+       /* Locking did not succeed */
+       return(RW_LOCK_NOT_LOCKED);
+@@ -472,19 +602,33 @@
+       ulint           line)   /* in: line where requested */
+ {
+       ulint   index;  /* index of the reserved wait cell */
+-      ulint   state;  /* lock state acquired */
++      ulint   state = RW_LOCK_NOT_LOCKED;     /* lock state acquired */
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      ulint   prev_state = RW_LOCK_NOT_LOCKED;
++#endif
+       ulint   i;      /* spin round count */
+       ut_ad(rw_lock_validate(lock));
+ lock_loop:
++      i = 0;
++
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      prev_state = state;
++#else
+       /* Acquire the mutex protecting the rw-lock fields */
+       mutex_enter_fast(&(lock->mutex));
++#endif
+       state = rw_lock_x_lock_low(lock, pass, file_name, line);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if (state != prev_state) i=0; /* if progress, reset counter. */
++#else
+       mutex_exit(&(lock->mutex));
++#endif
++spin_loop:
+       if (state == RW_LOCK_EX) {
+               return; /* Locking succeeded */
+@@ -492,10 +636,9 @@
+       } else if (state == RW_LOCK_NOT_LOCKED) {
+               /* Spin waiting for the writer field to become free */
+-              i = 0;
+-              while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
+-                     && i < SYNC_SPIN_ROUNDS) {
++              while (i < SYNC_SPIN_ROUNDS
++                     && rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) {
+                       if (srv_spin_wait_delay) {
+                               ut_delay(ut_rnd_interval(0,
+                                                        srv_spin_wait_delay));
+@@ -509,9 +652,12 @@
+       } else if (state == RW_LOCK_WAIT_EX) {
+               /* Spin waiting for the reader count field to become zero */
+-              i = 0;
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++              while (lock->lock_word != RW_LOCK_BIAS
++#else
+               while (rw_lock_get_reader_count(lock) != 0
++#endif
+                      && i < SYNC_SPIN_ROUNDS) {
+                       if (srv_spin_wait_delay) {
+                               ut_delay(ut_rnd_interval(0,
+@@ -524,7 +670,6 @@
+                       os_thread_yield();
+               }
+       } else {
+-              i = 0; /* Eliminate a compiler warning */
+               ut_error;
+       }
+@@ -541,34 +686,69 @@
+       /* We try once again to obtain the lock. Acquire the mutex protecting
+       the rw-lock fields */
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      prev_state = state;
++#else
+       mutex_enter(rw_lock_get_mutex(lock));
++#endif
+       state = rw_lock_x_lock_low(lock, pass, file_name, line);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      if (state != prev_state) i=0; /* if progress, reset counter. */
++#endif
++
+       if (state == RW_LOCK_EX) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+               mutex_exit(rw_lock_get_mutex(lock));
++#endif
+               return; /* Locking succeeded */
+       }
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      /* like sync0sync.c doing */
++      i++;
++
++      if (i < SYNC_SPIN_ROUNDS) {
++              goto spin_loop;
++      }
++#endif
++
+       rw_x_system_call_count++;
+       sync_array_reserve_cell(sync_primary_wait_array,
+                               lock,
+-#ifdef __WIN__
+-                              /* On windows RW_LOCK_WAIT_EX signifies
+-                              that this thread should wait on the
+-                              special wait_ex_event. */
+                               (state == RW_LOCK_WAIT_EX)
+                                ? RW_LOCK_WAIT_EX :
+-#endif
+                               RW_LOCK_EX,
+                               file_name, line,
+                               &index);
+-      rw_lock_set_waiters(lock, 1);
++      if (state == RW_LOCK_WAIT_EX) {
++              rw_lock_set_wx_waiters(lock, 1);
++      } else {
++              rw_lock_set_x_waiters(lock, 1);
++      }
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++      /* like sync0sync.c doing */
++      for (i = 0; i < 4; i++) {
++              prev_state = state;
++              state = rw_lock_x_lock_low(lock, pass, file_name, line);
++              if (state == RW_LOCK_EX) {
++                      sync_array_free_cell(sync_primary_wait_array, index);
++                      return; /* Locking succeeded */
++              }
++              if (state != prev_state) {
++                      /* retry! */
++                      sync_array_free_cell(sync_primary_wait_array, index);
++                      goto lock_loop;
++              }
++      }
++#else
+       mutex_exit(rw_lock_get_mutex(lock));
++#endif
+       if (srv_print_latch_waits) {
+               fprintf(stderr,
+@@ -730,7 +910,9 @@
+       ut_ad(lock);
+       ut_ad(rw_lock_validate(lock));
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_enter(&(lock->mutex));
++#endif
+       info = UT_LIST_GET_FIRST(lock->debug_list);
+@@ -740,7 +922,9 @@
+                   && (info->pass == 0)
+                   && (info->lock_type == lock_type)) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+                       mutex_exit(&(lock->mutex));
++#endif
+                       /* Found! */
+                       return(TRUE);
+@@ -748,7 +932,9 @@
+               info = UT_LIST_GET_NEXT(list, info);
+       }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_exit(&(lock->mutex));
++#endif
+       return(FALSE);
+ }
+@@ -770,21 +956,25 @@
+       ut_ad(lock);
+       ut_ad(rw_lock_validate(lock));
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_enter(&(lock->mutex));
++#endif
+       if (lock_type == RW_LOCK_SHARED) {
+               if (lock->reader_count > 0) {
+                       ret = TRUE;
+               }
+       } else if (lock_type == RW_LOCK_EX) {
+-              if (lock->writer == RW_LOCK_EX) {
++              if (rw_lock_get_writer(lock) == RW_LOCK_EX) {
+                       ret = TRUE;
+               }
+       } else {
+               ut_error;
+       }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+       mutex_exit(&(lock->mutex));
++#endif
+       return(ret);
+ }
+@@ -814,16 +1004,26 @@
+               count++;
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+               mutex_enter(&(lock->mutex));
++#endif
+               if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
+                   || (rw_lock_get_reader_count(lock) != 0)
+-                  || (rw_lock_get_waiters(lock) != 0)) {
++                  || (rw_lock_get_s_waiters(lock) != 0)
++                  || (rw_lock_get_x_waiters(lock) != 0)
++                  || (rw_lock_get_wx_waiters(lock) != 0)) {
+                       fprintf(file, "RW-LOCK: %p ", (void*) lock);
+-                      if (rw_lock_get_waiters(lock)) {
+-                              fputs(" Waiters for the lock exist\n", file);
++                      if (rw_lock_get_s_waiters(lock)) {
++                              fputs(" s_waiters for the lock exist,", file);
++                      }
++                      if (rw_lock_get_x_waiters(lock)) {
++                              fputs(" x_waiters for the lock exist\n", file);
++                      }
++                      if (rw_lock_get_wx_waiters(lock)) {
++                              fputs(" wait_ex_waiters for the lock exist\n", file);
+                       } else {
+                               putc('\n', file);
+                       }
+@@ -835,7 +1035,9 @@
+                       }
+               }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+               mutex_exit(&(lock->mutex));
++#endif
+               lock = UT_LIST_GET_NEXT(list, lock);
+       }
+@@ -860,10 +1062,18 @@
+       if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
+           || (rw_lock_get_reader_count(lock) != 0)
+-          || (rw_lock_get_waiters(lock) != 0)) {
++          || (rw_lock_get_s_waiters(lock) != 0)
++          || (rw_lock_get_x_waiters(lock) != 0)
++          || (rw_lock_get_wx_waiters(lock) != 0)) {
+-              if (rw_lock_get_waiters(lock)) {
+-                      fputs(" Waiters for the lock exist\n", stderr);
++              if (rw_lock_get_s_waiters(lock)) {
++                      fputs(" s_waiters for the lock exist,", stderr);
++              }
++              if (rw_lock_get_x_waiters(lock)) {
++                      fputs(" x_waiters for the lock exist\n", stderr);
++              }
++              if (rw_lock_get_wx_waiters(lock)) {
++                      fputs(" wait_ex_waiters for the lock exist\n", stderr);
+               } else {
+                       putc('\n', stderr);
+               }
+@@ -922,14 +1132,18 @@
+       lock = UT_LIST_GET_FIRST(rw_lock_list);
+       while (lock != NULL) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+               mutex_enter(rw_lock_get_mutex(lock));
++#endif
+               if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
+                   || (rw_lock_get_reader_count(lock) != 0)) {
+                       count++;
+               }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+               mutex_exit(rw_lock_get_mutex(lock));
++#endif
+               lock = UT_LIST_GET_NEXT(list, lock);
+       }
+diff -ruN mysql-5.1.29-rc_orig/patch_info/innodb_rw_lock.info mysql-5.1.29-rc/patch_info/innodb_rw_lock.info
+--- /dev/null  1970-01-01 09:00:00.000000000 +0900
++++ mysql-5.1.29-rc/patch_info/innodb_rw_lock.info     2008-11-17 15:23:46.000000000 +0900
+@@ -0,0 +1,6 @@
++File=innodb_rw_lock.patch
++Name=Fix of InnoDB rw_locks
++Version=1.0
++Author=Yasufumi Kinoshita
++License=BSD
++Comment=
index e2321f54da500ea1e6fe0fe24c178859589a025d..15085d8b66ce1939211ad3e022177b3d04524d99 100644 (file)
@@ -1,16 +1,6 @@
-diff -r debbd352c16a patch_info/microslow.info
---- /dev/null  Thu Jan 01 00:00:00 1970 +0000
-+++ b/patch_info/microslow.info        Thu Sep 04 12:16:10 2008 -0700
-@@ -0,0 +1,6 @@
-+File=microslow.patch
-+Name=Extended statistics in slow.log
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-diff -r debbd352c16a sql/event_scheduler.cc
---- a/sql/event_scheduler.cc   Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/event_scheduler.cc   Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/event_scheduler.cc
+--- a/sql/event_scheduler.cc   Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/event_scheduler.cc   Thu Dec 04 08:55:29 2008 -0800
 @@ -192,6 +192,7 @@
    thd->client_capabilities|= CLIENT_MULTI_RESULTS;
    pthread_mutex_lock(&LOCK_thread_count);
@@ -19,9 +9,9 @@ diff -r debbd352c16a sql/event_scheduler.cc
    pthread_mutex_unlock(&LOCK_thread_count);
  
    /*
-diff -r debbd352c16a sql/filesort.cc
---- a/sql/filesort.cc  Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/filesort.cc  Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/filesort.cc
+--- a/sql/filesort.cc  Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/filesort.cc  Thu Dec 04 08:55:29 2008 -0800
 @@ -188,6 +188,7 @@
    {
      status_var_increment(thd->status_var.filesort_scan_count);
@@ -38,7 +28,7 @@ diff -r debbd352c16a sql/filesort.cc
      if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
      {
        x_free(table_sort.buffpek);
-@@ -1162,6 +1164,7 @@
+@@ -1202,6 +1204,7 @@
    DBUG_ENTER("merge_buffers");
  
    status_var_increment(current_thd->status_var.filesort_merge_passes);
@@ -46,10 +36,10 @@ diff -r debbd352c16a sql/filesort.cc
    if (param->not_killable)
    {
      killed= &not_killable;
-diff -r debbd352c16a sql/log.cc
---- a/sql/log.cc       Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/log.cc       Thu Sep 04 12:16:10 2008 -0700
-@@ -955,7 +955,7 @@
+diff -r 0b1f42e1aacf sql/log.cc
+--- a/sql/log.cc       Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/log.cc       Thu Dec 04 08:55:29 2008 -0800
+@@ -963,7 +963,7 @@
      /* fill in user_host value: the format is "%s[%s] @ %s [%s]" */
      user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
                               sctx->priv_user ? sctx->priv_user : "", "[",
@@ -58,7 +48,7 @@ diff -r debbd352c16a sql/log.cc
                               sctx->host ? sctx->host : "", " [",
                               sctx->ip ? sctx->ip : "", "]", NullS) -
                      user_host_buff);
-@@ -977,6 +977,13 @@
+@@ -985,6 +985,13 @@
        query= command_name[thd->command].str;
        query_length= command_name[thd->command].length;
      }
@@ -72,7 +62,7 @@ diff -r debbd352c16a sql/log.cc
  
      for (current_handler= slow_log_handler_list; *current_handler ;)
        error= (*current_handler++)->log_slow(thd, current_time, thd->start_time,
-@@ -2233,16 +2240,31 @@
+@@ -2242,16 +2249,31 @@
        if (my_b_write(&log_file, (uchar*) "\n", 1))
          tmp_errno= errno;
      }
@@ -106,10 +96,10 @@ diff -r debbd352c16a sql/log.cc
      if (thd->db && strcmp(thd->db, db))
      {                                         // Database changed
        if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
-diff -r debbd352c16a sql/mysql_priv.h
---- a/sql/mysql_priv.h Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/mysql_priv.h Thu Sep 04 12:16:10 2008 -0700
-@@ -595,6 +595,73 @@
+diff -r 0b1f42e1aacf sql/mysql_priv.h
+--- a/sql/mysql_priv.h Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/mysql_priv.h Thu Dec 04 08:55:29 2008 -0800
+@@ -597,6 +597,73 @@
  #define WEEK_FIRST_WEEKDAY   4
  
  #define STRING_BUFFER_USUAL_SIZE 80
@@ -183,9 +173,9 @@ diff -r debbd352c16a sql/mysql_priv.h
  
  /*
    Some defines for exit codes for ::is_equal class functions.
-diff -r debbd352c16a sql/mysqld.cc
---- a/sql/mysqld.cc    Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/mysqld.cc    Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/mysqld.cc
+--- a/sql/mysqld.cc    Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/mysqld.cc    Thu Dec 04 08:55:29 2008 -0800
 @@ -5553,6 +5553,9 @@
    OPT_SECURE_FILE_PRIV,
    OPT_MIN_EXAMINED_ROW_LIMIT,
@@ -194,9 +184,9 @@ diff -r debbd352c16a sql/mysqld.cc
 +  OPT_LOG_SLOW_VERBOSITY, 
 +  OPT_LOG_SLOW_FILTER, 
    OPT_OLD_MODE,
-   OPT_SLAVE_EXEC_MODE
- };
-@@ -6467,6 +6470,17 @@
+   OPT_SLAVE_EXEC_MODE,
+   OPT_GENERAL_LOG_FILE,
+@@ -6480,6 +6483,17 @@
     (uchar**) 0,
     0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
     1, 100, 0, 1, 0},
@@ -214,7 +204,7 @@ diff -r debbd352c16a sql/mysqld.cc
    {"long_query_time", OPT_LONG_QUERY_TIME,
     "Log all queries that have taken more than long_query_time seconds to execute to file. "
     "The argument will be treated as a decimal value with microsecond precission.",
-@@ -7542,6 +7556,10 @@
+@@ -7556,6 +7570,10 @@
    global_system_variables.old_passwords= 0;
    global_system_variables.old_alter_table= 0;
    global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC;
@@ -225,7 +215,7 @@ diff -r debbd352c16a sql/mysqld.cc
    /*
      Default behavior for 4.1 and 5.0 is to treat NULL values as unequal
      when collecting index statistics for MyISAM tables.
-@@ -7988,6 +8006,24 @@
+@@ -8007,6 +8025,24 @@
    case OPT_BOOTSTRAP:
      opt_noacl=opt_bootstrap=1;
      break;
@@ -250,9 +240,9 @@ diff -r debbd352c16a sql/mysqld.cc
    case OPT_SERVER_ID:
      server_id_supplied = 1;
      break;
-diff -r debbd352c16a sql/set_var.cc
---- a/sql/set_var.cc   Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/set_var.cc   Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/set_var.cc
+--- a/sql/set_var.cc   Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/set_var.cc   Thu Dec 04 08:55:29 2008 -0800
 @@ -336,6 +336,20 @@
                                              &SV::max_join_size,
                                              fix_max_join_size);
@@ -274,7 +264,7 @@ diff -r debbd352c16a sql/set_var.cc
  static sys_var_long_ptr_global
  sys_max_prepared_stmt_count(&vars, "max_prepared_stmt_count",
                              &max_prepared_stmt_count,
-@@ -3605,6 +3619,192 @@
+@@ -3631,6 +3645,192 @@
  #endif
  }
  
@@ -467,9 +457,9 @@ diff -r debbd352c16a sql/set_var.cc
  /****************************************************************************
   Functions to handle table_type
  ****************************************************************************/
-diff -r debbd352c16a sql/set_var.h
---- a/sql/set_var.h    Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/set_var.h    Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/set_var.h
+--- a/sql/set_var.h    Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/set_var.h    Thu Dec 04 08:55:29 2008 -0800
 @@ -1057,6 +1057,68 @@
    bool update(THD *thd, set_var *var);
  };
@@ -539,7 +529,7 @@ diff -r debbd352c16a sql/set_var.h
  
  /**
    Handler for setting the system variable --read-only.
-@@ -1322,3 +1384,10 @@
+@@ -1323,3 +1385,10 @@
  bool process_key_caches(process_key_cache_t func);
  void delete_elements(I_List<NAMED_LIST> *list,
                     void (*free_element)(const char*, uchar*));
@@ -550,9 +540,9 @@ diff -r debbd352c16a sql/set_var.h
 +                               const ulong none_val, const ulong invalid_val);
 +const char *msl_option_get_name(const struct msl_opts *opts, ulong val);
 +char *msl_flag_get_name(const struct msl_opts *opts, char *buf, ulong val);
-diff -r debbd352c16a sql/slave.cc
---- a/sql/slave.cc     Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/slave.cc     Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/slave.cc
+--- a/sql/slave.cc     Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/slave.cc     Thu Dec 04 08:55:29 2008 -0800
 @@ -1561,6 +1561,7 @@
      + MAX_LOG_EVENT_HEADER;  /* note, incr over the global not session var */
    thd->slave_thread = 1;
@@ -561,9 +551,9 @@ diff -r debbd352c16a sql/slave.cc
    set_slave_thread_options(thd);
    thd->client_capabilities = CLIENT_LOCAL_FILES;
    pthread_mutex_lock(&LOCK_thread_count);
-diff -r debbd352c16a sql/sql_cache.cc
---- a/sql/sql_cache.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_cache.cc Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/sql_cache.cc
+--- a/sql/sql_cache.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_cache.cc Thu Dec 04 08:55:29 2008 -0800
 @@ -1465,6 +1465,7 @@
  
    thd->limit_found_rows = query->found_rows();
@@ -580,22 +570,22 @@ diff -r debbd352c16a sql/sql_cache.cc
    DBUG_RETURN(0);                             // Query was not cached
  }
  
-diff -r debbd352c16a sql/sql_class.h
---- a/sql/sql_class.h  Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_class.h  Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/sql_class.h
+--- a/sql/sql_class.h  Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_class.h  Thu Dec 04 08:55:29 2008 -0800
 @@ -396,6 +396,11 @@
    DATE_TIME_FORMAT *datetime_format;
    DATE_TIME_FORMAT *time_format;
    my_bool sysdate_is_now;
 +
-+  ulong log_slow_rate_limit;
-+  ulong log_slow_filter;
-+  ulong log_slow_verbosity;
-+
++  ulong log_slow_rate_limit; 
++  ulong log_slow_filter; 
++  ulong log_slow_verbosity; 
++            
  };
  
  
-@@ -1322,6 +1326,11 @@
+@@ -1339,6 +1344,11 @@
    
    thr_lock_type update_lock_default;
    Delayed_insert *di;
@@ -607,9 +597,9 @@ diff -r debbd352c16a sql/sql_class.h
  
    /* <> 0 if we are inside of trigger or stored function. */
    uint in_sub_stmt;
-diff -r debbd352c16a sql/sql_connect.cc
---- a/sql/sql_connect.cc       Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_connect.cc       Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/sql_connect.cc
+--- a/sql/sql_connect.cc       Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_connect.cc       Thu Dec 04 08:55:29 2008 -0800
 @@ -1124,6 +1124,15 @@
  
      prepare_new_connection_state(thd);
@@ -626,10 +616,10 @@ diff -r debbd352c16a sql/sql_connect.cc
      while (!net->error && net->vio != 0 &&
             !(thd->killed == THD::KILL_CONNECTION))
      {
-diff -r debbd352c16a sql/sql_parse.cc
---- a/sql/sql_parse.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_parse.cc Thu Sep 04 12:16:10 2008 -0700
-@@ -1629,6 +1629,27 @@
+diff -r 0b1f42e1aacf sql/sql_parse.cc
+--- a/sql/sql_parse.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_parse.cc Thu Dec 04 08:55:29 2008 -0800
+@@ -1692,6 +1692,27 @@
    if (unlikely(thd->in_sub_stmt))
      DBUG_VOID_RETURN;                           // Don't set time for sub stmt
  
@@ -657,7 +647,7 @@ diff -r debbd352c16a sql/sql_parse.cc
    /*
      Do not log administrative statements unless the appropriate option is
      set; do not log into slow log if reading from backup.
-@@ -5640,6 +5661,9 @@
+@@ -5773,6 +5794,9 @@
    thd->total_warn_count=0;                    // Warnings for this query
    thd->rand_used= 0;
    thd->sent_row_count= thd->examined_row_count= 0;
@@ -667,10 +657,10 @@ diff -r debbd352c16a sql/sql_parse.cc
  
    /*
      Because we come here only for start of top-statements, binlog format is
-diff -r debbd352c16a sql/sql_select.cc
---- a/sql/sql_select.cc        Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_select.cc        Thu Sep 04 12:16:10 2008 -0700
-@@ -6479,7 +6479,10 @@
+diff -r 0b1f42e1aacf sql/sql_select.cc
+--- a/sql/sql_select.cc        Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_select.cc        Thu Dec 04 08:55:29 2008 -0800
+@@ -6480,7 +6480,10 @@
          {
            join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
            if (statistics)
@@ -681,7 +671,7 @@ diff -r debbd352c16a sql/sql_select.cc
          }
        }
        else
-@@ -6493,7 +6496,10 @@
+@@ -6494,7 +6497,10 @@
          {
            join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
            if (statistics)
@@ -692,7 +682,7 @@ diff -r debbd352c16a sql/sql_select.cc
          }
        }
        if (!table->no_keyread)
-@@ -9629,6 +9635,7 @@
+@@ -9638,6 +9644,7 @@
                (ulong) rows_limit,test(group)));
  
    status_var_increment(thd->status_var.created_tmp_tables);
@@ -700,7 +690,7 @@ diff -r debbd352c16a sql/sql_select.cc
  
    if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES))
      temp_pool_slot = bitmap_lock_set_next(&temp_pool);
-@@ -10499,6 +10506,7 @@
+@@ -10508,6 +10515,7 @@
      goto err;
    }
    status_var_increment(table->in_use->status_var.created_tmp_disk_tables);
diff --git a/mysql-split_buf_pool_mutex_fixed_optimistic_safe.patch b/mysql-split_buf_pool_mutex_fixed_optimistic_safe.patch
new file mode 100644 (file)
index 0000000..ef673d9
--- /dev/null
@@ -0,0 +1,1281 @@
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/buf/buf0buf.c mysql-5.1.29-rc/storage/innobase/buf/buf0buf.c
+--- mysql-5.1.29-rc_orig/storage/innobase/buf/buf0buf.c        2008-10-12 06:54:12.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/buf/buf0buf.c     2008-11-18 15:44:00.000000000 +0900
+@@ -596,6 +596,15 @@
+       ---------------------------- */
+       mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
++      mutex_create(&(buf_pool->flush_list_mutex), SYNC_NO_ORDER_CHECK);
++      mutex_create(&(buf_pool->LRU_mutex), SYNC_NO_ORDER_CHECK);
++      mutex_create(&(buf_pool->free_mutex), SYNC_NO_ORDER_CHECK);
++      mutex_create(&(buf_pool->hash_mutex), SYNC_NO_ORDER_CHECK);
++
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
++      mutex_enter(&(buf_pool->free_mutex));
++      mutex_enter(&(buf_pool->hash_mutex));
+       mutex_enter(&(buf_pool->mutex));
+       if (srv_use_awe) {
+@@ -773,6 +782,10 @@
+               block->in_free_list = TRUE;
+       }
++      mutex_exit(&(buf_pool->LRU_mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
++      mutex_exit(&(buf_pool->free_mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       mutex_exit(&(buf_pool->mutex));
+       if (srv_use_adaptive_hash_indexes) {
+@@ -905,12 +918,12 @@
+       if (buf_block_peek_if_too_old(block)) {
+-              mutex_enter(&buf_pool->mutex);
++              mutex_enter(&(buf_pool->LRU_mutex));
+               /* There has been freeing activity in the LRU list:
+               best to move to the head of the LRU list */
+               buf_LRU_make_block_young(block);
+-              mutex_exit(&buf_pool->mutex);
++              mutex_exit(&(buf_pool->LRU_mutex));
+       }
+ }
+@@ -926,7 +939,7 @@
+ {
+       buf_block_t*    block;
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
+       block = buf_block_align(frame);
+@@ -934,7 +947,7 @@
+       buf_LRU_make_block_young(block);
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
+ }
+ /************************************************************************
+@@ -945,7 +958,7 @@
+ /*===========*/
+       buf_block_t*    block)  /* in, own: block to be freed */
+ {
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->free_mutex));
+       mutex_enter(&block->mutex);
+@@ -955,7 +968,7 @@
+       mutex_exit(&block->mutex);
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->free_mutex));
+ }
+ /*************************************************************************
+@@ -996,11 +1009,11 @@
+ {
+       buf_block_t*    block;
+-      mutex_enter_fast(&(buf_pool->mutex));
++      mutex_enter_fast(&(buf_pool->hash_mutex));
+       block = buf_page_hash_get(space, offset);
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       return(block);
+ }
+@@ -1017,7 +1030,7 @@
+ {
+       buf_block_t*    block;
+-      mutex_enter_fast(&(buf_pool->mutex));
++      mutex_enter_fast(&(buf_pool->hash_mutex));
+       block = buf_page_hash_get(space, offset);
+@@ -1025,7 +1038,7 @@
+               block->check_index_page_at_flush = FALSE;
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+ }
+ /************************************************************************
+@@ -1044,7 +1057,7 @@
+       buf_block_t*    block;
+       ibool           is_hashed;
+-      mutex_enter_fast(&(buf_pool->mutex));
++      mutex_enter_fast(&(buf_pool->hash_mutex));
+       block = buf_page_hash_get(space, offset);
+@@ -1054,7 +1067,7 @@
+               is_hashed = block->is_hashed;
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       return(is_hashed);
+ }
+@@ -1096,7 +1109,7 @@
+ {
+       buf_block_t*    block;
+-      mutex_enter_fast(&(buf_pool->mutex));
++      mutex_enter_fast(&(buf_pool->hash_mutex));
+       block = buf_page_hash_get(space, offset);
+@@ -1104,7 +1117,7 @@
+               block->file_page_was_freed = TRUE;
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       return(block);
+ }
+@@ -1125,7 +1138,7 @@
+ {
+       buf_block_t*    block;
+-      mutex_enter_fast(&(buf_pool->mutex));
++      mutex_enter_fast(&(buf_pool->hash_mutex));
+       block = buf_page_hash_get(space, offset);
+@@ -1133,7 +1146,7 @@
+               block->file_page_was_freed = FALSE;
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       return(block);
+ }
+@@ -1174,26 +1187,33 @@
+       buf_pool->n_page_gets++;
+ loop:
+       block = NULL;
+-      mutex_enter_fast(&(buf_pool->mutex));
++      // mutex_enter_fast(&(buf_pool->mutex));
+       if (guess) {
+               block = buf_block_align(guess);
++              mutex_enter(&block->mutex);
+               if ((offset != block->offset) || (space != block->space)
+                   || (block->state != BUF_BLOCK_FILE_PAGE)) {
++                      mutex_exit(&block->mutex);
+                       block = NULL;
+               }
+       }
+       if (block == NULL) {
++              mutex_enter_fast(&(buf_pool->hash_mutex));
+               block = buf_page_hash_get(space, offset);
++              if(block) {
++                      mutex_enter(&block->mutex);
++              }
++              mutex_exit(&(buf_pool->hash_mutex));
+       }
+       if (block == NULL) {
+               /* Page not in buf_pool: needs to be read from file */
+-              mutex_exit(&(buf_pool->mutex));
++              // mutex_exit(&(buf_pool->mutex));
+               if (mode == BUF_GET_IF_IN_POOL) {
+@@ -1212,7 +1232,7 @@
+               goto loop;
+       }
+-      mutex_enter(&block->mutex);
++      // mutex_enter(&block->mutex);
+       ut_a(block->state == BUF_BLOCK_FILE_PAGE);
+@@ -1224,7 +1244,7 @@
+               if (mode == BUF_GET_IF_IN_POOL) {
+                       /* The page is only being read to buffer */
+-                      mutex_exit(&buf_pool->mutex);
++                      // mutex_exit(&buf_pool->mutex);
+                       mutex_exit(&block->mutex);
+                       return(NULL);
+@@ -1241,7 +1261,9 @@
+               LRU list and we must put it to awe_LRU_free_mapped list once
+               mapped to a frame */
++              mutex_enter_fast(&(buf_pool->mutex));
+               buf_awe_map_page_to_frame(block, TRUE);
++              mutex_exit(&buf_pool->mutex);
+       }
+ #ifdef UNIV_SYNC_DEBUG
+@@ -1249,7 +1271,7 @@
+ #else
+       buf_block_buf_fix_inc(block);
+ #endif
+-      mutex_exit(&buf_pool->mutex);
++      // mutex_exit(&buf_pool->mutex);
+       /* Check if this is the first access to the page */
+@@ -1747,7 +1769,8 @@
+       ut_a(block);
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->hash_mutex));
+       mutex_enter(&block->mutex);
+       if (fil_tablespace_deleted_or_being_deleted_in_mem(
+@@ -1763,7 +1786,8 @@
+               already in buf_pool, return */
+               mutex_exit(&block->mutex);
+-              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&(buf_pool->LRU_mutex));
++              mutex_exit(&(buf_pool->hash_mutex));
+               buf_block_free(block);
+@@ -1778,10 +1802,14 @@
+       ut_ad(block);
+       buf_page_init(space, offset, block);
++      mutex_exit(&(buf_pool->hash_mutex));
+       /* The block must be put to the LRU list, to the old blocks */
+       buf_LRU_add_block(block, TRUE);         /* TRUE == to old blocks */
++      mutex_exit(&(buf_pool->LRU_mutex));
++
++      mutex_enter(&(buf_pool->mutex)); /* for consistency about aio */
+       block->io_fix = BUF_IO_READ;
+@@ -1830,7 +1858,8 @@
+       free_block = buf_LRU_get_free_block();
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->hash_mutex));
+       block = buf_page_hash_get(space, offset);
+@@ -1841,7 +1870,8 @@
+               block->file_page_was_freed = FALSE;
+               /* Page can be found in buf_pool */
+-              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&(buf_pool->LRU_mutex));
++              mutex_exit(&(buf_pool->hash_mutex));
+               buf_block_free(free_block);
+@@ -1864,6 +1894,7 @@
+       mutex_enter(&block->mutex);
+       buf_page_init(space, offset, block);
++      mutex_exit(&(buf_pool->hash_mutex));
+       /* The block must be put to the LRU list */
+       buf_LRU_add_block(block, FALSE);
+@@ -1875,7 +1906,7 @@
+ #endif
+       buf_pool->n_pages_created++;
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
+       mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
+@@ -1889,7 +1920,7 @@
+       ibuf_merge_or_delete_for_page(NULL, space, offset, TRUE);
+       /* Flush pages from the end of the LRU list if necessary */
+-      buf_flush_free_margin();
++      buf_flush_free_margin(FALSE);
+       frame = block->frame;
+@@ -1928,6 +1959,7 @@
+       buf_block_t*    block)  /* in: pointer to the block in question */
+ {
+       ulint           io_type;
++      ulint           flush_type;
+       ut_ad(block);
+@@ -2040,9 +2072,6 @@
+               }
+       }
+-      mutex_enter(&(buf_pool->mutex));
+-      mutex_enter(&block->mutex);
+-
+ #ifdef UNIV_IBUF_DEBUG
+       ut_a(ibuf_count_get(block->space, block->offset) == 0);
+ #endif
+@@ -2051,9 +2080,12 @@
+       removes the newest lock debug record, without checking the thread
+       id. */
+-      block->io_fix = 0;
+-
+       if (io_type == BUF_IO_READ) {
++              mutex_enter(&block->mutex);
++              mutex_enter(&(buf_pool->mutex));
++
++              block->io_fix = 0;
++
+               /* NOTE that the call to ibuf may have moved the ownership of
+               the x-latch to this OS thread: do not let this confuse you in
+               debugging! */
+@@ -2064,6 +2096,8 @@
+               rw_lock_x_unlock_gen(&(block->lock), BUF_IO_READ);
++              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&block->mutex);
+ #ifdef UNIV_DEBUG
+               if (buf_debug_prints) {
+                       fputs("Has read ", stderr);
+@@ -2072,15 +2106,33 @@
+       } else {
+               ut_ad(io_type == BUF_IO_WRITE);
++              flush_type = block->flush_type;
++              if (flush_type == BUF_FLUSH_LRU) { /* optimistic! */
++                      mutex_enter(&(buf_pool->LRU_mutex));
++              }
++              mutex_enter(&(buf_pool->flush_list_mutex));
++              mutex_enter(&block->mutex);
++              mutex_enter(&(buf_pool->mutex));
++
++              block->io_fix = 0;
++
+               /* Write means a flush operation: call the completion
+               routine in the flush system */
+               buf_flush_write_complete(block);
++              mutex_exit(&(buf_pool->flush_list_mutex));
++              if (flush_type == BUF_FLUSH_LRU) { /* optimistic! */
++                      mutex_exit(&(buf_pool->LRU_mutex));
++              }
++
+               rw_lock_s_unlock_gen(&(block->lock), BUF_IO_WRITE);
+               buf_pool->n_pages_written++;
++              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&block->mutex);
++
+ #ifdef UNIV_DEBUG
+               if (buf_debug_prints) {
+                       fputs("Has written ", stderr);
+@@ -2088,9 +2140,6 @@
+ #endif /* UNIV_DEBUG */
+       }
+-      mutex_exit(&block->mutex);
+-      mutex_exit(&(buf_pool->mutex));
+-
+ #ifdef UNIV_DEBUG
+       if (buf_debug_prints) {
+               fprintf(stderr, "page space %lu page no %lu\n",
+@@ -2118,11 +2167,11 @@
+               freed = buf_LRU_search_and_free_block(100);
+       }
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
+       ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
+ }
+ #ifdef UNIV_DEBUG
+@@ -2142,10 +2191,22 @@
+       ulint           n_flush         = 0;
+       ulint           n_free          = 0;
+       ulint           n_page          = 0;
++      ulint           n_single_flush_tmp      = 0;
++      ulint           n_lru_flush_tmp         = 0;
++      ulint           n_list_flush_tmp        = 0;
+       ut_ad(buf_pool);
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
++      mutex_enter(&(buf_pool->free_mutex));
++      mutex_enter(&(buf_pool->hash_mutex));
++
+       mutex_enter(&(buf_pool->mutex));
++      n_single_flush_tmp = buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
++      n_list_flush_tmp = buf_pool->n_flush[BUF_FLUSH_LIST];
++      n_lru_flush_tmp = buf_pool->n_flush[BUF_FLUSH_LRU];
++      mutex_exit(&(buf_pool->mutex));
+       for (i = 0; i < buf_pool->curr_size; i++) {
+@@ -2216,11 +2277,14 @@
+       }
+       ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
+-      ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
+-      ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
+-      ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
+-
+-      mutex_exit(&(buf_pool->mutex));
++      ut_a(n_single_flush_tmp == n_single_flush);
++      ut_a(n_list_flush_tmp == n_list_flush);
++      ut_a(n_lru_flush_tmp == n_lru_flush);
++      
++      mutex_exit(&(buf_pool->LRU_mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
++      mutex_exit(&(buf_pool->free_mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       ut_a(buf_LRU_validate());
+       ut_a(buf_flush_validate());
+@@ -2252,7 +2316,9 @@
+       index_ids = mem_alloc(sizeof(dulint) * size);
+       counts = mem_alloc(sizeof(ulint) * size);
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
++      mutex_enter(&(buf_pool->free_mutex));
+       fprintf(stderr,
+               "buf_pool size %lu\n"
+@@ -2305,7 +2371,9 @@
+               }
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
++      mutex_exit(&(buf_pool->free_mutex));
+       for (i = 0; i < n_found; i++) {
+               index = dict_index_get_if_in_cache(index_ids[i]);
+@@ -2339,8 +2407,6 @@
+       ulint           i;
+       ulint           fixed_pages_number = 0;
+-      mutex_enter(&(buf_pool->mutex));
+-
+       for (i = 0; i < buf_pool->curr_size; i++) {
+               block = buf_pool_get_nth_block(buf_pool, i);
+@@ -2356,7 +2422,6 @@
+               }
+       }
+-      mutex_exit(&(buf_pool->mutex));
+       return(fixed_pages_number);
+ }
+@@ -2385,7 +2450,9 @@
+ {
+       ulint   ratio;
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
++      mutex_enter(&(buf_pool->free_mutex));
+       ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
+               / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
+@@ -2393,7 +2460,9 @@
+       /* 1 + is there to avoid division by zero */
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
++      mutex_exit(&(buf_pool->free_mutex));
+       return(ratio);
+ }
+@@ -2413,6 +2482,9 @@
+       ut_ad(buf_pool);
+       size = buf_pool->curr_size;
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
++      mutex_enter(&(buf_pool->free_mutex));
+       mutex_enter(&(buf_pool->mutex));
+       if (srv_use_awe) {
+@@ -2487,6 +2559,9 @@
+       buf_pool->n_pages_written_old = buf_pool->n_pages_written;
+       buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
++      mutex_exit(&(buf_pool->LRU_mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
++      mutex_exit(&(buf_pool->free_mutex));
+       mutex_exit(&(buf_pool->mutex));
+ }
+@@ -2517,8 +2592,6 @@
+       ut_ad(buf_pool);
+-      mutex_enter(&(buf_pool->mutex));
+-
+       for (i = 0; i < buf_pool->curr_size; i++) {
+               block = buf_pool_get_nth_block(buf_pool, i);
+@@ -2540,8 +2613,6 @@
+               mutex_exit(&block->mutex);
+       }
+-      mutex_exit(&(buf_pool->mutex));
+-
+       return(TRUE);
+ }
+@@ -2580,11 +2651,11 @@
+ {
+       ulint   len;
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->free_mutex));
+       len = UT_LIST_GET_LEN(buf_pool->free);
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->free_mutex));
+       return(len);
+ }
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/buf/buf0flu.c mysql-5.1.29-rc/storage/innobase/buf/buf0flu.c
+--- mysql-5.1.29-rc_orig/storage/innobase/buf/buf0flu.c        2008-10-12 06:54:12.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/buf/buf0flu.c     2008-11-18 15:26:07.000000000 +0900
+@@ -109,13 +109,15 @@
+       ut_ad(mutex_own(&(buf_pool->mutex)));
+       ut_ad(mutex_own(&block->mutex));
+       if (block->state != BUF_BLOCK_FILE_PAGE) {
++              /* It is permited not to own LRU_mutex..  */
++/*
+               ut_print_timestamp(stderr);
+               fprintf(stderr,
+                       "  InnoDB: Error: buffer block state %lu"
+                       " in the LRU list!\n",
+                       (ulong)block->state);
+               ut_print_buf(stderr, block, sizeof(buf_block_t));
+-
++*/
+               return(FALSE);
+       }
+@@ -546,18 +548,20 @@
+       ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST
+             || flush_type == BUF_FLUSH_SINGLE_PAGE);
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->hash_mutex));
+       block = buf_page_hash_get(space, offset);
+       ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);
+       if (!block) {
+-              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&(buf_pool->hash_mutex));
+               return(0);
+       }
+       mutex_enter(&block->mutex);
++      mutex_enter(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       if (flush_type == BUF_FLUSH_LIST
+           && buf_flush_ready_for_flush(block, flush_type)) {
+@@ -755,7 +759,7 @@
+               high = fil_space_get_size(space);
+       }
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->hash_mutex));
+       for (i = low; i < high; i++) {
+@@ -789,7 +793,7 @@
+                               mutex_exit(&block->mutex);
+-                              mutex_exit(&(buf_pool->mutex));
++                              mutex_exit(&(buf_pool->hash_mutex));
+                               /* Note: as we release the buf_pool mutex
+                               above, in buf_flush_try_page we cannot be sure
+@@ -800,14 +804,14 @@
+                               count += buf_flush_try_page(space, i,
+                                                           flush_type);
+-                              mutex_enter(&(buf_pool->mutex));
++                              mutex_enter(&(buf_pool->hash_mutex));
+                       } else {
+                               mutex_exit(&block->mutex);
+                       }
+               }
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       return(count);
+ }
+@@ -863,6 +867,13 @@
+       (buf_pool->init_flush)[flush_type] = TRUE;
++      mutex_exit(&(buf_pool->mutex));
++
++      if (flush_type == BUF_FLUSH_LRU) {
++              mutex_enter(&(buf_pool->LRU_mutex));
++      }
++      mutex_enter(&(buf_pool->flush_list_mutex));
++
+       for (;;) {
+               /* If we have flushed enough, leave the loop */
+               if (page_count >= min_n) {
+@@ -908,7 +919,10 @@
+                               offset = block->offset;
+                               mutex_exit(&block->mutex);
+-                              mutex_exit(&(buf_pool->mutex));
++                              if (flush_type == BUF_FLUSH_LRU) {
++                                      mutex_exit(&(buf_pool->LRU_mutex));
++                              }
++                              mutex_exit(&(buf_pool->flush_list_mutex));
+                               old_page_count = page_count;
+@@ -920,7 +934,10 @@
+                               flush_type, offset,
+                               page_count - old_page_count); */
+-                              mutex_enter(&(buf_pool->mutex));
++                              if (flush_type == BUF_FLUSH_LRU) {
++                                      mutex_enter(&(buf_pool->LRU_mutex));
++                              }
++                              mutex_enter(&(buf_pool->flush_list_mutex));
+                       } else if (flush_type == BUF_FLUSH_LRU) {
+@@ -943,6 +960,13 @@
+               }
+       }
++      if (flush_type == BUF_FLUSH_LRU) {
++              mutex_exit(&(buf_pool->LRU_mutex));
++      }
++      mutex_exit(&(buf_pool->flush_list_mutex));
++
++      mutex_enter(&(buf_pool->mutex));
++
+       (buf_pool->init_flush)[flush_type] = FALSE;
+       if ((buf_pool->n_flush[flush_type] == 0)
+@@ -1001,10 +1025,14 @@
+       ulint           n_replaceable;
+       ulint           distance        = 0;
+-      mutex_enter(&(buf_pool->mutex));
++      /* optimistic search... */
++      //mutex_enter(&(buf_pool->LRU_mutex));
++      //mutex_enter(&(buf_pool->free_mutex));
+       n_replaceable = UT_LIST_GET_LEN(buf_pool->free);
++      //mutex_exit(&(buf_pool->free_mutex));
++
+       block = UT_LIST_GET_LAST(buf_pool->LRU);
+       while ((block != NULL)
+@@ -1025,7 +1053,7 @@
+               block = UT_LIST_GET_PREV(LRU, block);
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      //mutex_exit(&(buf_pool->LRU_mutex));
+       if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN) {
+@@ -1044,8 +1072,9 @@
+ immediately, without waiting. */
+ void
+-buf_flush_free_margin(void)
++buf_flush_free_margin(
+ /*=======================*/
++      ibool   wait)
+ {
+       ulint   n_to_flush;
+       ulint   n_flushed;
+@@ -1055,7 +1084,7 @@
+       if (n_to_flush > 0) {
+               n_flushed = buf_flush_batch(BUF_FLUSH_LRU, n_to_flush,
+                                           ut_dulint_zero);
+-              if (n_flushed == ULINT_UNDEFINED) {
++              if (wait && n_flushed == ULINT_UNDEFINED) {
+                       /* There was an LRU type flush batch already running;
+                       let us wait for it to end */
+@@ -1105,11 +1134,11 @@
+ {
+       ibool   ret;
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
+       ret = buf_flush_validate_low();
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
+       return(ret);
+ }
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/buf/buf0lru.c mysql-5.1.29-rc/storage/innobase/buf/buf0lru.c
+--- mysql-5.1.29-rc_orig/storage/innobase/buf/buf0lru.c        2008-10-12 06:54:12.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/buf/buf0lru.c     2008-11-18 15:09:58.000000000 +0900
+@@ -79,7 +79,10 @@
+       ibool           all_freed;
+ scan_again:
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
++      mutex_enter(&(buf_pool->free_mutex));
++      mutex_enter(&(buf_pool->hash_mutex));
+       all_freed = TRUE;
+@@ -119,7 +122,10 @@
+                               mutex_exit(&block->mutex);
+-                              mutex_exit(&(buf_pool->mutex));
++                              mutex_exit(&(buf_pool->LRU_mutex));
++                              mutex_exit(&(buf_pool->flush_list_mutex));
++                              mutex_exit(&(buf_pool->free_mutex));
++                              mutex_exit(&(buf_pool->hash_mutex));
+                               /* Note that the following call will acquire
+                               an S-latch on the page */
+@@ -149,7 +155,10 @@
+               block = prev_block;
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
++      mutex_exit(&(buf_pool->free_mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       if (!all_freed) {
+               os_thread_sleep(20000);
+@@ -172,14 +181,14 @@
+       ulint           len;
+       ulint           limit;
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
+       len = UT_LIST_GET_LEN(buf_pool->LRU);
+       if (len < BUF_LRU_OLD_MIN_LEN) {
+               /* The LRU list is too short to do read-ahead */
+-              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&(buf_pool->LRU_mutex));
+               return(0);
+       }
+@@ -188,7 +197,7 @@
+       limit = block->LRU_position - len / BUF_LRU_INITIAL_RATIO;
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
+       return(limit);
+ }
+@@ -212,13 +221,15 @@
+       ulint           distance = 0;
+       ibool           freed;
+-      mutex_enter(&(buf_pool->mutex));
++      /* optimistic search... */
++      //mutex_enter(&(buf_pool->LRU_mutex));
++retry:
+       freed = FALSE;
+       block = UT_LIST_GET_LAST(buf_pool->LRU);
+       while (block != NULL) {
+-              ut_a(block->in_LRU_list);
++              //ut_a(block->in_LRU_list); /* optimistic */
+               mutex_enter(&block->mutex);
+@@ -234,9 +245,17 @@
+                       }
+ #endif /* UNIV_DEBUG */
++                      mutex_exit(&block->mutex);
++
++                      mutex_enter(&(buf_pool->LRU_mutex));/* optimistic */
++
++                      mutex_enter(&(buf_pool->hash_mutex));
++                      mutex_enter(&block->mutex);
++                      if(block->in_LRU_list && buf_flush_ready_for_replace(block)) {
+                       buf_LRU_block_remove_hashed_page(block);
++                      mutex_exit(&(buf_pool->hash_mutex));
+-                      mutex_exit(&(buf_pool->mutex));
++                      mutex_exit(&(buf_pool->LRU_mutex));
+                       mutex_exit(&block->mutex);
+                       /* Remove possible adaptive hash index built on the
+@@ -257,14 +276,25 @@
+                       ut_a(block->buf_fix_count == 0);
+-                      mutex_enter(&(buf_pool->mutex));
++                      mutex_enter(&(buf_pool->free_mutex));
+                       mutex_enter(&block->mutex);
+                       buf_LRU_block_free_hashed_page(block);
+                       freed = TRUE;
++                      mutex_exit(&(buf_pool->free_mutex));
+                       mutex_exit(&block->mutex);
+                       break;
++                      } else { /* someone may interrupt...??? */
++                      mutex_exit(&(buf_pool->LRU_mutex));/* optimistic */
++
++                      mutex_exit(&(buf_pool->hash_mutex));
++
++                      if (!(block->in_LRU_list)) {
++                              mutex_exit(&block->mutex);
++                              goto retry;
++                      }
++                      }
+               }
+               mutex_exit(&block->mutex);
+@@ -275,13 +305,21 @@
+               if (!freed && n_iterations <= 10
+                   && distance > 100 + (n_iterations * buf_pool->curr_size)
+                   / 10) {
+-                      buf_pool->LRU_flush_ended = 0;
++                      mutex_enter(&(buf_pool->mutex));
++                      buf_pool->LRU_flush_ended = 0;
+                       mutex_exit(&(buf_pool->mutex));
++                      //mutex_exit(&(buf_pool->LRU_mutex));
++
+                       return(FALSE);
+               }
+       }
++      if (!freed) {
++              //mutex_exit(&(buf_pool->LRU_mutex));
++      }
++
++      mutex_enter(&(buf_pool->mutex));
+       if (buf_pool->LRU_flush_ended > 0) {
+               buf_pool->LRU_flush_ended--;
+       }
+@@ -333,7 +371,8 @@
+ {
+       ibool   ret     = FALSE;
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->free_mutex));
+       if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+           + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
+@@ -341,7 +380,8 @@
+               ret = TRUE;
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
++      mutex_exit(&(buf_pool->free_mutex));
+       return(ret);
+ }
+@@ -364,7 +404,7 @@
+       ibool           mon_value_was   = FALSE;
+       ibool           started_monitor = FALSE;
+ loop:
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->free_mutex)); /* LRU info:optimistic */
+       if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+           + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
+@@ -461,7 +501,7 @@
+               mutex_exit(&block->mutex);
+-              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&(buf_pool->free_mutex));
+               if (started_monitor) {
+                       srv_print_innodb_monitor = mon_value_was;
+@@ -473,7 +513,7 @@
+       /* If no block was in the free list, search from the end of the LRU
+       list and try to free a block there */
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->free_mutex));
+       freed = buf_LRU_search_and_free_block(n_iterations);
+@@ -517,7 +557,7 @@
+       /* No free block was found: try to flush the LRU list */
+-      buf_flush_free_margin();
++      buf_flush_free_margin(TRUE);
+       ++srv_buf_pool_wait_free;
+       os_aio_simulated_wake_handler_threads();
+@@ -988,7 +1028,7 @@
+       ulint           LRU_pos;
+       ut_ad(buf_pool);
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
+       if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
+@@ -1033,6 +1073,9 @@
+               ut_a(buf_pool->LRU_old_len == old_len);
+       }
++      mutex_exit(&(buf_pool->LRU_mutex));
++      mutex_enter(&(buf_pool->free_mutex));
++
+       UT_LIST_VALIDATE(free, buf_block_t, buf_pool->free);
+       block = UT_LIST_GET_FIRST(buf_pool->free);
+@@ -1043,7 +1086,7 @@
+               block = UT_LIST_GET_NEXT(free, block);
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->free_mutex));
+       return(TRUE);
+ }
+@@ -1059,7 +1102,7 @@
+       ulint           len;
+       ut_ad(buf_pool);
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->LRU_mutex));
+       fprintf(stderr, "Pool ulint clock %lu\n",
+               (ulong) buf_pool->ulint_clock);
+@@ -1105,6 +1148,6 @@
+               }
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->LRU_mutex));
+ }
+ #endif /* UNIV_DEBUG */
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/buf/buf0rea.c mysql-5.1.29-rc/storage/innobase/buf/buf0rea.c
+--- mysql-5.1.29-rc_orig/storage/innobase/buf/buf0rea.c        2008-10-12 06:54:12.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/buf/buf0rea.c     2008-11-18 15:28:13.000000000 +0900
+@@ -219,10 +219,12 @@
+               return(0);
+       }
++      mutex_exit(&(buf_pool->mutex));
+       /* Count how many blocks in the area have been recently accessed,
+       that is, reside near the start of the LRU list. */
++      mutex_enter(&(buf_pool->hash_mutex));
+       for (i = low; i < high; i++) {
+               block = buf_page_hash_get(space, i);
+@@ -233,8 +235,9 @@
+                       recent_blocks++;
+               }
+       }
++      mutex_exit(&(buf_pool->hash_mutex));
+-      mutex_exit(&(buf_pool->mutex));
++      // mutex_exit(&(buf_pool->mutex));
+       if (recent_blocks < BUF_READ_AHEAD_RANDOM_THRESHOLD) {
+               /* Do nothing */
+@@ -334,7 +337,7 @@
+       }
+       /* Flush pages from the end of the LRU list if necessary */
+-      buf_flush_free_margin();
++      buf_flush_free_margin(FALSE);
+       return(count + count2);
+ }
+@@ -432,6 +435,7 @@
+               return(0);
+       }
++      mutex_exit(&(buf_pool->mutex));
+       /* Check that almost all pages in the area have been accessed; if
+       offset == low, the accesses must be in a descending order, otherwise,
+@@ -445,6 +449,7 @@
+       fail_count = 0;
++      mutex_enter(&(buf_pool->hash_mutex));
+       for (i = low; i < high; i++) {
+               block = buf_page_hash_get(space, i);
+@@ -462,12 +467,13 @@
+                       pred_block = block;
+               }
+       }
++      mutex_exit(&(buf_pool->hash_mutex));
+       if (fail_count > BUF_READ_AHEAD_LINEAR_AREA
+           - BUF_READ_AHEAD_LINEAR_THRESHOLD) {
+               /* Too many failures: return */
+-              mutex_exit(&(buf_pool->mutex));
++              //mutex_exit(&(buf_pool->mutex));
+               return(0);
+       }
+@@ -475,10 +481,11 @@
+       /* If we got this far, we know that enough pages in the area have
+       been accessed in the right order: linear read-ahead can be sensible */
++      mutex_enter(&(buf_pool->hash_mutex));
+       block = buf_page_hash_get(space, offset);
+       if (block == NULL) {
+-              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&(buf_pool->hash_mutex));
+               return(0);
+       }
+@@ -494,7 +501,7 @@
+       pred_offset = fil_page_get_prev(frame);
+       succ_offset = fil_page_get_next(frame);
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->hash_mutex));
+       if ((offset == low) && (succ_offset == offset + 1)) {
+@@ -573,7 +580,7 @@
+       os_aio_simulated_wake_handler_threads();
+       /* Flush pages from the end of the LRU list if necessary */
+-      buf_flush_free_margin();
++      buf_flush_free_margin(FALSE);
+ #ifdef UNIV_DEBUG
+       if (buf_debug_prints && (count > 0)) {
+@@ -639,7 +646,7 @@
+       os_aio_simulated_wake_handler_threads();
+       /* Flush pages from the end of the LRU list if necessary */
+-      buf_flush_free_margin();
++      buf_flush_free_margin(FALSE);
+ #ifdef UNIV_DEBUG
+       if (buf_debug_prints) {
+@@ -716,7 +723,7 @@
+       os_aio_simulated_wake_handler_threads();
+       /* Flush pages from the end of the LRU list if necessary */
+-      buf_flush_free_margin();
++      buf_flush_free_margin(FALSE);
+ #ifdef UNIV_DEBUG
+       if (buf_debug_prints) {
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/buf0buf.h mysql-5.1.29-rc/storage/innobase/include/buf0buf.h
+--- mysql-5.1.29-rc_orig/storage/innobase/include/buf0buf.h    2008-10-12 06:54:13.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/buf0buf.h 2008-11-18 15:09:58.000000000 +0900
+@@ -926,6 +926,7 @@
+                                       currently always the same as
+                                       max_size */
+       hash_table_t*   page_hash;      /* hash table of the file pages */
++      mutex_t         hash_mutex;
+       ulint           n_pend_reads;   /* number of pending read operations */
+@@ -958,6 +959,7 @@
+       UT_LIST_BASE_NODE_T(buf_block_t) flush_list;
+                                       /* base node of the modified block
+                                       list */
++      mutex_t         flush_list_mutex;
+       ibool           init_flush[BUF_FLUSH_LIST + 1];
+                                       /* this is TRUE when a flush of the
+                                       given type is being initialized */
+@@ -991,8 +993,10 @@
+                                       in the case of AWE, at the start are
+                                       always free blocks for which the
+                                       physical memory is mapped to a frame */
++      mutex_t         free_mutex;
+       UT_LIST_BASE_NODE_T(buf_block_t) LRU;
+                                       /* base node of the LRU list */
++      mutex_t         LRU_mutex;
+       buf_block_t*    LRU_old;        /* pointer to the about 3/8 oldest
+                                       blocks in the LRU list; NULL if LRU
+                                       length less than BUF_LRU_OLD_MIN_LEN */
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/buf0buf.ic mysql-5.1.29-rc/storage/innobase/include/buf0buf.ic
+--- mysql-5.1.29-rc_orig/storage/innobase/include/buf0buf.ic   2008-10-12 06:54:13.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/buf0buf.ic        2008-11-18 15:09:58.000000000 +0900
+@@ -104,7 +104,7 @@
+       buf_block_t*    block;
+       dulint          lsn;
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
+       block = UT_LIST_GET_LAST(buf_pool->flush_list);
+@@ -114,7 +114,7 @@
+               lsn = block->oldest_modification;
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
+       return(lsn);
+ }
+@@ -388,18 +388,18 @@
+                               /* out: TRUE if io going on */
+       buf_block_t*    block)  /* in: buf_pool block, must be bufferfixed */
+ {
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&block->mutex);
+       ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
+       ut_ad(block->buf_fix_count > 0);
+       if (block->io_fix != 0) {
+-              mutex_exit(&(buf_pool->mutex));
++              mutex_exit(&block->mutex);
+               return(TRUE);
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&block->mutex);
+       return(FALSE);
+ }
+@@ -421,7 +421,7 @@
+       block = buf_block_align(frame);
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&block->mutex);
+       if (block->state == BUF_BLOCK_FILE_PAGE) {
+               lsn = block->newest_modification;
+@@ -429,7 +429,7 @@
+               lsn = ut_dulint_zero;
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&block->mutex);
+       return(lsn);
+ }
+@@ -624,9 +624,9 @@
+       ut_a(block->buf_fix_count > 0);
+       if (rw_latch == RW_X_LATCH && mtr->modifications) {
+-              mutex_enter(&buf_pool->mutex);
++              mutex_enter(&buf_pool->flush_list_mutex);
+               buf_flush_note_modification(block, mtr);
+-              mutex_exit(&buf_pool->mutex);
++              mutex_exit(&buf_pool->flush_list_mutex);
+       }
+       mutex_enter(&block->mutex);
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/buf0flu.h mysql-5.1.29-rc/storage/innobase/include/buf0flu.h
+--- mysql-5.1.29-rc_orig/storage/innobase/include/buf0flu.h    2008-10-12 06:54:13.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/buf0flu.h 2008-11-18 15:09:58.000000000 +0900
+@@ -26,8 +26,9 @@
+ a margin of replaceable pages there. */
+ void
+-buf_flush_free_margin(void);
++buf_flush_free_margin(
+ /*=======================*/
++      ibool   wait);
+ /************************************************************************
+ Initializes a page for writing to the tablespace. */
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/buf0flu.ic mysql-5.1.29-rc/storage/innobase/include/buf0flu.ic
+--- mysql-5.1.29-rc_orig/storage/innobase/include/buf0flu.ic   2008-10-12 06:54:13.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/buf0flu.ic        2008-11-18 15:09:58.000000000 +0900
+@@ -84,7 +84,7 @@
+       ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
+ #endif /* UNIV_SYNC_DEBUG */
+-      mutex_enter(&(buf_pool->mutex));
++      mutex_enter(&(buf_pool->flush_list_mutex));
+       ut_ad(ut_dulint_cmp(block->newest_modification, end_lsn) <= 0);
+@@ -102,5 +102,5 @@
+                                   start_lsn) <= 0);
+       }
+-      mutex_exit(&(buf_pool->mutex));
++      mutex_exit(&(buf_pool->flush_list_mutex));
+ }
+diff -ruN mysql-5.1.29-rc_orig/patch_info/split_buf_pool_mutex_fixed_optimistic_safe.info mysql-5.1.29-rc/patch_info/split_buf_pool_mutex_fixed_optimistic_safe.info
+--- /dev/null  1970-01-01 09:00:00.000000000 +0900
++++ mysql-5.1.29-rc/patch_info/split_buf_pool_mutex_fixed_optimistic_safe.info 2008-11-18 15:09:58.000000000 +0900
+@@ -0,0 +1,6 @@
++File=split_buf_pool_mutex_fixed_optimistic_safe.patch
++Name=InnoDB patch to fix buffer pool scalability
++Version=1.0
++Author=Yasufumi Kinoshita
++License=BSD
++Comment=
index e896c081c825f00848fba3661b920fc8e00208b0..09392a1bd244f4524078983c5330bb4fd7072cd2 100644 (file)
@@ -1,6 +1,6 @@
-diff -r ab66c8ca382a include/mysql_com.h
---- a/include/mysql_com.h      Thu Sep 04 12:08:00 2008 -0700
-+++ b/include/mysql_com.h      Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 include/mysql_com.h
+--- a/include/mysql_com.h      Thu Dec 04 08:54:17 2008 -0800
++++ b/include/mysql_com.h      Thu Dec 04 08:54:27 2008 -0800
 @@ -115,6 +115,8 @@
                                           thread */
  #define REFRESH_MASTER          128     /* Remove all bin logs in the index
@@ -10,20 +10,10 @@ diff -r ab66c8ca382a include/mysql_com.h
  
  /* The following can't be set with mysql_refresh() */
  #define REFRESH_READ_LOCK     16384   /* Lock tables for read */
-diff -r ab66c8ca382a patch_info/userstats.info
---- /dev/null  Thu Jan 01 00:00:00 1970 +0000
-+++ b/patch_info/userstats.info        Thu Sep 04 12:12:44 2008 -0700
-@@ -0,0 +1,6 @@
-+File=userstats.patch
-+Name=SHOW USER/TABLE/INDEX statistics
-+Version=1.0
-+Author=Google
-+License=GPL
-+Comment=Added INFORMATION_SCHEMA.*_STATISTICS
-diff -r ab66c8ca382a sql/handler.cc
---- a/sql/handler.cc   Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/handler.cc   Thu Sep 04 12:12:44 2008 -0700
-@@ -1168,6 +1168,7 @@
+diff -r 3ed7e96969f9 sql/handler.cc
+--- a/sql/handler.cc   Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/handler.cc   Thu Dec 04 08:54:27 2008 -0800
+@@ -1205,6 +1205,7 @@
          error=1;
        }
        status_var_increment(thd->status_var.ha_commit_count);
@@ -31,7 +21,7 @@ diff -r ab66c8ca382a sql/handler.cc
        ha_info_next= ha_info->next();
        ha_info->reset(); /* keep it conveniently zero-filled */
      }
-@@ -1235,6 +1236,7 @@
+@@ -1272,6 +1273,7 @@
          error=1;
        }
        status_var_increment(thd->status_var.ha_rollback_count);
@@ -39,7 +29,7 @@ diff -r ab66c8ca382a sql/handler.cc
        ha_info_next= ha_info->next();
        ha_info->reset(); /* keep it conveniently zero-filled */
      }
-@@ -1682,6 +1684,7 @@
+@@ -1724,6 +1726,7 @@
        error=1;
      }
      status_var_increment(thd->status_var.ha_rollback_count);
@@ -47,7 +37,7 @@ diff -r ab66c8ca382a sql/handler.cc
      ha_info_next= ha_info->next();
      ha_info->reset(); /* keep it conveniently zero-filled */
    }
-@@ -2016,6 +2019,8 @@
+@@ -2058,6 +2061,8 @@
        dup_ref=ref+ALIGN_SIZE(ref_length);
      cached_table_flags= table_flags();
    }
@@ -56,7 +46,7 @@ diff -r ab66c8ca382a sql/handler.cc
    DBUG_RETURN(error);
  }
  
-@@ -3448,6 +3453,97 @@
+@@ -3487,6 +3492,97 @@
    return;
  }
  
@@ -154,9 +144,9 @@ diff -r ab66c8ca382a sql/handler.cc
  
  /****************************************************************************
  ** Some general functions that isn't in the handler class
-diff -r ab66c8ca382a sql/handler.h
---- a/sql/handler.h    Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/handler.h    Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/handler.h
+--- a/sql/handler.h    Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/handler.h    Thu Dec 04 08:54:27 2008 -0800
 @@ -29,6 +29,10 @@
  #endif
  
@@ -176,9 +166,9 @@ diff -r ab66c8ca382a sql/handler.h
     /*
       Iterators creator.
       Presence of the pointer should be checked before using
-@@ -1130,6 +1135,10 @@
+@@ -1137,6 +1142,10 @@
    */
-   Discrete_interval auto_inc_interval_for_cur_row;
+   uint auto_inc_intervals_count;
  
 +   ulonglong rows_read;
 +   ulonglong rows_changed;
@@ -187,7 +177,7 @@ diff -r ab66c8ca382a sql/handler.h
    handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
      :table_share(share_arg), table(0),
      estimation_rows_to_insert(0), ht(ht_arg),
-@@ -1154,8 +1154,10 @@
+@@ -1145,8 +1154,10 @@
      ft_handler(0), inited(NONE),
      locked(FALSE), implicit_emptied(0),
      pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0),
@@ -195,12 +185,12 @@ diff -r ab66c8ca382a sql/handler.h
 -    {}
 +    auto_inc_intervals_count(0), rows_read(0), rows_changed(0)
 +    {
-+      memset(index_rows_read, 0, sizeof(index_rows_read));
++        memset(index_rows_read, 0, sizeof(index_rows_read));
 +    }
    virtual ~handler(void)
    {
      DBUG_ASSERT(locked == FALSE);
-@@ -1262,7 +1273,13 @@
+@@ -1267,7 +1278,13 @@
    {
      table= table_arg;
      table_share= share;
@@ -214,9 +204,9 @@ diff -r ab66c8ca382a sql/handler.h
    virtual double scan_time()
    { return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; }
    virtual double read_time(uint index, uint ranges, ha_rows rows)
-diff -r ab66c8ca382a sql/lex.h
---- a/sql/lex.h        Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/lex.h        Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/lex.h
+--- a/sql/lex.h        Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/lex.h        Thu Dec 04 08:54:27 2008 -0800
 @@ -245,6 +245,7 @@
    { "IN",             SYM(IN_SYM)},
    { "INDEX",          SYM(INDEX_SYM)},
@@ -241,10 +231,10 @@ diff -r ab66c8ca382a sql/lex.h
    { "USE_FRM",                SYM(USE_FRM)},
    { "USING",          SYM(USING)},
    { "UTC_DATE",         SYM(UTC_DATE_SYM)},
-diff -r ab66c8ca382a sql/mysql_priv.h
---- a/sql/mysql_priv.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/mysql_priv.h Thu Sep 04 12:12:44 2008 -0700
-@@ -1058,7 +1058,19 @@
+diff -r 3ed7e96969f9 sql/mysql_priv.h
+--- a/sql/mysql_priv.h Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/mysql_priv.h Thu Dec 04 08:54:27 2008 -0800
+@@ -1060,7 +1060,19 @@
  bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
  void init_max_user_conn(void);
  void init_update_queries(void);
@@ -264,7 +254,7 @@ diff -r ab66c8ca382a sql/mysql_priv.h
  pthread_handler_t handle_bootstrap(void *arg);
  int mysql_execute_command(THD *thd);
  bool do_command(THD *thd);
-@@ -2009,6 +2021,12 @@
+@@ -2015,6 +2027,12 @@
  extern struct system_variables max_system_variables;
  extern struct system_status_var global_status_var;
  extern struct rand_struct sql_rand;
@@ -277,10 +267,10 @@ diff -r ab66c8ca382a sql/mysql_priv.h
  
  extern const char *opt_date_time_formats[];
  extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
-diff -r ab66c8ca382a sql/mysqld.cc
---- a/sql/mysqld.cc    Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/mysqld.cc    Thu Sep 04 12:12:44 2008 -0700
-@@ -588,6 +588,11 @@
+diff -r 3ed7e96969f9 sql/mysqld.cc
+--- a/sql/mysqld.cc    Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/mysqld.cc    Thu Dec 04 08:54:27 2008 -0800
+@@ -589,6 +589,11 @@
                LOCK_global_system_variables,
                LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
                  LOCK_connection_count;
@@ -292,7 +282,7 @@ diff -r ab66c8ca382a sql/mysqld.cc
  /**
    The below lock protects access to two global server variables:
    max_prepared_stmt_count and prepared_stmt_count. These variables
-@@ -1265,6 +1270,9 @@
+@@ -1266,6 +1271,9 @@
    x_free(opt_secure_file_priv);
    bitmap_free(&temp_pool);
    free_max_user_conn();
@@ -302,7 +292,7 @@ diff -r ab66c8ca382a sql/mysqld.cc
  #ifdef HAVE_REPLICATION
    end_slave_list();
  #endif
-@@ -1377,6 +1385,9 @@
+@@ -1378,6 +1386,9 @@
    (void) pthread_cond_destroy(&COND_thread_cache);
    (void) pthread_cond_destroy(&COND_flush_thread_cache);
    (void) pthread_cond_destroy(&COND_manager);
@@ -312,7 +302,7 @@ diff -r ab66c8ca382a sql/mysqld.cc
  }
  
  #endif /*EMBEDDED_LIBRARY*/
-@@ -3069,6 +3080,7 @@
+@@ -3072,6 +3083,7 @@
    {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
    {"show_grants",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
    {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
@@ -320,7 +310,7 @@ diff -r ab66c8ca382a sql/mysqld.cc
    {"show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
    {"show_new_master",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
    {"show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
-@@ -3085,9 +3097,11 @@
+@@ -3089,9 +3101,11 @@
    {"show_slave_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
    {"show_status",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
    {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
@@ -332,7 +322,7 @@ diff -r ab66c8ca382a sql/mysqld.cc
    {"show_variables",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
    {"show_warnings",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
    {"slave_start",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
-@@ -3503,6 +3517,9 @@
+@@ -3507,6 +3521,9 @@
  #endif
    (void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
    (void) pthread_cond_init(&COND_server_started,NULL);
@@ -360,23 +350,23 @@ diff -r ab66c8ca382a sql/mysqld.cc
    DBUG_RETURN(0);
  }
  
-diff -r ab66c8ca382a sql/sql_base.cc
---- a/sql/sql_base.cc  Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_base.cc  Thu Sep 04 12:12:44 2008 -0700
-@@ -1342,6 +1342,12 @@
-   DBUG_ASSERT(!table->file || table->file->inited == handler::NONE);
+diff -r 3ed7e96969f9 sql/sql_base.cc
+--- a/sql/sql_base.cc  Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_base.cc  Thu Dec 04 08:54:27 2008 -0800
+@@ -1343,6 +1343,12 @@
    DBUG_PRINT("tcache", ("table: '%s'.'%s' 0x%lx", table->s->db.str,
                          table->s->table_name.str, (long) table));
-+
 +  if(table->file)
 +  {
 +    table->file->update_global_table_stats();
 +    table->file->update_global_index_stats();
 +  }
++
    *table_ptr=table->next;
    /*
-@@ -1880,6 +1886,9 @@
+     When closing a MERGE parent or child table, detach the children first.
+@@ -1882,6 +1888,9 @@
    DBUG_ENTER("close_temporary");
    DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'",
                            table->s->db.str, table->s->table_name.str));
@@ -386,10 +376,10 @@ diff -r ab66c8ca382a sql/sql_base.cc
  
    free_io_cache(table);
    closefrm(table, 0);
-diff -r ab66c8ca382a sql/sql_class.cc
---- a/sql/sql_class.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_class.cc Thu Sep 04 12:12:44 2008 -0700
-@@ -577,6 +577,8 @@
+diff -r 3ed7e96969f9 sql/sql_class.cc
+--- a/sql/sql_class.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_class.cc Thu Dec 04 08:54:27 2008 -0800
+@@ -578,6 +578,8 @@
    bzero(ha_data, sizeof(ha_data));
    mysys_var=0;
    binlog_evt_union.do_union= FALSE;
@@ -398,7 +388,7 @@ diff -r ab66c8ca382a sql/sql_class.cc
    enable_slow_log= 0;
  #ifndef DBUG_OFF
    dbug_sentry=THD_SENTRY_MAGIC;
-@@ -761,8 +763,55 @@
+@@ -762,8 +764,55 @@
    reset_current_stmt_binlog_row_based();
    bzero((char *) &status_var, sizeof(status_var));
    sql_log_bin_toplevel= options & OPTION_BIN_LOG;
@@ -454,10 +444,10 @@ diff -r ab66c8ca382a sql/sql_class.cc
  
  /*
    Init THD for query processing.
-diff -r ab66c8ca382a sql/sql_class.h
---- a/sql/sql_class.h  Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_class.h  Thu Sep 04 12:12:44 2008 -0700
-@@ -1310,6 +1310,8 @@
+diff -r 3ed7e96969f9 sql/sql_class.h
+--- a/sql/sql_class.h  Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_class.h  Thu Dec 04 08:54:27 2008 -0800
+@@ -1327,6 +1327,8 @@
      first byte of the packet in do_command()
    */
    enum enum_server_command command;
@@ -466,7 +456,7 @@ diff -r ab66c8ca382a sql/sql_class.h
    uint32     server_id;
    uint32     file_id;                 // for LOAD DATA INFILE
    /* remote (peer) port */
-@@ -1584,6 +1586,7 @@
+@@ -1616,6 +1618,7 @@
    ulonglong  options;           /* Bitmap of states */
    longlong   row_count_func;    /* For the ROW_COUNT() function */
    ha_rows    cuted_fields;
@@ -474,7 +464,7 @@ diff -r ab66c8ca382a sql/sql_class.h
  
    /*
      number of rows we actually sent to the client, including "synthetic"
-@@ -1735,6 +1738,27 @@
+@@ -1767,6 +1770,27 @@
    */
    LOG_INFO*  current_linfo;
    NET*       slave_net;                       // network connection from slave -> m.
@@ -502,7 +492,7 @@ diff -r ab66c8ca382a sql/sql_class.h
    /* Used by the sys_var class to store temporary values */
    union
    {
-@@ -1797,6 +1821,9 @@
+@@ -1827,6 +1851,9 @@
      alloc_root. 
    */
    void init_for_queries();
@@ -512,9 +502,9 @@ diff -r ab66c8ca382a sql/sql_class.h
    void change_user(void);
    void cleanup(void);
    void cleanup_after_query();
-diff -r ab66c8ca382a sql/sql_connect.cc
---- a/sql/sql_connect.cc       Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_connect.cc       Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_connect.cc
+--- a/sql/sql_connect.cc       Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_connect.cc       Thu Dec 04 08:54:27 2008 -0800
 @@ -520,6 +520,14 @@
                   0,0,
                   (hash_get_key) get_key_conn, (hash_free_key) free_user,
@@ -553,9 +543,9 @@ diff -r ab66c8ca382a sql/sql_connect.cc
      if (thread_scheduler.end_thread(thd,1))
        return 0;                                 // Probably no-threads
  
-diff -r ab66c8ca382a sql/sql_delete.cc
---- a/sql/sql_delete.cc        Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_delete.cc        Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_delete.cc
+--- a/sql/sql_delete.cc        Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_delete.cc        Thu Dec 04 08:54:27 2008 -0800
 @@ -402,6 +402,7 @@
      my_ok(thd, (ha_rows) thd->row_count_func);
      DBUG_PRINT("info",("%ld records deleted",(long) deleted));
@@ -572,9 +562,9 @@ diff -r ab66c8ca382a sql/sql_delete.cc
    return 0;
  }
  
-diff -r ab66c8ca382a sql/sql_insert.cc
---- a/sql/sql_insert.cc        Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_insert.cc        Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_insert.cc
+--- a/sql/sql_insert.cc        Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_insert.cc        Thu Dec 04 08:54:27 2008 -0800
 @@ -969,6 +969,7 @@
      thd->row_count_func= info.copied + info.deleted + updated;
      ::my_ok(thd, (ulong) thd->row_count_func, id, buff);
@@ -583,9 +573,9 @@ diff -r ab66c8ca382a sql/sql_insert.cc
    thd->abort_on_warning= 0;
    DBUG_RETURN(FALSE);
  
-diff -r ab66c8ca382a sql/sql_lex.h
---- a/sql/sql_lex.h    Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_lex.h    Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_lex.h
+--- a/sql/sql_lex.h    Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_lex.h    Thu Dec 04 08:54:27 2008 -0800
 @@ -118,7 +118,7 @@
    SQLCOM_SHOW_CREATE_TRIGGER,
    SQLCOM_ALTER_DB_UPGRADE,
@@ -595,9 +585,9 @@ diff -r ab66c8ca382a sql/sql_lex.h
    /*
      When a command is added here, be sure it's also added in mysqld.cc
      in "struct show_var_st status_vars[]= {" ...
-diff -r ab66c8ca382a sql/sql_parse.cc
---- a/sql/sql_parse.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_parse.cc Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_parse.cc
+--- a/sql/sql_parse.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_parse.cc Thu Dec 04 08:54:27 2008 -0800
 @@ -45,6 +45,15 @@
  
  static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
@@ -614,7 +604,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
  
  const char *any_db="*any*";   // Special symbol for check_access
  
-@@ -278,7 +287,9 @@
+@@ -326,7 +335,9 @@
    sql_command_flags[SQLCOM_SHOW_FUNC_CODE]=  CF_STATUS_COMMAND;
    sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]=  CF_STATUS_COMMAND;
    sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
@@ -625,7 +615,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
  
     sql_command_flags[SQLCOM_SHOW_TABLES]=       (CF_STATUS_COMMAND |
                                                   CF_SHOW_TABLE_COMMAND |
-@@ -481,6 +492,86 @@
+@@ -544,6 +555,86 @@
    DBUG_RETURN(0);
  }
  
@@ -712,7 +702,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
  
  /**
    @brief Check access privs for a MERGE table and fix children lock types.
-@@ -899,6 +990,9 @@
+@@ -962,6 +1053,9 @@
    DBUG_PRINT("info",("packet: '%*.s'; command: %d", packet_length, packet, command));
  
    thd->command=command;
@@ -722,7 +712,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
    /*
      Commands which always take a long time are logged into
      the slow log only if opt_log_slow_admin_statements is set.
-@@ -1677,6 +1771,9 @@
+@@ -1740,6 +1834,9 @@
    case SCH_COLUMN_PRIVILEGES:
    case SCH_TABLE_CONSTRAINTS:
    case SCH_KEY_COLUMN_USAGE:
@@ -732,7 +722,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
    default:
      break;
    }
-@@ -2020,6 +2117,9 @@
+@@ -2129,6 +2226,9 @@
      my_error(ER_NOT_SUPPORTED_YET, MYF(0), "embedded server");
      break;
  #endif
@@ -741,8 +731,8 @@ diff -r ab66c8ca382a sql/sql_parse.cc
 +  case SQLCOM_SHOW_INDEX_STATS:
    case SQLCOM_SHOW_STATUS_PROC:
    case SQLCOM_SHOW_STATUS_FUNC:
-     res= execute_sqlcom_select(thd, all_tables);
-@@ -2195,6 +2295,7 @@
+     if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
+@@ -2306,6 +2406,7 @@
    }
  #endif
  
@@ -750,7 +740,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
    case SQLCOM_BACKUP_TABLE:
    {
      DBUG_ASSERT(first_table == all_tables && first_table != 0);
-@@ -5245,6 +5346,130 @@
+@@ -5372,6 +5473,130 @@
  #endif /*NO_EMBEDDED_ACCESS_CHECKS*/
  
  
@@ -881,7 +871,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
  /**
    check for global access and give descriptive error message if it fails.
  
-@@ -5406,6 +5631,10 @@
+@@ -5539,6 +5764,10 @@
      reset_dynamic(&thd->user_var_events);
      thd->user_var_events_alloc= thd->mem_root;
    }
@@ -892,7 +882,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
    thd->clear_error();
    thd->main_da.reset_diagnostics_area();
    thd->total_warn_count=0;                    // Warnings for this query
-@@ -5585,6 +5814,16 @@
+@@ -5722,6 +5951,16 @@
    DBUG_ENTER("mysql_parse");
  
    DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
@@ -909,7 +899,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
  
    /*
      Warning.
-@@ -5674,6 +5913,27 @@
+@@ -5816,6 +6055,27 @@
      *found_semicolon= NULL;
    }
  
@@ -937,7 +927,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
    DBUG_VOID_RETURN;
  }
  
-@@ -6256,6 +6516,7 @@
+@@ -6398,6 +6658,7 @@
      tables->lock_type= lock_type;
      tables->updating=  for_update;
    }
@@ -945,7 +935,7 @@ diff -r ab66c8ca382a sql/sql_parse.cc
    DBUG_VOID_RETURN;
  }
  
-@@ -6623,6 +6884,21 @@
+@@ -6779,6 +7040,21 @@
  #endif
   if (options & REFRESH_USER_RESOURCES)
     reset_mqh((LEX_USER *) NULL, 0);             /* purecov: inspected */
@@ -967,10 +957,10 @@ diff -r ab66c8ca382a sql/sql_parse.cc
   *write_to_binlog= tmp_write_to_binlog;
   return result;
  }
-diff -r ab66c8ca382a sql/sql_show.cc
---- a/sql/sql_show.cc  Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_show.cc  Thu Sep 04 12:12:44 2008 -0700
-@@ -2239,6 +2239,90 @@
+diff -r 3ed7e96969f9 sql/sql_show.cc
+--- a/sql/sql_show.cc  Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_show.cc  Thu Dec 04 08:54:27 2008 -0800
+@@ -2260,6 +2260,90 @@
    DBUG_RETURN(FALSE);
  }
  
@@ -1061,7 +1051,7 @@ diff -r ab66c8ca382a sql/sql_show.cc
  
  /* collect status for all running threads */
  
-@@ -6565,6 +6649,38 @@
+@@ -6606,6 +6690,38 @@
    {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
  };
  
@@ -1100,7 +1090,7 @@ diff -r ab66c8ca382a sql/sql_show.cc
  
  /*
    Description of ST_FIELD_INFO in table.h
-@@ -6798,6 +6798,8 @@
+@@ -6824,6 +6824,8 @@
     fill_status, make_old_format, 0, 0, -1, 0, 0},
    {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
     fill_variables, make_old_format, 0, 0, -1, 0, 0},
@@ -1109,7 +1099,7 @@ diff -r ab66c8ca382a sql/sql_show.cc
    {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
     get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
     OPEN_TABLE_ONLY},
-@@ -6642,11 +6760,15 @@
+@@ -6683,11 +6801,15 @@
     get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
    {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
     fill_schema_table_privileges, 0, 0, -1, -1, 0, 0},
@@ -1125,9 +1115,9 @@ diff -r ab66c8ca382a sql/sql_show.cc
    {"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
     make_old_format, 0, -1, -1, 1, 0},
    {"VIEWS", view_fields_info, create_schema_table, 
-diff -r ab66c8ca382a sql/sql_update.cc
---- a/sql/sql_update.cc        Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_update.cc        Thu Sep 04 12:12:45 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_update.cc
+--- a/sql/sql_update.cc        Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_update.cc        Thu Dec 04 08:54:27 2008 -0800
 @@ -816,6 +816,7 @@
      thd->row_count_func=
        (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
@@ -1136,17 +1126,17 @@ diff -r ab66c8ca382a sql/sql_update.cc
      DBUG_PRINT("info",("%ld records updated", (long) updated));
    }
    thd->count_cuted_fields= CHECK_FIELD_IGNORE;                /* calc cuted fields */
-@@ -2007,5 +2008,6 @@
+@@ -2038,5 +2039,6 @@
    thd->row_count_func=
      (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
    ::my_ok(thd, (ulong) thd->row_count_func, id, buff);
 +  thd->updated_row_count += thd->row_count_func;
    DBUG_RETURN(FALSE);
  }
-diff -r ab66c8ca382a sql/sql_yacc.yy
---- a/sql/sql_yacc.yy  Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_yacc.yy  Thu Sep 04 12:12:45 2008 -0700
-@@ -737,6 +737,7 @@
+diff -r 3ed7e96969f9 sql/sql_yacc.yy
+--- a/sql/sql_yacc.yy  Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_yacc.yy  Thu Dec 04 08:54:27 2008 -0800
+@@ -738,6 +738,7 @@
  %token  IMPORT
  %token  INDEXES
  %token  INDEX_SYM
@@ -1154,7 +1144,7 @@ diff -r ab66c8ca382a sql/sql_yacc.yy
  %token  INFILE
  %token  INITIAL_SIZE_SYM
  %token  INNER_SYM                     /* SQL-2003-R */
-@@ -1025,6 +1026,7 @@
+@@ -1026,6 +1027,7 @@
  %token  TABLE_REF_PRIORITY
  %token  TABLE_SYM                     /* SQL-2003-R */
  %token  TABLE_CHECKSUM_SYM
@@ -1162,7 +1152,7 @@ diff -r ab66c8ca382a sql/sql_yacc.yy
  %token  TEMPORARY                     /* SQL-2003-N */
  %token  TEMPTABLE_SYM
  %token  TERMINATED
-@@ -1070,6 +1072,7 @@
+@@ -1071,6 +1073,7 @@
  %token  UPGRADE_SYM
  %token  USAGE                         /* SQL-2003-N */
  %token  USER                          /* SQL-2003-R */
@@ -1170,7 +1160,7 @@ diff -r ab66c8ca382a sql/sql_yacc.yy
  %token  USE_FRM
  %token  USE_SYM
  %token  USING                         /* SQL-2003-R */
-@@ -9353,6 +9356,27 @@
+@@ -10090,6 +10093,27 @@
            {
              Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
            }
@@ -1198,7 +1188,7 @@ diff -r ab66c8ca382a sql/sql_yacc.yy
          | CREATE PROCEDURE sp_name
            {
              LEX *lex= Lex;
-@@ -9567,6 +9591,10 @@
+@@ -10304,6 +10328,10 @@
            { Lex->type|= REFRESH_DES_KEY_FILE; }
          | RESOURCES
            { Lex->type|= REFRESH_USER_RESOURCES; }
@@ -1209,9 +1199,9 @@ diff -r ab66c8ca382a sql/sql_yacc.yy
          ;
  
  opt_table_list:
-diff -r ab66c8ca382a sql/structs.h
---- a/sql/structs.h    Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/structs.h    Thu Sep 04 12:12:45 2008 -0700
+diff -r 3ed7e96969f9 sql/structs.h
+--- a/sql/structs.h    Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/structs.h    Thu Dec 04 08:54:27 2008 -0800
 @@ -226,6 +226,28 @@
    /* Maximum amount of resources which account is allowed to consume. */
    USER_RESOURCES user_resources;
@@ -1241,10 +1231,10 @@ diff -r ab66c8ca382a sql/structs.h
  
        /* Bits in form->update */
  #define REG_MAKE_DUPP         1       /* Make a copy of record when read */
-diff -r ab66c8ca382a sql/table.h
---- a/sql/table.h      Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/table.h      Thu Sep 04 12:12:45 2008 -0700
-@@ -824,6 +824,7 @@
+diff -r 3ed7e96969f9 sql/table.h
+--- a/sql/table.h      Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/table.h      Thu Dec 04 08:54:27 2008 -0800
+@@ -879,6 +879,7 @@
    SCH_FILES,
    SCH_GLOBAL_STATUS,
    SCH_GLOBAL_VARIABLES,
@@ -1252,7 +1242,7 @@ diff -r ab66c8ca382a sql/table.h
    SCH_KEY_COLUMN_USAGE,
    SCH_OPEN_TABLES,
    SCH_PARTITIONS,
-@@ -842,8 +843,10 @@
+@@ -897,8 +898,10 @@
    SCH_TABLE_CONSTRAINTS,
    SCH_TABLE_NAMES,
    SCH_TABLE_PRIVILEGES,
@@ -1263,10 +1253,10 @@ diff -r ab66c8ca382a sql/table.h
    SCH_VARIABLES,
    SCH_VIEWS
  };
-diff -r ab66c8ca382a storage/innobase/handler/ha_innodb.cc
---- a/storage/innobase/handler/ha_innodb.cc    Thu Sep 04 12:08:00 2008 -0700
-+++ b/storage/innobase/handler/ha_innodb.cc    Thu Sep 04 12:12:45 2008 -0700
-@@ -3925,6 +3925,8 @@
+diff -r 3ed7e96969f9 storage/innobase/handler/ha_innodb.cc
+--- a/storage/innobase/handler/ha_innodb.cc    Thu Dec 04 08:54:17 2008 -0800
++++ b/storage/innobase/handler/ha_innodb.cc    Thu Dec 04 08:54:27 2008 -0800
+@@ -3494,6 +3494,8 @@
  
        error = row_insert_for_mysql((byte*) record, prebuilt);
  
@@ -1275,7 +1265,7 @@ diff -r ab66c8ca382a storage/innobase/handler/ha_innodb.cc
        /* Handle duplicate key errors */
        if (auto_inc_used) {
                ulint           err;
-@@ -4001,6 +4003,8 @@
+@@ -3571,6 +3573,8 @@
                        break;
                }
        }
@@ -1284,7 +1274,7 @@ diff -r ab66c8ca382a storage/innobase/handler/ha_innodb.cc
  
        innodb_srv_conc_exit_innodb(prebuilt->trx);
  
-@@ -4647,6 +4651,8 @@
+@@ -4178,6 +4182,8 @@
                ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
                                           match_mode, 0);
  
@@ -1293,7 +1283,7 @@ diff -r ab66c8ca382a storage/innobase/handler/ha_innodb.cc
                innodb_srv_conc_exit_innodb(prebuilt->trx);
        } else {
  
-@@ -4193,6 +4193,9 @@
+@@ -4187,6 +4193,9 @@
        if (ret == DB_SUCCESS) {
                error = 0;
                table->status = 0;
@@ -1303,7 +1293,7 @@ diff -r ab66c8ca382a storage/innobase/handler/ha_innodb.cc
  
        } else if (ret == DB_RECORD_NOT_FOUND) {
                error = HA_ERR_KEY_NOT_FOUND;
-@@ -4366,6 +4369,9 @@
+@@ -4360,6 +4369,9 @@
        if (ret == DB_SUCCESS) {
                error = 0;
                table->status = 0;
@@ -1313,9 +1303,9 @@ diff -r ab66c8ca382a storage/innobase/handler/ha_innodb.cc
  
        } else if (ret == DB_RECORD_NOT_FOUND) {
                error = HA_ERR_END_OF_FILE;
-diff -r ab66c8ca382a storage/myisam/ha_myisam.cc
---- a/storage/myisam/ha_myisam.cc      Thu Sep 04 12:08:00 2008 -0700
-+++ b/storage/myisam/ha_myisam.cc      Thu Sep 04 12:12:45 2008 -0700
+diff -r 3ed7e96969f9 storage/myisam/ha_myisam.cc
+--- a/storage/myisam/ha_myisam.cc      Thu Dec 04 08:54:17 2008 -0800
++++ b/storage/myisam/ha_myisam.cc      Thu Dec 04 08:54:27 2008 -0800
 @@ -738,7 +738,9 @@
      if ((error= update_auto_increment()))
        return error;
index 0571c527c80f58e25f76a4ef5e5ad325eb2a7bb5..99fea3548f056a107b0649a3cd0e313780d3b1a4 100644 (file)
@@ -32,7 +32,7 @@ Summary(uk.UTF-8):    MySQL - швидкий SQL-сервер
 Summary(zh_CN.UTF-8):  MySQL数据库服务器
 Name:          mysql
 Version:       5.1.35
-Release:       1
+Release:       2
 License:       GPL + MySQL FLOSS Exception
 Group:         Applications/Databases
 #Source0Download: http://dev.mysql.com/downloads/mysql/5.1.html#source
@@ -71,6 +71,8 @@ Patch14:      %{name}-bug-43594.patch
 Patch15:       %{name}-userstats.patch
 Patch16:       %{name}-microslow.patch
 Patch17:       %{name}-acc-pslist.patch
+Patch18:       %{name}-split_buf_pool_mutex_fixed_optimistic_safe.patch
+Patch19:       %{name}-innodb_rw_lock.patch
 # </percona>
 URL:           http://www.mysql.com/products/database/mysql/community_edition.html
 BuildRequires: autoconf
@@ -499,6 +501,8 @@ mv sphinx-*/mysqlse storage/sphinx
 %patch15 -p1
 %patch16 -p1
 %patch17 -p1
+%patch18 -p1
+%patch19 -p1
 
 %build
 %{__libtoolize}
This page took 0.349608 seconds and 4 git commands to generate.