Below is the list of changes that have just been committed into a local
5.1 repository of rafal. When rafal does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-06-11 22:14:14+02:00, rafal@quant.(none) +4 -0
WL#3327, WL#3576: Implementation of the critical zone mechanism.
Critical zones can be used in several places in the backup code -
during backup/binlog synchronization, to block DDL's during backup and
in other places. This patch provides basic implementation of the
mechanism. On platforms on which pthread library is not avialable or
incomplete an alternative implementation using more primitive notions
would have to be given.
sql/CMakeLists.txt@stripped, 2007-06-11 22:14:08+02:00, rafal@quant.(none) +1 -1
Adding new source critical_zone.cc.
sql/backup/Makefile.am@stripped, 2007-06-11 22:14:09+02:00, rafal@quant.(none) +4 -2
Adding new sources critical_zone.{cc,h}
sql/backup/critical_zone.cc@stripped, 2007-06-11 22:14:09+02:00, rafal@quant.(none) +63 -0
Critical zone implementation using read-write locks of pthread library.
sql/backup/critical_zone.cc@stripped, 2007-06-11 22:14:09+02:00, rafal@quant.(none) +0 -0
sql/backup/critical_zone.h@stripped, 2007-06-11 22:14:09+02:00, rafal@quant.(none) +120 -0
Classes and API to create critical zones.
sql/backup/critical_zone.h@stripped, 2007-06-11 22:14:09+02:00, rafal@quant.(none) +0 -0
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: rafal
# Host: quant.(none)
# Root: /ext/mysql/bk/backup/prototype
--- 1.7/sql/backup/Makefile.am 2007-06-11 22:14:21 +02:00
+++ 1.8/sql/backup/Makefile.am 2007-06-11 22:14:21 +02:00
@@ -31,7 +31,8 @@
be_nodata.cc \
archive.cc \
stream.cc \
- string_pool.cc
+ string_pool.cc \
+ critical_zone.cc
noinst_HEADERS = \
api_types.h \
@@ -45,7 +46,8 @@
stream.h \
string_pool.h \
map.h \
- debug.h
+ debug.h \
+ critical_zone.h
DEFS = \
-DMYSQL_SERVER \
--- New file ---
+++ sql/backup/critical_zone.cc 07/06/11 22:14:09
/**
@file Implementation of critical zone mechanism.
This implementation uses pthread's read-write locks. Each zone has its dedicated
lock. To enter the zone, the lock is taken in read (shared) mode. To lock zone,
its rwlock is taken in write (exclusive) mode.
*/
/*
TODO:
- add user specified timeouts
*/
#include "../mysql_priv.h"
#include "critical_zone.h"
Critical_zone::Critical_zone(): m_locked(FALSE)
{
pthread_rwlock_init(&m_lock,NULL);
}
Critical_zone::~Critical_zone()
{
pthread_rwlock_destroy(&m_lock);
}
/**
Construct instance of ticket for a given zone and of a given type.
Upon construction appropriate lock is taken. Thus, the constructor will possibly
wait for the lock. If not successful in taking the lock, @c is_valid() will return
FALSE.
*/
Critical_zone::Ticket::Ticket(Critical_zone &z, type t): m_zone(z)
{
m_taken= ! (t==EXCLUSIVE ? pthread_rwlock_wrlock(&m_zone.m_lock)
: pthread_rwlock_rdlock(&m_zone.m_lock));
}
/**
Drop a ticket.
Depending on the type of the ticket (SHARED or EXCLUSIVE) the zone is either left or unlocked
by the holder. This happens only if the ticket is valid at the time of calling this method.
*/
int Critical_zone::Ticket::drop()
{
if (!m_taken)
return 0;
int res= pthread_rwlock_unlock(&m_zone.m_lock);
if (!res)
{
m_taken= FALSE;
m_zone.m_locked= FALSE; // Note: even when SHARED ticked is dropped, the zone can't be locked.
}
return res;
}
--- New file ---
+++ sql/backup/critical_zone.h 07/06/11 22:14:09
#ifndef _CRITICAL_ZONE_H
#define _CRITICAL_ZONE_H
#include <pthread.h>
/**
Clas representing a critical zone.
Thread enter a critical zone when they perform some sensitive operations. A zone
can be locked by a thread after which no other thread can enter it (and perform the
sensitive operations). Locking the zone also ensures that it is empty, i.e. all
threads which entered, have left it.
When entering or locking a critical zone, a Ticket object is obtained. Thread is in
the zone (resp. locks the zone) as long as it holds a valid ticket. Ticket is
invalidated when the ticket object is destroyed (its destructor is called) or via an
explicit call to ticket's drop() method.
*/
class Critical_zone
{
public:
/// The class of ticket objects.
class Ticket;
Critical_zone();
~Critical_zone();
/// Produce a ticket for entering the zone. Will hang if zone is locked.
Ticket enter();
/// Produce a ticket for locking the zone. Will wait until all threads leave it.
Ticket lock();
/// Tell if the zone is currently locked.
bool is_locked() const
{ return m_locked; }
private:
Critical_zone(const Critical_zone&) // prevent copying of zone objects.
{ DBUG_ASSERT(FALSE); }
pthread_rwlock_t m_lock; ///< A pthread's read-write lock used to implement the zone.
bool m_locked; ///< TRUE if zone was locked.
friend class Ticket;
};
/**
A class of ticked objects used for entering or locking a critical zone.
Tickets are obtained by calls to @c Critical_zone::enter() or @c Critical_zone::lock() methods.
A thread stays in the zone, resp. keeps lock on the zone, as long as it holds the ticket. When the
ticket is destroyed, or after explicit call to @c drop() method, ticket is dropped and the zone is
left or unlocked, respectively. Method @c is_valid() tells if a given @c Ticket object is currently
"active", i.e. not being dropped or unassigned.
Calling @c Critical_zone methods is the only valid way of creating @c Ticket objects. The constructor
is private and should remain such. It is possible to copy @c Ticket objects. Only the last copy is
active - previous copies are deactivated so that the zone is not leaved/unlocked multiple times.
*/
class Critical_zone::Ticket
{
Critical_zone &m_zone; ///< The zone for which the ticket was issued.
bool m_taken; ///< TRUE if this instance stores a valid ticket.
/**
Types of tickets.
*/
enum type {
SHARED , ///< Ticket obtained when entering zone - many threads can hold one.
EXCLUSIVE ///< Ticket obtained when locking zone - only one thread can hold it.
};
Ticket(Critical_zone&, type);
public:
/**
Copy constructior: the ticket is passed to the new instance while the old one
becomes inactive.
*/
Ticket(const Ticket &t): m_zone(t.m_zone), m_taken(t.m_taken)
{
if (this != &t)
const_cast<Ticket*>(&t)->m_taken= FALSE;
}
/// Tells if this instance stores a valid ticket.
bool is_valid()
{ return m_taken; }
int drop();
~Ticket()
{ drop(); }
friend class Critical_zone;
};
inline
Critical_zone::Ticket Critical_zone::enter()
{
return Ticket(*this,Ticket::SHARED);
}
inline
Critical_zone::Ticket Critical_zone::lock()
{
Ticket t(*this,Ticket::EXCLUSIVE);
m_locked= t.is_valid();
return t;
}
#endif
--- 1.38/sql/CMakeLists.txt 2007-06-11 22:14:21 +02:00
+++ 1.39/sql/CMakeLists.txt 2007-06-11 22:14:21 +02:00
@@ -73,7 +73,7 @@
sql_connect.cc scheduler.cc
backup/archive.cc backup/be_default.cc backup/data_backup.cc
backup/meta_backup.cc backup/sql_backup.cc backup/stream.cc
- backup/string_pool.cc
+ backup/string_pool.cc backup/critical_zone.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
${PROJECT_SOURCE_DIR}/include/mysqld_error.h
| Thread |
|---|
| • bk commit into 5.1 tree (rafal:1.2536) | rsomla | 11 Jun |