Commit d6c8fcd4 authored by Paul McCullagh's avatar Paul McCullagh

Merged with 1.0 trunk

parent 13fdbbe1
......@@ -3,6 +3,10 @@ PBXT Release Notes
+------- 1.0.11 Pre-GA - Not released yet
RN322: Creating a table the references a non-existing table can now only be done if you set: foreign_key_checks = 0. Also fixed a failure when creating tables with recursive foreign key declarations.
RN321: Added "Extended record count" to the CHECK TABLE output. This indicates the number of records that have a data log component.
RN320: All tests now run with MySQL 5.1.46.
------- 1.0.10n RC4 - 2010-04-28
......
......@@ -2286,8 +2286,8 @@ void XTDDForeignKey::removeReference(XTThreadPtr self)
{
XTDDTable *ref_tab;
xt_xlock_rwlock(self, &co_table->dt_ref_lock);
pushr_(xt_unlock_rwlock, &co_table->dt_ref_lock);
xt_recurrwlock_xlock(self, &co_table->dt_ref_lock);
pushr_(xt_recurrwlock_unxlock, &co_table->dt_ref_lock);
if ((ref_tab = fk_ref_table)) {
fk_ref_table = NULL;
......@@ -2297,7 +2297,7 @@ void XTDDForeignKey::removeReference(XTThreadPtr self)
fk_ref_index = UINT_MAX;
freer_(); // xt_unlock_rwlock(&co_table->dt_ref_lock);
freer_(); // xt_recurrwlock_unxlock(&co_table->dt_ref_lock);
}
/*
......@@ -2316,7 +2316,7 @@ bool XTDDForeignKey::insertRow(xtWord1 *before_buf, xtWord1 *rec_buf, XTThreadPt
/* This lock ensures that the foreign key references are not
* changed.
*/
xt_slock_rwlock_ns(&co_table->dt_ref_lock);
xt_recurrwlock_slock_ns(&co_table->dt_ref_lock);
if (!(loc_ind = getIndexPtr()))
goto failed;
......@@ -2401,11 +2401,11 @@ bool XTDDForeignKey::insertRow(xtWord1 *before_buf, xtWord1 *rec_buf, XTThreadPt
xt_db_return_table_to_pool_ns(ot);
failed:
xt_unlock_rwlock_ns(&co_table->dt_ref_lock);
xt_recurrwlock_unslock_ns(&co_table->dt_ref_lock);
return false;
success:
xt_unlock_rwlock_ns(&co_table->dt_ref_lock);
xt_recurrwlock_unslock_ns(&co_table->dt_ref_lock);
return true;
}
......@@ -2433,7 +2433,7 @@ const char *XTDDForeignKey::actionTypeToString(int action)
void XTDDTable::init(XTThreadPtr self)
{
xt_init_rwlock_with_autoname(self, &dt_ref_lock);
xt_recurrwlock_init_with_autoname(self, &dt_ref_lock);
dt_trefs = NULL;
}
......@@ -2470,7 +2470,7 @@ void XTDDTable::finalize(XTThreadPtr self)
ptr->release(self);
}
xt_free_rwlock(&dt_ref_lock);
xt_recurrwlock_free(&dt_ref_lock);
}
XTDDColumn *XTDDTable::findColumn(char *name)
......@@ -2546,8 +2546,8 @@ void XTDDTable::attachReference(XTThreadPtr self, XTDDForeignKey *fk)
throw_();
}
xt_xlock_rwlock(self, &dt_ref_lock);
pushr_(xt_unlock_rwlock, &dt_ref_lock);
xt_recurrwlock_xlock(self, &dt_ref_lock);
pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
if (!(tr = new XTDDTableRef()))
xt_throw_errno(XT_CONTEXT, XT_ENOMEM);
......@@ -2562,7 +2562,7 @@ void XTDDTable::attachReference(XTThreadPtr self, XTDDForeignKey *fk)
*/
xt_heap_reference(self, fk->co_table->dt_table);
freer_(); // xt_unlock_rwlock(&dt_ref_lock);
freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
}
/*
......@@ -2572,8 +2572,8 @@ void XTDDTable::removeReference(XTThreadPtr self, XTDDForeignKey *fk)
{
XTDDTableRef *tr, *prev_tr = NULL;
xt_xlock_rwlock(self, &dt_ref_lock);
pushr_(xt_unlock_rwlock, &dt_ref_lock);
xt_recurrwlock_xlock(self, &dt_ref_lock);
pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
tr = dt_trefs;
while (tr) {
......@@ -2587,7 +2587,7 @@ void XTDDTable::removeReference(XTThreadPtr self, XTDDForeignKey *fk)
prev_tr = tr;
tr = tr->tr_next;
}
freer_(); // xt_unlock_rwlock(&dt_ref_lock);
freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
if (tr)
tr->release(self);
}
......@@ -2614,8 +2614,8 @@ void XTDDTable::attachReference(XTThreadPtr self, XTDDTable *dt)
dt->attachReference(self, fk);
xt_xlock_rwlock(self, &dt_ref_lock);
pushr_(xt_unlock_rwlock, &dt_ref_lock);
xt_recurrwlock_xlock(self, &dt_ref_lock);
pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
/* Referenced the table, not the index!
* We do this because we know that if the table is referenced, the
* index will remain valid!
......@@ -2625,7 +2625,7 @@ void XTDDTable::attachReference(XTThreadPtr self, XTDDTable *dt)
*/
xt_heap_reference(self, dt->dt_table);
fk->fk_ref_table = dt;
freer_(); // xt_unlock_rwlock(&dt_ref_lock);
freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
}
}
}
......@@ -2689,8 +2689,8 @@ void XTDDTable::removeReferences(XTThreadPtr self)
XTDDTableRef *tr;
XTDDTable *tab;
xt_xlock_rwlock(self, &dt_ref_lock);
pushr_(xt_unlock_rwlock, &dt_ref_lock);
xt_recurrwlock_xlock(self, &dt_ref_lock);
pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
for (u_int i=0; i<dt_fkeys.size(); i++) {
fk = dt_fkeys.itemAt(i);
......@@ -2701,13 +2701,13 @@ void XTDDTable::removeReferences(XTThreadPtr self)
/* To avoid deadlock we do not hold more than
* one lock at a time!
*/
freer_(); // xt_unlock_rwlock(&dt_ref_lock);
freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
tab->removeReference(self, fk);
xt_heap_release(self, tab->dt_table); /* We referenced the table, not the index! */
xt_xlock_rwlock(self, &dt_ref_lock);
pushr_(xt_unlock_rwlock, &dt_ref_lock);
xt_recurrwlock_xlock(self, &dt_ref_lock);
pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
}
}
}
......@@ -2715,13 +2715,13 @@ void XTDDTable::removeReferences(XTThreadPtr self)
while (dt_trefs) {
tr = dt_trefs;
dt_trefs = tr->tr_next;
freer_(); // xt_unlock_rwlock(&dt_ref_lock);
freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
tr->release(self);
xt_xlock_rwlock(self, &dt_ref_lock);
pushr_(xt_unlock_rwlock, &dt_ref_lock);
xt_recurrwlock_xlock(self, &dt_ref_lock);
pushr_(xt_recurrwlock_unxlock, &dt_ref_lock);
}
freer_(); // xt_unlock_rwlock(&dt_ref_lock);
freer_(); // xt_recurrwlock_unxlock(&dt_ref_lock);
}
void XTDDTable::checkForeignKeys(XTThreadPtr self, bool temp_table)
......@@ -2871,7 +2871,7 @@ bool XTDDTable::checkNoAction(XTOpenTablePtr ot, xtRecordID rec_id)
return false;
rec_ptr = rec_buf.ib_db.db_data;
xt_slock_rwlock_ns(&dt_ref_lock);
xt_recurrwlock_slock_ns(&dt_ref_lock);
tr = dt_trefs;
while (tr) {
if (!tr->checkReference(rec_ptr, ot->ot_thread)) {
......@@ -2880,7 +2880,7 @@ bool XTDDTable::checkNoAction(XTOpenTablePtr ot, xtRecordID rec_id)
}
tr = tr->tr_next;
}
xt_unlock_rwlock_ns(&dt_ref_lock);
xt_recurrwlock_unslock_ns(&dt_ref_lock);
xt_ib_free(NULL, &rec_buf);
return ok;
}
......@@ -2901,7 +2901,7 @@ bool XTDDTable::deleteRow(XTOpenTablePtr ot, xtWord1 *rec_ptr)
rec_ptr = rec_buf.ib_db.db_data;
}
xt_slock_rwlock_ns(&dt_ref_lock);
xt_recurrwlock_slock_ns(&dt_ref_lock);
tr = dt_trefs;
while (tr) {
if (!tr->modifyRow(ot, rec_ptr, NULL, ot->ot_thread)) {
......@@ -2910,7 +2910,7 @@ bool XTDDTable::deleteRow(XTOpenTablePtr ot, xtWord1 *rec_ptr)
}
tr = tr->tr_next;
}
xt_unlock_rwlock_ns(&dt_ref_lock);
xt_recurrwlock_unslock_ns(&dt_ref_lock);
xt_ib_free(NULL, &rec_buf);
return ok;
}
......@@ -2919,8 +2919,8 @@ void XTDDTable::deleteAllRows(XTThreadPtr self)
{
XTDDTableRef *tr;
xt_slock_rwlock(self, &dt_ref_lock);
pushr_(xt_unlock_rwlock, &dt_ref_lock);
xt_recurrwlock_slock(self, &dt_ref_lock);
pushr_(xt_recurrwlock_unslock, &dt_ref_lock);
tr = dt_trefs;
while (tr) {
......@@ -2928,7 +2928,7 @@ void XTDDTable::deleteAllRows(XTThreadPtr self)
tr = tr->tr_next;
}
freer_(); // xt_unlock_rwlock(&dt_ref_lock);
freer_(); // xt_recurrwlock_unslock(&dt_ref_lock);
}
bool XTDDTable::updateRow(XTOpenTablePtr ot, xtWord1 *before, xtWord1 *after)
......@@ -2958,7 +2958,7 @@ bool XTDDTable::updateRow(XTOpenTablePtr ot, xtWord1 *before, xtWord1 *after)
ok = true;
before_buf.ib_free = FALSE;
xt_slock_rwlock_ns(&dt_ref_lock);
xt_recurrwlock_slock_ns(&dt_ref_lock);
if ((tr = dt_trefs)) {
if (!before) {
if (!xt_tab_load_record(ot, ot->ot_curr_rec_id, &before_buf))
......@@ -2974,7 +2974,7 @@ bool XTDDTable::updateRow(XTOpenTablePtr ot, xtWord1 *before, xtWord1 *after)
tr = tr->tr_next;
}
}
xt_unlock_rwlock_ns(&dt_ref_lock);
xt_recurrwlock_unslock_ns(&dt_ref_lock);
xt_ib_free(NULL, &before_buf);
return ok;
......
......@@ -258,7 +258,7 @@ class XTDDTable : public XTObject {
XTList<XTDDColumn> dt_cols;
XTList<XTDDIndex> dt_indexes;
xt_rwlock_type dt_ref_lock; /* The lock for adding and using references. */
XTRecurRWLockRec dt_ref_lock; /* The lock for adding and using references. */
XTList<XTDDForeignKey> dt_fkeys; /* The foreign keys on this table. */
XTDDTableRef *dt_trefs; /* A list of tables that reference this table. */
......
......@@ -5980,14 +5980,20 @@ static MYSQL_SYSVAR_INT(max_threads, pbxt_max_threads,
NULL, NULL, 0, 0, 20000, 1);
#endif
/* In MySQL 5.1.46 this assertion: (total_ha_2pc == (ulong) opt_bin_log+1),
* in function ha_recover, file handler.cc, line 1557, has been removed.
* So enable XA by default.
*/
#ifndef DEBUG
static MYSQL_SYSVAR_BOOL(support_xa, pbxt_support_xa,
PLUGIN_VAR_OPCMDARG,
"Enable PBXT support for the XA two-phase commit, default is enabled",
NULL, NULL, TRUE);
#else
static MYSQL_SYSVAR_BOOL(support_xa, pbxt_support_xa,
PLUGIN_VAR_OPCMDARG,
"Enable PBXT support for the XA two-phase commit, default is disabled (due to assertion failure in MySQL)",
/* The problem is, in MySQL an assertion fails in debug mode:
* Assertion failed: (total_ha_2pc == (ulong) opt_bin_log+1), function ha_recover, file handler.cc, line 1557.
*/
NULL, NULL, FALSE);
#endif
static MYSQL_SYSVAR_INT(flush_log_at_trx_commit, xt_db_flush_log_at_trx_commit,
PLUGIN_VAR_OPCMDARG,
......
......@@ -1894,6 +1894,124 @@ xtPublic xtBool xt_skewrwlock_unlock(XTSkewRWLockPtr srw, xtBool xlocked)
return OK;
}
/*
* -----------------------------------------------------------------------
* RECURSIVE R/W LOCK (allows X lockers to lock again)
*/
#ifdef XT_THREAD_LOCK_INFO
void xt_recursivemutex_init(XTThreadPtr self, XTRecursiveMutexPtr rm, const char *name)
{
rm->rm_locker = NULL;
rm->rm_lock_count = 0;
xt_init_mutex(self, &rm->rm_mutex, name);
}
#else
xtPublic void xt_recursivemutex_init(XTThreadPtr self, XTRecursiveMutexPtr rm)
{
rm->rm_locker = NULL;
rm->rm_lock_count = 0;
xt_init_mutex(self, &rm->rm_mutex);
}
#endif
xtPublic void xt_recursivemutex_free(XTRecursiveMutexPtr rm)
{
xt_free_mutex(&rm->rm_mutex);
#ifdef XT_THREAD_LOCK_INFO
xt_thread_lock_info_free(&rm->rm_lock_info);
#endif
}
xtPublic void xt_recursivemutex_lock(XTThreadPtr self, XTRecursiveMutexPtr rm)
{
if (self != rm->rm_locker) {
xt_lock_mutex(self, &rm->rm_mutex);
rm->rm_locker = self;
}
rm->rm_lock_count++;
}
xtPublic void xt_recursivemutex_unlock(XTThreadPtr self, XTRecursiveMutexPtr rm)
{
ASSERT(self == rm->rm_locker);
ASSERT(rm->rm_lock_count > 0);
rm->rm_lock_count--;
if (!rm->rm_lock_count) {
rm->rm_locker = NULL;
xt_unlock_mutex(self, &rm->rm_mutex);
}
}
/*
* -----------------------------------------------------------------------
* RECURSIVE MUTEX (allows lockers to lock again)
*/
#ifdef XT_THREAD_LOCK_INFO
void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw, const char *name)
{
rrw->rrw_locker = NULL;
rrw->rrw_lock_count = 0;
xt_init_rwlock(self, &rrw->rrw_lock, name);
}
#else
void xt_recurrwlock_init(struct XTThread *self, XTRecurRWLockPtr rrw)
{
rrw->rrw_locker = NULL;
rrw->rrw_lock_count = 0;
xt_init_rwlock(self, &rrw->rrw_lock);
}
#endif
void xt_recurrwlock_free(XTRecurRWLockPtr rrw)
{
xt_free_rwlock(&rrw->rrw_lock);
#ifdef XT_THREAD_LOCK_INFO
xt_thread_lock_info_free(&rrw->rrw_lock_info);
#endif
}
void xt_recurrwlock_xlock(struct XTThread *self, XTRecurRWLockPtr rrw)
{
if (self != rrw->rrw_locker) {
xt_xlock_rwlock(self, &rrw->rrw_lock);
rrw->rrw_locker = self;
}
rrw->rrw_lock_count++;
}
void xt_recurrwlock_slock(struct XTThread *self, XTRecurRWLockPtr rrw)
{
xt_slock_rwlock(self, &rrw->rrw_lock);
}
void xt_recurrwlock_slock_ns(XTRecurRWLockPtr rrw)
{
xt_slock_rwlock_ns(&rrw->rrw_lock);
}
void xt_recurrwlock_unxlock(struct XTThread *self, XTRecurRWLockPtr rrw)
{
ASSERT(self == rrw->rrw_locker);
ASSERT(rrw->rrw_lock_count > 0);
rrw->rrw_lock_count--;
if (!rrw->rrw_lock_count) {
rrw->rrw_locker = NULL;
xt_unlock_rwlock(self, &rrw->rrw_lock);
}
}
void xt_recurrwlock_unslock(struct XTThread *self, XTRecurRWLockPtr rrw)
{
xt_unlock_rwlock(self, &rrw->rrw_lock);
}
void xt_recurrwlock_unslock_ns(XTRecurRWLockPtr rrw)
{
xt_unlock_rwlock_ns(&rrw->rrw_lock);
}
/*
* -----------------------------------------------------------------------
* UNIT TESTS
......
......@@ -61,6 +61,11 @@
#define CHECK_TABLE_STATS
/* The problem is that this can take a long time
* if the table is very large!
*/
//#define CHECK_TABLE_READ_DATA_LOG
#ifdef TRACE_TABLE_IDS
//#define PRINTF xt_ftracef
#define PRINTF xt_trace
......@@ -488,6 +493,12 @@ xtPublic void xt_tab_init_db(XTThreadPtr self, XTDatabaseHPtr db)
}
freer_(); // xt_describe_tables_exit(&desc)
/*
* When we open all tables, we ignore problems with foreign keys.
* This must be done or we will not be able to load tables that
* were created with foreign key checks off.
*/
self->st_ignore_fkeys = 1;
/*
* The purpose of this code is to ensure that all tables are opened and cached,
* which is actually only required if tables have foreign key references.
......@@ -513,12 +524,17 @@ xtPublic void xt_tab_init_db(XTThreadPtr self, XTDatabaseHPtr db)
xt_add_dir_char(PATH_MAX, pbuf);
xt_strcat(PATH_MAX, pbuf, te_ptr->te_tab_name);
try_(a) {
xt_heap_release(self, xt_use_table_no_lock(self, db, (XTPathStrPtr)pbuf, FALSE, FALSE, NULL));
} catch_(a) {
/* ignore errors */
xt_heap_release(self, xt_use_table_no_lock(self, db, (XTPathStrPtr) pbuf, FALSE, FALSE, NULL));
}
catch_(a) {
/* ignore errors, because we are just loading all
* the tables that we can...
*/
xt_log_and_clear_warning(self);
} cont_(a);
}
cont_(a);
}
self->st_ignore_fkeys = 0;
popr_(); // Discard xt_tab_exit_db(db)
exit_();
......@@ -1165,10 +1181,14 @@ static int tab_new_handle(XTThreadPtr self, XTTableHPtr *r_tab, XTDatabaseHPtr d
if (tab->tab_dic.dic_table) {
try_(a) {
tab->tab_dic.dic_table->attachReferences(self, db);
} catch_(a) {
/* ignore problems of referenced tables */
xt_log_and_clear_warning(self);
} cont_(a);
}
catch_(a) {
/* Errors are thrown when: set foreign_key_checks = 1 */
/* Undo everything done above: */
xt_ht_del(self, db->db_tables, tab->tab_name);
xt_throw(self);
}
cont_(a);
}
*r_tab = tab;
......@@ -1790,6 +1810,7 @@ xtPublic void xt_check_table(XTThreadPtr self, XTOpenTablePtr ot)
size_t rec_size;
size_t row_size;
u_llong ext_data_len = 0;
u_llong ext_rec_count = 0;
#if defined(DUMP_CHECK_TABLE) || defined(CHECK_TABLE_STATS)
printf("\nCHECK TABLE: %s\n", tab->tab_name->ps_path);
......@@ -1889,6 +1910,7 @@ xtPublic void xt_check_table(XTThreadPtr self, XTOpenTablePtr ot)
printf("record-X ");
#endif
alloc_rec_count++;
ext_rec_count++;
ext_data_len += XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);
row_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4) + ot->ot_rec_size - XT_REC_EXT_HEADER_SIZE;
alloc_rec_bytes += row_size;
......@@ -1918,6 +1940,7 @@ xtPublic void xt_check_table(XTThreadPtr self, XTOpenTablePtr ot)
printf(" prev=%-3llu xact=%-3llu row=%lu Xlog=%lu Xoff=%llu Xsiz=%lu\n", (u_llong) prev_rec_id, (u_llong) xn_id, (u_long) row_id, (u_long) XT_GET_DISK_2(rec_buf->re_log_id_2), (u_llong) XT_GET_DISK_6(rec_buf->re_log_offs_6), (u_long) XT_GET_DISK_4(rec_buf->re_log_dat_siz_4));
#endif
#ifdef CHECK_TABLE_READ_DATA_LOG
log_size = XT_GET_DISK_4(rec_buf->re_log_dat_siz_4);
XT_GET_LOG_REF(log_id, log_offset, rec_buf);
if (!self->st_dlog_buf.dlb_read_log(log_id, log_offset, offsetof(XTactExtRecEntryDRec, er_data), (xtWord1 *) &ext_rec, self))
......@@ -1934,6 +1957,7 @@ xtPublic void xt_check_table(XTThreadPtr self, XTOpenTablePtr ot)
xt_logf(XT_INFO, "Table %s: record %llu, extended record %lu:%llu not valid\n", tab->tab_name, (u_llong) rec_id, (u_long) log_id, (u_llong) log_offset);
}
}
#endif
break;
default:
#ifdef DUMP_CHECK_TABLE
......@@ -1945,8 +1969,10 @@ xtPublic void xt_check_table(XTThreadPtr self, XTOpenTablePtr ot)
}
#ifdef CHECK_TABLE_STATS
if (!tab->tab_dic.dic_rec_fixed)
printf("Extendend data length = %llu\n", ext_data_len);
if (!tab->tab_dic.dic_rec_fixed) {
printf("Extended data length = %llu\n", ext_data_len);
printf("Extended record count = %llu\n", ext_rec_count);
}
if (alloc_rec_count) {
printf("Minumum comp. rec. len. = %llu\n", (u_llong) min_comp_rec_len);
......
......@@ -794,11 +794,9 @@ xtPublic void xt_register_tabcolerr(c_char *func, c_char *file, u_int line, int
xt_2nd_last_name_of_path(sizeof(buffer), buffer, tab_item->ps_path);
xt_strcat(sizeof(buffer), buffer, ".");
xt_strcpy(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
xt_strcat(sizeof(buffer), buffer, ".");
xt_strcat(sizeof(buffer), buffer, item2);
xt_strcat(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
xt_register_ixterr(func, file, line, xt_err, buffer);
xt_register_i2xterr(func, file, line, xt_err, buffer, item2);
}
xtPublic void xt_register_taberr(c_char *func, c_char *file, u_int line, int xt_err, XTPathStrPtr tab_item)
......@@ -807,7 +805,7 @@ xtPublic void xt_register_taberr(c_char *func, c_char *file, u_int line, int xt_
xt_2nd_last_name_of_path(sizeof(buffer), buffer, tab_item->ps_path);
xt_strcat(sizeof(buffer), buffer, ".");
xt_strcpy(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
xt_strcat(sizeof(buffer), buffer, xt_last_name_of_path(tab_item->ps_path));
xt_register_ixterr(func, file, line, xt_err, buffer);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment