1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge branch '10.1' into 10.2

This commit is contained in:
Sergei Golubchik
2018-02-22 08:39:24 +01:00
15 changed files with 318 additions and 73 deletions

View File

@ -160,6 +160,7 @@ INCLUDE(plugin)
INCLUDE(install_macros) INCLUDE(install_macros)
INCLUDE(systemd) INCLUDE(systemd)
INCLUDE(mysql_add_executable) INCLUDE(mysql_add_executable)
INCLUDE(compile_flags)
INCLUDE(crc32-vpmsum) INCLUDE(crc32-vpmsum)
# Handle options # Handle options

View File

@ -186,8 +186,10 @@ sub create_process {
# it and any childs(that hasn't changed group themself) # it and any childs(that hasn't changed group themself)
setpgrp(0,0) if $opts{setpgrp}; setpgrp(0,0) if $opts{setpgrp};
if ( $output and !open(STDOUT, $open_mode, $output) ) { if ( $output ) {
croak("can't redirect STDOUT to '$output': $!"); close STDOUT;
open(STDOUT, $open_mode, $output)
or croak "can't redirect STDOUT to '$output': $!";
} }
if ( $error ) { if ( $error ) {
@ -196,8 +198,10 @@ sub create_process {
croak("can't dup STDOUT: $!"); croak("can't dup STDOUT: $!");
} }
} }
elsif ( ! open(STDERR, $open_mode, $error) ) { else {
croak("can't redirect STDERR to '$error': $!"); close STDERR;
open(STDERR, $open_mode, $error)
or croak "can't redirect STDERR to '$error': $!";
} }
} }

23
mysql-test/lib/My/Tee.pm Normal file
View File

@ -0,0 +1,23 @@
package My::Tee;
# see PerlIO::via
our $copyfh;
sub PUSHED
{
open($copyfh, '>', "$::opt_vardir/log/stdout.log")
or die "open(>$::opt_vardir/log/stdout.log): $!"
unless $copyfh;
bless { }, shift;
}
sub WRITE
{
my ($obj, $buf, $fh) = @_;
print $fh $buf;
print $copyfh $buf;
return length($buf);
}
1;

View File

@ -91,6 +91,7 @@ use My::Platform;
use My::SafeProcess; use My::SafeProcess;
use My::ConfigFactory; use My::ConfigFactory;
use My::Options; use My::Options;
use My::Tee;
use My::Find; use My::Find;
use My::SysInfo; use My::SysInfo;
use My::CoreDump; use My::CoreDump;
@ -384,6 +385,11 @@ sub main {
initialize_servers(); initialize_servers();
init_timers(); init_timers();
unless (IS_WINDOWS) {
binmode(STDOUT,":via(My::Tee)") or die "binmode(STDOUT, :via(My::Tee)):$!";
binmode(STDERR,":via(My::Tee)") or die "binmode(STDERR, :via(My::Tee)):$!";
}
mtr_report("Checking supported features..."); mtr_report("Checking supported features...");
executable_setup(); executable_setup();
@ -6253,7 +6259,8 @@ sub xterm_stat {
my $done = $num_tests - $left; my $done = $num_tests - $left;
my $spent = time - $^T; my $spent = time - $^T;
printf "\e];mtr: spent %s on %d tests. %s (%d tests) left\a", syswrite STDOUT, sprintf
"\e];mtr: spent %s on %d tests. %s (%d tests) left\a",
time_format($spent), $done, time_format($spent), $done,
time_format($spent/$done * $left), $left; time_format($spent/$done * $left), $left;
} }

View File

@ -134,6 +134,13 @@ count(*)
select count(*) from innodb_page_compressed9 where c1 < 500000; select count(*) from innodb_page_compressed9 where c1 < 500000;
count(*) count(*)
2000 2000
flush tables innodb_page_compressed1, innodb_page_compressed2,
innodb_page_compressed3, innodb_page_compressed4,
innodb_page_compressed5, innodb_page_compressed6,
innodb_page_compressed7, innodb_page_compressed8,
innodb_page_compressed9 for export;
unlock tables;
# Wait until dirty pages are compressed and encrypted
SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_encrypted'; SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_encrypted';
variable_value > 0 variable_value > 0
1 1
@ -151,9 +158,14 @@ update innodb_page_compressed6 set c1 = c1 + 1;
update innodb_page_compressed7 set c1 = c1 + 1; update innodb_page_compressed7 set c1 = c1 + 1;
update innodb_page_compressed8 set c1 = c1 + 1; update innodb_page_compressed8 set c1 = c1 + 1;
update innodb_page_compressed9 set c1 = c1 + 1; update innodb_page_compressed9 set c1 = c1 + 1;
SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_encrypted'; flush tables innodb_page_compressed1, innodb_page_compressed2,
variable_value > 0 innodb_page_compressed3, innodb_page_compressed4,
1 innodb_page_compressed5, innodb_page_compressed6,
innodb_page_compressed7, innodb_page_compressed8,
innodb_page_compressed9 for export;
unlock tables;
# Wait until dirty pages are compressed and encrypted 2
unlock tables;
SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decrypted'; SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decrypted';
variable_value > 0 variable_value > 0
1 1

View File

