Commit 1ea806b1 authored by unknown's avatar unknown

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
parents 6ed46be7 23d10db8
...@@ -57,8 +57,12 @@ check_status: ...@@ -57,8 +57,12 @@ check_status:
In MyISAM this is a simple check if the insert can be done In MyISAM this is a simple check if the insert can be done
at the end of the datafile. at the end of the datafile.
update_status: update_status:
Before a write lock is released, this function is called. in thr_reschedule_write_lock(), when an insert delayed thread
In MyISAM this functions updates the count and length of the datafile 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: get_status:
When one gets a lock this functions is called. When one gets a lock this functions is called.
In MyISAM this stores the number of rows and size of the datafile In MyISAM this stores the number of rows and size of the datafile
...@@ -762,16 +766,6 @@ void thr_unlock(THR_LOCK_DATA *data) ...@@ -762,16 +766,6 @@ void thr_unlock(THR_LOCK_DATA *data)
} }
else else
lock->write.last=data->prev; 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) if (lock_type == TL_READ_NO_INSERT)
lock->read_no_write_count--; lock->read_no_write_count--;
data->type=TL_UNLOCK; /* Mark unlocked */ data->type=TL_UNLOCK; /* Mark unlocked */
......
...@@ -289,10 +289,10 @@ static int lock_external(THD *thd, TABLE **tables, uint count) ...@@ -289,10 +289,10 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock) void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
{ {
DBUG_ENTER("mysql_unlock_tables"); 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) if (sql_lock->table_count)
VOID(unlock_external(thd,sql_lock->table,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)); my_free((uchar*) sql_lock,MYF(0));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -441,7 +441,7 @@ ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg) ...@@ -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), current_position(0), next_position(0), local_saved_data_file_length(0),
file_buff(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH), 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 */ /* Set our original buffers from pre-allocated memory */
buffer.set((char*)byte_buffer, IO_SIZE, &my_charset_bin); buffer.set((char*)byte_buffer, IO_SIZE, &my_charset_bin);
...@@ -1395,6 +1395,14 @@ int ha_tina::delete_all_rows() ...@@ -1395,6 +1395,14 @@ int ha_tina::delete_all_rows()
DBUG_RETURN(rc); 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 Called by the database to lock the table. Keep in mind that this
is an internal lock. is an internal lock.
......
...@@ -81,6 +81,8 @@ class ha_tina: public handler ...@@ -81,6 +81,8 @@ class ha_tina: public handler
bool records_is_known; bool records_is_known;
private: private:
int curr_lock_type;
bool get_write_pos(off_t *end_pos, tina_set *closest_hole); bool get_write_pos(off_t *end_pos, tina_set *closest_hole);
int open_update_temp_file_if_needed(); int open_update_temp_file_if_needed();
int init_tina_writer(); int init_tina_writer();
...@@ -155,6 +157,8 @@ public: ...@@ -155,6 +157,8 @@ public:
bool check_if_incompatible_data(HA_CREATE_INFO *info, bool check_if_incompatible_data(HA_CREATE_INFO *info,
uint table_changes); uint table_changes);
int external_lock(THD *thd, int lock_type);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); enum thr_lock_type lock_type);
......
...@@ -1811,9 +1811,11 @@ static my_bool write_block_record(MARIA_HA *info, ...@@ -1811,9 +1811,11 @@ static my_bool write_block_record(MARIA_HA *info,
ulong length; ulong length;
ulong data_length= (tmp_data - info->rec_buff); ulong data_length= (tmp_data - info->rec_buff);
#ifdef MONTY_WILL_KNOW
#ifdef SANITY_CHECKS #ifdef SANITY_CHECKS
if (cur_block->sub_blocks == 1) if (cur_block->sub_blocks == 1)
goto crashed; /* no reserved full or tails */ goto crashed; /* no reserved full or tails */
#endif
#endif #endif
/* /*
......
...@@ -1925,7 +1925,11 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info,int extend) ...@@ -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 Recover old table by reading each record and writing all keys
NOTES 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) IMPLEMENTATION (for hard repair with block format)
- Create new, unrelated MARIA_HA of the table - Create new, unrelated MARIA_HA of the table
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
First version written by Guilhem Bichot on 2006-04-27. 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 */ /* Here is the interface of this module */
......
...@@ -55,9 +55,15 @@ int maria_lock_database(MARIA_HA *info, int lock_type) ...@@ -55,9 +55,15 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
case F_UNLCK: case F_UNLCK:
maria_ftparser_call_deinitializer(info); maria_ftparser_call_deinitializer(info);
if (info->lock_type == F_RDLCK) if (info->lock_type == F_RDLCK)
{
count= --share->r_locks; count= --share->r_locks;
_ma_restore_status(info);
}
else else
{
count= --share->w_locks; count= --share->w_locks;
_ma_update_status(info);
}
--share->tot_locks; --share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks) if (info->lock_type == F_WRLCK && !share->w_locks)
{ {
......
...@@ -5623,7 +5623,7 @@ static my_bool write_hook_for_redo(enum translog_record_type type ...@@ -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 non-transactional log records (REPAIR, CREATE, RENAME, DROP) should not
call this hook; we trust them but verify ;) 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 If the hook stays so simple, it would be faster to pass
!trn->rec_lsn ? trn->rec_lsn : some_dummy_lsn !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 ...@@ -5650,7 +5650,7 @@ static my_bool write_hook_for_undo(enum translog_record_type type
struct st_translog_parts *parts struct st_translog_parts *parts
__attribute__ ((unused))) __attribute__ ((unused)))
{ {
DBUG_ASSERT(trn->trid != 0); /* see write_hook_for_redo() */ DBUG_ASSERT(!(maria_multi_threaded && (trn->trid == 0)));
trn->undo_lsn= *lsn; trn->undo_lsn= *lsn;
if (unlikely(LSN_WITH_FLAGS_TO_LSN(trn->first_undo_lsn) == 0)) if (unlikely(LSN_WITH_FLAGS_TO_LSN(trn->first_undo_lsn) == 0))
trn->first_undo_lsn= trn->first_undo_lsn=
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
# Remove # from following line if you need some more information # Remove # from following line if you need some more information
#set -x -v -e #set -x -v -e
set -e # abort at first failure
valgrind="valgrind --alignment=8 --leak-check=yes" valgrind="valgrind --alignment=8 --leak-check=yes"
silent="-s" silent="-s"
suffix="" suffix=""
...@@ -196,15 +198,19 @@ run_repair_tests "-M -T" ...@@ -196,15 +198,19 @@ run_repair_tests "-M -T"
run_pack_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/ma_test2$suffix $silent -L -K -W -P -S -R1 -m500
$maria_path/maria_chk$suffix -sm test2 $maria_path/maria_chk$suffix -sm test2
echo "ma_test2$suffix $silent -L -K -R1 -m2000 ; Should give error 135" 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'" 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 $maria_path/maria_chk$suffix -ssm test2
# #
......
...@@ -209,16 +209,21 @@ static TrID new_trid() ...@@ -209,16 +209,21 @@ static TrID new_trid()
static void set_short_trid(TRN *trn) static void set_short_trid(TRN *trn)
{ {
int i= (global_trid_generator + (intptr)trn) * 312089 % SHORT_TRID_MAX + 1; int i= (global_trid_generator + (intptr)trn) * 312089 % SHORT_TRID_MAX + 1;
for ( ; !trn->short_id ; i= 1)
{
my_atomic_rwlock_wrlock(&LOCK_short_trid_to_trn); my_atomic_rwlock_wrlock(&LOCK_short_trid_to_trn);
for ( ; ; i= i % SHORT_TRID_MAX + 1) /* the range is [1..SHORT_TRID_MAX] */ for ( ; i <= SHORT_TRID_MAX; i++) /* the range is [1..SHORT_TRID_MAX] */
{ {
void *tmp= NULL; void *tmp= NULL;
if (short_trid_to_active_trn[i] == NULL && if (short_trid_to_active_trn[i] == NULL &&
my_atomic_casptr((void **)&short_trid_to_active_trn[i], &tmp, trn)) my_atomic_casptr((void **)&short_trid_to_active_trn[i], &tmp, trn))
{
trn->short_id= i;
break; break;
} }
}
my_atomic_rwlock_wrunlock(&LOCK_short_trid_to_trn); my_atomic_rwlock_wrunlock(&LOCK_short_trid_to_trn);
trn->short_id= i; }
} }
/* /*
......
...@@ -84,6 +84,6 @@ ma_pagecache_consist_64kWR_t_big_CPPFLAGS = $(ma_pagecache_common_cppflags) -DPA ...@@ -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, # 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 # 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.???????? maria_log.????????
...@@ -56,9 +56,15 @@ int mi_lock_database(MI_INFO *info, int lock_type) ...@@ -56,9 +56,15 @@ int mi_lock_database(MI_INFO *info, int lock_type)
case F_UNLCK: case F_UNLCK:
ftparser_call_deinitializer(info); ftparser_call_deinitializer(info);
if (info->lock_type == F_RDLCK) if (info->lock_type == F_RDLCK)
{
count= --share->r_locks; count= --share->r_locks;
mi_restore_status(info);
}
else else
{
count= --share->w_locks; count= --share->w_locks;
mi_update_status(info);
}
--share->tot_locks; --share->tot_locks;
if (info->lock_type == F_WRLCK && !share->w_locks && if (info->lock_type == F_WRLCK && !share->w_locks &&
!share->delay_key_write && flush_key_blocks(share->key_cache, !share->delay_key_write && flush_key_blocks(share->key_cache,
...@@ -300,6 +306,7 @@ void mi_get_status(void* param, int concurrent_insert) ...@@ -300,6 +306,7 @@ void mi_get_status(void* param, int concurrent_insert)
void mi_update_status(void* param) void mi_update_status(void* param)
{ {
MI_INFO *info=(MI_INFO*) param; MI_INFO *info=(MI_INFO*) param;
DBUG_ENTER("mi_update_status");
/* /*
Because someone may have closed the table we point at, we only 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 update the state if its our own state. This isn't a problem as
...@@ -336,20 +343,32 @@ void mi_update_status(void* param) ...@@ -336,20 +343,32 @@ void mi_update_status(void* param)
} }
info->opt_flag&= ~WRITE_CACHE_USED; info->opt_flag&= ~WRITE_CACHE_USED;
} }
DBUG_VOID_RETURN;
} }
void mi_restore_status(void *param) void mi_restore_status(void *param)
{ {
MI_INFO *info= (MI_INFO*) 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->state= &info->s->state.state;
info->append_insert_at_end= 0; info->append_insert_at_end= 0;
DBUG_VOID_RETURN;
} }
void mi_copy_status(void* to,void *from) 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) ...@@ -377,17 +396,18 @@ void mi_copy_status(void* to,void *from)
my_bool mi_check_status(void *param) my_bool mi_check_status(void *param)
{ {
MI_INFO *info=(MI_INFO*) 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 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 external lock (in other words: w_locks == 1 means no other threads has
a write lock) a write lock)
*/ */
DBUG_PRINT("info",("dellink: %ld r_locks: %u w_locks: %u", DBUG_RETURN((my_bool) !(info->s->state.dellink == HA_OFFSET_ERROR ||
(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 ||
(myisam_concurrent_insert == 2 && info->s->r_locks && (myisam_concurrent_insert == 2 && info->s->r_locks &&
info->s->w_locks == 1)); info->s->w_locks == 1)));
} }
......
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