Commit fcdc76c2 authored by unknown's avatar unknown

in mysql_unlock_tables(), do thr_unlock() AFTER external_unlock().

it means, {update,restore}_status() should be called in external_lock, 
not in thr_unlock. Only affects storage engines that support
TL_WRITE_CONCURRENT.

parent 329ba0d4
...@@ -57,8 +57,12 @@ should put a pointer to the following functions in the lock structure: ...@@ -57,8 +57,12 @@ should put a pointer to the following functions in the lock structure:
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 */
......
...@@ -281,10 +281,10 @@ static int lock_external(THD *thd, TABLE **tables, uint count) ...@@ -281,10 +281,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((gptr) sql_lock,MYF(0)); my_free((gptr) 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, system_charset_info); buffer.set((char*)byte_buffer, IO_SIZE, system_charset_info);
...@@ -1394,6 +1394,14 @@ int ha_tina::delete_all_rows() ...@@ -1394,6 +1394,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();
...@@ -153,6 +155,8 @@ class ha_tina: public handler ...@@ -153,6 +155,8 @@ class ha_tina: public handler
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);
......
...@@ -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)
{ {
......
...@@ -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