@ -73,6 +73,15 @@ select count(*) from innodb_page_compressed7 where c1 < 500000;
select count(*) from innodb_page_compressed8 where c1 < 500000; select count(*) from innodb_page_compressed8 where c1 < 500000;
select count(*) from innodb_page_compressed9 where c1 < 500000; select count(*) from innodb_page_compressed9 where c1 < 500000;
flush tables innodb_page_compressed1, innodb_page_compressed2,
innodb_page_compressed3, innodb_page_compressed4,
innodb_page_compressed5, innodb_page_compressed6,
innodb_page_compressed7, innodb_page_compressed8,
innodb_page_compressed9 for export;
unlock tables;
--echo # Wait until dirty pages are compressed and encrypted
let $wait_condition= select variable_value > 0 from information_schema.global_status where variable_name = 'INNODB_NUM_PAGES_PAGE_COMPRESSED'; let $wait_condition= select variable_value > 0 from information_schema.global_status where variable_name = 'INNODB_NUM_PAGES_PAGE_COMPRESSED';
--source include/wait_condition.inc --source include/wait_condition.inc
let $wait_condition= select variable_value > 0 from information_schema.global_status where variable_name = 'INNODB_NUM_PAGES_ENCRYPTED'; let $wait_condition= select variable_value > 0 from information_schema.global_status where variable_name = 'INNODB_NUM_PAGES_ENCRYPTED';
@ -96,12 +105,20 @@ update innodb_page_compressed7 set c1 = c1 + 1;
update innodb_page_compressed8 set c1 = c1 + 1; update innodb_page_compressed8 set c1 = c1 + 1;
update innodb_page_compressed9 set c1 = c1 + 1; update innodb_page_compressed9 set c1 = c1 + 1;
let $wait_condition= select variable_value > 0 from information_schema.global_status where variable_name = 'INNODB_NUM_PAGES_ENCRYPTED'; flush tables innodb_page_compressed1, innodb_page_compressed2,
--source include/wait_condition.inc innodb_page_compressed3, innodb_page_compressed4,
innodb_page_compressed5, innodb_page_compressed6,
innodb_page_compressed7, innodb_page_compressed8,
innodb_page_compressed9 for export;
unlock tables;
--echo # Wait until dirty pages are compressed and encrypted 2
let $wait_condition= select variable_value > 0 from information_schema.global_status where variable_name = 'INNODB_NUM_PAGES_PAGE_COMPRESSED'; let $wait_condition= select variable_value > 0 from information_schema.global_status where variable_name = 'INNODB_NUM_PAGES_PAGE_COMPRESSED';
--source include/wait_condition.inc --source include/wait_condition.inc
unlock tables;
let $wait_condition= select variable_value > 0 from information_schema.global_status where variable_name = 'INNODB_NUM_PAGES_DECRYPTED';
--source include/wait_condition.inc
SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_encrypted';
SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decrypted'; SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_decrypted';
SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_page_compressed'; SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_page_compressed';
SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_page_decompressed'; SELECT variable_value > 0 FROM information_schema.global_status WHERE variable_name = 'innodb_num_pages_page_decompressed';

View File

@ -61,3 +61,6 @@ MW-328B: MDEV-13549 Galera test failures 10.1
MW-328: MDEV-13549 Galera test failures 10.1 MW-328: MDEV-13549 Galera test failures 10.1
galera_suspend_slave: MDEV-13549 Galera test failures 10.1 galera_suspend_slave: MDEV-13549 Galera test failures 10.1
galera_ist_progress: MDEV-15236 galera_ist_progress fails when trying to read transfer status galera_ist_progress: MDEV-15236 galera_ist_progress fails when trying to read transfer status
galera_gtid : MDEV-13549 Galera test failures 10.1
galera_gtid_slave : MDEV-13549 Galera test failures 10.1
galera_unicode_identifiers : MDEV-13549 Galera test failures 10.1

View File

@ -1,4 +1,5 @@
--source include/have_partition.inc --source include/have_partition.inc
--source include/have_symlink.inc
--let $engine=MyISAM --let $engine=MyISAM
--source inc/part_alter_values.inc --source inc/part_alter_values.inc

View File

@ -644,7 +644,7 @@ wait_for_listen()
for i in {1..300} for i in {1..300}
do do
LSOF_OUT=$(lsof -sTCP:LISTEN -i TCP:${PORT} -a -c nc -c socat -F c) LSOF_OUT=$(lsof -sTCP:LISTEN -i TCP:${PORT} -a -c nc -c socat -F c 2> /dev/null || :)
[ -n "${LSOF_OUT}" ] && break [ -n "${LSOF_OUT}" ] && break
sleep 0.2 sleep 0.2
done done

View File

@ -6025,12 +6025,14 @@ int mysqld_main(int argc, char **argv)
mysqld_port, MYSQL_COMPILATION_COMMENT); mysqld_port, MYSQL_COMPILATION_COMMENT);
} }
#ifndef _WIN32
// try to keep fd=0 busy // try to keep fd=0 busy
if (!freopen(IF_WIN("NUL","/dev/null"), "r", stdin)) if (!freopen("/dev/null", "r", stdin))
{ {
// fall back on failure // fall back on failure
fclose(stdin); fclose(stdin);
} }
#endif
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY) #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
Service.SetRunning(); Service.SetRunning();

View File

@ -2383,23 +2383,6 @@ end:
} }
bool partition_info::error_if_requires_values() const
{
switch (part_type) {
case NOT_A_PARTITION:
case HASH_PARTITION:
break;
case RANGE_PARTITION:
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN");
return true;
case LIST_PARTITION:
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN");
return true;
}
return false;
}
/** /**
Fix partition data from parser. Fix partition data from parser.
@ -2893,3 +2876,19 @@ bool check_partition_dirs(partition_info *part_info)
} }
#endif /* WITH_PARTITION_STORAGE_ENGINE */ #endif /* WITH_PARTITION_STORAGE_ENGINE */
bool partition_info::error_if_requires_values() const
{
switch (part_type) {
case NOT_A_PARTITION:
case HASH_PARTITION:
break;
case RANGE_PARTITION:
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN");
return true;
case LIST_PARTITION:
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN");
return true;
}
return false;
}

