summaryrefslogtreecommitdiff
path: root/storage/maria
diff options
context:
space:
mode:
Diffstat (limited to 'storage/maria')
-rw-r--r--storage/maria/CMakeLists.txt3
-rw-r--r--storage/maria/Makefile.am6
-rw-r--r--storage/maria/compat_aliases.cc250
-rw-r--r--storage/maria/compat_aliases.h27
-rw-r--r--storage/maria/ha_maria.cc247
-rw-r--r--storage/maria/ha_maria.h38
-rw-r--r--storage/maria/lockman.c6
-rw-r--r--storage/maria/ma_check.c69
-rw-r--r--storage/maria/ma_check_standalone.h7
-rw-r--r--storage/maria/ma_checkpoint.c88
-rw-r--r--storage/maria/ma_create.c12
-rw-r--r--storage/maria/ma_extra.c18
-rw-r--r--storage/maria/ma_ft_boolean_search.c13
-rw-r--r--storage/maria/ma_ft_nlq_search.c4
-rw-r--r--storage/maria/ma_key.c78
-rw-r--r--storage/maria/ma_loghandler.c29
-rw-r--r--storage/maria/ma_loghandler.h3
-rw-r--r--storage/maria/ma_norec.c66
-rw-r--r--storage/maria/ma_open.c27
-rw-r--r--storage/maria/ma_recovery.c14
-rw-r--r--storage/maria/ma_rkey.c83
-rw-r--r--storage/maria/ma_rnext.c24
-rw-r--r--storage/maria/ma_rnext_same.c20
-rw-r--r--storage/maria/ma_rprev.c26
-rw-r--r--storage/maria/ma_search.c8
-rw-r--r--storage/maria/ma_sort.c31
-rw-r--r--storage/maria/ma_static.c4
-rw-r--r--storage/maria/ma_test1.c19
-rw-r--r--storage/maria/ma_unique.c14
-rw-r--r--storage/maria/ma_write.c21
-rw-r--r--storage/maria/maria_chk.c4
-rw-r--r--storage/maria/maria_def.h33
-rw-r--r--storage/maria/maria_pack.c36
-rw-r--r--storage/maria/tablockman.c2
-rw-r--r--storage/maria/unittest/ma_loghandler_examples.c3
-rwxr-xr-xstorage/maria/unittest/ma_test_all-t1
-rw-r--r--storage/maria/unittest/trnman-t.c12
37 files changed, 886 insertions, 460 deletions
diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt
index 82a631d5086..77083c5839f 100644
--- a/storage/maria/CMakeLists.txt
+++ b/storage/maria/CMakeLists.txt
@@ -40,9 +40,10 @@ SET(ARIA_SOURCES ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c
ha_maria.cc trnman.c lockman.c tablockman.c
ma_rt_index.c ma_rt_key.c ma_rt_mbr.c ma_rt_split.c
ma_sp_key.c ma_control_file.c ma_loghandler.c
- ma_pagecache.c ma_pagecaches.c compat_aliases.cc compat_aliases.h
+ ma_pagecache.c ma_pagecaches.c
ma_checkpoint.c ma_recovery.c ma_commit.c ma_pagecrc.c
ha_maria.h maria_def.h ma_recovery_util.c ma_servicethread.c
+ ma_norec.c
)
MYSQL_STORAGE_ENGINE(ARIA)
diff --git a/storage/maria/Makefile.am b/storage/maria/Makefile.am
index c2bb61e77dd..fa01c2a602d 100644
--- a/storage/maria/Makefile.am
+++ b/storage/maria/Makefile.am
@@ -79,7 +79,7 @@ noinst_HEADERS = maria_def.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h \
ma_checkpoint.h ma_recovery.h ma_commit.h ma_state.h \
trnman_public.h ma_check_standalone.h \
ma_key_recover.h ma_recovery_util.h \
- ma_servicethread.h compat_aliases.h
+ ma_servicethread.h
ma_test1_DEPENDENCIES= $(LIBRARIES)
ma_test1_LDADD= @CLIENT_EXTRA_LDFLAGS@ libaria.a \
$(top_builddir)/storage/myisam/libmyisam.a \
@@ -124,7 +124,7 @@ libaria_la_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ma_search.c ma_page.c ma_key_recover.c ma_key.c \
ma_locking.c ma_state.c \
ma_rrnd.c ma_scan.c ma_cache.c \
- ma_statrec.c ma_packrec.c ma_dynrec.c \
+ ma_statrec.c ma_packrec.c ma_dynrec.c ma_norec.c \
ma_blockrec.c ma_bitmap.c \
ma_update.c ma_write.c ma_unique.c \
ma_delete.c \
@@ -142,7 +142,7 @@ libaria_la_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ma_pagecache.c ma_pagecaches.c \
ma_checkpoint.c ma_recovery.c ma_commit.c \
ma_pagecrc.c ma_recovery_util.c \
- compat_aliases.cc ma_servicethread.c
+ ma_servicethread.c
libaria_s_la_SOURCES = ha_maria.cc
libaria_s_la_CXXFLAGS = $(AM_CXXFLAGS)
diff --git a/storage/maria/compat_aliases.cc b/storage/maria/compat_aliases.cc
deleted file mode 100644
index ce8838b2da2..00000000000
--- a/storage/maria/compat_aliases.cc
+++ /dev/null
@@ -1,250 +0,0 @@
-/* Copyright (C) 2010 Monty Program Ab
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- compatibility aliases for system and static variables
-*/
-#include <my_global.h>
-#include <maria.h>
-#include <mysql/plugin.h>
-#include "ma_loghandler.h"
-#include "compat_aliases.h"
-
-ulong block_size_alias;
-static MYSQL_SYSVAR_ULONG(block_size, block_size_alias,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "Deprecated, use --aria-block-size instead", 0, 0,
- MARIA_KEY_BLOCK_LENGTH, MARIA_MIN_KEY_BLOCK_LENGTH,
- MARIA_MAX_KEY_BLOCK_LENGTH, MARIA_MIN_KEY_BLOCK_LENGTH);
-
-ulong checkpoint_interval_alias;
-static MYSQL_SYSVAR_ULONG(checkpoint_interval, checkpoint_interval_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-checkpoint-interval instead",
- NULL, NULL, 30, 0, UINT_MAX, 1);
-
-ulong force_start_after_recovery_failures_alias;
-static MYSQL_SYSVAR_ULONG(force_start_after_recovery_failures, force_start_after_recovery_failures_alias,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "Deprecated, use --aria-force-start-after-recovery-failures instead",
- NULL, NULL, 0, 0, UINT_MAX8, 1);
-
-my_bool page_checksum_alias;
-static MYSQL_SYSVAR_BOOL(page_checksum, page_checksum_alias, 0,
- "Deprecated, use --aria-page-checksum instead", 0, 0, 1);
-
-char *log_dir_path_alias;
-static MYSQL_SYSVAR_STR(log_dir_path, log_dir_path_alias,
- PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "Deprecated, use --aria-log-dir-path instead",
- NULL, NULL, mysql_real_data_home);
-
-ulong log_file_size_alias;
-static MYSQL_SYSVAR_ULONG(log_file_size, log_file_size_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-log-file-size instead",
- NULL, NULL, TRANSLOG_FILE_SIZE,
- TRANSLOG_MIN_FILE_SIZE, 0xffffffffL, TRANSLOG_PAGE_SIZE);
-
-ulong group_commit_alias;
-static MYSQL_SYSVAR_ENUM(group_commit, group_commit_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-group-commit instead",
- NULL, NULL,
- TRANSLOG_GCOMMIT_NONE, &maria_group_commit_typelib);
-
-ulong group_commit_interval_alias;
-static MYSQL_SYSVAR_ULONG(group_commit_interval, group_commit_interval_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-group-commit-interval instead",
- NULL, NULL, 0, 0, UINT_MAX, 1);
-
-ulong log_purge_type_alias;
-static MYSQL_SYSVAR_ENUM(log_purge_type, log_purge_type_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-log-purge-type instead",
- NULL, NULL, TRANSLOG_PURGE_IMMIDIATE,
- &maria_translog_purge_type_typelib);
-
-ulonglong max_sort_file_size_alias;
-static MYSQL_SYSVAR_ULONGLONG(max_sort_file_size, max_sort_file_size_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-max-temp-length instead",
- 0, 0, MAX_FILE_SIZE, 0, MAX_FILE_SIZE, 1024*1024);
-
-ulong pagecache_age_threshold_alias;
-static MYSQL_SYSVAR_ULONG(pagecache_age_threshold, pagecache_age_threshold_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-pagecache-age-threshold instead",
- 0, 0, 300, 100, ~0L, 100);
-
-ulonglong pagecache_buffer_size_alias;
-static MYSQL_SYSVAR_ULONGLONG(pagecache_buffer_size, pagecache_buffer_size_alias,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
- "Deprecated, use --aria-pagecache-buffer-size instead",
- 0, 0, KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~0UL, IO_SIZE);
-
-ulong pagecache_division_limit_alias;
-static MYSQL_SYSVAR_ULONG(pagecache_division_limit, pagecache_division_limit_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-pagecache-division-limit instead",
- 0, 0, 100, 1, 100, 1);
-
-ulong recover_alias;
-static MYSQL_SYSVAR_ENUM(recover, recover_alias, PLUGIN_VAR_OPCMDARG,
- "Deprecated, use --aria-recover instead",
- NULL, NULL, HA_RECOVER_DEFAULT, &maria_recover_typelib);
-
-ulong repair_threads_alias;
-static MYSQL_THDVAR_ULONG(repair_threads, PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-repair-threads instead",
- 0, 0, 1, 1, ~0L, 1);
-
-ulong sort_buffer_size_alias;
-static MYSQL_THDVAR_ULONG(sort_buffer_size, PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-sort-buffer-size instead",
- 0, 0, 128L*1024L*1024L, 4, ~0L, 1);
-
-ulong stats_method_alias;
-static MYSQL_THDVAR_ENUM(stats_method, PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-stats-method instead",
- 0, 0, 0, &maria_stats_method_typelib);
-
-ulong sync_log_dir_alias;
-static MYSQL_SYSVAR_ENUM(sync_log_dir, sync_log_dir_alias,
- PLUGIN_VAR_RQCMDARG,
- "Deprecated, use --aria-sync-log-dir instead",
- NULL, NULL, TRANSLOG_SYNC_DIR_NEWFILE,
- &maria_sync_log_dir_typelib);
-
-my_bool used_for_temp_tables_alias= 1;
-static MYSQL_SYSVAR_BOOL(used_for_temp_tables,
- used_for_temp_tables_alias, PLUGIN_VAR_READONLY | PLUGIN_VAR_NOCMDOPT,
- NULL, 0, 0, 1);
-
-static struct st_mysql_show_var status_variables_aliases[]= {
- {"Maria", (char*) &status_variables, SHOW_ARRAY},
- {NullS, NullS, SHOW_LONG}
-};
-
-/*
- There is one problem with aliases for command-line options.
- Plugin initialization works like this
-
- for all plugins:
- prepare command-line options
- initialize command-line option variables to the default values
- parse command line, assign values as necessary
-
- for all plugins:
- call the plugin initialization function
-
- it means, we cannot have maria* and aria* command-line options to use
- the same underlying variables - because after assigning maria* values,
- MySQL will put there default values again preparing for parsing aria*
- values. So, maria* values will be lost.
-
- So, we create separate set of variables for maria* options,
- and take both values into account in ha_maria_init().
-
- When the command line was parsed, we patch maria* options
- to use the same variables as aria* options so that
- set @@maria_some_var would have the same value as @@aria_some_var
- without forcing us to copy the values around all the time.
-*/
-
-static struct st_mysql_sys_var* system_variables_aliases[]= {
- MYSQL_SYSVAR(block_size),
- MYSQL_SYSVAR(checkpoint_interval),
- MYSQL_SYSVAR(force_start_after_recovery_failures),
- MYSQL_SYSVAR(group_commit),
- MYSQL_SYSVAR(group_commit_interval),
- MYSQL_SYSVAR(log_dir_path),
- MYSQL_SYSVAR(log_file_size),
- MYSQL_SYSVAR(log_purge_type),
- MYSQL_SYSVAR(max_sort_file_size),
- MYSQL_SYSVAR(page_checksum),
- MYSQL_SYSVAR(pagecache_age_threshold),
- MYSQL_SYSVAR(pagecache_buffer_size),
- MYSQL_SYSVAR(pagecache_division_limit),
- MYSQL_SYSVAR(recover),
- MYSQL_SYSVAR(repair_threads),
- MYSQL_SYSVAR(sort_buffer_size),
- MYSQL_SYSVAR(stats_method),
- MYSQL_SYSVAR(sync_log_dir),
- MYSQL_SYSVAR(used_for_temp_tables),
- NULL
-};
-
-#define COPY_SYSVAR(name) \
- memcpy(&MYSQL_SYSVAR_NAME(name), system_variables[i++], \
- sizeof(MYSQL_SYSVAR_NAME(name))); \
- if (name ## _alias != MYSQL_SYSVAR_NAME(name).def_val && \
- *MYSQL_SYSVAR_NAME(name).value == MYSQL_SYSVAR_NAME(name).def_val) \
- *MYSQL_SYSVAR_NAME(name).value= name ## _alias;
-
-#define COPY_THDVAR(name) \
- name ## _alias= THDVAR(0, name); \
- memcpy(&MYSQL_SYSVAR_NAME(name), system_variables[i++], \
- sizeof(MYSQL_SYSVAR_NAME(name))); \
- if (name ## _alias != MYSQL_SYSVAR_NAME(name).def_val && \
- THDVAR(0, name) == MYSQL_SYSVAR_NAME(name).def_val) \
- THDVAR(0, name)= name ## _alias;
-
-/* Note:
- The following list must be identical to the list for system_variables[] in ha_maria.cc
-*/
-
-void copy_variable_aliases()
-{
- int i= 0;
- COPY_SYSVAR(block_size);
- COPY_SYSVAR(checkpoint_interval);
- i++; // Skip checkpoint_min_log_activity
- COPY_SYSVAR(force_start_after_recovery_failures);
- COPY_SYSVAR(group_commit);
- COPY_SYSVAR(group_commit_interval);
- COPY_SYSVAR(log_dir_path);
- COPY_SYSVAR(log_file_size);
- COPY_SYSVAR(log_purge_type);
- COPY_SYSVAR(max_sort_file_size);
- COPY_SYSVAR(page_checksum);
- COPY_SYSVAR(pagecache_age_threshold);
- COPY_SYSVAR(pagecache_buffer_size);
- COPY_SYSVAR(pagecache_division_limit);
- COPY_SYSVAR(recover);
- COPY_THDVAR(repair_threads);
- COPY_THDVAR(sort_buffer_size);
- COPY_THDVAR(stats_method);
- COPY_SYSVAR(sync_log_dir);
- COPY_SYSVAR(used_for_temp_tables);
-}
-
-struct st_maria_plugin compat_aliases= {
- MYSQL_DAEMON_PLUGIN,
- &maria_storage_engine,
- "Maria",
- "Monty Program Ab",
- "Compatibility aliases for the Aria engine",
- PLUGIN_LICENSE_GPL,
- NULL,
- NULL,
- 0x0105,
- status_variables_aliases,
- system_variables_aliases,
- "1.5",
- MariaDB_PLUGIN_MATURITY_GAMMA
-};
-
diff --git a/storage/maria/compat_aliases.h b/storage/maria/compat_aliases.h
deleted file mode 100644
index 46a4da74eec..00000000000
--- a/storage/maria/compat_aliases.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright (C) 2010 Monty Program Ab
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-extern struct st_maria_plugin compat_aliases;
-extern char mysql_real_data_home[FN_REFLEN];
-extern TYPELIB maria_recover_typelib;
-extern TYPELIB maria_stats_method_typelib;
-extern TYPELIB maria_translog_purge_type_typelib;
-extern TYPELIB maria_sync_log_dir_typelib;
-extern TYPELIB maria_group_commit_typelib;
-extern struct st_mysql_storage_engine maria_storage_engine;
-extern my_bool use_maria_for_temp_tables;
-extern struct st_mysql_sys_var* system_variables[];
-extern st_mysql_show_var status_variables[];
-void copy_variable_aliases();
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index 60fa7a58fb6..e65ac7e443c 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -29,7 +29,6 @@
#include "ha_maria.h"
#include "trnman_public.h"
#include "trnman.h"
-#include "compat_aliases.h"
C_MODE_START
#include "maria_def.h"
@@ -219,7 +218,8 @@ static MYSQL_SYSVAR_ULONGLONG(max_sort_file_size,
maria_max_temp_length, PLUGIN_VAR_RQCMDARG,
"Don't use the fast sort index method to created index if the "
"temporary file would get bigger than this.",
- 0, 0, MAX_FILE_SIZE & ~(1*MB-1), 0, MAX_FILE_SIZE, 1*MB);
+ 0, 0, MAX_FILE_SIZE & ~((ulonglong) (1*MB-1)),
+ 0, MAX_FILE_SIZE, 1*MB);
static MYSQL_SYSVAR_ULONG(pagecache_age_threshold,
pagecache_age_threshold, PLUGIN_VAR_RQCMDARG,
@@ -511,6 +511,8 @@ static int table2maria(TABLE *table_arg, data_file_type row_type,
if (found->flags & BLOB_FLAG)
recinfo_pos->type= FIELD_BLOB;
+ else if (found->type() == MYSQL_TYPE_TIMESTAMP)
+ recinfo_pos->type= FIELD_NORMAL;
else if (found->type() == MYSQL_TYPE_VARCHAR)
recinfo_pos->type= FIELD_VARCHAR;
else if (!(options & HA_OPTION_PACK_RECORD) ||
@@ -720,6 +722,34 @@ int _ma_killed_ptr(HA_CHECK *param)
}
+/*
+ Report progress to mysqld
+
+ This is a bit more complex than what a normal progress report
+ function normally is.
+
+ The reason is that this is called by enable_index/repair which
+ is one stage in ALTER TABLE and we can't use the external
+ stage/max_stage for this.
+
+ thd_progress_init/thd_progress_next_stage is to be called by
+ high level commands like CHECK TABLE or REPAIR TABLE, not
+ by sub commands like enable_index().
+
+ In ma_check.c it's easier to work with stages than with a total
+ progress, so we use internal stage/max_stage here to keep the
+ code simple.
+*/
+
+void _ma_report_progress(HA_CHECK *param, ulonglong progress,
+ ulonglong max_progress)
+{
+ thd_progress_report((THD*)param->thd,
+ progress + max_progress * param->stage,
+ max_progress * param->max_stage);
+}
+
+
void _ma_check_print_error(HA_CHECK *param, const char *fmt, ...)
{
va_list args;
@@ -769,7 +799,7 @@ void _ma_check_print_warning(HA_CHECK *param, const char *fmt, ...)
static int maria_create_trn_for_mysql(MARIA_HA *info)
{
- THD *thd= (THD*) info->external_ptr;
+ THD *thd= ((TABLE*) info->external_ref)->in_use;
TRN *trn= THD_TRN;
DBUG_ENTER("maria_create_trn_for_mysql");
@@ -808,6 +838,11 @@ static int maria_create_trn_for_mysql(MARIA_HA *info)
DBUG_RETURN(0);
}
+my_bool ma_killed_in_mariadb(MARIA_HA *info)
+{
+ return (((TABLE*) (info->external_ref))->in_use->killed != 0);
+}
+
} /* extern "C" */
/**
@@ -1025,6 +1060,8 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
return (my_errno ? my_errno : -1);
file->s->chst_invalidator= query_cache_invalidate_by_MyISAM_filename_ref;
+ /* Set external_ref, mainly for temporary tables */
+ file->external_ref= (void*) table; // For ma_killed()
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
VOID(maria_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
@@ -1048,6 +1085,16 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD))
int_table_flags |= HA_HAS_NEW_CHECKSUM;
+ /*
+ For static size rows, tell MariaDB that we will access all bytes
+ in the record when writing it. This signals MariaDB to initalize
+ the full row to ensure we don't get any errors from valgrind and
+ that all bytes in the row is properly reset.
+ */
+ if (file->s->data_file_type == STATIC_RECORD &&
+ (file->s->has_varchar_fields | file->s->has_null_fields))
+ int_table_flags|= HA_RECORD_MUST_BE_CLEAN_ON_WRITE;
+
for (i= 0; i < table->s->keys; i++)
{
plugin_ref parser= table->key_info[i].parser;
@@ -1064,6 +1111,8 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
int ha_maria::close(void)
{
MARIA_HA *tmp= file;
+ if (!tmp)
+ return 0;
file= 0;
return maria_close(tmp);
}
@@ -1094,7 +1143,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
int error;
HA_CHECK &param= *(HA_CHECK*) thd->alloc(sizeof(param));
MARIA_SHARE *share= file->s;
- const char *old_proc_info= thd_proc_info(thd, "Checking table");
+ const char *old_proc_info;
TRN *old_trn= file->trn;
if (!file || !&param) return HA_ADMIN_INTERNAL_ERROR;
@@ -1122,12 +1171,18 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
return HA_ADMIN_ALREADY_DONE;
maria_chk_init_for_check(&param, file);
+ old_proc_info= thd_proc_info(thd, "Checking status");
+ thd_progress_init(thd, 3);
(void) maria_chk_status(&param, file); // Not fatal
error= maria_chk_size(&param, file);
if (!error)
error|= maria_chk_del(&param, file, param.testflag);
+ thd_proc_info(thd, "Checking keys");
+ thd_progress_next_stage(thd);
if (!error)
error= maria_chk_key(&param, file);
+ thd_proc_info(thd, "Checking data");
+ thd_progress_next_stage(thd);
if (!error)
{
if ((!(param.testflag & T_QUICK) &&
@@ -1178,6 +1233,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
/* Reset trn, that may have been set by repair */
_ma_set_trn_for_table(file, old_trn);
thd_proc_info(thd, old_proc_info);
+ thd_progress_end(thd);
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
}
@@ -1193,6 +1249,7 @@ int ha_maria::analyze(THD *thd, HA_CHECK_OPT * check_opt)
int error= 0;
HA_CHECK &param= *(HA_CHECK*) thd->alloc(sizeof(param));
MARIA_SHARE *share= file->s;
+ const char *old_proc_info;
if (!&param)
return HA_ADMIN_INTERNAL_ERROR;
@@ -1210,6 +1267,8 @@ int ha_maria::analyze(THD *thd, HA_CHECK_OPT * check_opt)
if (!(share->state.changed & STATE_NOT_ANALYZED))
return HA_ADMIN_ALREADY_DONE;
+ old_proc_info= thd_proc_info(thd, "Scanning");
+ thd_progress_init(thd, 1);
error= maria_chk_key(&param, file);
if (!error)
{
@@ -1219,6 +1278,8 @@ int ha_maria::analyze(THD *thd, HA_CHECK_OPT * check_opt)
}
else if (!maria_is_crashed(file) && !thd->killed)
maria_mark_crashed(file);
+ thd_proc_info(thd, old_proc_info);
+ thd_progress_end(thd);
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
}
@@ -1352,6 +1413,7 @@ int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt)
int error;
HA_CHECK &param= *(HA_CHECK*) thd->alloc(sizeof(param));
ha_rows start_records;
+ const char *old_proc_info;
if (!file || !&param)
return HA_ADMIN_INTERNAL_ERROR;
@@ -1365,6 +1427,8 @@ int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt)
param.sort_buffer_length= THDVAR(thd, sort_buffer_size);
param.backup_time= check_opt->start_time;
start_records= file->state->records;
+ old_proc_info= thd_proc_info(thd, "Checking table");
+ thd_progress_init(thd, 1);
while ((error= repair(thd, &param, 0)) && param.retry_repair)
{
param.retry_repair= 0;
@@ -1400,6 +1464,8 @@ int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt)
llstr(start_records, llbuff2),
table->s->path.str);
}
+ thd_proc_info(thd, old_proc_info);
+ thd_progress_end(thd);
return error;
}
@@ -1447,14 +1513,15 @@ int ha_maria::optimize(THD * thd, HA_CHECK_OPT *check_opt)
param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE |
T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX);
param.sort_buffer_length= THDVAR(thd, sort_buffer_size);
+ thd_progress_init(thd, 1);
if ((error= repair(thd, &param, 1)) && param.retry_repair)
{
sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying",
my_errno, param.db_name, param.table_name);
param.testflag &= ~T_REP_BY_SORT;
- error= repair(thd, &param, 1);
+ error= repair(thd, &param, 0);
}
-
+ thd_progress_end(thd);
return error;
}
@@ -1628,6 +1695,7 @@ int ha_maria::repair(THD *thd, HA_CHECK *param, bool do_optimize)
}
pthread_mutex_unlock(&share->intern_lock);
thd_proc_info(thd, old_proc_info);
+ thd_progress_end(thd); // Mark done
if (!thd->locked_tables)
maria_lock_database(file, F_UNLCK);
@@ -1954,15 +2022,27 @@ void ha_maria::start_bulk_insert(ha_rows rows)
{
DBUG_ENTER("ha_maria::start_bulk_insert");
THD *thd= table->in_use;
- ulong size= min(thd->variables.read_buff_size,
- (ulong) (table->s->avg_row_length * rows));
MARIA_SHARE *share= file->s;
- DBUG_PRINT("info", ("start_bulk_insert: rows %lu size %lu",
- (ulong) rows, size));
+ DBUG_PRINT("info", ("start_bulk_insert: rows %lu", (ulong) rows));
/* don't enable row cache if too few rows */
if (!rows || (rows > MARIA_MIN_ROWS_TO_USE_WRITE_CACHE))
- maria_extra(file, HA_EXTRA_WRITE_CACHE, (void*) &size);
+ {
+ ulonglong size= thd->variables.read_buff_size, tmp;
+ if (rows)
+ {
+ if (file->state->records)
+ {
+ MARIA_INFO maria_info;
+ maria_status(file, &maria_info, HA_STATUS_NO_LOCK |HA_STATUS_VARIABLE);
+ set_if_smaller(size, maria_info.mean_reclength * rows);
+ }
+ else if (table->s->avg_row_length)
+ set_if_smaller(size, (size_t) (table->s->avg_row_length * rows));
+ }
+ tmp= (ulong) size; // Safe becasue of limits
+ maria_extra(file, HA_EXTRA_WRITE_CACHE, (void*) &tmp);
+ }
can_enable_indexes= (maria_is_all_keys_active(share->state.key_map,
share->base.keys));
@@ -1997,7 +2077,14 @@ void ha_maria::start_bulk_insert(ha_rows rows)
@todo for a single-row INSERT SELECT, we will go into repair, which
is more costly (flushes, syncs) than a row write.
*/
- maria_disable_non_unique_index(file, rows);
+ if (file->open_flags & HA_OPEN_INTERNAL_TABLE)
+ {
+ /* Internal table; If we get a duplicate something is very wrong */
+ file->update|= HA_STATE_CHANGED;
+ maria_clear_all_keys_active(file->s->state.key_map);
+ }
+ else
+ maria_disable_non_unique_index(file, rows);
if (share->now_transactional)
{
bulk_insert_single_undo= BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR;
@@ -2157,6 +2244,20 @@ int ha_maria::delete_row(const uchar * buf)
return maria_delete(file, buf);
}
+C_MODE_START
+
+ICP_RESULT index_cond_func_maria(void *arg)
+{
+ ha_maria *h= (ha_maria*)arg;
+ if (h->end_range)
+ {
+ if (h->compare_key2(h->end_range) > 0)
+ return ICP_OUT_OF_RANGE; /* caller should return HA_ERR_END_OF_FILE already */
+ }
+ return h->pushed_idx_cond->val_int() ? ICP_MATCH : ICP_NO_MATCH;
+}
+
+C_MODE_END
int ha_maria::index_read_map(uchar * buf, const uchar * key,
key_part_map keypart_map,
@@ -2173,7 +2274,15 @@ int ha_maria::index_read_idx_map(uchar * buf, uint index, const uchar * key,
key_part_map keypart_map,
enum ha_rkey_function find_flag)
{
- int error= maria_rkey(file, buf, index, key, keypart_map, find_flag);
+ int error;
+ /* Use the pushed index condition if it matches the index we're scanning */
+ end_range= NULL;
+ if (index == pushed_idx_cond_keyno)
+ ma_set_index_cond_func(file, index_cond_func_maria, this);
+
+ error= maria_rkey(file, buf, index, key, keypart_map, find_flag);
+
+ ma_set_index_cond_func(file, NULL, 0);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
}
@@ -2246,6 +2355,25 @@ int ha_maria::index_next_same(uchar * buf,
}
+int ha_maria::index_init(uint idx, bool sorted)
+{
+ active_index=idx;
+ if (pushed_idx_cond_keyno == idx)
+ ma_set_index_cond_func(file, index_cond_func_maria, this);
+ return 0;
+}
+
+
+int ha_maria::index_end()
+{
+ active_index=MAX_KEY;
+ ma_set_index_cond_func(file, NULL, 0);
+ in_range_check_pushed_down= FALSE;
+ ds_mrr.dsmrr_close();
+ return 0;
+}
+
+
int ha_maria::rnd_init(bool scan)
{
if (scan)
@@ -2256,6 +2384,7 @@ int ha_maria::rnd_init(bool scan)
int ha_maria::rnd_end()
{
+ ds_mrr.dsmrr_close();
/* Safe to call even if we don't have started a scan */
maria_scan_end(file);
return 0;
@@ -2300,7 +2429,7 @@ void ha_maria::position(const uchar *record)
int ha_maria::info(uint flag)
{
- return info(flag, table->s->tmp_table == NO_TMP_TABLE);
+ return (!table ? 1 : info(flag, table->s->tmp_table == NO_TMP_TABLE));
}
int ha_maria::info(uint flag, my_bool lock_table_share)
@@ -2328,6 +2457,7 @@ int ha_maria::info(uint flag, my_bool lock_table_share)
ref_length= maria_info.reflength;
share->db_options_in_use= maria_info.options;
stats.block_size= maria_block_size;
+ stats.mrr_length_per_rec= maria_info.reflength + 8; // 8 = max(sizeof(void *))
/* Update share */
if (lock_table_share)
@@ -2409,6 +2539,11 @@ int ha_maria::extra(enum ha_extra_function operation)
int ha_maria::reset(void)
{
+ pushed_idx_cond= NULL;
+ pushed_idx_cond_keyno= MAX_KEY;
+ in_range_check_pushed_down= FALSE;
+ ma_set_index_cond_func(file, NULL, 0);
+ ds_mrr.dsmrr_close();
if (file->trn)
{
/* Next statement is a new statement. Ensure it's logged */
@@ -2461,7 +2596,7 @@ int ha_maria::delete_table(const char *name)
void ha_maria::drop_table(const char *name)
{
DBUG_ASSERT(file->s->temporary);
- (void) close();
+ (void) ha_close();
(void) maria_delete_table_files(name, 0);
}
@@ -2469,6 +2604,7 @@ void ha_maria::drop_table(const char *name)
int ha_maria::external_lock(THD *thd, int lock_type)
{
DBUG_ENTER("ha_maria::external_lock");
+ file->external_ref= (void*) table; // For ma_killed()
/*
We don't test now_transactional because it may vary between lock/unlock
and thus confuse our reference counting.
@@ -2487,8 +2623,6 @@ int ha_maria::external_lock(THD *thd, int lock_type)
/* Transactional table */
if (lock_type != F_UNLCK)
{
- file->external_ptr= thd; // For maria_register_trn()
-
if (!file->s->lock_key_trees) // If we don't use versioning
{
/*
@@ -2567,7 +2701,7 @@ int ha_maria::external_lock(THD *thd, int lock_type)
changes to commit (rollback shouldn't be tested).
*/
DBUG_ASSERT(!thd->main_da.is_sent ||
- thd->killed == THD::KILL_CONNECTION);
+ thd->killed == KILL_CONNECTION);
/* autocommit ? rollback a transaction */
#ifdef MARIA_CANNOT_ROLLBACK
if (ma_commit(trn))
@@ -3120,6 +3254,14 @@ bool maria_flush_logs(handlerton *hton)
}
+int maria_checkpoint_state(handlerton *hton, bool disabled)
+{
+ maria_checkpoint_disabled= (my_bool) disabled;
+ return 0;
+}
+
+
+
#define SHOW_MSG_LEN (FN_REFLEN + 20)
/**
@brief show status handler
@@ -3299,7 +3441,6 @@ bool ha_maria::is_changed() const
static int ha_maria_init(void *p)
{
int res;
- copy_variable_aliases();
const char *log_dir= maria_data_root;
maria_hton= (handlerton *)p;
maria_hton->state= SHOW_OPTION_YES;
@@ -3308,6 +3449,7 @@ static int ha_maria_init(void *p)
maria_hton->panic= maria_hton_panic;
maria_hton->commit= maria_commit;
maria_hton->rollback= maria_rollback;
+ maria_hton->checkpoint_state= maria_checkpoint_state;
#ifdef MARIA_CANNOT_ROLLBACK
maria_hton->commit= 0;
#endif
@@ -3344,6 +3486,9 @@ static int ha_maria_init(void *p)
#endif
if (res)
maria_hton= 0;
+
+ ma_killed= ma_killed_in_mariadb;
+
return res ? HA_ERR_INITIALIZATION : 0;
}
@@ -3578,11 +3723,73 @@ static struct st_mysql_show_var aria_status_variables[]= {
{NullS, NullS, SHOW_LONG}
};
+/****************************************************************************
+ * Maria MRR implementation: use DS-MRR
+ ***************************************************************************/
+
+int ha_maria::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
+ uint n_ranges, uint mode,
+ HANDLER_BUFFER *buf)
+{
+ return ds_mrr.dsmrr_init(this, seq, seq_init_param, n_ranges, mode, buf);
+}
+
+int ha_maria::multi_range_read_next(range_id_t *range_info)
+{
+ return ds_mrr.dsmrr_next(range_info);
+}
+
+ha_rows ha_maria::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
+ void *seq_init_param,
+ uint n_ranges, uint *bufsz,
+ uint *flags, COST_VECT *cost)
+{
+ /*
+ This call is here because there is no location where this->table would
+ already be known.
+ TODO: consider moving it into some per-query initialization call.
+ */
+ ds_mrr.init(this, table);
+ return ds_mrr.dsmrr_info_const(keyno, seq, seq_init_param, n_ranges, bufsz,
+ flags, cost);
+}
+
+ha_rows ha_maria::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
+ uint key_parts, uint *bufsz,
+ uint *flags, COST_VECT *cost)
+{
+ ds_mrr.init(this, table);
+ return ds_mrr.dsmrr_info(keyno, n_ranges, keys, key_parts, bufsz, flags, cost);
+}
+
+int ha_maria::multi_range_read_explain_info(uint mrr_mode, char *str,
+ size_t size)
+{
+ return ds_mrr.dsmrr_explain_info(mrr_mode, str, size);
+}
+/* MyISAM MRR implementation ends */
+
+
+/* Index condition pushdown implementation*/
+
+
+Item *ha_maria::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
+{
+ pushed_idx_cond_keyno= keyno_arg;
+ pushed_idx_cond= idx_cond_arg;
+ in_range_check_pushed_down= TRUE;
+ if (active_index == pushed_idx_cond_keyno)
+ ma_set_index_cond_func(file, index_cond_func_maria, this);
+ return NULL;
+}
+
+
+
+
struct st_mysql_storage_engine maria_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
maria_declare_plugin(aria)
-compat_aliases,
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&maria_storage_engine,
diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h
index c7af191c1e7..0ba134a5b45 100644
--- a/storage/maria/ha_maria.h
+++ b/storage/maria/ha_maria.h
@@ -13,6 +13,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifndef HA_MARIA_INCLUDED
+#define HA_MARIA_INCLUDED
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
@@ -22,6 +24,16 @@
#include <maria.h>
+#define HA_RECOVER_NONE 0 /* No automatic recover */
+#define HA_RECOVER_DEFAULT 1 /* Automatic recover active */
+#define HA_RECOVER_BACKUP 2 /* Make a backupfile on recover */
+#define HA_RECOVER_FORCE 4 /* Recover even if we loose rows */
+#define HA_RECOVER_QUICK 8 /* Don't check rows in data file */
+
+C_MODE_START
+ICP_RESULT index_cond_func_maria(void *arg);
+C_MODE_END
+
extern ulong maria_sort_buffer_size;
extern TYPELIB maria_recover_typelib;
extern ulong maria_recover_options;
@@ -56,7 +68,7 @@ public:
{
return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_FULLTEXT) ?
0 : HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
- HA_READ_ORDER | HA_KEYREAD_ONLY);
+ HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN);
}
uint max_supported_keys() const
{ return MARIA_MAX_KEY; }
@@ -98,6 +110,8 @@ public:
key->charset(), table->record[0]);
}
int ft_read(uchar * buf);
+ int index_init(uint idx, bool sorted);
+ int index_end();
int rnd_init(bool scan);
int rnd_end(void);
int rnd_next(uchar * buf);
@@ -159,4 +173,26 @@ public:
return file;
}
static int implicit_commit(THD *thd, bool new_trn);
+ /**
+ * Multi Range Read interface
+ */
+ int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
+ uint n_ranges, uint mode, HANDLER_BUFFER *buf);
+ int multi_range_read_next(range_id_t *range_info);
+ ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
+ void *seq_init_param,
+ uint n_ranges, uint *bufsz,
+ uint *flags, COST_VECT *cost);
+ ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys,
+ uint key_parts, uint *bufsz,
+ uint *flags, COST_VECT *cost);
+ int multi_range_read_explain_info(uint mrr_mode, char *str, size_t size);
+
+ /* Index condition pushdown implementation */
+ Item *idx_cond_push(uint keyno, Item* idx_cond);
+private:
+ DsMrr_impl ds_mrr;
+ friend ICP_RESULT index_cond_func_maria(void *arg);
};
+
+#endif /* HA_MARIA_INCLUDED */
diff --git a/storage/maria/lockman.c b/storage/maria/lockman.c
index d6d4dcd44e6..459ee5d8ae2 100644
--- a/storage/maria/lockman.c
+++ b/storage/maria/lockman.c
@@ -690,12 +690,12 @@ enum lockman_getlock_result lockman_getlock(LOCKMAN *lm, LOCK_OWNER *lo,
}
/* yuck. waiting */
- deadline= my_getsystime() + lm->lock_timeout * 10000;
- set_timespec_nsec(timeout,lm->lock_timeout * 1000000);
+ deadline= my_hrtime().val*1000 + lm->lock_timeout * 1000000;
+ set_timespec_time_nsec(timeout, deadline);
do
{
pthread_cond_timedwait(wait_for_lo->cond, wait_for_lo->mutex, &timeout);
- } while (!DELETED(blocker->link) && my_getsystime() < deadline);
+ } while (!DELETED(blocker->link) && my_hrtime().val < deadline/1000);
pthread_mutex_unlock(wait_for_lo->mutex);
lf_rwlock_by_pins(pins);
if (!DELETED(blocker->link))
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index f4470f846f5..72c01fc9995 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -125,6 +125,7 @@ void maria_chk_init(HA_CHECK *param)
param->max_record_length= LONGLONG_MAX;
param->pagecache_block_size= KEY_CACHE_BLOCK_SIZE;
param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
+ param->max_stage= 1;
}
@@ -530,6 +531,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
continue;
}
found_keys++;
+ _ma_report_progress(param, key, share->base.keys);
param->record_checksum=init_checksum;
@@ -1013,10 +1015,12 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
/* fall through */
}
if ((share->data_file_type != BLOCK_RECORD &&
+ share->data_file_type != NO_RECORD &&
record >= share->state.state.data_file_length) ||
(share->data_file_type == BLOCK_RECORD &&
ma_recordpos_to_page(record) * share->base.min_block_length >=
- share->state.state.data_file_length))
+ share->state.state.data_file_length) ||
+ (share->data_file_type == NO_RECORD && record != 0))
{
#ifndef DBUG_OFF
char llbuff2[22], llbuff3[22];
@@ -1134,10 +1138,14 @@ static int check_keys_in_record(HA_CHECK *param, MARIA_HA *info, int extend,
param->tmp_record_checksum+= (ha_checksum) start_recpos;
param->records++;
- if (param->testflag & T_WRITE_LOOP && param->records % WRITE_COUNT == 0)
+ if (param->records % WRITE_COUNT == 0)
{
- printf("%s\r", llstr(param->records, llbuff));
- VOID(fflush(stdout));
+ if (param->testflag & T_WRITE_LOOP)
+ {
+ printf("%s\r", llstr(param->records, llbuff));
+ VOID(fflush(stdout));
+ }
+ _ma_report_progress(param, param->records, share->state.state.records);
}
/* Check if keys match the record */
@@ -2086,6 +2094,12 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
case COMPRESSED_RECORD:
error= check_compressed_record(param, info, extend, record);
break;
+ case NO_RECORD:
+ param->records= share->state.state.records;
+ param->record_checksum= 0;
+ extend= 1; /* No row checksums */
+ /* no data, nothing to do */
+ break;
} /* switch */
info->in_check_table= 0;
@@ -2323,6 +2337,13 @@ static int initialize_variables_for_repair(HA_CHECK *param,
{
MARIA_SHARE *share= info->s;
+ if (share->data_file_type == NO_RECORD)
+ {
+ _ma_check_print_error(param,
+ "Can't repair tables with record type NO_DATA");
+ return 1;
+ }
+
/* Make a copy to allow us to restore state and check how state changed */
memcpy(org_share, share, sizeof(*share));
@@ -2369,6 +2390,7 @@ static int initialize_variables_for_repair(HA_CHECK *param,
/* calculate max_records */
sort_info->filelength= my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0));
+ param->max_progress= sort_info->filelength;
if ((param->testflag & T_CREATE_MISSING_KEYS) ||
sort_info->org_data_file_type == COMPRESSED_RECORD)
sort_info->max_records= share->state.state.records;
@@ -2391,6 +2413,8 @@ static int initialize_variables_for_repair(HA_CHECK *param,
maria_ignore_trids(info);
/* Don't write transid's during repair */
maria_versioning(info, 0);
+ /* remember original number of rows */
+ *info->state= info->s->state.state;
return 0;
}
@@ -3623,7 +3647,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
const char * name, my_bool rep_quick)
{
int got_error;
- uint i;
+ uint i, keys_to_repair;
ha_rows start_records;
my_off_t new_header_length, org_header_length, del;
File new_file;
@@ -3749,6 +3773,17 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
del=share->state.state.del;
+ /* Calculate number of keys to repair */
+ keys_to_repair= 0;
+ for (sort_param.key=0 ; sort_param.key < share->base.keys ;
+ sort_param.key++)
+ {
+ if (maria_is_key_active(key_map, sort_param.key))
+ keys_to_repair++;
+ }
+ /* For each key we scan and merge sort the keys */
+ param->max_stage= keys_to_repair*2;
+
rec_per_key_part= param->new_rec_per_key_part;
for (sort_param.key=0 ; sort_param.key < share->base.keys ;
rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++)
@@ -3869,6 +3904,9 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
/* Set for next loop */
sort_info.max_records= (ha_rows) sort_info.new_info->s->state.state.records;
+ param->stage++; /* Next stage */
+ param->progress= 0;
+
if (param->testflag & T_STATISTICS)
maria_update_key_parts(sort_param.keyinfo, rec_per_key_part,
sort_param.unique,
@@ -3949,6 +3987,10 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
sort_info.org_data_file_type= share->data_file_type;
sort_info.filelength= share->state.state.data_file_length;
sort_param.fix_datafile=0;
+
+ /* Offsets are now in proportion to the new file length */
+ param->max_progress= sort_info.filelength;
+
}
else
share->state.state.data_file_length=sort_param.max_pos;
@@ -4749,6 +4791,11 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
if (_ma_killed_ptr(param))
DBUG_RETURN(1);
+ if (param->progress_counter++ >= WRITE_COUNT)
+ {
+ param->progress_counter= 0;
+ _ma_report_progress(param, param->progress, param->max_progress);
+ }
switch (sort_info->org_data_file_type) {
case BLOCK_RECORD:
@@ -4789,6 +4836,9 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
flag= HA_ERR_ROW_NOT_VISIBLE;
}
}
+ param->progress= (ma_recordpos_to_page(info->cur_row.lastpos)*
+ share->block_size);
+
share->page_type= save_page_type;
if (!flag)
{
@@ -4841,6 +4891,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
DBUG_RETURN(-1);
}
sort_param->start_recpos=sort_param->pos;
+ param->progress= sort_param->pos;
if (!sort_param->fix_datafile)
{
sort_param->current_filepos= sort_param->pos;
@@ -4868,6 +4919,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
LINT_INIT(to);
pos=sort_param->pos;
+ param->progress= pos;
searching=(sort_param->fix_datafile && (param->testflag & T_EXTEND));
parallel_flag= (sort_param->read_cache.file < 0) ? READING_NEXT : 0;
for (;;)
@@ -5177,6 +5229,7 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
}
}
case COMPRESSED_RECORD:
+ param->progress= sort_param->pos;
for (searching=0 ;; searching=1, sort_param->pos++)
{
if (_ma_read_cache(info, &sort_param->read_cache, block_info.header,
@@ -5251,8 +5304,10 @@ static int sort_get_next_record(MARIA_SORT_PARAM *sort_param)
}
DBUG_RETURN(0);
}
+ case NO_RECORD:
+ DBUG_RETURN(1); /* Impossible */
}
- DBUG_RETURN(1); /* Impossible */
+ DBUG_RETURN(1); /* Impossible */
}
@@ -5375,6 +5430,8 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
sort_param->filepos+=reclength+length;
share->state.split++;
break;
+ case NO_RECORD:
+ DBUG_RETURN(1); /* Impossible */
}
}
if (sort_param->master)
diff --git a/storage/maria/ma_check_standalone.h b/storage/maria/ma_check_standalone.h
index 8cda285bb99..f9242bbe123 100644
--- a/storage/maria/ma_check_standalone.h
+++ b/storage/maria/ma_check_standalone.h
@@ -35,6 +35,13 @@ int _ma_killed_ptr(HA_CHECK *param __attribute__((unused)))
return 0;
}
+
+void _ma_report_progress(HA_CHECK *param __attribute__((unused)),
+ ulonglong progress __attribute__((unused)),
+ ulonglong max_progress __attribute__((unused)))
+{
+}
+
/* print warnings and errors */
/* VARARGS */
diff --git a/storage/maria/ma_checkpoint.c b/storage/maria/ma_checkpoint.c
index 6576c365a47..602e5da3065 100644
--- a/storage/maria/ma_checkpoint.c
+++ b/storage/maria/ma_checkpoint.c
@@ -580,51 +580,59 @@ pthread_handler_t ma_checkpoint_background(void *arg)
{
case 0:
{
- TRANSLOG_ADDRESS horizon= translog_get_horizon();
+ /* If checkpoints are disabled, wait 1 second and try again */
+ if (maria_checkpoint_disabled)
+ {
+ sleep_time= 1;
+ break;
+ }
+ {
+ TRANSLOG_ADDRESS horizon= translog_get_horizon();
- /*
- With background flushing evenly distributed over the time
- between two checkpoints, we should have only little flushing to do
- in the checkpoint.
- */
- /*
- No checkpoint if little work of interest for recovery was done
- since last checkpoint. Such work includes log writing (lengthens
- recovery, checkpoint would shorten it), page flushing (checkpoint
- would decrease the amount of read pages in recovery).
- In case of one short statement per minute (very low load), we don't
- want to checkpoint every minute, hence the positive
- maria_checkpoint_min_activity.
- */
- if ((ulonglong) (horizon - log_horizon_at_last_checkpoint) <=
- maria_checkpoint_min_log_activity &&
- ((ulonglong) (maria_pagecache->global_cache_write -
- pagecache_flushes_at_last_checkpoint) *
+ /*
+ With background flushing evenly distributed over the time
+ between two checkpoints, we should have only little flushing to do
+ in the checkpoint.
+ */
+ /*
+ No checkpoint if little work of interest for recovery was done
+ since last checkpoint. Such work includes log writing (lengthens
+ recovery, checkpoint would shorten it), page flushing (checkpoint
+ would decrease the amount of read pages in recovery).
+ In case of one short statement per minute (very low load), we don't
+ want to checkpoint every minute, hence the positive
+ maria_checkpoint_min_activity.
+ */
+ if ((ulonglong) (horizon - log_horizon_at_last_checkpoint) <=
+ maria_checkpoint_min_log_activity &&
+ ((ulonglong) (maria_pagecache->global_cache_write -
+ pagecache_flushes_at_last_checkpoint) *
maria_pagecache->block_size) <=
- maria_checkpoint_min_cache_activity)
- {
+ maria_checkpoint_min_cache_activity)
+ {
+ /*
+ Not enough has happend since last checkpoint.
+ Sleep for a while and try again later
+ */
+ sleep_time= interval;
+ break;
+ }
+ sleep_time= 1;
+ ma_checkpoint_execute(CHECKPOINT_MEDIUM, TRUE);
/*
- Not enough has happend since last checkpoint.
- Sleep for a while and try again later
+ Snapshot this kind of "state" of the engine. Note that the value
+ below is possibly greater than last_checkpoint_lsn.
+ */
+ log_horizon_at_last_checkpoint= translog_get_horizon();
+ pagecache_flushes_at_last_checkpoint=
+ maria_pagecache->global_cache_write;
+ /*
+ If the checkpoint above succeeded it has set d|kfiles and
+ d|kfiles_end. If is has failed, it has set
+ pages_to_flush_before_next_checkpoint to 0 so we will skip flushing
+ and sleep until the next checkpoint.
*/
- sleep_time= interval;
- break;
}
- sleep_time= 1;
- ma_checkpoint_execute(CHECKPOINT_MEDIUM, TRUE);
- /*
- Snapshot this kind of "state" of the engine. Note that the value below
- is possibly greater than last_checkpoint_lsn.
- */
- log_horizon_at_last_checkpoint= translog_get_horizon();
- pagecache_flushes_at_last_checkpoint=
- maria_pagecache->global_cache_write;
- /*
- If the checkpoint above succeeded it has set d|kfiles and
- d|kfiles_end. If is has failed, it has set
- pages_to_flush_before_next_checkpoint to 0 so we will skip flushing
- and sleep until the next checkpoint.
- */
break;
}
case 1:
diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c
index 54ebcdc709e..ea9671d4b07 100644
--- a/storage/maria/ma_create.c
+++ b/storage/maria/ma_create.c
@@ -251,10 +251,16 @@ int maria_create(const char *name, enum data_file_type datafile_type,
datafile_type= BLOCK_RECORD;
}
+ if (datafile_type == NO_RECORD && uniques)
+ {
+ /* Can't do unique without data, revert to block records */
+ datafile_type= BLOCK_RECORD;
+ }
+
if (datafile_type == DYNAMIC_RECORD)
options|= HA_OPTION_PACK_RECORD; /* Must use packed records */
- if (datafile_type == STATIC_RECORD)
+ if (datafile_type == STATIC_RECORD || datafile_type == NO_RECORD)
{
/* We can't use checksum with static length rows */
flags&= ~HA_CREATE_CHECKSUM;
@@ -375,7 +381,9 @@ int maria_create(const char *name, enum data_file_type datafile_type,
}
else
{
- if (datafile_type != STATIC_RECORD)
+ if (datafile_type == NO_RECORD)
+ pointer= 0;
+ else if (datafile_type != STATIC_RECORD)
pointer= maria_get_pointer_length(ci->data_file_length,
maria_data_pointer_size);
else
diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c
index d2e011fcf24..183f74835b2 100644
--- a/storage/maria/ma_extra.c
+++ b/storage/maria/ma_extra.c
@@ -415,9 +415,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
if (!share->temporary)
error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
FLUSH_KEEP, FLUSH_KEEP);
-#ifdef HAVE_PREAD
+
_ma_decrement_open_count(info, 1);
-#endif
if (share->not_flushed)
{
share->not_flushed= 0;
@@ -490,6 +489,14 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
} /* maria_extra */
+void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func,
+ void *func_arg)
+{
+ info->index_cond_func= func;
+ info->index_cond_func_arg= func_arg;
+}
+
+
/*
Start/Stop Inserting Duplicates Into a Table, WL#1648.
*/
@@ -644,3 +651,10 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
_ma_set_fatal_error(info->s, HA_ERR_CRASHED);
DBUG_RETURN(1);
}
+
+
+my_bool ma_killed_standalone(MARIA_HA *info __attribute__((unused)))
+{
+ return 0;
+}
+
diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c
index 35a34d32713..13c3a24f362 100644
--- a/storage/maria/ma_ft_boolean_search.c
+++ b/storage/maria/ma_ft_boolean_search.c
@@ -475,14 +475,15 @@ static void _ftb_init_index_search(FT_INFO *ftb)
int i;
FTB_WORD *ftbw;
- if ((ftb->state != READY && ftb->state !=INDEX_DONE) ||
- ftb->keynr == NO_SUCH_KEY)
+ if (ftb->state == UNINITIALIZED || ftb->keynr == NO_SUCH_KEY)
return;
ftb->state=INDEX_SEARCH;
- for (i=ftb->queue.elements; i; i--)
+ for (i= queue_last_element(&ftb->queue);
+ (int) i >= (int) queue_first_element(&ftb->queue);
+ i--)
{
- ftbw=(FTB_WORD *)(ftb->queue.root[i]);
+ ftbw=(FTB_WORD *)(queue_element(&ftb->queue, i));
if (ftbw->flags & FTB_FLAG_TRUNC)
{
@@ -587,7 +588,7 @@ FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr,
sizeof(void *))))
goto err;
reinit_queue(&ftb->queue, ftb->queue.max_elements, 0, 0,
- (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0);
+ (int (*)(void*, uchar*, uchar*))FTB_WORD_cmp, 0, 0, 0);
for (ftbw= ftb->last_word; ftbw; ftbw= ftbw->prev)
queue_insert(&ftb->queue, (uchar *)ftbw);
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
@@ -830,7 +831,7 @@ int maria_ft_boolean_read_next(FT_INFO *ftb, char *record)
/* update queue */
_ft2_search(ftb, ftbw, 0);
- queue_replaced(& ftb->queue);
+ queue_replace_top(&ftb->queue);
}
ftbe=ftb->root;
diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c
index 927f34f8b72..3bb7defcaaf 100644
--- a/storage/maria/ma_ft_nlq_search.c
+++ b/storage/maria/ma_ft_nlq_search.c
@@ -253,12 +253,12 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, uchar *query,
{
QUEUE best;
init_queue(&best,ft_query_expansion_limit,0,0, (queue_compare) &FT_DOC_cmp,
- 0);
+ 0, 0, 0);
tree_walk(&aio.dtree, (tree_walk_action) &walk_and_push,
&best, left_root_right);
while (best.elements)
{
- my_off_t docid=((FT_DOC *)queue_remove(& best, 0))->dpos;
+ my_off_t docid= ((FT_DOC *)queue_remove_top(&best))->dpos;
if (!(*info->read_record)(info, record, docid))
{
info->update|= HA_STATE_AKTIV;
diff --git a/storage/maria/ma_key.c b/storage/maria/ma_key.c
index 207ae9a8bda..1e60e6a8c06 100644
--- a/storage/maria/ma_key.c
+++ b/storage/maria/ma_key.c
@@ -26,7 +26,8 @@
#define CHECK_KEYS /* Enable safety checks */
-static int _ma_put_key_in_record(MARIA_HA *info,uint keynr,uchar *record);
+static int _ma_put_key_in_record(MARIA_HA *info, uint keynr,
+ my_bool unpack_blobs, uchar *record);
#define FIX_LENGTH(cs, pos, length, char_length) \
do { \
@@ -476,6 +477,9 @@ void _ma_copy_key(MARIA_KEY *to, const MARIA_KEY *from)
_ma_put_key_in_record()
info MARIA handler
keynr Key number that was used
+ unpack_blobs TRUE <=> Unpack blob columns
+ FALSE <=> Skip them. This is used by index condition
+ pushdown check function
record Store key here
Last read key is in info->lastkey
@@ -489,7 +493,7 @@ void _ma_copy_key(MARIA_KEY *to, const MARIA_KEY *from)
*/
static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr,
- uchar *record)
+ my_bool unpack_blobs, uchar *record)
{
reg2 uchar *key;
uchar *pos,*key_end;
@@ -582,16 +586,19 @@ static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr,
if (length > keyseg->length || key+length > key_end)
goto err;
#endif
- memcpy(record+keyseg->start+keyseg->bit_start,
- (char*) &blob_ptr,sizeof(char*));
- memcpy(blob_ptr,key,length);
- blob_ptr+=length;
+ if (unpack_blobs)
+ {
+ memcpy(record+keyseg->start+keyseg->bit_start,
+ (char*) &blob_ptr,sizeof(char*));
+ memcpy(blob_ptr,key,length);
+ blob_ptr+=length;
- /* The above changed info->lastkey2. Inform maria_rnext_same(). */
- info->update&= ~HA_STATE_RNEXT_SAME;
+ /* The above changed info->lastkey2. Inform maria_rnext_same(). */
+ info->update&= ~HA_STATE_RNEXT_SAME;
- _ma_store_blob_length(record+keyseg->start,
- (uint) keyseg->bit_start,length);
+ _ma_store_blob_length(record+keyseg->start,
+ (uint) keyseg->bit_start,length);
+ }
key+=length;
}
else if (keyseg->flag & HA_SWAP_KEY)
@@ -621,6 +628,7 @@ static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr,
DBUG_RETURN(0);
err:
+ DBUG_PRINT("info",("error"));
DBUG_RETURN(1); /* Crashed row */
} /* _ma_put_key_in_record */
@@ -634,7 +642,7 @@ int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
{
if (info->lastinx >= 0)
{ /* Read only key */
- if (_ma_put_key_in_record(info,(uint) info->lastinx,buf))
+ if (_ma_put_key_in_record(info, (uint)info->lastinx, TRUE, buf))
{
_ma_set_fatal_error(info->s, HA_ERR_CRASHED);
return -1;
@@ -648,6 +656,54 @@ int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
}
+
+/*
+ Save current key tuple to record and call index condition check function
+
+ SYNOPSIS
+ ma_check_index_cond()
+ info MyISAM handler
+ keynr Index we're running a scan on
+ record Record buffer to use (it is assumed that index check function
+ will look for column values there)
+
+ RETURN
+ ICP_ERROR Error ; my_errno set to HA_ERR_CRASHED
+ ICP_NO_MATCH Index condition is not satisfied, continue scanning
+ ICP_MATCH Index condition is satisfied
+ ICP_OUT_OF_RANGE Index condition is not satisfied, end the scan.
+ my_errno set to HA_ERR_END_OF_FILE
+
+ info->cur_row.lastpos is set to HA_OFFSET_ERROR in case of ICP_ERROR or
+ ICP_OUT_OF_RANGE to indicate that we don't have any active row.
+*/
+
+ICP_RESULT ma_check_index_cond(register MARIA_HA *info, uint keynr,
+ uchar *record)
+{
+ ICP_RESULT res= ICP_MATCH;
+ if (info->index_cond_func)
+ {
+ if (_ma_put_key_in_record(info, keynr, FALSE, record))
+ {
+ /* Impossible case; Can only happen if bug in code */
+ maria_print_error(info->s, HA_ERR_CRASHED);
+ info->cur_row.lastpos= HA_OFFSET_ERROR; /* No active record */
+ my_errno= HA_ERR_CRASHED;
+ res= ICP_ERROR;
+ }
+ else if ((res= info->index_cond_func(info->index_cond_func_arg)) ==
+ ICP_OUT_OF_RANGE)
+ {
+ /* We got beyond the end of scanned range */
+ info->cur_row.lastpos= HA_OFFSET_ERROR; /* No active record */
+ my_errno= HA_ERR_END_OF_FILE;
+ }
+ }
+ return res;
+}
+
+
/*
Retrieve auto_increment info
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index a01e0949b68..cdb26716e3f 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -458,7 +458,9 @@ void translog_lock_handler_assert_owner()
@param num how many records should be filled
*/
-static void check_translog_description_table(int num)
+static uint max_allowed_translog_type= 0;
+
+void check_translog_description_table(int num)
{
int i;
DBUG_ENTER("check_translog_description_table");
@@ -467,6 +469,7 @@ static void check_translog_description_table(int num)
/* last is reserved for extending the table */
DBUG_ASSERT(num < LOGREC_NUMBER_OF_TYPES - 1);
DBUG_ASSERT(log_record_type_descriptor[0].rclass == LOGRECTYPE_NOT_ALLOWED);
+ max_allowed_translog_type= num;
for (i= 0; i <= num; i++)
{
@@ -1078,7 +1081,7 @@ static my_bool translog_write_file_header()
memcpy(page, maria_trans_file_magic, sizeof(maria_trans_file_magic));
page+= sizeof(maria_trans_file_magic);
/* timestamp */
- timestamp= my_getsystime();
+ timestamp= my_hrtime().val;
int8store(page, timestamp);
page+= 8;
/* maria version */
@@ -3583,6 +3586,7 @@ my_bool translog_init_with_table(const char *directory,
log_descriptor.flush_no= 0;
log_descriptor.next_pass_max_lsn= LSN_IMPOSSIBLE;
+ /* Normally in Aria this this calls translog_table_init() */
(*init_table_func)();
compile_time_assert(sizeof(log_descriptor.dirty_buffer_mask) * 8 >=
TRANSLOG_BUFFERS_NO);
@@ -6224,6 +6228,8 @@ my_bool translog_write_record(LSN *lsn,
(uint) short_trid, (ulong) rec_len));
DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY);
+ DBUG_ASSERT(type != 0);
+ DBUG_ASSERT((uint)type <= max_allowed_translog_type);
if (unlikely(translog_status != TRANSLOG_OK))
{
DBUG_PRINT("error", ("Transaction log is write protected"));
@@ -6322,9 +6328,9 @@ my_bool translog_write_record(LSN *lsn,
/* process this parts */
if (!(rc= (log_record_type_descriptor[type].prewrite_hook &&
- (*log_record_type_descriptor[type].prewrite_hook) (type, trn,
- tbl_info,
- hook_arg))))
+ (*log_record_type_descriptor[type].prewrite_hook)(type, trn,
+ tbl_info,
+ hook_arg))))
{
switch (log_record_type_descriptor[type].rclass) {
case LOGRECTYPE_VARIABLE_LENGTH:
@@ -6337,6 +6343,7 @@ my_bool translog_write_record(LSN *lsn,
short_trid, &parts, trn, hook_arg);
break;
case LOGRECTYPE_NOT_ALLOWED:
+ DBUG_ASSERT(0);
default:
DBUG_ASSERT(0);
rc= 1;
@@ -7712,7 +7719,7 @@ static my_bool translog_sync_files(uint32 min, uint32 max,
flush_interval= group_commit_wait;
if (flush_interval)
- flush_start= my_micro_time();
+ flush_start= microsecond_interval_timer();
for (fn= min; fn <= max; fn++)
{
TRANSLOG_FILE *file= get_logfile_by_number(fn);
@@ -7979,7 +7986,8 @@ retest:
/*
We do not check time here because pthread_mutex_lock rarely takes
a lot of time so we can sacrifice a bit precision to performance
- (taking into account that my_micro_time() might be expensive call).
+ (taking into account that microsecond_interval_timer() might be
+ expensive call).
*/
if (flush_interval == 0)
break; /* flush pass is ended */
@@ -7988,7 +7996,8 @@ retest:
if (log_descriptor.next_pass_max_lsn == LSN_IMPOSSIBLE)
{
if (flush_interval == 0 ||
- (time_spent= (my_micro_time() - flush_start)) >= flush_interval)
+ (time_spent= (microsecond_interval_timer() - flush_start)) >=
+ flush_interval)
{
pthread_mutex_unlock(&log_descriptor.log_flush_lock);
break;
@@ -8780,7 +8789,7 @@ ma_soft_sync_background( void *arg __attribute__((unused)))
DBUG_ENTER("ma_soft_sync_background");
for(;;)
{
- ulonglong prev_loop= my_micro_time();
+ ulonglong prev_loop= microsecond_interval_timer();
ulonglong time, sleep;
uint32 min, max, sync_request;
min= soft_sync_min;
@@ -8792,7 +8801,7 @@ ma_soft_sync_background( void *arg __attribute__((unused)))
sleep= group_commit_wait;
if (sync_request)
translog_sync_files(min, max, FALSE);
- time= my_micro_time() - prev_loop;
+ time= microsecond_interval_timer() - prev_loop;
if (time > sleep)
sleep= 0;
else
diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h
index f33e92e9771..5ac6d67413a 100644
--- a/storage/maria/ma_loghandler.h
+++ b/storage/maria/ma_loghandler.h
@@ -312,6 +312,9 @@ extern my_bool translog_init_with_table(const char *directory,
my_bool readonly,
void (*init_table_func)(),
my_bool no_error);
+#ifndef DBUG_OFF
+void check_translog_description_table(int num);
+#endif
extern my_bool
translog_write_record(LSN *lsn, enum translog_record_type type, TRN *trn,
diff --git a/storage/maria/ma_norec.c b/storage/maria/ma_norec.c
new file mode 100644
index 00000000000..6d4f37e34fd
--- /dev/null
+++ b/storage/maria/ma_norec.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 2010 Monty Program Ab
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ Functions to handle tables with no row data (only index)
+ This is useful when you just want to do key reads or want to use
+ the index to check against duplicates.
+*/
+
+#include "maria_def.h"
+
+my_bool _ma_write_no_record(MARIA_HA *info __attribute__((unused)),
+ const uchar *record __attribute__((unused)))
+{
+ return 0;
+}
+
+my_bool _ma_update_no_record(MARIA_HA *info __attribute__((unused)),
+ MARIA_RECORD_POS pos __attribute__((unused)),
+ const uchar *oldrec __attribute__((unused)),
+ const uchar *record __attribute__((unused)))
+{
+ return HA_ERR_WRONG_COMMAND;
+}
+
+
+my_bool _ma_delete_no_record(MARIA_HA *info __attribute__((unused)),
+ const uchar *record __attribute__((unused)))
+{
+ return HA_ERR_WRONG_COMMAND;
+}
+
+
+int _ma_read_no_record(MARIA_HA *info __attribute__((unused)),
+ uchar *record __attribute__((unused)),
+ MARIA_RECORD_POS pos __attribute__((unused)))
+{
+ return HA_ERR_WRONG_COMMAND;
+}
+
+
+int _ma_read_rnd_no_record(MARIA_HA *info __attribute__((unused)),
+ uchar *buf __attribute__((unused)),
+ MARIA_RECORD_POS filepos __attribute__((unused)),
+ my_bool skip_deleted_blocks __attribute__((unused)))
+{
+ return HA_ERR_WRONG_COMMAND;
+}
+
+my_off_t _ma_no_keypos_to_recpos(MARIA_SHARE *share __attribute__ ((unused)),
+ my_off_t pos __attribute__ ((unused)))
+{
+ return 0;
+}
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index 498904f89a7..c9dc20ce78b 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -205,6 +205,9 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, const char *name,
#ifdef THREAD
thr_lock_data_init(&share->lock,&m_info->lock,(void*) m_info);
#endif
+ if (share->options & HA_OPTION_TMP_TABLE)
+ m_info->lock.type= TL_WRITE;
+
m_info->open_list.data=(void*) m_info;
maria_open_list=list_add(maria_open_list,&m_info->open_list);
@@ -491,6 +494,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
(uint) share->base.block_size,
(uint) maria_block_size));
my_errno=HA_ERR_UNSUPPORTED;
+ my_printf_error(my_errno, "Wrong block size %u; Expected %u",
+ MYF(0),
+ (uint) share->base.block_size,
+ (uint) maria_block_size);
goto err;
}
@@ -786,6 +793,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->blobs[j].offset= share->columndef[i].offset;
j++;
}
+ if (share->columndef[i].type == FIELD_VARCHAR)
+ share->has_varchar_fields= 1;
+ if (share->columndef[i].null_bit)
+ share->has_null_fields= 1;
}
share->columndef[i].type= FIELD_LAST; /* End marker */
disk_pos= _ma_column_nr_read(disk_pos, share->column_nr,
@@ -968,6 +979,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->state.changed));
pthread_mutex_unlock(&THR_LOCK_maria);
+
+ m_info->open_flags= open_flags;
DBUG_RETURN(m_info);
err:
@@ -1109,6 +1122,20 @@ void _ma_setup_functions(register MARIA_SHARE *share)
else
share->calc_checksum= _ma_checksum;
break;
+ case NO_RECORD:
+ share->read_record= _ma_read_no_record;
+ share->scan= _ma_read_rnd_no_record;
+ share->delete_record= _ma_delete_no_record;
+ share->update_record= _ma_update_no_record;
+ share->write_record= _ma_write_no_record;
+ share->recpos_to_keypos= _ma_no_keypos_to_recpos;
+ share->keypos_to_recpos= _ma_no_keypos_to_recpos;
+
+ /* Abort if following functions are called */
+ share->compare_record= 0;
+ share->compare_unique= 0;
+ share->calc_checksum= 0;
+ break;
case BLOCK_RECORD:
share->once_init= _ma_once_init_block_record;
share->once_end= _ma_once_end_block_record;
diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c
index 96504cfba2d..33112a1ec5e 100644
--- a/storage/maria/ma_recovery.c
+++ b/storage/maria/ma_recovery.c
@@ -344,7 +344,7 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn,
}
}
- now= my_getsystime();
+ now= microsecond_interval_timer();
in_redo_phase= TRUE;
if (run_redo_phase(from_lsn, end_lsn, apply))
{
@@ -374,10 +374,10 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn,
in_redo_phase= FALSE;
old_now= now;
- now= my_getsystime();
+ now= microsecond_interval_timer();
if (recovery_message_printed == REC_MSG_REDO)
{
- double phase_took= (now - old_now)/10000000.0;
+ double phase_took= (now - old_now)/1000000.0;
/*
Detailed progress info goes to stderr, because ma_message_no_user()
cannot put several messages on one line.
@@ -443,10 +443,10 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn,
}
old_now= now;
- now= my_getsystime();
+ now= microsecond_interval_timer();
if (recovery_message_printed == REC_MSG_UNDO)
{
- double phase_took= (now - old_now)/10000000.0;
+ double phase_took= (now - old_now)/1000000.0;
procent_printed= 1;
fprintf(stderr, " (%.1f seconds); ", phase_took);
fflush(stderr);
@@ -463,10 +463,10 @@ int maria_apply_log(LSN from_lsn, LSN end_lsn,
}
old_now= now;
- now= my_getsystime();
+ now= microsecond_interval_timer();
if (recovery_message_printed == REC_MSG_FLUSH)
{
- double phase_took= (now - old_now)/10000000.0;
+ double phase_took= (now - old_now)/1000000.0;
procent_printed= 1;
fprintf(stderr, " (%.1f seconds); ", phase_took);
fflush(stderr);
diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c
index 976e09ece99..1ece9e0049e 100644
--- a/storage/maria/ma_rkey.c
+++ b/storage/maria/ma_rkey.c
@@ -34,6 +34,7 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
HA_KEYSEG *last_used_keyseg;
uint32 nextflag;
MARIA_KEY key;
+ ICP_RESULT icp_res= ICP_MATCH;
DBUG_ENTER("maria_rkey");
DBUG_PRINT("enter", ("base: 0x%lx buf: 0x%lx inx: %d search_flag: %d",
(long) info, (long) buf, inx, search_flag));
@@ -82,10 +83,11 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
rw_rdlock(&keyinfo->root_lock);
nextflag= maria_read_vec[search_flag] | key.flag;
- if (search_flag != HA_READ_KEY_EXACT ||
- ((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME))
+ if (search_flag != HA_READ_KEY_EXACT)
+ {
+ /* Assume we will get a read next/previous call after this one */
nextflag|= SEARCH_SAVE_BUFF;
-
+ }
switch (keyinfo->key_alg) {
#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
@@ -101,16 +103,18 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
if (!_ma_search(info, &key, nextflag, info->s->state.key_root[inx]))
{
MARIA_KEY lastkey;
- lastkey.keyinfo= keyinfo;
- lastkey.data= info->lastkey_buff;
/*
Found a key, but it might not be usable. We cannot use rows that
are inserted by other threads after we got our table lock
("concurrent inserts"). The record may not even be present yet.
Keys are inserted into the index(es) before the record is
- inserted into the data file.
+ inserted into the data file.
+
+ If index condition is present, it must be either satisfied or
+ not satisfied with an out-of-range condition.
*/
- if ((*share->row_is_visible)(info))
+ if ((*share->row_is_visible)(info) &&
+ ((icp_res= ma_check_index_cond(info, inx, buf)) != ICP_NO_MATCH))
break;
/* The key references a concurrently inserted record. */
@@ -122,7 +126,9 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
info->cur_row.lastpos= HA_OFFSET_ERROR;
break;
}
-
+
+ lastkey.keyinfo= keyinfo;
+ lastkey.data= info->lastkey_buff;
do
{
uint not_used[2];
@@ -138,6 +144,18 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
if (_ma_search_next(info, &lastkey, maria_readnext_vec[search_flag],
info->s->state.key_root[inx]))
break; /* purecov: inspected */
+
+ /*
+ If we are at the last key on the key page, allow writers to
+ access the index.
+ */
+ if (info->int_keypos >= info->int_maxpos &&
+ ma_yield_and_check_if_killed(info, inx))
+ {
+ DBUG_ASSERT(info->cur_row.lastpos == HA_OFFSET_ERROR);
+ break;
+ }
+
/*
Check that the found key does still match the search.
_ma_search_next() delivers the next key regardless of its
@@ -153,7 +171,13 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
break;
/* purecov: end */
}
- } while (!(*share->row_is_visible)(info));
+
+ } while (!(*share->row_is_visible)(info) ||
+ ((icp_res= ma_check_index_cond(info, inx, buf)) == 0));
+ }
+ else
+ {
+ DBUG_ASSERT(info->cur_row.lastpos);
}
}
if (share->lock_key_trees)
@@ -161,10 +185,15 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
if (info->cur_row.lastpos == HA_OFFSET_ERROR)
{
+ if (icp_res == ICP_OUT_OF_RANGE)
+ {
+ /* We don't want HA_ERR_END_OF_FILE in this particular case */
+ my_errno= HA_ERR_KEY_NOT_FOUND;
+ }
fast_ma_writeinfo(info);
goto err;
}
-
+
/* Calculate length of the found key; Used by maria_rnext_same */
if ((keyinfo->flag & HA_VAR_LENGTH_KEY))
info->last_rkey_length= _ma_keylength_part(keyinfo, info->lastkey_buff,
@@ -200,3 +229,37 @@ err:
info->update|=HA_STATE_NEXT_FOUND; /* Previous gives last row */
DBUG_RETURN(my_errno);
} /* _ma_rkey */
+
+
+/*
+ Yield to possible other writers during a index scan.
+ Check also if we got killed by the user and if yes, return
+ HA_ERR_LOCK_WAIT_TIMEOUT
+
+ return 0 ok
+ return 1 Query has been requested to be killed
+*/
+
+my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx)
+{
+ MARIA_SHARE *share;
+ if (ma_killed(info))
+ {
+ /* purecov: begin tested */
+ /* Mark that we don't have an active row */
+ info->cur_row.lastpos= HA_OFFSET_ERROR;
+ /* Set error that we where aborted by kill from application */
+ my_errno= HA_ERR_ABORTED_BY_USER;
+ return 1;
+ /* purecov: end */
+ }
+
+ if ((share= info->s)->lock_key_trees)
+ {
+ /* Give writers a chance to access index */
+ rw_unlock(&share->keyinfo[inx].root_lock);
+ rw_rdlock(&share->keyinfo[inx].root_lock);
+ }
+ return 0;
+}
+
diff --git a/storage/maria/ma_rnext.c b/storage/maria/ma_rnext.c
index c49bbb19e83..e5ee84b61c7 100644
--- a/storage/maria/ma_rnext.c
+++ b/storage/maria/ma_rnext.c
@@ -30,6 +30,7 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
uint flag;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo;
+ ICP_RESULT icp_res= ICP_MATCH;
uint update_mask= HA_STATE_NEXT_FOUND;
DBUG_ENTER("maria_rnext");
@@ -105,8 +106,21 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
if (!error)
{
- while (!(*share->row_is_visible)(info))
+ while (!(*share->row_is_visible)(info) ||
+ ((icp_res= ma_check_index_cond(info, inx, buf)) == ICP_NO_MATCH))
{
+ /*
+ If we are at the last key on the key page, allow writers to
+ access the index.
+ */
+ if (info->int_keypos >= info->int_maxpos &&
+ ma_yield_and_check_if_killed(info, inx))
+ {
+ /* my_errno is set by ma_yield_and_check_if_killed() */
+ error= 1;
+ break;
+ }
+
/* Skip rows inserted by other threads since we got a lock */
if ((error= _ma_search_next(info, &info->last_key,
SEARCH_BIGGER,
@@ -120,14 +134,16 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
/* Don't clear if database-changed */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= update_mask;
-
- if (error)
+
+ if (error || icp_res != ICP_MATCH)
{
+ fast_ma_writeinfo(info);
if (my_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_END_OF_FILE;
+ my_errno= HA_ERR_END_OF_FILE;
}
else if (!buf)
{
+ fast_ma_writeinfo(info);
DBUG_RETURN(info->cur_row.lastpos == HA_OFFSET_ERROR ? my_errno : 0);
}
else if (!(*info->read_record)(info, buf, info->cur_row.lastpos))
diff --git a/storage/maria/ma_rnext_same.c b/storage/maria/ma_rnext_same.c
index cbd81d20816..c35d8ae0222 100644
--- a/storage/maria/ma_rnext_same.c
+++ b/storage/maria/ma_rnext_same.c
@@ -30,6 +30,7 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
int error;
uint inx,not_used[2];
MARIA_KEYDEF *keyinfo;
+ ICP_RESULT icp_res= ICP_MATCH;
DBUG_ENTER("maria_rnext_same");
if ((int) (inx= info->lastinx) < 0 ||
@@ -79,8 +80,19 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
info->cur_row.lastpos= HA_OFFSET_ERROR;
break;
}
+ /*
+ If we are at the last key on the key page, allow writers to
+ access the index.
+ */
+ if (info->int_keypos >= info->int_maxpos &&
+ ma_yield_and_check_if_killed(info, inx))
+ {
+ error= 1;
+ break;
+ }
/* Skip rows that are inserted by other threads since we got a lock */
- if ((info->s->row_is_visible)(info))
+ if ((info->s->row_is_visible)(info) &&
+ ((icp_res= ma_check_index_cond(info, inx, buf)) != ICP_NO_MATCH))
break;
}
}
@@ -90,13 +102,15 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME;
- if (error)
+ if (error || icp_res != ICP_MATCH)
{
+ fast_ma_writeinfo(info);
if (my_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_END_OF_FILE;
+ my_errno= HA_ERR_END_OF_FILE;
}
else if (!buf)
{
+ fast_ma_writeinfo(info);
DBUG_RETURN(info->cur_row.lastpos == HA_OFFSET_ERROR ? my_errno : 0);
}
else if (!(*info->read_record)(info, buf, info->cur_row.lastpos))
diff --git a/storage/maria/ma_rprev.c b/storage/maria/ma_rprev.c
index b9f46d7c405..c4bcb9de967 100644
--- a/storage/maria/ma_rprev.c
+++ b/storage/maria/ma_rprev.c
@@ -28,6 +28,7 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
register uint flag;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo;
+ ICP_RESULT icp_res= ICP_MATCH;
DBUG_ENTER("maria_rprev");
if ((inx = _ma_check_index(info,inx)) < 0)
@@ -55,8 +56,24 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
if (!error)
{
- while (!(*share->row_is_visible)(info))
+ my_off_t cur_keypage= info->last_keypage;
+ while (!(*share->row_is_visible)(info) ||
+ ((icp_res= ma_check_index_cond(info, inx, buf)) == ICP_NO_MATCH))
{
+ /*
+ If we are at the last (i.e. first?) key on the key page,
+ allow writers to access the index.
+ */
+ if (info->last_keypage != cur_keypage)
+ {
+ cur_keypage= info->last_keypage;
+ if (ma_yield_and_check_if_killed(info, inx))
+ {
+ error= 1;
+ break;
+ }
+ }
+
/* Skip rows that are inserted by other threads since we got a lock */
if ((error= _ma_search_next(info, &info->last_key,
SEARCH_SMALLER,
@@ -68,13 +85,16 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
rw_unlock(&keyinfo->root_lock);
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= HA_STATE_PREV_FOUND;
- if (error)
+
+ if (error || icp_res != ICP_MATCH)
{
+ fast_ma_writeinfo(info);
if (my_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_END_OF_FILE;
+ my_errno= HA_ERR_END_OF_FILE;
}
else if (!buf)
{
+ fast_ma_writeinfo(info);
DBUG_RETURN(info->cur_row.lastpos == HA_OFFSET_ERROR ? my_errno : 0);
}
else if (!(*info->read_record)(info, buf, info->cur_row.lastpos))
diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c
index d6270daacee..84123fec93a 100644
--- a/storage/maria/ma_search.c
+++ b/storage/maria/ma_search.c
@@ -149,7 +149,11 @@ static int _ma_search_no_save(register MARIA_HA *info, MARIA_KEY *key,
flag= (*keyinfo->bin_search)(key, &page, nextflag, &keypos, lastkey,
&last_key_not_used);
if (flag == MARIA_FOUND_WRONG_KEY)
- DBUG_RETURN(-1);
+ {
+ maria_print_error(info->s, HA_ERR_CRASHED);
+ my_errno= HA_ERR_CRASHED;
+ goto err;
+ }
page_flag= page.flag;
used_length= page.size;
nod_flag= page.node;
@@ -790,6 +794,7 @@ MARIA_RECORD_POS _ma_row_pos_from_key(const MARIA_KEY *key)
case 4: pos= (my_off_t) mi_uint4korr(after_key); break;
case 3: pos= (my_off_t) mi_uint3korr(after_key); break;
case 2: pos= (my_off_t) mi_uint2korr(after_key); break;
+ case 0: /* NO_RECORD */
default:
pos=0L; /* Shut compiler up */
}
@@ -899,6 +904,7 @@ void _ma_dpointer(MARIA_SHARE *share, uchar *buff, my_off_t pos)
case 4: mi_int4store(buff,pos); break;
case 3: mi_int3store(buff,pos); break;
case 2: mi_int2store(buff,(uint) pos); break;
+ case 0: break; /* For NO_RECORD */
default: abort(); /* Impossible */
}
} /* _ma_dpointer */
diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
index 5c5bd8f8d6c..7bfb53ca0a1 100644
--- a/storage/maria/ma_sort.c
+++ b/storage/maria/ma_sort.c
@@ -191,6 +191,9 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
&tempfile,&tempfile_for_exceptions))
== HA_POS_ERROR)
goto err; /* purecov: tested */
+
+ info->sort_info->param->stage++; /* Merge stage */
+
if (maxbuffer == 0)
{
if (!no_messages)
@@ -769,6 +772,8 @@ static int write_index(MARIA_SORT_PARAM *info,
if ((*info->key_write)(info, *sort_keys++))
DBUG_RETURN(-1); /* purecov: inspected */
}
+ if (info->sort_info->param->max_stage != 1) /* If not parallel */
+ _ma_report_progress(info->sort_info->param, 1, 1);
DBUG_RETURN(0);
} /* write_index */
@@ -779,7 +784,7 @@ static int merge_many_buff(MARIA_SORT_PARAM *info, uint keys,
uchar **sort_keys, BUFFPEK *buffpek,
int *maxbuffer, IO_CACHE *t_file)
{
- register int i;
+ int tmp, merges, max_merges;
IO_CACHE t_file2, *from_file, *to_file, *temp;
BUFFPEK *lastbuff;
DBUG_ENTER("merge_many_buff");
@@ -791,9 +796,21 @@ static int merge_many_buff(MARIA_SORT_PARAM *info, uint keys,
DISK_BUFFER_SIZE, info->sort_info->param->myf_rw))
DBUG_RETURN(1); /* purecov: inspected */
+ /* Calculate how many merges are needed */
+ max_merges= 1; /* Count merge_index */
+ tmp= *maxbuffer;
+ while (tmp >= MERGEBUFF2)
+ {
+ merges= (tmp-MERGEBUFF*3/2 + 1) / MERGEBUFF + 1;
+ max_merges+= merges;
+ tmp= merges;
+ }
+ merges= 0;
+
from_file= t_file ; to_file= &t_file2;
while (*maxbuffer >= MERGEBUFF2)
{
+ int i;
reinit_io_cache(from_file,READ_CACHE,0L,0,0);
reinit_io_cache(to_file,WRITE_CACHE,0L,0,0);
lastbuff=buffpek;
@@ -802,6 +819,8 @@ static int merge_many_buff(MARIA_SORT_PARAM *info, uint keys,
if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
buffpek+i,buffpek+i+MERGEBUFF-1))
goto cleanup;
+ if (info->sort_info->param->max_stage != 1) /* If not parallel */
+ _ma_report_progress(info->sort_info->param, merges++, max_merges);
}
if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
buffpek+i,buffpek+ *maxbuffer))
@@ -810,6 +829,8 @@ static int merge_many_buff(MARIA_SORT_PARAM *info, uint keys,
break; /* purecov: inspected */
temp=from_file; from_file=to_file; to_file=temp;
*maxbuffer= (int) (lastbuff-buffpek)-1;
+ if (info->sort_info->param->max_stage != 1) /* If not parallel */
+ _ma_report_progress(info->sort_info->param, merges++, max_merges);
}
cleanup:
close_cached_file(to_file); /* This holds old result */
@@ -939,7 +960,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
(int (*)(void*, uchar *,uchar*)) info->key_cmp,
- (void*) info))
+ (void*) info, 0, 0))
DBUG_RETURN(1); /* purecov: inspected */
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
@@ -988,7 +1009,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
uchar *base= buffpek->base;
uint max_keys=buffpek->max_keys;
- VOID(queue_remove(&queue,0));
+ VOID(queue_remove_top(&queue));
/* Put room used by buffer to use in other buffer */
for (refpek= (BUFFPEK**) &queue_top(&queue);
@@ -1013,7 +1034,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
}
else if (error == -1)
goto err; /* purecov: inspected */
- queue_replaced(&queue); /* Top element has been replaced */
+ queue_replace_top(&queue); /* Top element has been replaced */
}
}
buffpek=(BUFFPEK*) queue_top(&queue);
@@ -1066,6 +1087,8 @@ merge_index(MARIA_SORT_PARAM *info, uint keys, uchar **sort_keys,
if (merge_buffers(info,keys,tempfile,(IO_CACHE*) 0,sort_keys,buffpek,buffpek,
buffpek+maxbuffer))
DBUG_RETURN(1); /* purecov: inspected */
+ if (info->sort_info->param->max_stage != 1) /* If not parallel */
+ _ma_report_progress(info->sort_info->param, 1, 1);
DBUG_RETURN(0);
} /* merge_index */
diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c
index 5c88ba6745b..71094fb0343 100644
--- a/storage/maria/ma_static.c
+++ b/storage/maria/ma_static.c
@@ -39,6 +39,7 @@ my_bool maria_inited= FALSE;
my_bool maria_in_ha_maria= FALSE; /* If used from ha_maria or not */
my_bool maria_recovery_changed_data= 0, maria_recovery_verbose= 0;
my_bool maria_assert_if_crashed_table= 0;
+my_bool maria_checkpoint_disabled= 0;
pthread_mutex_t THR_LOCK_maria;
#if defined(THREAD) && !defined(DONT_USE_RW_LOCKS)
@@ -109,3 +110,6 @@ static int always_valid(const char *filename __attribute__((unused)))
}
int (*maria_test_invalid_symlink)(const char *filename)= always_valid;
+
+my_bool (*ma_killed)(MARIA_HA *)= ma_killed_standalone;
+
diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c
index ec3060822f9..4b0eb0f5644 100644
--- a/storage/maria/ma_test1.c
+++ b/storage/maria/ma_test1.c
@@ -410,6 +410,10 @@ static int run_test(const char *filename)
if (!silent)
printf("- Reading rows with key\n");
record[1]= 0; /* For nicer printf */
+
+ if (record_type == NO_RECORD)
+ maria_extra(file, HA_EXTRA_KEYREAD, 0);
+
for (i=0 ; i <= 25 ; i++)
{
create_key(key,i);
@@ -423,9 +427,15 @@ static int run_test(const char *filename)
(int) key_length,key+offset_to_key,error,my_errno,record+1);
}
}
+ if (record_type == NO_RECORD)
+ {
+ maria_extra(file, HA_EXTRA_NO_KEYREAD, 0);
+ goto end;
+ }
if (!silent)
printf("- Reading rows with position\n");
+
if (maria_scan_init(file))
{
fprintf(stderr, "maria_scan_init failed\n");
@@ -760,6 +770,8 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"rows-in-block", 'M', "Store rows in block format",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"rows-no-data", 'n', "Don't store any data, only keys",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"row-pointer-size", 'R', "Undocumented", (uchar**) &rec_pointer_size,
(uchar**) &rec_pointer_size, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"silent", 's', "Undocumented",
@@ -819,6 +831,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'M':
record_type= BLOCK_RECORD;
break;
+ case 'n':
+ record_type= NO_RECORD;
+ break;
case 'S':
if (key_field == FIELD_VARCHAR)
{
@@ -890,6 +905,10 @@ static void get_options(int argc, char *argv[])
exit(ho_error);
if (transactional)
record_type= BLOCK_RECORD;
+ if (record_type == NO_RECORD)
+ skip_update= skip_delete= 1;
+
+
return;
} /* get options */
diff --git a/storage/maria/ma_unique.c b/storage/maria/ma_unique.c
index 2fcca9cbe10..6f92ca1559c 100644
--- a/storage/maria/ma_unique.c
+++ b/storage/maria/ma_unique.c
@@ -52,7 +52,8 @@ my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, uchar *record,
info->lastinx= ~0;
DBUG_ASSERT(key.data_length == MARIA_UNIQUE_HASH_LENGTH);
- if (_ma_search(info, &key, SEARCH_FIND, info->s->state.key_root[def->key]))
+ if (_ma_search(info, &key, SEARCH_FIND | SEARCH_SAVE_BUFF,
+ info->s->state.key_root[def->key]))
{
info->page_changed=1; /* Can't optimize read next */
info->cur_row.lastpos= lastpos;
@@ -145,13 +146,14 @@ ha_checksum _ma_unique_hash(MARIA_UNIQUEDEF *def, const uchar *record)
keyseg->charset->coll->hash_sort(keyseg->charset,
(const uchar*) pos, length, &seed1,
&seed2);
- crc^= seed1;
+ crc+= seed1;
}
else
- while (pos != end)
- crc=((crc << 8) +
- (((uchar) *pos++))) +
- (crc >> (8*sizeof(ha_checksum)-8));
+ {
+ my_hash_sort_bin((CHARSET_INFO*) 0, pos, (size_t) (end-pos),
+ &seed1, &seed2);
+ crc+= seed1;
+ }
}
return crc;
}
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c
index 629e07b872d..7b80ca5a5b8 100644
--- a/storage/maria/ma_write.c
+++ b/storage/maria/ma_write.c
@@ -124,12 +124,23 @@ int maria_write(MARIA_HA *info, uchar *record)
goto err2;
/* Calculate and check all unique constraints */
- for (i=0 ; i < share->state.header.uniques ; i++)
+
+ if (share->state.header.uniques)
{
- if (_ma_check_unique(info,share->uniqueinfo+i,record,
- _ma_unique_hash(share->uniqueinfo+i,record),
- HA_OFFSET_ERROR))
- goto err2;
+ for (i=0 ; i < share->state.header.uniques ; i++)
+ {
+ MARIA_UNIQUEDEF *def= share->uniqueinfo + i;
+ ha_checksum unique_hash= _ma_unique_hash(share->uniqueinfo+i,record);
+ if (maria_is_key_active(share->state.key_map, def->key))
+ {
+ if (_ma_check_unique(info, def, record,
+ unique_hash, HA_OFFSET_ERROR))
+ goto err2;
+ }
+ else
+ maria_unique_store(record+ share->keyinfo[def->key].seg->start,
+ unique_hash);
+ }
}
/* Ensure we don't try to restore auto_increment if it doesn't change */
diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c
index 52a30dce235..34e9ed108ba 100644
--- a/storage/maria/maria_chk.c
+++ b/storage/maria/maria_chk.c
@@ -70,7 +70,7 @@ static const char *field_pack[]=
static const char *record_formats[]=
{
- "Fixed length", "Packed", "Compressed", "Block", "?"
+ "Fixed length", "Packed", "Compressed", "Block", "No data", "?", "?"
};
static const char *bitmap_description[]=
@@ -436,7 +436,7 @@ static struct my_option my_long_options[] =
static void print_version(void)
{
- printf("%s Ver 1.0 for %s at %s\n", my_progname, SYSTEM_TYPE,
+ printf("%s Ver 1.1 for %s at %s\n", my_progname, SYSTEM_TYPE,
MACHINE_TYPE);
NETWARE_SET_SCREEN_MODE(1);
}
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index 4692896212d..392e0f8d95c 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -386,6 +386,8 @@ typedef struct st_maria_share
my_bool temporary;
/* Below flag is needed to make log tables work with concurrent insert */
my_bool is_log_table;
+ my_bool has_null_fields;
+ my_bool has_varchar_fields; /* If table has varchar fields */
/*
Set to 1 if open_count was wrong at open. Set to avoid asserts for
wrong open count on close.
@@ -497,12 +499,12 @@ typedef struct st_maria_block_scan
MARIA_RECORD_POS row_base_page;
} MARIA_BLOCK_SCAN;
+typedef ICP_RESULT (*index_cond_func_t)(void *param);
struct st_maria_handler
{
MARIA_SHARE *s; /* Shared between open:s */
struct st_ma_transaction *trn; /* Pointer to active transaction */
- void *external_ptr; /* Pointer to THD in mysql */
MARIA_STATUS_INFO *state, state_save;
MARIA_STATUS_INFO *state_start; /* State at start of transaction */
MARIA_ROW cur_row; /* The active row that we just read */
@@ -519,6 +521,7 @@ struct st_maria_handler
DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */
MEM_ROOT ft_memroot; /* used by the parser */
MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */
+ void *external_ref; /* For MariaDB TABLE */
uchar *buff; /* page buffer */
uchar *keyread_buff; /* Buffer for last key read */
uchar *lastkey_buff; /* Last used search key */
@@ -560,6 +563,7 @@ struct st_maria_handler
ulong row_base_length; /* Length of row header */
uint row_flag; /* Flag to store in row header */
uint opt_flag; /* Optim. for space/speed */
+ uint open_flags; /* Flags used in open() */
uint update; /* If file changed since open */
int lastinx; /* Last used index */
uint last_rkey_length; /* Last length in maria_rkey() */
@@ -601,6 +605,9 @@ struct st_maria_handler
uchar *maria_rtree_recursion_state; /* For RTREE */
uchar length_buff[5]; /* temp buff to store blob lengths */
int maria_rtree_recursion_depth;
+
+ index_cond_func_t index_cond_func; /* Index condition function */
+ void *index_cond_func_arg; /* parameter for the func */
};
/* Some defines used by maria-functions */
@@ -819,11 +826,12 @@ extern uint maria_quick_table_bits;
extern char *maria_data_root;
extern uchar maria_zero_string[];
extern my_bool maria_inited, maria_in_ha_maria, maria_recovery_changed_data;
-extern my_bool maria_recovery_verbose;
+extern my_bool maria_recovery_verbose, maria_checkpoint_disabled;
extern my_bool maria_assert_if_crashed_table;
extern ulong maria_checkpoint_min_log_activity;
extern HASH maria_stored_state;
extern int (*maria_create_trn_hook)(MARIA_HA *);
+extern my_bool (*ma_killed)(MARIA_HA *);
/* This is used by _ma_calc_xxx_key_length och _ma_store_key */
typedef struct st_maria_s_param
@@ -883,6 +891,18 @@ extern my_bool _ma_update_static_record(MARIA_HA *, MARIA_RECORD_POS,
const uchar *, const uchar *);
extern my_bool _ma_delete_static_record(MARIA_HA *info, const uchar *record);
extern my_bool _ma_cmp_static_record(MARIA_HA *info, const uchar *record);
+
+extern my_bool _ma_write_no_record(MARIA_HA *info, const uchar *record);
+extern my_bool _ma_update_no_record(MARIA_HA *info, MARIA_RECORD_POS pos,
+ const uchar *oldrec, const uchar *record);
+extern my_bool _ma_delete_no_record(MARIA_HA *info, const uchar *record);
+extern int _ma_read_no_record(MARIA_HA *info, uchar *record,
+ MARIA_RECORD_POS pos);
+extern int _ma_read_rnd_no_record(MARIA_HA *info, uchar *buf,
+ MARIA_RECORD_POS filepos,
+ my_bool skip_deleted_blocks);
+my_off_t _ma_no_keypos_to_recpos(MARIA_SHARE *share, my_off_t pos);
+
extern my_bool _ma_ck_write(MARIA_HA *info, MARIA_KEY *key);
extern my_bool _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key,
MARIA_RECORD_POS *root);
@@ -1207,6 +1227,8 @@ int _ma_flush_table_files(MARIA_HA *info, uint flush_data_or_index,
See ma_check_standalone.h .
*/
int _ma_killed_ptr(HA_CHECK *param);
+void _ma_report_progress(HA_CHECK *param, ulonglong progress,
+ ulonglong max_progress);
void _ma_check_print_error _VARARGS((HA_CHECK *param, const char *fmt, ...))
ATTRIBUTE_FORMAT(printf, 2, 3);
void _ma_check_print_warning _VARARGS((HA_CHECK *param, const char *fmt, ...))
@@ -1281,4 +1303,11 @@ extern my_bool maria_flush_log_for_page_none(uchar *page,
pgcache_page_no_t page_no,
uchar *data_ptr);
extern PAGECACHE *maria_log_pagecache;
+extern void ma_set_index_cond_func(MARIA_HA *info, index_cond_func_t func,
+ void *func_arg);
+ICP_RESULT ma_check_index_cond(register MARIA_HA *info, uint keynr, uchar *record);
+
+extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx);
+extern my_bool ma_killed_standalone(MARIA_HA *);
+
extern uint _ma_file_callback_to_id(void *callback_data);
diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c
index 983a38e69e7..8332af60de5 100644
--- a/storage/maria/maria_pack.c
+++ b/storage/maria/maria_pack.c
@@ -590,7 +590,7 @@ static int compress(PACK_MRG_INFO *mrg,char *result_table)
Create a global priority queue in preparation for making
temporary Huffman trees.
*/
- if (init_queue(&queue,256,0,0,compare_huff_elements,0))
+ if (init_queue(&queue, 256, 0, 0, compare_huff_elements, 0, 0, 0))
goto err;
/*
@@ -1523,7 +1523,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
if (queue.max_elements < found)
{
delete_queue(&queue);
- if (init_queue(&queue,found,0,0,compare_huff_elements,0))
+ if (init_queue(&queue,found, 0, 0, compare_huff_elements, 0, 0, 0))
return -1;
}
@@ -1627,8 +1627,7 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Make a priority queue from the queue. Construct its index so that we
have a partially ordered tree.
*/
- for (i=found/2 ; i > 0 ; i--)
- _downheap(&queue,i);
+ queue_fix(&queue);
/* The Huffman algorithm. */
bytes_packed=0; bits_packed=0;
@@ -1639,12 +1638,9 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Popping from a priority queue includes a re-ordering of the queue,
to get the next least incidence element to the top.
*/
- a=(HUFF_ELEMENT*) queue_remove(&queue,0);
- /*
- Copy the next least incidence element. The queue implementation
- reserves root[0] for temporary purposes. root[1] is the top.
- */
- b=(HUFF_ELEMENT*) queue.root[1];
+ a=(HUFF_ELEMENT*) queue_remove_top(&queue);
+ /* Copy the next least incidence element */
+ b=(HUFF_ELEMENT*) queue_top(&queue);
/* Get a new element from the element buffer. */
new_huff_el=huff_tree->element_buffer+found+i;
/* The new element gets the sum of the two least incidence elements. */
@@ -1666,8 +1662,8 @@ static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
Replace the copied top element by the new element and re-order the
queue.
*/
- queue.root[1]=(uchar*) new_huff_el;
- queue_replaced(&queue);
+ queue_top(&queue)= (uchar*) new_huff_el;
+ queue_replace_top(&queue);
}
huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8;
@@ -1798,8 +1794,7 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
Make a priority queue from the queue. Construct its index so that we
have a partially ordered tree.
*/
- for (i=(found+1)/2 ; i > 0 ; i--)
- _downheap(&queue,i);
+ queue_fix(&queue);
/* The Huffman algorithm. */
for (i=0 ; i < found-1 ; i++)
@@ -1813,12 +1808,9 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
incidence). Popping from a priority queue includes a re-ordering
of the queue, to get the next least incidence element to the top.
*/
- a= (my_off_t*) queue_remove(&queue, 0);
- /*
- Copy the next least incidence element. The queue implementation
- reserves root[0] for temporary purposes. root[1] is the top.
- */
- b= (my_off_t*) queue.root[1];
+ a= (my_off_t*) queue_remove_top(&queue);
+ /* Copy the next least incidence element. */
+ b= (my_off_t*) queue_top(&queue);
/* Create a new element in a local (automatic) buffer. */
new_huff_el= element_buffer + i;
/* The new element gets the sum of the two least incidence elements. */
@@ -1838,8 +1830,8 @@ static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,
queue. This successively replaces the references to counts by
references to HUFF_ELEMENTs.
*/
- queue.root[1]=(uchar*) new_huff_el;
- queue_replaced(&queue);
+ queue_top(&queue)= (uchar*) new_huff_el;
+ queue_replace_top(&queue);
}
DBUG_RETURN(bytes_packed+(bits_packed+7)/8);
}
diff --git a/storage/maria/tablockman.c b/storage/maria/tablockman.c
index 1bb8889aaa7..eb494a8d19b 100644
--- a/storage/maria/tablockman.c
+++ b/storage/maria/tablockman.c
@@ -607,7 +607,7 @@ void tablockman_init(TABLOCKMAN *lm, loid_to_tlo_func *func, uint timeout)
lm->loid_to_tlo= func;
lm->lock_timeout= timeout;
pthread_mutex_init(& lm->pool_mutex, MY_MUTEX_INIT_FAST);
- my_getsystime(); /* ensure that my_getsystime() is initialized */
+ my_interval_timer(); /* ensure that my_interval_timer() is initialized */
}
void tablockman_destroy(TABLOCKMAN *lm)
diff --git a/storage/maria/unittest/ma_loghandler_examples.c b/storage/maria/unittest/ma_loghandler_examples.c
index 0c11a3b9a8e..cd5d927587a 100644
--- a/storage/maria/unittest/ma_loghandler_examples.c
+++ b/storage/maria/unittest/ma_loghandler_examples.c
@@ -59,6 +59,9 @@ void translog_example_table_init()
i < LOGREC_NUMBER_OF_TYPES;
i++)
log_record_type_descriptor[i].rclass= LOGRECTYPE_NOT_ALLOWED;
+#ifndef DBUG_OFF
+ check_translog_description_table(LOGREC_VARIABLE_RECORD_2LSN_EXAMPLE);
+#endif
}
diff --git a/storage/maria/unittest/ma_test_all-t b/storage/maria/unittest/ma_test_all-t
index 4d72c6dfadf..e66d269ab93 100755
--- a/storage/maria/unittest/ma_test_all-t
+++ b/storage/maria/unittest/ma_test_all-t
@@ -283,6 +283,7 @@ sub run_check_tests
["-p -B --key_length=480","-sm"],
["--checksum --unique","-se"],
["--unique","-se"],
+ ["--rows-no-data", "-s"],
["--key_multiple -N -S","-sm"],
["--key_multiple -a -p --key_length=480","-sm"],
["--key_multiple -a -B --key_length=480","-sm"],
diff --git a/storage/maria/unittest/trnman-t.c b/storage/maria/unittest/trnman-t.c
index 43cf982a7f2..92919b37152 100644
--- a/storage/maria/unittest/trnman-t.c
+++ b/storage/maria/unittest/trnman-t.c
@@ -75,7 +75,7 @@ pthread_handler_t test_trnman(void *arg)
void run_test(const char *test, pthread_handler handler, int n, int m)
{
pthread_t *threads;
- ulonglong now= my_getsystime();
+ ulonglong now= microsecond_interval_timer();
int i;
litmus= 0;
@@ -97,8 +97,8 @@ void run_test(const char *test, pthread_handler handler, int n, int m)
}
for (i= 0 ; i < n ; i++)
pthread_join(threads[i], 0);
- now= my_getsystime()-now;
- ok(litmus == 0, "Tested %s in %g secs (%d)", test, ((double)now)/1e7, litmus);
+ now= microsecond_interval_timer() - now;
+ ok(litmus == 0, "Tested %s in %g secs (%d)", test, ((double)now)/1e6, litmus);
my_free((void*)threads, MYF(0));
}
@@ -162,10 +162,10 @@ int main(int argc __attribute__((unused)), char **argv)
diag("mallocs: %d", trnman_allocated_transactions);
{
- ulonglong now= my_getsystime();
+ ulonglong now= microsecond_interval_timer();
trnman_destroy();
- now= my_getsystime()-now;
- diag("trnman_destroy: %g", ((double)now)/1e7);
+ now= microsecond_interval_timer() - now;
+ diag("trnman_destroy: %g", ((double)now)/1e6);
}
pthread_mutex_destroy(&rt_mutex);