summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2012-11-20 13:28:53 +0100
committerunknown <knielsen@knielsen-hq.org>2012-11-20 13:28:53 +0100
commit47c5018f592b61b5e000842bdf5862ff458de488 (patch)
tree5f20f3e187ca419f218a1bfea363f3cbfd962f7f
parent9e7d870b360b165ac7960814a2fa5bf6011eab1a (diff)
downloadmariadb-git-47c5018f592b61b5e000842bdf5862ff458de488.tar.gz
MDEV-3861: assertions in TC_LOG_MMAP.
Fix some problems in the TC_LOG_MMAP commit processing, which could lead to assertions in some cases. Problems are mostly reproducible in MariaDB 10.0 with asynchroneous commit checkpoints, but most of the problems were present in earlier versions also.
-rw-r--r--sql/log.cc19
-rw-r--r--sql/log.h2
2 files changed, 11 insertions, 10 deletions
diff --git a/sql/log.cc b/sql/log.cc
index eb248c63b19..e44f8ff3067 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -5550,8 +5550,9 @@ int TC_LOG_MMAP::open(const char *opt_name)
syncing= 0;
active=pages;
+ DBUG_ASSERT(npages >= 2);
pool=pages+1;
- pool_last=pages+npages-1;
+ pool_last_ptr= &((pages+npages-1)->next);
return 0;
@@ -5582,8 +5583,8 @@ void TC_LOG_MMAP::get_active_from_pool()
do
{
best_p= p= &pool;
- if ((*p)->waiters == 0) // can the first page be used ?
- break; // yes - take it.
+ if ((*p)->waiters == 0 && (*p)->free > 0) // can the first page be used ?
+ break; // yes - take it.
best_free=0; // no - trying second strategy
for (p=&(*p)->next; *p; p=&(*p)->next)
@@ -5600,10 +5601,10 @@ void TC_LOG_MMAP::get_active_from_pool()
safe_mutex_assert_owner(&LOCK_active);
active=*best_p;
- if ((*best_p)->next) // unlink the page from the pool
- *best_p=(*best_p)->next;
- else
- pool_last=*best_p;
+ /* Unlink the page from the pool. */
+ if (!(*best_p)->next)
+ pool_last_ptr= best_p;
+ *best_p=(*best_p)->next;
pthread_mutex_unlock(&LOCK_pool);
pthread_mutex_lock(&active->lock);
@@ -5764,8 +5765,8 @@ int TC_LOG_MMAP::sync()
/* page is synced. let's move it to the pool */
pthread_mutex_lock(&LOCK_pool);
- pool_last->next=syncing;
- pool_last=syncing;
+ (*pool_last_ptr)=syncing;
+ pool_last_ptr=&(syncing->next);
syncing->next=0;
syncing->state= err ? ERROR : POOL;
pthread_cond_signal(&COND_pool); // in case somebody's waiting
diff --git a/sql/log.h b/sql/log.h
index f42ef514307..9fb233fed86 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -81,7 +81,7 @@ class TC_LOG_MMAP: public TC_LOG
my_off_t file_length;
uint npages, inited;
uchar *data;
- struct st_page *pages, *syncing, *active, *pool, *pool_last;
+ struct st_page *pages, *syncing, *active, *pool, **pool_last_ptr;
/*
note that, e.g. LOCK_active is only used to protect
'active' pointer, to protect the content of the active page