View File

@ -1754,11 +1754,13 @@ bool ha_connect::CheckVirtualIndex(TABLE_SHARE *s)
bool ha_connect::IsPartitioned(void) bool ha_connect::IsPartitioned(void)
{ {
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (tshp) if (tshp)
return tshp->partition_info_str_len > 0; return tshp->partition_info_str_len > 0;
else if (table && table->part_info) else if (table && table->part_info)
return true; return true;
else else
#endif
return false; return false;
} // end of IsPartitioned } // end of IsPartitioned
@ -6165,8 +6167,10 @@ int ha_connect::create(const char *name, TABLE *table_arg,
TABLE *st= table; // Probably unuseful TABLE *st= table; // Probably unuseful
THD *thd= ha_thd(); THD *thd= ha_thd();
LEX_STRING cnc = table_arg->s->connect_string; LEX_STRING cnc = table_arg->s->connect_string;
#if defined(WITH_PARTITION_STORAGE_ENGINE) #ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *part_info= table_arg->part_info; partition_info *part_info= table_arg->part_info;
#else
#define part_info 0
#endif // WITH_PARTITION_STORAGE_ENGINE #endif // WITH_PARTITION_STORAGE_ENGINE
xp= GetUser(thd, xp); xp= GetUser(thd, xp);
PGLOBAL g= xp->g; PGLOBAL g= xp->g;
@ -6268,9 +6272,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
// fall through // fall through
case TAB_MYSQL: case TAB_MYSQL:
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (!part_info) if (!part_info)
#endif // WITH_PARTITION_STORAGE_ENGINE
{const char *src= options->srcdef; {const char *src= options->srcdef;
PCSZ host, db, tab= options->tabname; PCSZ host, db, tab= options->tabname;
int port; int port;
@ -6534,7 +6536,6 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} else } else
lwt[i]= tolower(options->type[i]); lwt[i]= tolower(options->type[i]);
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info) { if (part_info) {
char *p; char *p;
@ -6544,7 +6545,6 @@ int ha_connect::create(const char *name, TABLE *table_arg,
strcat(strcat(strcpy(buf, p), "."), lwt); strcat(strcat(strcpy(buf, p), "."), lwt);
*p= 0; *p= 0;
} else { } else {
#endif // WITH_PARTITION_STORAGE_ENGINE
strcat(strcat(strcpy(buf, GetTableName()), "."), lwt); strcat(strcat(strcpy(buf, GetTableName()), "."), lwt);
sprintf(g->Message, "No file name. Table will use %s", buf); sprintf(g->Message, "No file name. Table will use %s", buf);
@ -6552,9 +6552,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message); push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
strcat(strcat(strcpy(dbpath, "./"), table->s->db.str), "/"); strcat(strcat(strcpy(dbpath, "./"), table->s->db.str), "/");
#if defined(WITH_PARTITION_STORAGE_ENGINE)
} // endif part_info } // endif part_info
#endif // WITH_PARTITION_STORAGE_ENGINE
PlugSetPath(fn, buf, dbpath); PlugSetPath(fn, buf, dbpath);
@ -6619,11 +6617,9 @@ int ha_connect::create(const char *name, TABLE *table_arg,
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0,
"Unexpected command in create, please contact CONNECT team"); "Unexpected command in create, please contact CONNECT team");
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info && !inward) if (part_info && !inward)
strncpy(partname, decode(g, strrchr(name, '#') + 1), sizeof(partname) - 1); strncpy(partname, decode(g, strrchr(name, '#') + 1), sizeof(partname) - 1);
// strcpy(partname, part_info->curr_part_elem->partition_name); // strcpy(partname, part_info->curr_part_elem->partition_name);
#endif // WITH_PARTITION_STORAGE_ENGINE
if (g->Alchecked == 0 && if (g->Alchecked == 0 &&
(!IsFileType(type) || FileExists(options->filename, false))) { (!IsFileType(type) || FileExists(options->filename, false))) {
@ -6659,12 +6655,10 @@ int ha_connect::create(const char *name, TABLE *table_arg,
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
rc = HA_ERR_INTERNAL_ERROR; rc = HA_ERR_INTERNAL_ERROR;
} else if (cat) { } else if (cat) {
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info) if (part_info)
strncpy(partname, strncpy(partname,
decode(g, strrchr(name, (inward ? slash : '#')) + 1), decode(g, strrchr(name, (inward ? slash : '#')) + 1),
sizeof(partname) - 1); sizeof(partname) - 1);
#endif // WITH_PARTITION_STORAGE_ENGINE
if ((rc= optimize(table->in_use, NULL))) { if ((rc= optimize(table->in_use, NULL))) {
htrc("Create rc=%d %s\n", rc, g->Message); htrc("Create rc=%d %s\n", rc, g->Message);

View File

@ -145,6 +145,11 @@ static my_bool _ma_bitmap_create_missing(MARIA_HA *info,
MARIA_FILE_BITMAP *bitmap, MARIA_FILE_BITMAP *bitmap,
pgcache_page_no_t page); pgcache_page_no_t page);
static void _ma_bitmap_unpin_all(MARIA_SHARE *share); static void _ma_bitmap_unpin_all(MARIA_SHARE *share);
#ifndef DBUG_OFF
static void _ma_check_bitmap(MARIA_FILE_BITMAP *bitmap);
#else
#define _ma_check_bitmap(A) do { } while(0)
#endif
/* Write bitmap page to key cache */ /* Write bitmap page to key cache */
@ -267,6 +272,13 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file,
bitmap->sizes[6]= max_page_size - max_page_size * 80 / 100; bitmap->sizes[6]= max_page_size - max_page_size * 80 / 100;
bitmap->sizes[7]= 0; bitmap->sizes[7]= 0;
/*
If a record size will fit into the smallest empty page, return first
found page in find_head()
*/
if (bitmap->sizes[3] >= share->base.max_pack_length)
bitmap->return_first_match= 1;
mysql_mutex_init(key_SHARE_BITMAP_lock, mysql_mutex_init(key_SHARE_BITMAP_lock,
&share->bitmap.bitmap_lock, MY_MUTEX_INIT_SLOW); &share->bitmap.bitmap_lock, MY_MUTEX_INIT_SLOW);
mysql_cond_init(key_SHARE_BITMAP_cond, mysql_cond_init(key_SHARE_BITMAP_cond,
@ -677,7 +689,8 @@ void _ma_bitmap_delete_all(MARIA_SHARE *share)
bzero(bitmap->map, bitmap->block_size); bzero(bitmap->map, bitmap->block_size);
bitmap->changed= 1; bitmap->changed= 1;
bitmap->page= 0; bitmap->page= 0;
bitmap->used_size= bitmap->total_size= bitmap->max_total_size; bitmap->used_size= bitmap->full_tail_size= bitmap->full_head_size= 0;
bitmap->total_size= bitmap->max_total_size;
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -715,6 +728,7 @@ void _ma_bitmap_reset_cache(MARIA_SHARE *share)
*/ */
bitmap->page= ((pgcache_page_no_t) 0) - bitmap->pages_covered; bitmap->page= ((pgcache_page_no_t) 0) - bitmap->pages_covered;
bitmap->used_size= bitmap->total_size= bitmap->max_total_size; bitmap->used_size= bitmap->total_size= bitmap->max_total_size;
bitmap->full_head_size= bitmap->full_tail_size= bitmap->max_total_size;
bfill(bitmap->map, share->block_size, 255); bfill(bitmap->map, share->block_size, 255);
#ifndef DBUG_OFF #ifndef DBUG_OFF
memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size); memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size);
@ -1016,9 +1030,6 @@ static void adjust_total_size(MARIA_HA *info, pgcache_page_no_t page)
bitmap Bitmap handler bitmap Bitmap handler
page Page to read page Page to read
TODO
Update 'bitmap->used_size' to real size of used bitmap
NOTE NOTE
We don't always have share->bitmap.bitmap_lock here We don't always have share->bitmap.bitmap_lock here
(when called from_ma_check_bitmap_data() for example). (when called from_ma_check_bitmap_data() for example).
@ -1035,6 +1046,9 @@ static my_bool _ma_read_bitmap_page(MARIA_HA *info,
MARIA_SHARE *share= info->s; MARIA_SHARE *share= info->s;
my_bool res; my_bool res;
DBUG_ENTER("_ma_read_bitmap_page"); DBUG_ENTER("_ma_read_bitmap_page");
DBUG_PRINT("enter", ("page: %lld data_file_length: %lld",
(longlong) page,
(longlong) share->state.state.data_file_length));
DBUG_ASSERT(page % bitmap->pages_covered == 0); DBUG_ASSERT(page % bitmap->pages_covered == 0);
DBUG_ASSERT(!bitmap->changed); DBUG_ASSERT(!bitmap->changed);
@ -1049,13 +1063,22 @@ static my_bool _ma_read_bitmap_page(MARIA_HA *info,
} }
adjust_total_size(info, page); adjust_total_size(info, page);
bitmap->used_size= bitmap->total_size; bitmap->full_head_size= bitmap->full_tail_size= 0;
DBUG_ASSERT(share->pagecache->block_size == bitmap->block_size); DBUG_ASSERT(share->pagecache->block_size == bitmap->block_size);
res= pagecache_read(share->pagecache, res= pagecache_read(share->pagecache,
&bitmap->file, page, 0, &bitmap->file, page, 0,
bitmap->map, PAGECACHE_PLAIN_PAGE, bitmap->map, PAGECACHE_PLAIN_PAGE,
PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == NULL; PAGECACHE_LOCK_LEFT_UNLOCKED, 0) == NULL;
if (!res)
{
/* Calculate used_size */
const uchar *data, *end= bitmap->map;
for (data= bitmap->map + bitmap->total_size; --data >= end && *data == 0; )
{}
bitmap->used_size= (uint) ((data + 1) - end);
DBUG_ASSERT(bitmap->used_size <= bitmap->total_size);
}
/* /*
We can't check maria_bitmap_marker here as if the bitmap page We can't check maria_bitmap_marker here as if the bitmap page
previously had a true checksum and the user switched mode to not checksum previously had a true checksum and the user switched mode to not checksum
@ -1067,7 +1090,10 @@ static my_bool _ma_read_bitmap_page(MARIA_HA *info,
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (!res) if (!res)
{
memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size); memcpy(bitmap->map + bitmap->block_size, bitmap->map, bitmap->block_size);
_ma_check_bitmap(bitmap);
}
#endif #endif
DBUG_RETURN(res); DBUG_RETURN(res);
} }
@ -1097,6 +1123,8 @@ static my_bool _ma_change_bitmap_page(MARIA_HA *info,
{ {
DBUG_ENTER("_ma_change_bitmap_page"); DBUG_ENTER("_ma_change_bitmap_page");
_ma_check_bitmap(bitmap);
/* /*
We have to mark the file changed here, as otherwise the following We have to mark the file changed here, as otherwise the following
read/write to pagecache may force a page out from this file, which would read/write to pagecache may force a page out from this file, which would
@ -1228,6 +1256,9 @@ static void fill_block(MARIA_FILE_BITMAP *bitmap,
This is defined as the first page of the set of pages This is defined as the first page of the set of pages
with the smallest free space that can hold 'size'. with the smallest free space that can hold 'size'.
NOTES
Updates bitmap->full_head_size while scanning data
RETURN RETURN
0 ok (block is updated) 0 ok (block is updated)
1 error (no space in bitmap; block is not touched) 1 error (no space in bitmap; block is not touched)
@ -1238,10 +1269,11 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
MARIA_BITMAP_BLOCK *block) MARIA_BITMAP_BLOCK *block)
{ {
uint min_bits= size_to_head_pattern(bitmap, size); uint min_bits= size_to_head_pattern(bitmap, size);
uchar *data= bitmap->map, *end= data + bitmap->used_size; uchar *data, *end;
uchar *best_data= 0; uchar *best_data= 0;
uint best_bits= (uint) -1, UNINIT_VAR(best_pos); uint best_bits= (uint) -1, UNINIT_VAR(best_pos);
uint first_pattern= 0; /* if doing insert_order */ my_bool first_pattern= 0; /* if doing insert_order */
my_bool first_found= 1;
MARIA_SHARE *share= bitmap->share; MARIA_SHARE *share= bitmap->share;
my_bool insert_order= my_bool insert_order=
MY_TEST(share->base.extra_options & MA_EXTRA_OPTIONS_INSERT_ORDER); MY_TEST(share->base.extra_options & MA_EXTRA_OPTIONS_INSERT_ORDER);
@ -1249,16 +1281,19 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
DBUG_ASSERT(size <= FULL_PAGE_SIZE(share)); DBUG_ASSERT(size <= FULL_PAGE_SIZE(share));
end= bitmap->map + bitmap->used_size;
if (insert_order && bitmap->page == share->last_insert_bitmap) if (insert_order && bitmap->page == share->last_insert_bitmap)
{ {
uint last_insert_page= share->last_insert_page; uint last_insert_page= share->last_insert_page;
uint byte= 6 * (last_insert_page / 16); uint byte= 6 * (last_insert_page / 16);
first_pattern= last_insert_page % 16; first_pattern= last_insert_page % 16;
DBUG_ASSERT(data + byte < end); data= bitmap->map+byte;
data+= byte; DBUG_ASSERT(data <= end);
} }
else
data= bitmap->map + (bitmap->full_head_size/6)*6;
for (; data < end; data+= 6) for (; data < end; data+= 6, first_pattern= 0)
{ {
ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */ ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */
uint i; uint i;
@ -1271,17 +1306,24 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
*/ */
if ((!bits && best_data) || if ((!bits && best_data) ||
((bits & 04444444444444444LL) == 04444444444444444LL)) ((bits & 04444444444444444LL) == 04444444444444444LL))
{
first_pattern= 0; // always restart from 0 when moving to new 6-byte
continue; continue;
}
for (i= first_pattern, bits >>= (3 * first_pattern); i < 16 ; for (i= first_pattern, bits >>= (3 * first_pattern); i < 16 ;
i++, bits >>= 3) i++, bits >>= 3)
{ {
uint pattern= (uint) (bits & 7); uint pattern= (uint) (bits & 7);
if (pattern <= 3) /* Room for more data */
{
if (first_found)
{
first_found= 0;
bitmap->full_head_size= (uint)(data - bitmap->map);
}
}
if (pattern <= min_bits) if (pattern <= min_bits)
{ {
/* There is enough space here */ /* There is enough space here, check if we have found better */
if ((int) pattern > (int) best_bits) if ((int) pattern > (int) best_bits)
{ {
/* /*
@ -1292,23 +1334,32 @@ static my_bool allocate_head(MARIA_FILE_BITMAP *bitmap, uint size,
best_bits= pattern; best_bits= pattern;
best_data= data; best_data= data;
best_pos= i; best_pos= i;
if (pattern == min_bits) if (pattern == min_bits || bitmap->return_first_match)
goto found; /* Best possible match */ goto found; /* Best possible match */
} }
} }
} }
first_pattern= 0; // always restart from 0 when moving to new 6-byte
} }
if (!best_data) /* Found no place */ if (!best_data) /* Found no place */
{ {
if (data >= bitmap->map + bitmap->total_size) if (data >= bitmap->map + bitmap->total_size)
DBUG_RETURN(1); /* No space in bitmap */ DBUG_RETURN(1); /* No space in bitmap */
DBUG_ASSERT(uint6korr(data) == 0);
/* Allocate data at end of bitmap */ /* Allocate data at end of bitmap */
bitmap->used_size+= 6; bitmap->used_size= (uint) (data - bitmap->map) + 6;
set_if_smaller(bitmap->used_size, bitmap->total_size);
best_data= data; best_data= data;
best_pos= best_bits= 0; best_pos= best_bits= 0;
} }
else
{
/*
This is not stricly needed as used_size should be alligned on 6,
but for easier debugging lets try to keep it more accurate
*/
uint position= (uint) (best_data - bitmap->map) + 6;
set_if_bigger(bitmap->used_size, position);
}
DBUG_ASSERT(bitmap->used_size <= bitmap->total_size);
found: found:
if (insert_order) if (insert_order)
@ -1341,12 +1392,15 @@ static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size,
MARIA_BITMAP_BLOCK *block) MARIA_BITMAP_BLOCK *block)
{ {
uint min_bits= size_to_tail_pattern(bitmap, size); uint min_bits= size_to_tail_pattern(bitmap, size);
uchar *data= bitmap->map, *end= data + bitmap->used_size; uchar *data, *end, *best_data= 0;
uchar *best_data= 0; my_bool first_found= 1;
uint best_bits= (uint) -1, UNINIT_VAR(best_pos); uint best_bits= (uint) -1, UNINIT_VAR(best_pos);
DBUG_ENTER("allocate_tail"); DBUG_ENTER("allocate_tail");
DBUG_PRINT("enter", ("size: %u", size)); DBUG_PRINT("enter", ("size: %u", size));
data= bitmap->map + (bitmap->full_tail_size/6)*6;
end= bitmap->map + bitmap->used_size;
/* /*
We have to add DIR_ENTRY_SIZE here as this is not part of the data size We have to add DIR_ENTRY_SIZE here as this is not part of the data size
See call to allocate_tail() in find_tail(). See call to allocate_tail() in find_tail().
@ -1375,7 +1429,19 @@ static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size,
for (i= 0; i < 16; i++, bits >>= 3) for (i= 0; i < 16; i++, bits >>= 3)
{ {
uint pattern= (uint) (bits & 7); uint pattern= (uint) (bits & 7);
if (pattern <= min_bits && (!pattern || pattern >= 5))
if (pattern == 0 ||
(pattern > FULL_HEAD_PAGE && pattern < FULL_TAIL_PAGE))
{
/* There is room for tail data */
if (first_found)
{
first_found= 0;
bitmap->full_tail_size= (uint)(data - bitmap->map);
}
}
if (pattern <= min_bits && (!pattern || pattern > FULL_HEAD_PAGE))
{ {
if ((int) pattern > (int) best_bits) if ((int) pattern > (int) best_bits)
{ {
@ -1392,10 +1458,11 @@ static my_bool allocate_tail(MARIA_FILE_BITMAP *bitmap, uint size,
{ {
if (data >= bitmap->map + bitmap->total_size) if (data >= bitmap->map + bitmap->total_size)
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_ASSERT(uint6korr(data) == 0);
/* Allocate data at end of bitmap */ /* Allocate data at end of bitmap */
best_data= data; best_data= data;
bitmap->used_size+= 6; bitmap->used_size= (uint) (data - bitmap->map) + 6;
set_if_smaller(bitmap->used_size, bitmap->total_size); DBUG_ASSERT(bitmap->used_size <= bitmap->total_size);
best_pos= best_bits= 0; best_pos= best_bits= 0;
} }
@ -1434,8 +1501,7 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap,
ulong pages_needed, ulong pages_needed,
MARIA_BITMAP_BLOCK *block, my_bool full_page) MARIA_BITMAP_BLOCK *block, my_bool full_page)
{ {
uchar *data= bitmap->map, *data_end= data + bitmap->used_size; uchar *data, *data_end, *page_end;
uchar *page_end= data + bitmap->total_size;
uchar *best_data= 0; uchar *best_data= 0;
uint min_size; uint min_size;
uint best_area_size, UNINIT_VAR(best_prefix_area_size); uint best_area_size, UNINIT_VAR(best_prefix_area_size);
@ -1449,6 +1515,10 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap,
min_size= BLOB_SEGMENT_MIN_SIZE; min_size= BLOB_SEGMENT_MIN_SIZE;
best_area_size= ~(uint) 0; best_area_size= ~(uint) 0;
data= bitmap->map + (bitmap->full_head_size/6)*6;
data_end= bitmap->map + bitmap->used_size;
page_end= bitmap->map + bitmap->total_size;
for (; data < page_end; data+= 6) for (; data < page_end; data+= 6)
{ {
ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */ ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */
@ -1466,6 +1536,12 @@ static ulong allocate_full_pages(MARIA_FILE_BITMAP *bitmap,
if ((bits= uint6korr(data))) if ((bits= uint6korr(data)))
break; break;
} }
/*
Check if we are end of bitmap. In this case we know that
the rest of the bitmap is usable
*/
if (data >= data_end)
data= page_end;
area_size= (uint) (data - data_start) / 6 * 16; area_size= (uint) (data - data_start) / 6 * 16;
if (area_size >= best_area_size) if (area_size >= best_area_size)
continue; continue;
@ -1823,7 +1899,7 @@ static my_bool allocate_blobs(MARIA_HA *info, MARIA_ROW *row)
/* /*
Store in the bitmap the new size for a head page Reserve the current head page
SYNOPSIS SYNOPSIS
use_head() use_head()
@ -2225,7 +2301,7 @@ static my_bool set_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
pgcache_page_no_t page, uint fill_pattern) pgcache_page_no_t page, uint fill_pattern)
{ {
pgcache_page_no_t bitmap_page; pgcache_page_no_t bitmap_page;
uint offset_page, offset, tmp, org_tmp; uint offset_page, offset, tmp, org_tmp, used_offset;
uchar *data; uchar *data;
DBUG_ENTER("set_page_bits"); DBUG_ENTER("set_page_bits");
DBUG_ASSERT(fill_pattern <= 7); DBUG_ASSERT(fill_pattern <= 7);
@ -2237,6 +2313,7 @@ static my_bool set_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
/* Find page number from start of bitmap */ /* Find page number from start of bitmap */
offset_page= (uint) (page - bitmap->page - 1); offset_page= (uint) (page - bitmap->page - 1);
/* /*
Mark place used by reading/writing 2 bytes at a time to handle Mark place used by reading/writing 2 bytes at a time to handle
bitmaps in overlapping bytes bitmaps in overlapping bytes
@ -2248,11 +2325,37 @@ static my_bool set_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap,
tmp= (tmp & ~(7 << offset)) | (fill_pattern << offset); tmp= (tmp & ~(7 << offset)) | (fill_pattern << offset);
if (tmp == org_tmp) if (tmp == org_tmp)
DBUG_RETURN(0); /* No changes */ DBUG_RETURN(0); /* No changes */
int2store(data, tmp);
/*
Take care to not write bytes outside of bitmap.
fill_pattern is 3 bits, so we need to write two bytes
if bit position we write to is > (8-3)
*/
if (offset > 5)
int2store(data, tmp);
else
data[0]= tmp;
/*
Reset full_head_size or full_tail_size if we are releasing data before
it. Increase used_size if we are allocating data.
*/
used_offset= (uint) (data - bitmap->map);
if (fill_pattern < 4)
set_if_smaller(bitmap->full_head_size, used_offset);
if (fill_pattern == 0 || (fill_pattern > 4 && fill_pattern < 7))
set_if_smaller(bitmap->full_tail_size, used_offset);
if (fill_pattern != 0)
{
/* Calulcate which was the last changed byte */
used_offset+= offset > 5 ? 2 : 1;
set_if_bigger(bitmap->used_size, used_offset);
}
_ma_check_bitmap(bitmap);
bitmap->changed= 1; bitmap->changed= 1;
DBUG_EXECUTE("bitmap", _ma_print_bitmap_changes(bitmap);); DBUG_EXECUTE("bitmap", _ma_print_bitmap_changes(bitmap););
if (fill_pattern != 3 && fill_pattern != 7) if (fill_pattern != FULL_HEAD_PAGE && fill_pattern != FULL_TAIL_PAGE)
set_if_smaller(info->s->state.first_bitmap_with_space, bitmap_page); set_if_smaller(info->s->state.first_bitmap_with_space, bitmap_page);
/* /*
Note that if the condition above is false (page is full), and all pages of Note that if the condition above is false (page is full), and all pages of
@ -2345,7 +2448,7 @@ my_bool _ma_bitmap_reset_full_page_bits(MARIA_HA *info,
uint page_count) uint page_count)
{ {
ulonglong bitmap_page; ulonglong bitmap_page;
uint offset, bit_start, bit_count, tmp; uint offset, bit_start, bit_count, tmp, byte_offset;
uchar *data; uchar *data;
DBUG_ENTER("_ma_bitmap_reset_full_page_bits"); DBUG_ENTER("_ma_bitmap_reset_full_page_bits");
DBUG_PRINT("enter", ("page: %lu page_count: %u", (ulong) page, page_count)); DBUG_PRINT("enter", ("page: %lu page_count: %u", (ulong) page, page_count));
@ -2365,7 +2468,8 @@ my_bool _ma_bitmap_reset_full_page_bits(MARIA_HA *info,
bit_start= offset * 3; bit_start= offset * 3;
bit_count= page_count * 3; bit_count= page_count * 3;
data= bitmap->map + bit_start / 8; byte_offset= bit_start/8;
data= bitmap->map + byte_offset;
offset= bit_start & 7; offset= bit_start & 7;
tmp= (255 << offset); /* Bits to keep */ tmp= (255 << offset); /* Bits to keep */
@ -2376,6 +2480,9 @@ my_bool _ma_bitmap_reset_full_page_bits(MARIA_HA *info,
} }
*data&= ~tmp; *data&= ~tmp;
set_if_smaller(bitmap->full_head_size, byte_offset);
set_if_smaller(bitmap->full_tail_size, byte_offset);
if ((int) (bit_count-= (8 - offset)) > 0) if ((int) (bit_count-= (8 - offset)) > 0)
{ {
uint fill; uint fill;
@ -2477,6 +2584,8 @@ my_bool _ma_bitmap_set_full_page_bits(MARIA_HA *info,
tmp= (1 << bit_count) - 1; tmp= (1 << bit_count) - 1;
*data|= tmp; *data|= tmp;
} }
set_if_bigger(bitmap->used_size, (uint) (data - bitmap->map) + 1);
_ma_check_bitmap(bitmap);
bitmap->changed= 1; bitmap->changed= 1;
DBUG_EXECUTE("bitmap", _ma_print_bitmap_changes(bitmap);); DBUG_EXECUTE("bitmap", _ma_print_bitmap_changes(bitmap););
DBUG_RETURN(0); DBUG_RETURN(0);
@ -2835,6 +2944,72 @@ my_bool _ma_check_bitmap_data(MARIA_HA *info, enum en_page_type page_type,
return (bitmap_pattern != bits); return (bitmap_pattern != bits);
} }
/**
Check that bitmap looks correct
- All data before full_head_size and full_tail_size are allocated
- There is no allocated data after used_size
All of the above need to be correct only according to 6 byte
alignment as all loops reads 6 bytes at a time and we check both
start and end position according to the current 6 byte position.
*/
#ifndef DBUG_OFF
static void _ma_check_bitmap(MARIA_FILE_BITMAP *bitmap)
{
uchar *data= bitmap->map;
uchar *end= bitmap->map + bitmap->total_size;
uchar *full_head_end=0, *full_tail_end=0, *first_empty= bitmap->map;
for (; data < end; data+= 6)
{
ulonglong bits= uint6korr(data); /* 6 bytes = 6*8/3= 16 patterns */
uint i;
if (bits == 04444444444444444LL || bits == 0xffffffffffffLL)
{
first_empty= data + 6;
continue; /* block fully used */
}
if (bits == 0)
{
if (!full_head_end)
full_head_end= data;
if (!full_tail_end)
full_tail_end= data;
continue;
}
first_empty= data + 6;
if (!full_head_end || !full_tail_end)
{
for (i= 0, bits >>= 0; i < 16 ; i++, bits >>= 3)
{
uint pattern= (uint) (bits & 7);
if (pattern == FULL_HEAD_PAGE || pattern == FULL_TAIL_PAGE)
continue;
if (pattern < 4 && !full_head_end)
full_head_end= data;
if ((pattern == 0 || (pattern > 4 && pattern < 7)) && !full_tail_end)
full_tail_end= data;
}
}
}
if (!full_head_end)
full_head_end= data;
if (!full_tail_end)
full_tail_end= data;
/* used_size must point after the last byte that had some data) */
DBUG_ASSERT(bitmap->used_size <= bitmap->total_size);
DBUG_ASSERT((bitmap->map + (bitmap->used_size+5)/6*6) >= first_empty);
/* full_xxxx_size can't point after the first block that has free data */
DBUG_ASSERT((bitmap->map + (bitmap->full_head_size/6*6)) <= full_head_end);
DBUG_ASSERT((bitmap->map + (bitmap->full_tail_size/6*6)) <= full_tail_end);
}
#endif
/* /*
Check if the page type matches the one that we have in the bitmap Check if the page type matches the one that we have in the bitmap
@ -3072,6 +3247,7 @@ static my_bool _ma_bitmap_create_missing(MARIA_HA *info,
pgcache_page_no_t from, to; pgcache_page_no_t from, to;
my_off_t data_file_length= share->state.state.data_file_length; my_off_t data_file_length= share->state.state.data_file_length;
DBUG_ENTER("_ma_bitmap_create_missing"); DBUG_ENTER("_ma_bitmap_create_missing");
DBUG_PRINT("enter", ("page: %lld", (longlong) page));
/* First (in offset order) bitmap page to create */ /* First (in offset order) bitmap page to create */
if (data_file_length < block_size) if (data_file_length < block_size)
@ -3124,7 +3300,8 @@ static my_bool _ma_bitmap_create_missing(MARIA_HA *info,
only later as we are going to modify it very soon. only later as we are going to modify it very soon.
*/ */
bzero(bitmap->map, bitmap->block_size); bzero(bitmap->map, bitmap->block_size);
bitmap->used_size= 0; bitmap->used_size= bitmap->full_head_size= bitmap->full_tail_size= 0;
bitmap->changed=1;
#ifndef DBUG_OFF #ifndef DBUG_OFF
/* /*
Make a copy of the page to be able to print out bitmap changes during Make a copy of the page to be able to print out bitmap changes during

View File

@ -331,7 +331,10 @@ typedef struct st_maria_file_bitmap
pgcache_page_no_t last_bitmap_page; /* Last possible bitmap page */ pgcache_page_no_t last_bitmap_page; /* Last possible bitmap page */
my_bool changed; /* 1 if page needs to be written */ my_bool changed; /* 1 if page needs to be written */
my_bool changed_not_flushed; /* 1 if some bitmap is not flushed */ my_bool changed_not_flushed; /* 1 if some bitmap is not flushed */
my_bool return_first_match; /* Shortcut find_head() */
uint used_size; /* Size of bitmap head that is not 0 */ uint used_size; /* Size of bitmap head that is not 0 */
uint full_head_size; /* Where to start search for head */
uint full_tail_size; /* Where to start search for tail */
uint flush_all_requested; /**< If _ma_bitmap_flush_all waiting */ uint flush_all_requested; /**< If _ma_bitmap_flush_all waiting */
uint waiting_for_flush_all_requested; /* If someone is waiting for above */ uint waiting_for_flush_all_requested; /* If someone is waiting for above */
uint non_flushable; /**< 0 if bitmap and log are in sync */ uint non_flushable; /**< 0 if bitmap and log are in sync */

View File

@ -4,6 +4,8 @@ IF(CMAKE_VERSION VERSION_LESS "2.8.9")
MESSAGE(STATUS "CMake 2.8.9 or higher is required by TokuDB") MESSAGE(STATUS "CMake 2.8.9 or higher is required by TokuDB")
ELSEIF(NOT HAVE_DLOPEN) ELSEIF(NOT HAVE_DLOPEN)
MESSAGE(STATUS "dlopen is required by TokuDB") MESSAGE(STATUS "dlopen is required by TokuDB")
ELSEIF(NOT TARGET perfschema)
MESSAGE(STATUS "Performance Schema is required by TokuDB")
ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR
CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64")
# tokudb requires F_NOCACHE or O_DIRECT, and designated initializers # tokudb requires F_NOCACHE or O_DIRECT, and designated initializers