List:Maria Storage Engine« Previous MessageNext Message »
From:Michael Widenius Date:October 15 2008 10:46am
Subject:bzr commit into MySQL/Maria:mysql-maria branch (monty:2677)
View as plain text  
#At bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-maria/

 2677 Michael Widenius	2008-10-15 [merge]
      Automatic merge with main tree
      Fixed that mysql-test-run --skip-from starts from the given test
modified:
  mysql-test/lib/mtr_cases.pl
  mysql-test/mysql-test-run.pl
  storage/maria/ma_bitmap.c
  storage/maria/ma_blockrec.c
  storage/maria/ma_blockrec.h
  storage/maria/ma_check.c
  storage/maria/ma_key_recover.c
  storage/maria/ma_loghandler.c
  storage/maria/ma_pagecache.c
  storage/maria/ma_pagecache.h
  storage/maria/ma_preload.c
  storage/maria/unittest/ma_pagecache_rwconsist.c
  storage/maria/unittest/ma_pagecache_single.c

per-file messages:
  mysql-test/lib/mtr_cases.pl
    Moved testing of $opt_start_from to mysql-test-run.pl because tests are now run per suite and the old way would rerun not wanted tests
  mysql-test/mysql-test-run.pl
    Fixed that mysql-test-run --skip-from starts from the given test
