Commit 4906b5f0 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 808b8437 97a41052
......@@ -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 @@ 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
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 */
......
......@@ -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;
}
......
......@@ -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).
*/
......
......@@ -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 @@ class ha_tina: public handler
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);
......
......@@ -1811,9 +1811,11 @@ 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
/*
......
......@@ -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
......
......@@ -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 */
......
......@@ -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)
{
......
......@@ -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=
......
......@@ -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
#
......
......@@ -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;
}
/*
......
......@@ -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.????????
......@@ -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)));
}
......
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