Commit 442969fd authored by svoj@june.mysql.com's avatar svoj@june.mysql.com

Merge mysql.com:/home/svoj/devel/bk/mysql-5.1

into  mysql.com:/home/svoj/devel/mysql/merge/mysql-5.1-engines
parents 2ff938d2 fbb5c31a
...@@ -44,6 +44,7 @@ typedef struct st_keycache_wqueue ...@@ -44,6 +44,7 @@ typedef struct st_keycache_wqueue
typedef struct st_key_cache typedef struct st_key_cache
{ {
my_bool key_cache_inited; my_bool key_cache_inited;
my_bool in_resize; /* true during resize operation */
my_bool resize_in_flush; /* true during flush of resize operation */ my_bool resize_in_flush; /* true during flush of resize operation */
my_bool can_be_used; /* usage of cache for read/write is allowed */ my_bool can_be_used; /* usage of cache for read/write is allowed */
uint key_cache_shift; uint key_cache_shift;
...@@ -72,6 +73,11 @@ typedef struct st_key_cache ...@@ -72,6 +73,11 @@ typedef struct st_key_cache
BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */ BLOCK_LINK *used_ins; /* ptr to the insertion block in LRU chain */
pthread_mutex_t cache_lock; /* to lock access to the cache structure */ pthread_mutex_t cache_lock; /* to lock access to the cache structure */
KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */ KEYCACHE_WQUEUE resize_queue; /* threads waiting during resize operation */
/*
Waiting for a zero resize count. Using a queue for symmetry though
only one thread can wait here.
*/
KEYCACHE_WQUEUE waiting_for_resize_cnt;
KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */ KEYCACHE_WQUEUE waiting_for_hash_link; /* waiting for a free hash link */
KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */ KEYCACHE_WQUEUE waiting_for_block; /* requests waiting for a free block */
BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/ BLOCK_LINK *changed_blocks[CHANGED_BLOCKS_HASH]; /* hash for dirty file bl.*/
......
...@@ -66,8 +66,8 @@ extern int NEAR my_errno; /* Last error in mysys */ ...@@ -66,8 +66,8 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_ALLOW_ZERO_PTR 64 /* my_realloc() ; zero ptr -> malloc */ #define MY_ALLOW_ZERO_PTR 64 /* my_realloc() ; zero ptr -> malloc */
#define MY_FREE_ON_ERROR 128 /* my_realloc() ; Free old ptr on error */ #define MY_FREE_ON_ERROR 128 /* my_realloc() ; Free old ptr on error */
#define MY_HOLD_ON_ERROR 256 /* my_realloc() ; Return old ptr on error */ #define MY_HOLD_ON_ERROR 256 /* my_realloc() ; Return old ptr on error */
#define MY_THREADSAFE 128 /* pread/pwrite: Don't allow interrupts */
#define MY_DONT_OVERWRITE_FILE 1024 /* my_copy: Don't overwrite file */ #define MY_DONT_OVERWRITE_FILE 1024 /* my_copy: Don't overwrite file */
#define MY_THREADSAFE 2048 /* my_seek(): lock fd mutex */
#define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */ #define MY_CHECK_ERROR 1 /* Params to my_end; Check open-close */
#define MY_GIVE_INFO 2 /* Give time info about process*/ #define MY_GIVE_INFO 2 /* Give time info about process*/
......
...@@ -124,6 +124,16 @@ let $VERSION=`select version()`; ...@@ -124,6 +124,16 @@ let $VERSION=`select version()`;
source include/show_binlog_events.inc; source include/show_binlog_events.inc;
drop table t1,t2,t3; drop table t1,t2,t3;
#
# BUG#27998 - mysqld crashed when executing INSERT DELAYED on a BLACKHOLE
# table
#
CREATE TABLE t1(a INT) ENGINE=BLACKHOLE;
INSERT DELAYED INTO t1 VALUES(1);
DROP TABLE t1;
# End of 4.1 tests
# #
#Bug#19717: DELETE Query Error on BLACKHOLE when using WHERE on column with UNIQUE INDEX #Bug#19717: DELETE Query Error on BLACKHOLE when using WHERE on column with UNIQUE INDEX
# #
...@@ -139,7 +149,8 @@ ALTER TABLE t1 ADD PRIMARY KEY(a); ...@@ -139,7 +149,8 @@ ALTER TABLE t1 ADD PRIMARY KEY(a);
DELETE FROM t1 WHERE a=10; DELETE FROM t1 WHERE a=10;
DROP TABLE t1; DROP TABLE t1;
# End of 4.1 tests # End of 5.0 tests
# Test that a transaction which is rolled back does not go into binlog # Test that a transaction which is rolled back does not go into binlog
# and that a transaction which is committed does # and that a transaction which is committed does
...@@ -156,4 +167,4 @@ set autocommit=1; ...@@ -156,4 +167,4 @@ set autocommit=1;
source include/show_binlog_events.inc; source include/show_binlog_events.inc;
drop table if exists t1; drop table if exists t1;
# End of 5.0 tests # End of 5.1 tests
...@@ -120,7 +120,11 @@ sub mtr_get_opts_from_file ($) { ...@@ -120,7 +120,11 @@ sub mtr_get_opts_from_file ($) {
$arg =~ s/\$(\w+)/envsubst($1)/ge; $arg =~ s/\$(\w+)/envsubst($1)/ge;
# print STDERR "ARG: $arg\n"; # print STDERR "ARG: $arg\n";
push(@args, $arg); # Do not pass empty string since my_getopt is not capable to handle it.
if (length($arg))
{
push(@args, $arg)
}
} }
} }
close FILE; close FILE;
......
...@@ -1766,22 +1766,6 @@ sub environment_setup () { ...@@ -1766,22 +1766,6 @@ sub environment_setup () {
push(@ld_library_paths, "$glob_basedir/storage/ndb/src/.libs"); push(@ld_library_paths, "$glob_basedir/storage/ndb/src/.libs");
} }
# --------------------------------------------------------------------------
# Add the path where mysqld will find udf_example.so
# --------------------------------------------------------------------------
if ( $lib_udf_example )
{
push(@ld_library_paths, dirname($lib_udf_example));
}
# --------------------------------------------------------------------------
# Add the path where mysqld will find ha_example.so
# --------------------------------------------------------------------------
if ( $lib_example_plugin )
{
push(@ld_library_paths, dirname($lib_example_plugin));
}
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
# Valgrind need to be run with debug libraries otherwise it's almost # Valgrind need to be run with debug libraries otherwise it's almost
# impossible to add correct supressions, that means if "/usr/lib/debug" # impossible to add correct supressions, that means if "/usr/lib/debug"
...@@ -2060,12 +2044,16 @@ sub environment_setup () { ...@@ -2060,12 +2044,16 @@ sub environment_setup () {
# ---------------------------------------------------- # ----------------------------------------------------
$ENV{'UDF_EXAMPLE_LIB'}= $ENV{'UDF_EXAMPLE_LIB'}=
($lib_udf_example ? basename($lib_udf_example) : ""); ($lib_udf_example ? basename($lib_udf_example) : "");
$ENV{'UDF_EXAMPLE_LIB_OPT'}=
($lib_udf_example ? "--plugin_dir=" . dirname($lib_udf_example) : "");
# ---------------------------------------------------- # ----------------------------------------------------
# Add the path where mysqld will find ha_example.so # Add the path where mysqld will find ha_example.so
# ---------------------------------------------------- # ----------------------------------------------------
$ENV{'EXAMPLE_PLUGIN'}= $ENV{'EXAMPLE_PLUGIN'}=
($lib_example_plugin ? basename($lib_example_plugin) : ""); ($lib_example_plugin ? basename($lib_example_plugin) : "");
$ENV{'EXAMPLE_PLUGIN_OPT'}=
($lib_example_plugin ? "--plugin_dir=" . dirname($lib_example_plugin) : "");
# ---------------------------------------------------- # ----------------------------------------------------
# We are nice and report a bit about our settings # We are nice and report a bit about our settings
...@@ -3821,9 +3809,6 @@ sub mysqld_arguments ($$$$) { ...@@ -3821,9 +3809,6 @@ sub mysqld_arguments ($$$$) {
mtr_add_arg($args, "%s--ndb-extra-logging", $prefix); mtr_add_arg($args, "%s--ndb-extra-logging", $prefix);
} }
} }
mtr_add_arg($args, "%s--plugin_dir=%s", $prefix,
dirname($lib_example_plugin));
} }
else else
{ {
......
...@@ -121,6 +121,9 @@ master-bin.000001 # Query # # use `test`; alter table t1 add b int ...@@ -121,6 +121,9 @@ master-bin.000001 # Query # # use `test`; alter table t1 add b int
master-bin.000001 # Query # # use `test`; alter table t1 drop b master-bin.000001 # Query # # use `test`; alter table t1 drop b
master-bin.000001 # Query # # use `test`; create table t3 like t1 master-bin.000001 # Query # # use `test`; create table t3 like t1
drop table t1,t2,t3; drop table t1,t2,t3;
CREATE TABLE t1(a INT) ENGINE=BLACKHOLE;
INSERT DELAYED INTO t1 VALUES(1);
DROP TABLE t1;
CREATE TABLE t1(a INT, b INT) ENGINE=BLACKHOLE; CREATE TABLE t1(a INT, b INT) ENGINE=BLACKHOLE;
DELETE FROM t1 WHERE a=10; DELETE FROM t1 WHERE a=10;
ALTER TABLE t1 ADD INDEX(a); ALTER TABLE t1 ADD INDEX(a);
......
...@@ -122,6 +122,9 @@ master-bin.000001 # Query # # use `test`; create table t3 like t1 ...@@ -122,6 +122,9 @@ master-bin.000001 # Query # # use `test`; create table t3 like t1
master-bin.000001 # Query # # use `test`; insert into t1 select * from t3 master-bin.000001 # Query # # use `test`; insert into t1 select * from t3
master-bin.000001 # Query # # use `test`; replace into t1 select * from t3 master-bin.000001 # Query # # use `test`; replace into t1 select * from t3
drop table t1,t2,t3; drop table t1,t2,t3;
CREATE TABLE t1(a INT) ENGINE=BLACKHOLE;
INSERT DELAYED INTO t1 VALUES(1);
DROP TABLE t1;
CREATE TABLE t1(a INT, b INT) ENGINE=BLACKHOLE; CREATE TABLE t1(a INT, b INT) ENGINE=BLACKHOLE;
DELETE FROM t1 WHERE a=10; DELETE FROM t1 WHERE a=10;
ALTER TABLE t1 ADD INDEX(a); ALTER TABLE t1 ADD INDEX(a);
......
CREATE TABLE t1(a int) ENGINE=EXAMPLE; CREATE TABLE t1(a int) ENGINE=EXAMPLE;
Warnings: Warnings:
Error 1286 Unknown table engine 'EXAMPLE' Warning 1286 Unknown table engine 'EXAMPLE'
Warning 1266 Using storage engine MyISAM for table 't1'
DROP TABLE t1; DROP TABLE t1;
INSTALL PLUGIN example SONAME 'ha_example.so'; INSTALL PLUGIN example SONAME 'ha_example.so';
INSTALL PLUGIN EXAMPLE SONAME 'ha_example.so'; INSTALL PLUGIN EXAMPLE SONAME 'ha_example.so';
...@@ -11,5 +12,8 @@ CREATE TABLE t1(a int) ENGINE=EXAMPLE; ...@@ -11,5 +12,8 @@ CREATE TABLE t1(a int) ENGINE=EXAMPLE;
SELECT * FROM t1; SELECT * FROM t1;
a a
DROP TABLE t1; DROP TABLE t1;
UNINSTALL PLUGIN example;
UNINSTALL PLUGIN EXAMPLE;
ERROR 42000: PLUGIN EXAMPLE does not exist
UNINSTALL PLUGIN non_exist; UNINSTALL PLUGIN non_exist;
ERROR 42000: PLUGIN non_exist does not exist ERROR 42000: PLUGIN non_exist does not exist
...@@ -37,7 +37,6 @@ synchronization : Bug#24529 Test 'synchronization' fails on Mac pushb ...@@ -37,7 +37,6 @@ synchronization : Bug#24529 Test 'synchronization' fails on Mac pushb
#ndb_binlog_discover : bug#21806 2006-08-24 #ndb_binlog_discover : bug#21806 2006-08-24
#ndb_autodiscover3 : bug#21806 #ndb_autodiscover3 : bug#21806
plugin : Bug#25659 memory leak via "plugins" test
#rpl_ndb_dd_advance : Bug#25913 rpl_ndb_dd_advance fails randomly #rpl_ndb_dd_advance : Bug#25913 rpl_ndb_dd_advance fails randomly
rpl_ndb_stm_innodb : Bug#26783 rpl_ndb_stm_innodb : Bug#26783
......
...@@ -18,9 +18,9 @@ SELECT * FROM t1; ...@@ -18,9 +18,9 @@ SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
# Waiting for fix to BUG#22694 UNINSTALL PLUGIN example;
#UNINSTALL PLUGIN example; --error 1305
#UNINSTALL PLUGIN EXAMPLE; UNINSTALL PLUGIN EXAMPLE;
--error 1305 --error 1305
UNINSTALL PLUGIN non_exist; UNINSTALL PLUGIN non_exist;
$UDF_EXAMPLE_LIB_OPT
...@@ -426,6 +426,23 @@ ...@@ -426,6 +426,23 @@
fun:_dl_map_object fun:_dl_map_object
} }
{
libc pthread_exit 6
Memcheck:Leak
fun:malloc
fun:_dl_map_object
fun:openaux
fun:_dl_catch_error
}
{
libc pthread_exit 7
Memcheck:Leak
fun:malloc
fun:dl_open_worker
fun:_dl_catch_error
fun:_dl_open
}
# #
# This is seen internally in the system libraries on 64-bit RHAS3. # This is seen internally in the system libraries on 64-bit RHAS3.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -23,7 +23,9 @@ ...@@ -23,7 +23,9 @@
my_off_t pos The expected position (absolute or relative) my_off_t pos The expected position (absolute or relative)
int whence A direction parameter and one of int whence A direction parameter and one of
{SEEK_SET, SEEK_CUR, SEEK_END} {SEEK_SET, SEEK_CUR, SEEK_END}
myf MyFlags Not used. myf MyFlags MY_THREADSAFE must be set in case my_seek may be mixed
with my_pread/my_pwrite calls and fd is shared among
threads.
DESCRIPTION DESCRIPTION
The my_seek function is a wrapper around the system call lseek and The my_seek function is a wrapper around the system call lseek and
...@@ -54,9 +56,16 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, ...@@ -54,9 +56,16 @@ my_off_t my_seek(File fd, my_off_t pos, int whence,
Make sure we are using a valid file descriptor! Make sure we are using a valid file descriptor!
*/ */
DBUG_ASSERT(fd != -1); DBUG_ASSERT(fd != -1);
#if defined(THREAD) && !defined(HAVE_PREAD)
newpos= lseek(fd, pos, whence); if (MyFlags & MY_THREADSAFE)
{
pthread_mutex_lock(&my_file_info[fd].mutex);
newpos= lseek(fd, pos, whence);
pthread_mutex_unlock(&my_file_info[fd].mutex);
}
else
#endif
newpos= lseek(fd, pos, whence);
if (newpos == (os_off_t) -1) if (newpos == (os_off_t) -1)
{ {
my_errno=errno; my_errno=errno;
......
...@@ -48,9 +48,6 @@ struct st_remember _my_sig_remember[MAX_SIGNALS]={{0,0}}; ...@@ -48,9 +48,6 @@ struct st_remember _my_sig_remember[MAX_SIGNALS]={{0,0}};
sigset_t my_signals; /* signals blocked by mf_brkhant */ sigset_t my_signals; /* signals blocked by mf_brkhant */
#endif #endif
/* from mf_keycache.c */
my_bool key_cache_inited=0;
/* from mf_reccache.c */ /* from mf_reccache.c */
ulong my_default_record_cache_size=RECORD_CACHE_SIZE; ulong my_default_record_cache_size=RECORD_CACHE_SIZE;
......
...@@ -2717,8 +2717,8 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache) ...@@ -2717,8 +2717,8 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache)
if (!key_cache->key_cache_inited) if (!key_cache->key_cache_inited)
{ {
pthread_mutex_lock(&LOCK_global_system_variables); pthread_mutex_lock(&LOCK_global_system_variables);
long tmp_buff_size= (long) key_cache->param_buff_size; ulong tmp_buff_size= (ulong) key_cache->param_buff_size;
long tmp_block_size= (long) key_cache->param_block_size; uint tmp_block_size= (uint) key_cache->param_block_size;
uint division_limit= key_cache->param_division_limit; uint division_limit= key_cache->param_division_limit;
uint age_threshold= key_cache->param_age_threshold; uint age_threshold= key_cache->param_age_threshold;
pthread_mutex_unlock(&LOCK_global_system_variables); pthread_mutex_unlock(&LOCK_global_system_variables);
......
...@@ -4653,8 +4653,13 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, ...@@ -4653,8 +4653,13 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
bool mysql_preload_keys(THD* thd, TABLE_LIST* tables) bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
{ {
DBUG_ENTER("mysql_preload_keys"); DBUG_ENTER("mysql_preload_keys");
/*
We cannot allow concurrent inserts. The storage engine reads
directly from the index file, bypassing the cache. It could read
outdated information if parallel inserts into cache blocks happen.
*/
DBUG_RETURN(mysql_admin_table(thd, tables, 0, DBUG_RETURN(mysql_admin_table(thd, tables, 0,
"preload_keys", TL_READ, 0, 0, 0, 0, "preload_keys", TL_READ_NO_INSERT, 0, 0, 0, 0,
&handler::preload_keys, 0)); &handler::preload_keys, 0));
} }
......
...@@ -169,11 +169,15 @@ void udf_init() ...@@ -169,11 +169,15 @@ void udf_init()
Ensure that the .dll doesn't have a path Ensure that the .dll doesn't have a path
This is done to ensure that only approved dll from the system This is done to ensure that only approved dll from the system
directories are used (to make this even remotely secure). directories are used (to make this even remotely secure).
On windows we must check both FN_LIBCHAR and '/'.
*/ */
if (my_strchr(files_charset_info, dl_name, if (my_strchr(files_charset_info, dl_name,
dl_name + strlen(dl_name), FN_LIBCHAR) || dl_name + strlen(dl_name), FN_LIBCHAR) ||
check_string_char_length(&name, "", NAME_CHAR_LEN, IF_WIN(my_strchr(files_charset_info, dl_name,
system_charset_info, 1)) dl_name + strlen(dl_name), '/'), 0) ||
check_string_char_length(&name, "", NAME_CHAR_LEN,
system_charset_info, 1))
{ {
sql_print_error("Invalid row in mysql.func table for function '%.64s'", sql_print_error("Invalid row in mysql.func table for function '%.64s'",
name.str); name.str);
...@@ -190,10 +194,13 @@ void udf_init() ...@@ -190,10 +194,13 @@ void udf_init()
void *dl = find_udf_dl(tmp->dl); void *dl = find_udf_dl(tmp->dl);
if (dl == NULL) if (dl == NULL)
{ {
if (!(dl= dlopen(tmp->dl, RTLD_NOW))) char dlpath[FN_REFLEN];
strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", tmp->dl,
NullS);
if (!(dl= dlopen(dlpath, RTLD_NOW)))
{ {
/* Print warning to log */ /* Print warning to log */
sql_print_error(ER(ER_CANT_OPEN_LIBRARY), tmp->dl, errno, dlerror()); sql_print_error(ER(ER_CANT_OPEN_LIBRARY), tmp->dl, errno, dlerror());
/* Keep the udf in the hash so that we can remove it later */ /* Keep the udf in the hash so that we can remove it later */
continue; continue;
} }
...@@ -394,8 +401,13 @@ int mysql_create_function(THD *thd,udf_func *udf) ...@@ -394,8 +401,13 @@ int mysql_create_function(THD *thd,udf_func *udf)
Ensure that the .dll doesn't have a path Ensure that the .dll doesn't have a path
This is done to ensure that only approved dll from the system This is done to ensure that only approved dll from the system
directories are used (to make this even remotely secure). directories are used (to make this even remotely secure).
On windows we must check both FN_LIBCHAR and '/'.
*/ */
if (my_strchr(files_charset_info, udf->dl, udf->dl + strlen(udf->dl), FN_LIBCHAR)) if (my_strchr(files_charset_info, udf->dl,
udf->dl + strlen(udf->dl), FN_LIBCHAR) ||
IF_WIN(my_strchr(files_charset_info, udf->dl,
udf->dl + strlen(udf->dl), '/'), 0))
{ {
my_message(ER_UDF_NO_PATHS, ER(ER_UDF_NO_PATHS), MYF(0)); my_message(ER_UDF_NO_PATHS, ER(ER_UDF_NO_PATHS), MYF(0));
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -422,10 +434,12 @@ int mysql_create_function(THD *thd,udf_func *udf) ...@@ -422,10 +434,12 @@ int mysql_create_function(THD *thd,udf_func *udf)
} }
if (!(dl = find_udf_dl(udf->dl))) if (!(dl = find_udf_dl(udf->dl)))
{ {
if (!(dl = dlopen(udf->dl, RTLD_NOW))) char dlpath[FN_REFLEN];
strxnmov(dlpath, sizeof(dlpath) - 1, opt_plugin_dir, "/", udf->dl, NullS);
if (!(dl = dlopen(dlpath, RTLD_NOW)))
{ {
DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)", DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)",
udf->dl, errno, dlerror())); udf->dl, errno, dlerror()));
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), my_error(ER_CANT_OPEN_LIBRARY, MYF(0),
udf->dl, errno, dlerror()); udf->dl, errno, dlerror());
goto err; goto err;
......
...@@ -31,6 +31,14 @@ static handler *blackhole_create_handler(handlerton *hton, ...@@ -31,6 +31,14 @@ static handler *blackhole_create_handler(handlerton *hton,
} }
/* Static declarations for shared structures */
static pthread_mutex_t blackhole_mutex;
static HASH blackhole_open_tables;
static st_blackhole_share *get_share(const char *table_name);
static void free_share(st_blackhole_share *share);
/***************************************************************************** /*****************************************************************************
** BLACKHOLE tables ** BLACKHOLE tables
*****************************************************************************/ *****************************************************************************/
...@@ -53,15 +61,18 @@ const char **ha_blackhole::bas_ext() const ...@@ -53,15 +61,18 @@ const char **ha_blackhole::bas_ext() const
int ha_blackhole::open(const char *name, int mode, uint test_if_locked) int ha_blackhole::open(const char *name, int mode, uint test_if_locked)
{ {
DBUG_ENTER("ha_blackhole::open"); DBUG_ENTER("ha_blackhole::open");
thr_lock_init(&thr_lock);
thr_lock_data_init(&thr_lock,&lock,NULL); if (!(share= get_share(name)))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
thr_lock_data_init(&share->lock, &lock, NULL);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int ha_blackhole::close(void) int ha_blackhole::close(void)
{ {
DBUG_ENTER("ha_blackhole::close"); DBUG_ENTER("ha_blackhole::close");
thr_lock_delete(&thr_lock); free_share(share);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -136,17 +147,39 @@ int ha_blackhole::external_lock(THD *thd, int lock_type) ...@@ -136,17 +147,39 @@ int ha_blackhole::external_lock(THD *thd, int lock_type)
} }
uint ha_blackhole::lock_count(void) const
{
DBUG_ENTER("ha_blackhole::lock_count");
DBUG_RETURN(0);
}
THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd, THR_LOCK_DATA **ha_blackhole::store_lock(THD *thd,
THR_LOCK_DATA **to, THR_LOCK_DATA **to,
enum thr_lock_type lock_type) enum thr_lock_type lock_type)
{ {
DBUG_ENTER("ha_blackhole::store_lock"); DBUG_ENTER("ha_blackhole::store_lock");
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
{
/*
Here is where we get into the guts of a row level lock.
If TL_UNLOCK is set
If we are not doing a LOCK TABLE or DISCARD/IMPORT
TABLESPACE, then allow multiple writers
*/
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
lock_type <= TL_WRITE) && !thd_in_lock_tables(thd)
&& !thd_tablespace_op(thd))
lock_type = TL_WRITE_ALLOW_WRITE;
/*
In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
to t2. Convert the lock to a normal read lock to allow
concurrent inserts to t2.
*/
if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd))
lock_type = TL_READ;
lock.type= lock_type;
}
*to++= &lock;
DBUG_RETURN(to); DBUG_RETURN(to);
} }
...@@ -204,6 +237,63 @@ int ha_blackhole::index_last(byte * buf) ...@@ -204,6 +237,63 @@ int ha_blackhole::index_last(byte * buf)
DBUG_RETURN(HA_ERR_END_OF_FILE); DBUG_RETURN(HA_ERR_END_OF_FILE);
} }
static st_blackhole_share *get_share(const char *table_name)
{
st_blackhole_share *share;
uint length;
length= (uint) strlen(table_name);
pthread_mutex_lock(&blackhole_mutex);
if (!(share= (st_blackhole_share*) hash_search(&blackhole_open_tables,
(byte*) table_name, length)))
{
if (!(share= (st_blackhole_share*) my_malloc(sizeof(st_blackhole_share) +
length,
MYF(MY_WME | MY_ZEROFILL))))
goto error;
share->table_name_length= length;
strmov(share->table_name, table_name);
if (my_hash_insert(&blackhole_open_tables, (byte*) share))
{
my_free((gptr) share, MYF(0));
share= NULL;
goto error;
}
thr_lock_init(&share->lock);
}
share->use_count++;
error:
pthread_mutex_unlock(&blackhole_mutex);
return share;
}
static void free_share(st_blackhole_share *share)
{
pthread_mutex_lock(&blackhole_mutex);
if (!--share->use_count)
hash_delete(&blackhole_open_tables, (byte*) share);
pthread_mutex_unlock(&blackhole_mutex);
}
static void blackhole_free_key(st_blackhole_share *share)
{
thr_lock_delete(&share->lock);
my_free((gptr) share, MYF(0));
}
static byte* blackhole_get_key(st_blackhole_share *share, uint *length,
my_bool not_used __attribute__((unused)))
{
*length= share->table_name_length;
return (byte*) share->table_name;
}
static int blackhole_init(void *p) static int blackhole_init(void *p)
{ {
handlerton *blackhole_hton; handlerton *blackhole_hton;
...@@ -212,6 +302,20 @@ static int blackhole_init(void *p) ...@@ -212,6 +302,20 @@ static int blackhole_init(void *p)
blackhole_hton->db_type= DB_TYPE_BLACKHOLE_DB; blackhole_hton->db_type= DB_TYPE_BLACKHOLE_DB;
blackhole_hton->create= blackhole_create_handler; blackhole_hton->create= blackhole_create_handler;
blackhole_hton->flags= HTON_CAN_RECREATE; blackhole_hton->flags= HTON_CAN_RECREATE;
VOID(pthread_mutex_init(&blackhole_mutex, MY_MUTEX_INIT_FAST));
(void) hash_init(&blackhole_open_tables, system_charset_info,32,0,0,
(hash_get_key) blackhole_get_key,
(hash_free_key) blackhole_free_key, 0);
return 0;
}
static int blackhole_fini(void *p)
{
hash_free(&blackhole_open_tables);
pthread_mutex_destroy(&blackhole_mutex);
return 0; return 0;
} }
...@@ -227,7 +331,7 @@ mysql_declare_plugin(blackhole) ...@@ -227,7 +331,7 @@ mysql_declare_plugin(blackhole)
"/dev/null storage engine (anything you write to it disappears)", "/dev/null storage engine (anything you write to it disappears)",
PLUGIN_LICENSE_GPL, PLUGIN_LICENSE_GPL,
blackhole_init, /* Plugin Init */ blackhole_init, /* Plugin Init */
NULL, /* Plugin Deinit */ blackhole_fini, /* Plugin Deinit */
0x0100 /* 1.0 */, 0x0100 /* 1.0 */,
NULL, /* status variables */ NULL, /* status variables */
NULL, /* system variables */ NULL, /* system variables */
......
...@@ -17,6 +17,17 @@ ...@@ -17,6 +17,17 @@
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
/*
Shared structure for correct LOCK operation
*/
struct st_blackhole_share {
THR_LOCK lock;
uint use_count;
uint table_name_length;
char table_name[1];
};
/* /*
Class definition for the blackhole storage engine Class definition for the blackhole storage engine
"Dumbest named feature ever" "Dumbest named feature ever"
...@@ -24,7 +35,7 @@ ...@@ -24,7 +35,7 @@
class ha_blackhole: public handler class ha_blackhole: public handler
{ {
THR_LOCK_DATA lock; /* MySQL lock */ THR_LOCK_DATA lock; /* MySQL lock */
THR_LOCK thr_lock; st_blackhole_share *share;
public: public:
ha_blackhole(handlerton *hton, TABLE_SHARE *table_arg); ha_blackhole(handlerton *hton, TABLE_SHARE *table_arg);
...@@ -76,7 +87,6 @@ class ha_blackhole: public handler ...@@ -76,7 +87,6 @@ class ha_blackhole: public handler
void position(const byte *record); void position(const byte *record);
int info(uint flag); int info(uint flag);
int external_lock(THD *thd, int lock_type); int external_lock(THD *thd, int lock_type);
uint lock_count(void) const;
int create(const char *name, TABLE *table_arg, int create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *create_info); HA_CREATE_INFO *create_info);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **store_lock(THD *thd,
......
...@@ -1263,6 +1263,7 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -1263,6 +1263,7 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
ulonglong map; ulonglong map;
TABLE_LIST *table_list= table->pos_in_table_list; TABLE_LIST *table_list= table->pos_in_table_list;
my_bool ignore_leaves= table_list->ignore_leaves; my_bool ignore_leaves= table_list->ignore_leaves;
char buf[ERRMSGSIZE+20];
DBUG_ENTER("ha_myisam::preload_keys"); DBUG_ENTER("ha_myisam::preload_keys");
...@@ -1294,7 +1295,6 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -1294,7 +1295,6 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
errmsg= "Failed to allocate buffer"; errmsg= "Failed to allocate buffer";
break; break;
default: default:
char buf[ERRMSGSIZE+20];
my_snprintf(buf, ERRMSGSIZE, my_snprintf(buf, ERRMSGSIZE,
"Failed to read from index file (errno: %d)", my_errno); "Failed to read from index file (errno: %d)", my_errno);
errmsg= buf; errmsg= buf;
......
...@@ -335,7 +335,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info) ...@@ -335,7 +335,7 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
flush_key_blocks(info->s->key_cache, flush_key_blocks(info->s->key_cache,
info->s->kfile, FLUSH_FORCE_WRITE); info->s->kfile, FLUSH_FORCE_WRITE);
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)); size= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
if ((skr=(my_off_t) info->state->key_file_length) != size) if ((skr=(my_off_t) info->state->key_file_length) != size)
{ {
/* Don't give error if file generated by myisampack */ /* Don't give error if file generated by myisampack */
...@@ -595,7 +595,8 @@ static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo, ...@@ -595,7 +595,8 @@ static int chk_index_down(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
{ {
/* purecov: begin tested */ /* purecov: begin tested */
/* Give it a chance to fit in the real file size. */ /* Give it a chance to fit in the real file size. */
my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(0)); my_off_t max_length= my_seek(info->s->kfile, 0L, MY_SEEK_END,
MYF(MY_THREADSAFE));
mi_check_print_error(param, "Invalid key block position: %s " mi_check_print_error(param, "Invalid key block position: %s "
"key block size: %u file_length: %s", "key block size: %u file_length: %s",
llstr(page, llbuff), keyinfo->block_length, llstr(page, llbuff), keyinfo->block_length,
...@@ -4080,10 +4081,10 @@ int test_if_almost_full(MI_INFO *info) ...@@ -4080,10 +4081,10 @@ int test_if_almost_full(MI_INFO *info)
{ {
if (info->s->options & HA_OPTION_COMPRESS_RECORD) if (info->s->options & HA_OPTION_COMPRESS_RECORD)
return 0; return 0;
return (my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0))/10*9 > return my_seek(info->s->kfile, 0L, MY_SEEK_END, MYF(MY_THREADSAFE)) / 10 * 9 >
(my_off_t) (info->s->base.max_key_file_length) || (my_off_t) info->s->base.max_key_file_length ||
my_seek(info->dfile,0L,MY_SEEK_END,MYF(0))/10*9 > my_seek(info->dfile, 0L, MY_SEEK_END, MYF(0)) / 10 * 9 >
(my_off_t) info->s->base.max_data_file_length); (my_off_t) info->s->base.max_data_file_length;
} }
/* Recreate table with bigger more alloced record-data */ /* Recreate table with bigger more alloced record-data */
......
...@@ -55,12 +55,17 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves) ...@@ -55,12 +55,17 @@ int mi_preload(MI_INFO *info, ulonglong key_map, my_bool ignore_leaves)
block_length= keyinfo[0].block_length; block_length= keyinfo[0].block_length;
/* Check whether all indexes use the same block size */ if (ignore_leaves)
for (i= 1 ; i < keys ; i++)
{ {
if (keyinfo[i].block_length != block_length) /* Check whether all indexes use the same block size */
DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE); for (i= 1 ; i < keys ; i++)
{
if (keyinfo[i].block_length != block_length)
DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE);
}
} }
else
block_length= share->key_cache->key_cache_block_size;
length= info->preload_buff_size/block_length * block_length; length= info->preload_buff_size/block_length * block_length;
set_if_bigger(length, block_length); set_if_bigger(length, block_length);
......
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