=== modified file 'mysql-test/lib/mtr_cases.pl'
--- a/mysql-test/lib/mtr_cases.pl	2008-10-10 15:28:41 +0000
+++ b/mysql-test/lib/mtr_cases.pl	2008-10-15 10:46:40 +0000
@@ -513,19 +513,10 @@ sub collect_one_test_case($$$$$$$$$) {
   my $suite_opts= shift;
 
   my $path= "$testdir/$elem";
-
-  # ----------------------------------------------------------------------
-  # Skip some tests silently
-  # ----------------------------------------------------------------------
-
-  if ( $::opt_start_from and $tname lt $::opt_start_from )
-  {
-    return;
-  }
-
+  my $name= basename($suite) . ".$tname";
 
   my $tinfo= {};
-  $tinfo->{'name'}= basename($suite) . ".$tname";
+  $tinfo->{'name'}= $name;
   $tinfo->{'result_file'}= "$resdir/$tname.result";
   $tinfo->{'component_id'} = $component_id;
   push(@$cases, $tinfo);
@@ -534,7 +525,7 @@ sub collect_one_test_case($$$$$$$$$) {
   # Skip some tests but include in list, just mark them to skip
   # ----------------------------------------------------------------------
 
-  if ( $skip_test and $tname =~ /$skip_test/o )
+  if ( $skip_test and ($tname =~ /$skip_test/o || $name =~ /$skip_test/o))
   {
     $tinfo->{'skip'}= 1;
     return;

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2008-10-11 08:27:03 +0000
+++ b/mysql-test/mysql-test-run.pl	2008-10-15 10:46:40 +0000
@@ -3392,6 +3392,24 @@ sub run_testcase_check_skip_test($)
   my ($tinfo)= @_;
 
   # ----------------------------------------------------------------------
+  # Skip some tests silently
+  # ----------------------------------------------------------------------
+
+  if ( $::opt_start_from )
+  {
+    if ($tinfo->{'name'} eq $::opt_start_from )
+    {
+      ## Found parting test. Run this test and all tests after this one
+      $::opt_start_from= "";
+    }
+    else
+    {
+      $tinfo->{'result'}= 'MTR_RES_SKIPPED';
+      return 1;
+    }
+  }
+
+  # ----------------------------------------------------------------------
   # If marked to skip, just print out and return.
   # Note that a test case not marked as 'skip' can still be
   # skipped later, because of the test case itself in cooperation

=== modified file 'storage/maria/ma_bitmap.c'
--- a/storage/maria/ma_bitmap.c	2008-04-03 13:40:25 +0000
+++ b/storage/maria/ma_bitmap.c	2008-10-14 15:18:14 +0000
@@ -167,10 +167,10 @@ static inline my_bool write_changed_bitm
     int res= pagecache_write(share->pagecache,
                              &bitmap->file, bitmap->page, 0,
                              (uchar*) bitmap->map, PAGECACHE_PLAIN_PAGE,
-                             PAGECACHE_LOCK_WRITE, PAGECACHE_PIN,
+                             PAGECACHE_LOCK_LEFT_UNLOCKED, PAGECACHE_PIN,
                              PAGECACHE_WRITE_DELAY, &page_link.link,
                              LSN_IMPOSSIBLE);
-    page_link.unlock= PAGECACHE_LOCK_WRITE_UNLOCK;
+    page_link.unlock= PAGECACHE_LOCK_LEFT_UNLOCKED;
     page_link.changed= 1;
     push_dynamic(&bitmap->pinned_pages, (void*) &page_link);
     DBUG_RETURN(res);
@@ -281,6 +281,14 @@ my_bool _ma_bitmap_end(MARIA_SHARE *shar
     by this thread (ie, checking the changed flag is ok). The reason we
     check it again in the mutex is that if someone else did a flush at the
     same time, we don't have to do the write.
+    This is also ok for _ma_scan_init_block_record() which does not want to
+    miss rows: it cares only for committed rows, that is, rows for which there
+    was a commit before our transaction started; as commit and transaction's
+    start are protected by the same LOCK_trn_list mutex, we see memory at
+    least as new as at other transaction's commit time, so if the committed
+    rows caused bitmap->changed to be true, we see it; if we see 0 it really
+    means a flush happened since then. So, it's ok to read without bitmap's
+    mutex.
 
   RETURN
     0    ok
@@ -305,38 +313,6 @@ my_bool _ma_bitmap_flush(MARIA_SHARE *sh
 }
 
 
-/*
-  @brief Send updated bitmap to the page cache if bitmap is free
-
-  @note
-  This is used by reader threads which don't unpin things
-*/
-
-my_bool _ma_bitmap_wait_or_flush(MARIA_SHARE *share)
-{
-  my_bool res= 0;
-  MARIA_FILE_BITMAP *bitmap= &share->bitmap;
-  DBUG_ENTER("_ma_bitmap_flush");
-  if (bitmap->changed)
-  {
-    pthread_mutex_lock(&bitmap->bitmap_lock);
-    while (bitmap->non_flushable && bitmap->changed)
-    {
-      DBUG_PRINT("info", ("waiting for bitmap to be flushable"));
-      pthread_cond_wait(&bitmap->bitmap_cond, &bitmap->bitmap_lock);
-    }
-    if (bitmap->changed)
-    {
-      bitmap->changed= 0;
-      res= write_changed_bitmap(share, bitmap);
-    }
-    pthread_mutex_unlock(&bitmap->bitmap_lock);
-  }
-  DBUG_RETURN(res);
-}
-
-
-
 /**
    Dirty-page filtering criteria for bitmap pages
 
@@ -386,8 +362,11 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE
       unpinned. We keep the mutex to preserve this situation, and flush to the
       file.
     */
-    res= write_changed_bitmap(share, bitmap);
-    bitmap->changed= FALSE;
+    if (bitmap->changed)
+    {
+      res= write_changed_bitmap(share, bitmap);
+      bitmap->changed= FALSE;
+    }
     /*
       We do NOT use FLUSH_KEEP_LAZY because we must be sure that bitmap
       pages have been flushed. That's a condition of correctness of
@@ -424,6 +403,8 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE
 
   @return Operation status
     @retval   0   ok
+
+  @note This unpins pages pinned by other threads.
 */
 
 static void _ma_bitmap_unpin_all(MARIA_SHARE *share)
@@ -437,7 +418,7 @@ static void _ma_bitmap_unpin_all(MARIA_S
   while (pinned_page-- != page_link)
     pagecache_unlock_by_link(share->pagecache, pinned_page->link,
                              pinned_page->unlock, PAGECACHE_UNPIN,
-                             LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, TRUE);
+                             LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, TRUE, TRUE);
   bitmap->pinned_pages.elements= 0;
   DBUG_VOID_RETURN;
 }
@@ -2139,8 +2120,8 @@ my_bool _ma_bitmap_set_full_page_bits(MA
    function first waits for the flush to be done.
 
    @note
-   info->non_flushable_state is set to 1 if we have incremented
-   bitmap->info->non_flushable and not yet decremented it.
+   this sets info->non_flushable_state to 1 if we have incremented
+   bitmap->non_flushable and not yet decremented it.
 
    @param  share               Table's share
    @param  non_flushable_inc   Increment of MARIA_FILE_BITMAP::non_flushable
@@ -2151,20 +2132,21 @@ void _ma_bitmap_flushable(MARIA_HA *info
 {
   MARIA_SHARE *share= info->s;
   MARIA_FILE_BITMAP *bitmap;
+  DBUG_ENTER("_ma_bitmap_flushable");
 
   /*
     Not transactional tables are never automaticly flushed and needs no
     protection
   */
   if (!share->now_transactional)
-    return;
+    DBUG_VOID_RETURN;
 
   bitmap= &share->bitmap;
   if (non_flushable_inc == -1)
   {
     pthread_mutex_lock(&bitmap->bitmap_lock);
-    DBUG_ASSERT((int) bitmap->non_flushable > 0 &&
-                info->non_flushable_state == 1);
+    DBUG_ASSERT((int) bitmap->non_flushable > 0);
+    DBUG_ASSERT(info->non_flushable_state == 1);
     info->non_flushable_state= 0;
     if (--bitmap->non_flushable == 0)
     {
@@ -2182,14 +2164,15 @@ void _ma_bitmap_flushable(MARIA_HA *info
     }
     DBUG_PRINT("info", ("bitmap->non_flushable: %u", bitmap->non_flushable));
     pthread_mutex_unlock(&bitmap->bitmap_lock);
-    return;
+    DBUG_VOID_RETURN;
   }
-  DBUG_ASSERT(non_flushable_inc == 1 && info->non_flushable_state == 0);
+  DBUG_ASSERT(non_flushable_inc == 1);
+  DBUG_ASSERT(info->non_flushable_state == 0);
   /* It is a read without mutex because only an optimization */
   if (unlikely(bitmap->flush_all_requested))
   {
     /*
-      _ma_bitmap_flush_all() is waiting for the bitmap to become
+      Some other thread is waiting for the bitmap to become
       flushable. Not the moment to make the bitmap unflushable or more
       unflushable; let's rather back off and wait. If we didn't do this, with
       multiple writers, there may always be one thread causing the bitmap to
@@ -2214,6 +2197,7 @@ void _ma_bitmap_flushable(MARIA_HA *info
   bitmap->non_flushable++;
   info->non_flushable_state= 1;
   DBUG_PRINT("info", ("bitmap->non_flushable: %u", bitmap->non_flushable));
+  DBUG_VOID_RETURN;
 }
 
 
@@ -2321,10 +2305,10 @@ my_bool _ma_bitmap_release_unused(MARIA_
       goto err;
   }
 
-  if (info->s->now_transactional)
+  /* This duplicates ma_bitmap_flushable(-1) except it already has mutex */
+  if (info->non_flushable_state)
   {
-    DBUG_ASSERT((int) bitmap->non_flushable >= 0 &&
-                info->non_flushable_state);
+    DBUG_ASSERT((int) bitmap->non_flushable >= 0);
     info->non_flushable_state= 0;
     if (--bitmap->non_flushable == 0)
     {

=== modified file 'storage/maria/ma_blockrec.c'
--- a/storage/maria/ma_blockrec.c	2008-10-09 20:03:54 +0000
+++ b/storage/maria/ma_blockrec.c	2008-10-14 15:18:14 +0000
@@ -1964,7 +1964,7 @@ static my_bool write_tail(MARIA_HA *info
     pagecache_unlock_by_link(share->pagecache, page_link->link,
                              PAGECACHE_LOCK_WRITE_TO_READ,
                              PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE,
-                             LSN_IMPOSSIBLE, 1);
+                             LSN_IMPOSSIBLE, 1, FALSE);
     DBUG_ASSERT(page_link->changed);
     page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK;
     res= 0;
@@ -3026,7 +3026,7 @@ static my_bool write_block_record(MARIA_
     pagecache_unlock_by_link(share->pagecache, page_link->link,
                              PAGECACHE_LOCK_WRITE_TO_READ,
                              PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE,
-                             LSN_IMPOSSIBLE, 1);
+                             LSN_IMPOSSIBLE, 1, FALSE);
     page_link->unlock= PAGECACHE_LOCK_READ_UNLOCK;
     page_link->changed= 1;
   }
@@ -4025,7 +4025,7 @@ static my_bool delete_head_or_tail(MARIA
   pagecache_unlock_by_link(share->pagecache, page_link.link,
                            lock_at_write,
                            PAGECACHE_PIN_LEFT_PINNED, LSN_IMPOSSIBLE,
-                           LSN_IMPOSSIBLE, 1);
+                           LSN_IMPOSSIBLE, 1, FALSE);
   page_link.unlock= lock_at_unpin;
   set_dynamic(&info->pinned_pages, (void*) &page_link,
               info->pinned_pages.elements-1);
@@ -4982,10 +4982,12 @@ my_bool _ma_scan_init_block_record(MARIA
   info->scan.bitmap_pos= info->scan.bitmap_end;
   info->scan.bitmap_page= (pgcache_page_no_t) 0 - share->bitmap.pages_covered;
   /*
-    We have to flush bitmap as we will read the bitmap from the page cache
-    while scanning rows
+    We need to flush what's in memory (bitmap.map) to page cache otherwise, as
+    we are going to read bitmaps from page cache in table scan (see
+    _ma_scan_block_record()), we may miss recently inserted rows (bitmap page
+    in page cache would be too old).
   */
-  DBUG_RETURN(_ma_bitmap_wait_or_flush(info->s));
+  DBUG_RETURN(_ma_bitmap_flush(info->s));
 }
 
 
@@ -5141,7 +5143,9 @@ restart_record_read:
     if (end_of_data > info->scan.dir_end ||
         offset < PAGE_HEADER_SIZE || length < share->base.min_block_length)
     {
-      DBUG_ASSERT(0);
+      DBUG_ASSERT(!(end_of_data > info->scan.dir_end));
+      DBUG_ASSERT(!(offset < PAGE_HEADER_SIZE));
+      DBUG_ASSERT(!(length < share->base.min_block_length));
       goto err;
     }
 #endif
@@ -6033,7 +6037,7 @@ uint _ma_apply_redo_insert_row_head_or_t
       pagecache_unlock_by_link(share->pagecache, page_link.link,
                                PAGECACHE_LOCK_WRITE_UNLOCK,
                                PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                               LSN_IMPOSSIBLE, 0);
+                               LSN_IMPOSSIBLE, 0, FALSE);
       DBUG_RETURN(0);
     }
 
@@ -6123,7 +6127,7 @@ err:
     pagecache_unlock_by_link(share->pagecache, page_link.link,
                              PAGECACHE_LOCK_WRITE_UNLOCK,
                              PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                             LSN_IMPOSSIBLE, 0);
+                             LSN_IMPOSSIBLE, 0, FALSE);
   _ma_mark_file_crashed(share);
   DBUG_RETURN((my_errno= error));
 }
@@ -6193,7 +6197,7 @@ uint _ma_apply_redo_purge_row_head_or_ta
     pagecache_unlock_by_link(share->pagecache, page_link.link,
                              PAGECACHE_LOCK_WRITE_UNLOCK,
                              PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                             LSN_IMPOSSIBLE, 0);
+                             LSN_IMPOSSIBLE, 0, FALSE);
     DBUG_RETURN(0);
   }
 
@@ -6221,7 +6225,7 @@ err:
   pagecache_unlock_by_link(share->pagecache, page_link.link,
                            PAGECACHE_LOCK_WRITE_UNLOCK,
                            PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                           LSN_IMPOSSIBLE, 0);
+                           LSN_IMPOSSIBLE, 0, FALSE);
   _ma_mark_file_crashed(share);
   DBUG_RETURN((my_errno= error));
 
@@ -6325,7 +6329,7 @@ uint _ma_apply_redo_free_head_or_tail(MA
     pagecache_unlock_by_link(share->pagecache, page_link.link,
                              PAGECACHE_LOCK_WRITE_UNLOCK,
                              PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                             LSN_IMPOSSIBLE, 0);
+                             LSN_IMPOSSIBLE, 0, FALSE);
     goto err;
   }
   if (lsn_korr(buff) >= lsn)
@@ -6334,7 +6338,7 @@ uint _ma_apply_redo_free_head_or_tail(MA
     pagecache_unlock_by_link(share->pagecache, page_link.link,
                              PAGECACHE_LOCK_WRITE_UNLOCK,
                              PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                             LSN_IMPOSSIBLE, 0);
+                             LSN_IMPOSSIBLE, 0, FALSE);
   }
   else
   {
@@ -6474,7 +6478,7 @@ uint _ma_apply_redo_insert_row_blobs(MAR
               pagecache_unlock_by_link(share->pagecache, page_link.link,
                                        PAGECACHE_LOCK_WRITE_UNLOCK,
                                        PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                                       LSN_IMPOSSIBLE, 0);
+                                       LSN_IMPOSSIBLE, 0, FALSE);
               goto err;
             }
             /*
@@ -6494,7 +6498,7 @@ uint _ma_apply_redo_insert_row_blobs(MAR
               pagecache_unlock_by_link(share->pagecache, page_link.link,
                                        PAGECACHE_LOCK_WRITE_UNLOCK,
                                        PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                                       LSN_IMPOSSIBLE, 0);
+                                       LSN_IMPOSSIBLE, 0, FALSE);
               continue;
             }
           }

=== modified file 'storage/maria/ma_blockrec.h'
--- a/storage/maria/ma_blockrec.h	2008-04-10 02:26:36 +0000
+++ b/storage/maria/ma_blockrec.h	2008-10-14 09:38:07 +0000
@@ -182,7 +182,6 @@ maria_page_get_lsn(uchar *page, pgcache_
 my_bool _ma_bitmap_init(MARIA_SHARE *share, File file);
 my_bool _ma_bitmap_end(MARIA_SHARE *share);
 my_bool _ma_bitmap_flush(MARIA_SHARE *share);
-my_bool _ma_bitmap_wait_or_flush(MARIA_SHARE *share);
 my_bool _ma_bitmap_flush_all(MARIA_SHARE *share);
 void _ma_bitmap_reset_cache(MARIA_SHARE *share);
 my_bool _ma_bitmap_find_place(MARIA_HA *info, MARIA_ROW *row,

=== modified file 'storage/maria/ma_check.c'
--- a/storage/maria/ma_check.c	2008-10-14 21:23:33 +0000
+++ b/storage/maria/ma_check.c	2008-10-15 10:46:40 +0000
@@ -3184,7 +3184,7 @@ static my_bool maria_zerofill_index(HA_C
       pagecache_unlock_by_link(share->pagecache, page_link.link,
                                PAGECACHE_LOCK_WRITE_UNLOCK,
                                PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                               LSN_IMPOSSIBLE, 0);
+                               LSN_IMPOSSIBLE, 0, FALSE);
       _ma_check_print_error(param,
                             "Page %9s: Got error %d when reading index file",
                             llstr(pos, llbuff), my_errno);
@@ -3218,7 +3218,7 @@ static my_bool maria_zerofill_index(HA_C
     pagecache_unlock_by_link(share->pagecache, page_link.link,
                              PAGECACHE_LOCK_WRITE_UNLOCK,
                              PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                             LSN_IMPOSSIBLE, 1);
+                             LSN_IMPOSSIBLE, 1, FALSE);
   }
   if (flush_pagecache_blocks(share->pagecache, &share->kfile,
                              FLUSH_FORCE_WRITE))
@@ -3342,7 +3342,7 @@ static my_bool maria_zerofill_data(HA_CH
     pagecache_unlock_by_link(share->pagecache, page_link.link,
                              PAGECACHE_LOCK_WRITE_UNLOCK,
                              PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                             LSN_IMPOSSIBLE, 1);
+                             LSN_IMPOSSIBLE, 1, FALSE);
   }
   DBUG_RETURN(_ma_bitmap_flush(share) ||
               flush_pagecache_blocks(share->pagecache, &info->dfile,
@@ -3352,7 +3352,7 @@ err:
   pagecache_unlock_by_link(share->pagecache, page_link.link,
                            PAGECACHE_LOCK_WRITE_UNLOCK,
                            PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                           LSN_IMPOSSIBLE, 0);
+                           LSN_IMPOSSIBLE, 0, FALSE);
   DBUG_RETURN(1);
 }
 

=== modified file 'storage/maria/ma_key_recover.c'
--- a/storage/maria/ma_key_recover.c	2008-08-26 12:34:57 +0000
+++ b/storage/maria/ma_key_recover.c	2008-10-14 15:18:14 +0000
@@ -70,7 +70,7 @@ void _ma_unpin_all_pages(MARIA_HA *info,
     pagecache_unlock_by_link(info->s->pagecache, pinned_page->link,
                              pinned_page->unlock, PAGECACHE_UNPIN,
                              info->trn->rec_lsn, undo_lsn,
-                             pinned_page->changed);
+                             pinned_page->changed, FALSE);
   }
 
   info->pinned_pages.elements= 0;
@@ -700,7 +700,7 @@ err:
   pagecache_unlock_by_link(share->pagecache, page_link.link,
                            PAGECACHE_LOCK_WRITE_UNLOCK,
                            PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                           LSN_IMPOSSIBLE, 0);
+                           LSN_IMPOSSIBLE, 0, FALSE);
   DBUG_RETURN(result);
 }
 
@@ -779,7 +779,7 @@ err:
   pagecache_unlock_by_link(share->pagecache, page_link.link,
                            PAGECACHE_LOCK_WRITE_UNLOCK,
                            PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                           LSN_IMPOSSIBLE, 0);
+                           LSN_IMPOSSIBLE, 0, FALSE);
   DBUG_RETURN(result);
 }
 
@@ -1047,7 +1047,7 @@ err:
   pagecache_unlock_by_link(share->pagecache, page_link.link,
                            PAGECACHE_LOCK_WRITE_UNLOCK,
                            PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
-                           LSN_IMPOSSIBLE, 0);
+                           LSN_IMPOSSIBLE, 0, FALSE);
   if (result)
     _ma_mark_file_crashed(share);
   DBUG_RETURN(result);

=== modified file 'storage/maria/ma_loghandler.c'
--- a/storage/maria/ma_loghandler.c	2008-08-28 18:52:23 +0000
+++ b/storage/maria/ma_loghandler.c	2008-10-14 15:18:14 +0000
@@ -3028,7 +3028,7 @@ static void translog_free_link(PAGECACHE
   if (direct_link)
     pagecache_unlock_by_link(log_descriptor.pagecache, direct_link,
                              PAGECACHE_LOCK_READ_UNLOCK, PAGECACHE_UNPIN,
-                             LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0);
+                             LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, 0, FALSE);
   DBUG_VOID_RETURN;
 }
 

=== modified file 'storage/maria/ma_pagecache.c'
--- a/storage/maria/ma_pagecache.c	2008-08-25 18:26:50 +0000
+++ b/storage/maria/ma_pagecache.c	2008-10-14 15:18:14 +0000
@@ -267,16 +267,21 @@ static void info_unlink(PAGECACHE_PIN_IN
     list                 the list where to find the thread
     thread               thread ID (reference to the st_my_thread_var
                          of the thread)
+    any                  return any thread of the list
 
   RETURN
     0 - the thread was not found
-    pointer to the information node of the thread in the list
+    pointer to the information node of the thread in the list, or, if 'any',
+    to any thread of the list.
 */
 
 static PAGECACHE_PIN_INFO *info_find(PAGECACHE_PIN_INFO *list,
-                                     struct st_my_thread_var *thread)
+                                     struct st_my_thread_var *thread,
+                                     my_bool any)
 {
   register PAGECACHE_PIN_INFO *i= list;
+  if (any)
+    return i;
   for(; i != 0; i= i->next)
     if (i->thread == thread)
       return i;
@@ -2150,18 +2155,22 @@ static void add_pin(PAGECACHE_BLOCK_LINK
   DBUG_VOID_RETURN;
 }
 
-static void remove_pin(PAGECACHE_BLOCK_LINK *block)
+static void remove_pin(PAGECACHE_BLOCK_LINK *block, my_bool any
+#ifdef DBUG_OFF
+                       __attribute__((unused))
+#endif
+                       )
 {
   DBUG_ENTER("remove_pin");
-  DBUG_PRINT("enter", ("block: 0x%lx  pins: %u",
+  DBUG_PRINT("enter", ("block: 0x%lx  pins: %u  any: %d",
                        (ulong) block,
-                       block->pins));
+                       block->pins, (int)any));
   PCBLOCK_INFO(block);
   DBUG_ASSERT(block->pins > 0);
   block->pins--;
 #ifndef DBUG_OFF
   {
-    PAGECACHE_PIN_INFO *info= info_find(block->pin_list, my_thread_var);
+    PAGECACHE_PIN_INFO *info= info_find(block->pin_list, my_thread_var, any);
     DBUG_ASSERT(info != 0);
     info_unlink(info);
     my_free((uchar*) info, MYF(0));
@@ -2183,7 +2192,7 @@ static void info_remove_lock(PAGECACHE_B
 {
   PAGECACHE_LOCK_INFO *info=
     (PAGECACHE_LOCK_INFO *)info_find((PAGECACHE_PIN_INFO *)block->lock_list,
-                                     my_thread_var);
+                                     my_thread_var, FALSE);
   DBUG_ASSERT(info != 0);
   info_unlink((PAGECACHE_PIN_INFO *)info);
   my_free((uchar*)info, MYF(0));
@@ -2192,7 +2201,7 @@ static void info_change_lock(PAGECACHE_B
 {
   PAGECACHE_LOCK_INFO *info=
     (PAGECACHE_LOCK_INFO *)info_find((PAGECACHE_PIN_INFO *)block->lock_list,
-                                     my_thread_var);
+                                     my_thread_var, FALSE);
   DBUG_ASSERT(info != 0);
   DBUG_ASSERT(info->write_lock != wl);
   info->write_lock= wl;
@@ -2448,6 +2457,8 @@ static void release_rdlock(PAGECACHE_BLO
   @param lock            lock change mode
   @param pin             pinchange mode
   @param file            File handler requesting pin
+  @param any             allow unpinning block pinned by any thread; possible
+                         only if not locked, see pagecache_unlock_by_link()
 
   @retval 0 OK
   @retval 1 Try to lock the block failed
@@ -2456,7 +2467,8 @@ static void release_rdlock(PAGECACHE_BLO
 static my_bool make_lock_and_pin(PAGECACHE *pagecache,
                                  PAGECACHE_BLOCK_LINK *block,
                                  enum pagecache_page_lock lock,
-                                 enum pagecache_page_pin pin)
+                                 enum pagecache_page_pin pin,
+                                 my_bool any)
 {
   DBUG_ENTER("make_lock_and_pin");
 
@@ -2465,16 +2477,20 @@ static my_bool make_lock_and_pin(PAGECAC
   if (block)
   {
     DBUG_PRINT("enter", ("block: 0x%lx (%u)  wrlocks: %u  rdlocks: %u  "
-                         "rdlocks_q: %u  pins: %u  lock: %s  pin: %s",
+                         "rdlocks_q: %u  pins: %u  lock: %s  pin: %s any %d",
                          (ulong)block, PCBLOCK_NUMBER(pagecache, block),
                          block->wlocks, block->rlocks, block->rlocks_queue,
                          block->pins,
                          page_cache_page_lock_str[lock],
-                         page_cache_page_pin_str[pin]));
+                         page_cache_page_pin_str[pin], (int)any));
     PCBLOCK_INFO(block);
   }
 #endif
 
+  DBUG_ASSERT(!any ||
+              ((lock == PAGECACHE_LOCK_LEFT_UNLOCKED) &&
+               (pin == PAGECACHE_UNPIN)));
+
   switch (lock) {
   case PAGECACHE_LOCK_WRITE:               /* free  -> write */
     /* Writelock and pin the buffer */
@@ -2500,7 +2516,7 @@ static my_bool make_lock_and_pin(PAGECAC
   case PAGECACHE_LOCK_LEFT_READLOCKED:     /* read  -> read  */
     if (pin == PAGECACHE_UNPIN)
     {
-      remove_pin(block);
+      remove_pin(block, FALSE);
     }
     if (lock == PAGECACHE_LOCK_WRITE_TO_READ)
     {
@@ -2529,7 +2545,7 @@ static my_bool make_lock_and_pin(PAGECAC
   case PAGECACHE_LOCK_LEFT_UNLOCKED:       /* free  -> free  */
     if (pin == PAGECACHE_UNPIN)
     {
-      remove_pin(block);
+      remove_pin(block, any);
     }
     /* fall through */
   case PAGECACHE_LOCK_LEFT_WRITELOCKED:    /* write -> write */
@@ -2793,7 +2809,7 @@ void pagecache_unlock(PAGECACHE *pagecac
                         (ulong) block));
   }
 
-  if (make_lock_and_pin(pagecache, block, lock, pin))
+  if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
   {
     DBUG_ASSERT(0); /* should not happend */
   }
@@ -2863,7 +2879,7 @@ void pagecache_unpin(PAGECACHE *pagecach
   */
   if (make_lock_and_pin(pagecache, block,
                         PAGECACHE_LOCK_LEFT_READLOCKED,
-                        PAGECACHE_UNPIN))
+                        PAGECACHE_UNPIN, FALSE))
     DBUG_ASSERT(0);                           /* should not happend */
 
   remove_reader(block);
@@ -2886,15 +2902,22 @@ void pagecache_unpin(PAGECACHE *pagecach
   @brief Unlock/unpin page and put LSN stamp if it need
   (uses direct block/page pointer)
 
-  @param pagecache      pointer to a page cache data structure
-  @param link           direct link to page (returned by read or write)
-  @param lock           lock change
-  @param pin            pin page
+  @param pagecache       pointer to a page cache data structure
+  @param link            direct link to page (returned by read or write)
+  @param lock            lock change
+  @param pin             pin page
   @param first_REDO_LSN_for_page do not set it if it is LSN_IMPOSSIBLE (0)
-  @param lsn            if it is not LSN_IMPOSSIBLE and it is bigger then
-                        LSN on the page it will be written on the page
-  @param was_changed    should be true if the page was write locked with
-                        direct link giving and the page was changed
+  @param lsn             if it is not LSN_IMPOSSIBLE and it is bigger then
+                         LSN on the page it will be written on the page
+  @param was_changed     should be true if the page was write locked with
+                         direct link giving and the page was changed
+  @param any             allow unpinning block pinned by any thread; possible
+                         only if not locked
+
+  @note 'any' is a hack so that _ma_bitmap_unpin_all() is allowed to unpin
+  non-locked bitmap pages pinned by other threads. Because it always uses
+  PAGECACHE_LOCK_LEFT_UNLOCKED and PAGECACHE_UNPIN
+  (see write_changed_bitmap()), the hack is limited to these conditions.
 */
 
 void pagecache_unlock_by_link(PAGECACHE *pagecache,
@@ -2902,7 +2925,8 @@ void pagecache_unlock_by_link(PAGECACHE 
                               enum pagecache_page_lock lock,
                               enum pagecache_page_pin pin,
                               LSN first_REDO_LSN_for_page,
-                              LSN lsn, my_bool was_changed)
+                              LSN lsn, my_bool was_changed,
+                              my_bool any)
 {
   DBUG_ENTER("pagecache_unlock_by_link");
   DBUG_PRINT("enter", ("block: 0x%lx  fd: %u  page: %lu  changed: %d  %s  %s",
@@ -2922,7 +2946,7 @@ void pagecache_unlock_by_link(PAGECACHE 
   if (pin == PAGECACHE_PIN_LEFT_UNPINNED &&
       lock == PAGECACHE_LOCK_READ_UNLOCK)
   {
-    if (make_lock_and_pin(pagecache, block, lock, pin))
+    if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
       DBUG_ASSERT(0);                         /* should not happend */
     DBUG_VOID_RETURN;
   }
@@ -2976,7 +3000,7 @@ void pagecache_unlock_by_link(PAGECACHE 
                         (ulong) block));
   }
 
-  if (make_lock_and_pin(pagecache, block, lock, pin))
+  if (make_lock_and_pin(pagecache, block, lock, pin, any))
     DBUG_ASSERT(0);                           /* should not happend */
 
   /*
@@ -3039,7 +3063,7 @@ void pagecache_unpin_by_link(PAGECACHE *
   */
   if (make_lock_and_pin(pagecache, block,
                         PAGECACHE_LOCK_LEFT_READLOCKED,
-                        PAGECACHE_UNPIN))
+                        PAGECACHE_UNPIN, FALSE))
     DBUG_ASSERT(0); /* should not happend */
 
   /*
@@ -3190,7 +3214,7 @@ restart:
         block->type == PAGECACHE_EMPTY_PAGE)
       block->type= type;
 
-    if (make_lock_and_pin(pagecache, block, lock, pin))
+    if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
     {
       /*
         We failed to write lock the block, cache is unlocked,
@@ -3334,7 +3358,7 @@ static my_bool pagecache_delete_internal
   /* Cache is locked, so we can relese page before freeing it */
   if (make_lock_and_pin(pagecache, block,
                         PAGECACHE_LOCK_WRITE_UNLOCK,
-                        PAGECACHE_UNPIN))
+                        PAGECACHE_UNPIN, FALSE))
     DBUG_ASSERT(0);
   DBUG_ASSERT(block->hash_link->requests > 0);
   page_link->requests--;
@@ -3396,7 +3420,7 @@ my_bool pagecache_delete_by_link(PAGECAC
       make_lock_and_pin() can't fail here, because we are keeping pin on the
       block and it can't be evicted (which is cause of lock fail and retry)
     */
-    if (make_lock_and_pin(pagecache, block, lock, pin))
+    if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
       DBUG_ASSERT(0);
 
     /*
@@ -3514,7 +3538,7 @@ restart:
     if (pin == PAGECACHE_PIN)
       reg_requests(pagecache, block, 1);
     DBUG_ASSERT(block != 0);
-    if (make_lock_and_pin(pagecache, block, lock, pin))
+    if (make_lock_and_pin(pagecache, block, lock, pin, FALSE))
     {
       /*
         We failed to writelock the block, cache is unlocked, and last write
@@ -3736,7 +3760,7 @@ restart:
                           write_lock_change_table[lock].new_lock,
                           (need_lock_change ?
                            write_pin_change_table[pin].new_pin :
-                           pin)))
+                           pin), FALSE))
     {
       /*
         We failed to writelock the block, cache is unlocked, and last write
@@ -3823,7 +3847,7 @@ restart:
       */
       if (make_lock_and_pin(pagecache, block,
                             write_lock_change_table[lock].unlock_lock,
-                            write_pin_change_table[pin].unlock_pin))
+                            write_pin_change_table[pin].unlock_pin, FALSE))
         DBUG_ASSERT(0);
     }
 
@@ -4034,7 +4058,7 @@ static int flush_cached_blocks(PAGECACHE
     DBUG_ASSERT(block->wlocks == 0);
     DBUG_ASSERT(block->pins == 0);
     if (make_lock_and_pin(pagecache, block,
-                          PAGECACHE_LOCK_WRITE, PAGECACHE_PIN))
+                          PAGECACHE_LOCK_WRITE, PAGECACHE_PIN, FALSE))
       DBUG_ASSERT(0);
     DBUG_ASSERT(block->pins == 1);
 
@@ -4068,7 +4092,7 @@ static int flush_cached_blocks(PAGECACHE
 
     if (make_lock_and_pin(pagecache, block,
                           PAGECACHE_LOCK_WRITE_UNLOCK,
-                          PAGECACHE_UNPIN))
+                          PAGECACHE_UNPIN, FALSE))
       DBUG_ASSERT(0);
 
     pagecache->global_cache_write++;

=== modified file 'storage/maria/ma_pagecache.h'
--- a/storage/maria/ma_pagecache.h	2008-03-04 11:58:21 +0000
+++ b/storage/maria/ma_pagecache.h	2008-10-14 15:18:14 +0000
@@ -242,7 +242,8 @@ extern void pagecache_unlock_by_link(PAG
                                      enum pagecache_page_lock lock,
                                      enum pagecache_page_pin pin,
                                      LSN first_REDO_LSN_for_page,
-                                     LSN lsn, my_bool was_changed);
+                                     LSN lsn, my_bool was_changed,
+                                     my_bool any);
 extern void pagecache_unpin(PAGECACHE *pagecache,
                             PAGECACHE_FILE *file,
                             pgcache_page_no_t pageno,

=== modified file 'storage/maria/ma_preload.c'
--- a/storage/maria/ma_preload.c	2008-03-04 11:47:02 +0000
+++ b/storage/maria/ma_preload.c	2008-10-14 15:18:14 +0000
@@ -104,7 +104,7 @@ int maria_preload(MARIA_HA *info, ulongl
     else /* otherwise it stays in cache: */
       pagecache_unlock_by_link(share->pagecache, page_link,
                                PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN,
-                               LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, FALSE);
+                               LSN_IMPOSSIBLE, LSN_IMPOSSIBLE, FALSE, FALSE);
   }
 
   my_free(buff, MYF(0));

=== modified file 'storage/maria/unittest/ma_pagecache_rwconsist.c'
--- a/storage/maria/unittest/ma_pagecache_rwconsist.c	2008-04-21 14:17:21 +0000
+++ b/storage/maria/unittest/ma_pagecache_rwconsist.c	2008-10-14 15:18:14 +0000
@@ -114,7 +114,7 @@ void reader(int num)
     check_page(buff, num);
     pagecache_unlock_by_link(&pagecache, link,
                              PAGECACHE_LOCK_READ_UNLOCK,
-                             PAGECACHE_UNPIN, 0, 0, 0);
+                             PAGECACHE_UNPIN, 0, 0, 0, FALSE);
     {
       int lim= rand() % read_sleep_limit;
       int j;
@@ -149,7 +149,7 @@ void writer(int num)
     check_page(buff, num);
     pagecache_unlock_by_link(&pagecache, link,
                              PAGECACHE_LOCK_WRITE_UNLOCK,
-                             PAGECACHE_UNPIN, 0, 0, 1);
+                             PAGECACHE_UNPIN, 0, 0, 1, FALSE);
     SLEEP;
   }
 }

=== modified file 'storage/maria/unittest/ma_pagecache_single.c'
--- a/storage/maria/unittest/ma_pagecache_single.c	2008-03-04 11:58:21 +0000
+++ b/storage/maria/unittest/ma_pagecache_single.c	2008-10-14 15:18:14 +0000
@@ -391,7 +391,7 @@ int simple_pin_no_lock_test()
                   &link, LSN_IMPOSSIBLE);
   pagecache_unlock_by_link(&pagecache, link,
                            PAGECACHE_LOCK_WRITE_UNLOCK,
-                           PAGECACHE_PIN_LEFT_PINNED, 0, 0, 1);
+                           PAGECACHE_PIN_LEFT_PINNED, 0, 0, 1, FALSE);
   if (!flush_pagecache_blocks(&pagecache, &file1, FLUSH_FORCE_WRITE))
   {
     diag("Did not get error in flush_pagecache_blocks 3\n");

Thread
bzr commit into MySQL/Maria:mysql-maria branch (monty:2677) Michael Widenius15 Oct