summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <jani@labbari.dsl.inet.fi>2007-07-07 18:03:07 +0300
committerunknown <jani@labbari.dsl.inet.fi>2007-07-07 18:03:07 +0300
commit1ea806b1748c4ffc0904021d7d1e938fe837d73e (patch)
tree66e86ba43432e208ac5184873ea51fbe95cc8c60
parent6ed46be70e0c1886231729458b94fb3321ac1a31 (diff)
parent23d10db8a3fd1830afbca1e0ab374799cc715aaa (diff)
downloadmariadb-git-1ea806b1748c4ffc0904021d7d1e938fe837d73e.tar.gz
Merge jamppa@bk-internal.mysql.com:/home/bk/mysql-maria
into labbari.dsl.inet.fi:/home/my/bk/mysql-maria.prod mysys/thr_lock.c: Auto merged storage/csv/ha_tina.cc: Auto merged storage/csv/ha_tina.h: Auto merged storage/maria/ma_blockrec.c: Auto merged storage/maria/ma_check.c: Auto merged storage/maria/ma_loghandler.c: Auto merged storage/maria/trnman.c: Auto merged storage/myisam/mi_locking.c: Auto merged sql/lock.cc: SCCS merged
-rw-r--r--mysys/thr_lock.c20
-rw-r--r--sql/lock.cc4
-rw-r--r--storage/csv/ha_tina.cc12
-rw-r--r--storage/csv/ha_tina.h4
-rw-r--r--storage/maria/ma_blockrec.c2
-rw-r--r--storage/maria/ma_check.c6
-rw-r--r--storage/maria/ma_control_file.h2
-rw-r--r--storage/maria/ma_locking.c6
-rw-r--r--storage/maria/ma_loghandler.c4
-rwxr-xr-xstorage/maria/ma_test_all.sh12
-rw-r--r--storage/maria/trnman.c21
-rw-r--r--storage/maria/unittest/Makefile.am2
-rw-r--r--storage/myisam/mi_locking.c52
13 files changed, 98 insertions, 49 deletions
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index 20edffb49c2..d38bd2944f0 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -24,7 +24,7 @@ Locks are prioritized according to:
The current lock types are:
-TL_READ # Low priority read
+TL_READ # Low priority read
TL_READ_WITH_SHARED_LOCKS
TL_READ_HIGH_PRIORITY # High priority read
TL_READ_NO_INSERT # Read without concurrent inserts
@@ -57,8 +57,12 @@ check_status:
In MyISAM this is a simple check if the insert can be done
at the end of the datafile.
update_status:
- Before a write lock is released, this function is called.
- In MyISAM this functions updates the count and length of the datafile
+ in thr_reschedule_write_lock(), when an insert delayed thread
+ downgrades TL_WRITE lock to TL_WRITE_DELAYED, to allow SELECT
+ threads to proceed.
+ A storage engine should also call update_status internally
+ in the ::external_lock(F_UNLCK) method.
+ In MyISAM and CSV this functions updates the length of the datafile.
get_status:
When one gets a lock this functions is called.
In MyISAM this stores the number of rows and size of the datafile
@@ -762,16 +766,6 @@ void thr_unlock(THR_LOCK_DATA *data)
}
else
lock->write.last=data->prev;
- if (lock_type >= TL_WRITE_CONCURRENT_INSERT)
- {
- if (lock->update_status)
- (*lock->update_status)(data->status_param);
- }
- else
- {
- if (lock->restore_status)
- (*lock->restore_status)(data->status_param);
- }
if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count--;
data->type=TL_UNLOCK; /* Mark unlocked */
diff --git a/sql/lock.cc b/sql/lock.cc
index 50922a682a2..e129da27005 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -289,10 +289,10 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
{
DBUG_ENTER("mysql_unlock_tables");
- if (sql_lock->lock_count)
- thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
if (sql_lock->table_count)
VOID(unlock_external(thd,sql_lock->table,sql_lock->table_count));
+ if (sql_lock->lock_count)
+ thr_multi_unlock(sql_lock->locks,sql_lock->lock_count);
my_free((uchar*) sql_lock,MYF(0));
DBUG_VOID_RETURN;
}
diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index 6de153c82d7..1beb999b2e9 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -441,7 +441,7 @@ ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
*/
current_position(0), next_position(0), local_saved_data_file_length(0),
file_buff(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH),
- records_is_known(0)
+ records_is_known(0), curr_lock_type(F_UNLCK)
{
/* Set our original buffers from pre-allocated memory */
buffer.set((char*)byte_buffer, IO_SIZE, &my_charset_bin);
@@ -1395,6 +1395,14 @@ int ha_tina::delete_all_rows()
DBUG_RETURN(rc);
}
+int ha_tina::external_lock(THD *thd __attribute__((unused)), int lock_type)
+{
+ if (lock_type==F_UNLCK && curr_lock_type == F_WRLCK)
+ update_status();
+ curr_lock_type= lock_type;
+ return 0;
+}
+
/*
Called by the database to lock the table. Keep in mind that this
is an internal lock.
@@ -1409,7 +1417,7 @@ THR_LOCK_DATA **ha_tina::store_lock(THD *thd,
return to;
}
-/*
+/*
Create a table. You do not want to leave the table open after a call to
this (the database will call ::open() if it needs to).
*/
diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
index 8d2c6855b84..2572cbd286a 100644
--- a/storage/csv/ha_tina.h
+++ b/storage/csv/ha_tina.h
@@ -81,6 +81,8 @@ class ha_tina: public handler
bool records_is_known;
private:
+ int curr_lock_type;
+
bool get_write_pos(off_t *end_pos, tina_set *closest_hole);
int open_update_temp_file_if_needed();
int init_tina_writer();
@@ -155,6 +157,8 @@ public:
bool check_if_incompatible_data(HA_CREATE_INFO *info,
uint table_changes);
+ int external_lock(THD *thd, int lock_type);
+
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
index 3292ce65ff1..6376a3fef87 100644
--- a/storage/maria/ma_blockrec.c
+++ b/storage/maria/ma_blockrec.c
@@ -1811,10 +1811,12 @@ static my_bool write_block_record(MARIA_HA *info,
ulong length;
ulong data_length= (tmp_data - info->rec_buff);
+#ifdef MONTY_WILL_KNOW
#ifdef SANITY_CHECKS
if (cur_block->sub_blocks == 1)
goto crashed; /* no reserved full or tails */
#endif
+#endif
/*
Find out where to write tail for non-blob fields.
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index 4d23b66421d..7d936409170 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -1925,7 +1925,11 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend)
Recover old table by reading each record and writing all keys
NOTES
- Save new datafile-name in temp_filename
+ Save new datafile-name in temp_filename.
+ We overwrite the index file as we go (writekeys() for example), so if we
+ crash during this the table is unusable and user (or Recovery in the
+ future) must repeat the REPAIR/OPTIMIZE operation. We could use a
+ temporary index file in the future (drawback: more disk space).
IMPLEMENTATION (for hard repair with block format)
- Create new, unrelated MARIA_HA of the table
diff --git a/storage/maria/ma_control_file.h b/storage/maria/ma_control_file.h
index fa4ec442e41..d6c121b21be 100644
--- a/storage/maria/ma_control_file.h
+++ b/storage/maria/ma_control_file.h
@@ -18,7 +18,7 @@
First version written by Guilhem Bichot on 2006-04-27.
*/
-#define CONTROL_FILE_BASE_NAME "maria_control"
+#define CONTROL_FILE_BASE_NAME "maria_log_control"
/* Here is the interface of this module */
diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c
index 1825367c44c..f709d7e5759 100644
--- a/storage/maria/ma_locking.c
+++ b/storage/maria/ma_locking.c
@@ -55,9 +55,15 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
case F_UNLCK:
maria_ftparser_call_deinitializer(info);
if (info->lock_type == F_RDLCK)
+ {
count= --share->r_locks;
+ _ma_restore_status(info);
+ }
else
+ {
count= --share->w_locks;
+ _ma_update_status(info);
+ }
--share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks)
{
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index 8e38e374a4d..d5c4d59c45f 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -5623,7 +5623,7 @@ static my_bool write_hook_for_redo(enum translog_record_type type
non-transactional log records (REPAIR, CREATE, RENAME, DROP) should not
call this hook; we trust them but verify ;)
*/
- DBUG_ASSERT(trn->trid != 0);
+ DBUG_ASSERT(!(maria_multi_threaded && (trn->trid == 0)));
/*
If the hook stays so simple, it would be faster to pass
!trn->rec_lsn ? trn->rec_lsn : some_dummy_lsn
@@ -5650,7 +5650,7 @@ static my_bool write_hook_for_undo(enum translog_record_type type
struct st_translog_parts *parts
__attribute__ ((unused)))
{
- DBUG_ASSERT(trn->trid != 0); /* see write_hook_for_redo() */
+ DBUG_ASSERT(!(maria_multi_threaded && (trn->trid == 0)));
trn->undo_lsn= *lsn;
if (unlikely(LSN_WITH_FLAGS_TO_LSN(trn->first_undo_lsn) == 0))
trn->first_undo_lsn=
diff --git a/storage/maria/ma_test_all.sh b/storage/maria/ma_test_all.sh
index 5ea76a7037d..a6786315afe 100755
--- a/storage/maria/ma_test_all.sh
+++ b/storage/maria/ma_test_all.sh
@@ -9,6 +9,8 @@
# Remove # from following line if you need some more information
#set -x -v -e
+set -e # abort at first failure
+
valgrind="valgrind --alignment=8 --leak-check=yes"
silent="-s"
suffix=""
@@ -196,15 +198,19 @@ run_repair_tests "-M -T"
run_pack_tests "-M -T"
#
-# Tests that gives warnings
+# Tests that gives warnings or errors
#
$maria_path/ma_test2$suffix $silent -L -K -W -P -S -R1 -m500
$maria_path/maria_chk$suffix -sm test2
echo "ma_test2$suffix $silent -L -K -R1 -m2000 ; Should give error 135"
-$maria_path/ma_test2$suffix $silent -L -K -R1 -m2000
+$maria_path/ma_test2$suffix $silent -L -K -R1 -m2000 >ma_test2_message.txt 2>&1 && false # success is failure
+cat ma_test2_message.txt
+grep "Error: 135" ma_test2_message.txt > /dev/null
echo "$maria_path/maria_chk$suffix -sm test2 will warn that 'Datafile is almost full'"
-$maria_path/maria_chk$suffix -sm test2
+$maria_path/maria_chk$suffix -sm test2 >ma_test2_message.txt 2>&1
+cat ma_test2_message.txt
+grep "warning: Datafile is almost full" ma_test2_message.txt >/dev/null
$maria_path/maria_chk$suffix -ssm test2
#
diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c
index 4f009a7d5a8..75226588912 100644
--- a/storage/maria/trnman.c
+++ b/storage/maria/trnman.c
@@ -209,16 +209,21 @@ static TrID new_trid()
static void set_short_trid(TRN *trn)
{
int i= (global_trid_generator + (intptr)trn) * 312089 % SHORT_TRID_MAX + 1;
- my_atomic_rwlock_wrlock(&LOCK_short_trid_to_trn);
- for ( ; ; i= i % SHORT_TRID_MAX + 1) /* the range is [1..SHORT_TRID_MAX] */
+ for ( ; !trn->short_id ; i= 1)
{
- void *tmp= NULL;
- if (short_trid_to_active_trn[i] == NULL &&
- my_atomic_casptr((void **)&short_trid_to_active_trn[i], &tmp, trn))
- break;
+ my_atomic_rwlock_wrlock(&LOCK_short_trid_to_trn);
+ for ( ; i <= SHORT_TRID_MAX; i++) /* the range is [1..SHORT_TRID_MAX] */
+ {
+ void *tmp= NULL;
+ if (short_trid_to_active_trn[i] == NULL &&
+ my_atomic_casptr((void **)&short_trid_to_active_trn[i], &tmp, trn))
+ {
+ trn->short_id= i;
+ break;
+ }
+ }
+ my_atomic_rwlock_wrunlock(&LOCK_short_trid_to_trn);
}
- my_atomic_rwlock_wrunlock(&LOCK_short_trid_to_trn);
- trn->short_id= i;
}
/*
diff --git a/storage/maria/unittest/Makefile.am b/storage/maria/unittest/Makefile.am
index 28264d5d903..b63cb60c059 100644
--- a/storage/maria/unittest/Makefile.am
+++ b/storage/maria/unittest/Makefile.am
@@ -84,6 +84,6 @@ ma_pagecache_consist_64kWR_t_big_CPPFLAGS = $(ma_pagecache_common_cppflags) -DPA
# the generic lock manager may not be used in the end and lockman1-t crashes,
# so we don't build lockman-t and lockman1-t
-CLEANFILES = maria_control page_cache_test_file_1 \
+CLEANFILES = maria_log_control page_cache_test_file_1 \
maria_log.????????
diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c
index 6aa62b70ae3..e6d446d0b40 100644
--- a/storage/myisam/mi_locking.c
+++ b/storage/myisam/mi_locking.c
@@ -56,9 +56,15 @@ int mi_lock_database(MI_INFO *info, int lock_type)
case F_UNLCK:
ftparser_call_deinitializer(info);
if (info->lock_type == F_RDLCK)
+ {
count= --share->r_locks;
+ mi_restore_status(info);
+ }
else
+ {
count= --share->w_locks;
+ mi_update_status(info);
+ }
--share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks &&
!share->delay_key_write && flush_key_blocks(share->key_cache,
@@ -84,16 +90,16 @@ int mi_lock_database(MI_INFO *info, int lock_type)
if (share->changed && !share->w_locks)
{
#ifdef HAVE_MMAP
- if ((info->s->mmaped_length != info->s->state.state.data_file_length) &&
- (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
- {
- if (info->s->concurrent_insert)
- rw_wrlock(&info->s->mmap_lock);
- mi_remap_file(info, info->s->state.state.data_file_length);
- info->s->nonmmaped_inserts= 0;
- if (info->s->concurrent_insert)
- rw_unlock(&info->s->mmap_lock);
- }
+ if ((info->s->mmaped_length != info->s->state.state.data_file_length) &&
+ (info->s->nonmmaped_inserts > MAX_NONMAPPED_INSERTS))
+ {
+ if (info->s->concurrent_insert)
+ rw_wrlock(&info->s->mmap_lock);
+ mi_remap_file(info, info->s->state.state.data_file_length);
+ info->s->nonmmaped_inserts= 0;
+ if (info->s->concurrent_insert)
+ rw_unlock(&info->s->mmap_lock);
+ }
#endif
share->state.process= share->last_process=share->this_process;
share->state.unique= info->last_unique= info->this_unique;
@@ -300,6 +306,7 @@ void mi_get_status(void* param, int concurrent_insert)
void mi_update_status(void* param)
{
MI_INFO *info=(MI_INFO*) param;
+ DBUG_ENTER("mi_update_status");
/*
Because someone may have closed the table we point at, we only
update the state if its our own state. This isn't a problem as
@@ -336,20 +343,32 @@ void mi_update_status(void* param)
}
info->opt_flag&= ~WRITE_CACHE_USED;
}
+ DBUG_VOID_RETURN;
}
void mi_restore_status(void *param)
{
MI_INFO *info= (MI_INFO*) param;
+ DBUG_ENTER("mi_restore_status");
+ DBUG_PRINT("info",("key_file: %ld data_file: %ld",
+ (long) info->s->state.state.key_file_length,
+ (long) info->s->state.state.data_file_length));
info->state= &info->s->state.state;
info->append_insert_at_end= 0;
+ DBUG_VOID_RETURN;
}
void mi_copy_status(void* to,void *from)
{
- ((MI_INFO*) to)->state= &((MI_INFO*) from)->save_state;
+ MI_INFO *info= (MI_INFO*) to;
+ DBUG_ENTER("mi_copy_status");
+ info->state= &((MI_INFO*) from)->save_state;
+ DBUG_PRINT("info",("key_file: %ld data_file: %ld",
+ (long) info->state->key_file_length,
+ (long) info->state->data_file_length));
+ DBUG_VOID_RETURN;
}
@@ -377,17 +396,18 @@ void mi_copy_status(void* to,void *from)
my_bool mi_check_status(void *param)
{
MI_INFO *info=(MI_INFO*) param;
+ DBUG_ENTER("mi_check_status");
+ DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u",
+ (long) info->s->state.dellink, (uint) info->s->r_locks,
+ (uint) info->s->w_locks));
/*
The test for w_locks == 1 is here because this thread has already done an
external lock (in other words: w_locks == 1 means no other threads has
a write lock)
*/
- DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u",
- (long) info->s->state.dellink, (uint) info->s->r_locks,
- (uint) info->s->w_locks));
- return (my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
+ DBUG_RETURN((my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
(myisam_concurrent_insert == 2 && info->s->r_locks &&
- info->s->w_locks == 1));
+ info->s->w_locks == 1)));
}