summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2016-05-04 15:23:26 +0200
committerSergei Golubchik <serg@mariadb.org>2016-05-04 15:23:26 +0200
commit87e3e67f434628768b5125fbab7e8862fa60da1a (patch)
treedf19b8bcac9988d83270ed1da05f765bfc4e8624 /storage
parent80da57cc4f0c717ee3e01ac5abccc859b88a2fbf (diff)
parentcee9ab9d85a8d75290b0d60bc7af26c8cf179a1d (diff)
downloadmariadb-git-87e3e67f434628768b5125fbab7e8862fa60da1a.tar.gz
Merge branch '10.0' into 10.1
Diffstat (limited to 'storage')
-rw-r--r--storage/connect/CMakeLists.txt37
-rw-r--r--storage/connect/connect.cc2
-rw-r--r--storage/connect/ha_connect.cc43
-rw-r--r--storage/connect/ha_connect.h4
-rw-r--r--storage/connect/jsonudf.cpp11
-rw-r--r--storage/connect/maputil.cpp4
-rw-r--r--storage/connect/myconn.cpp11
-rw-r--r--storage/connect/myconn.h2
-rw-r--r--storage/connect/mysql-test/connect/r/grant3.result5
-rw-r--r--storage/connect/mysql-test/connect/r/mysql_index.result321
-rw-r--r--storage/connect/mysql-test/connect/r/part_table.result25
-rw-r--r--storage/connect/mysql-test/connect/t/grant3.test11
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_index.test67
-rw-r--r--storage/connect/mysql-test/connect/t/part_table.test15
-rw-r--r--storage/connect/tabmysql.cpp6
-rwxr-xr-xstorage/connect/xindex.cpp26
-rw-r--r--storage/connect/xindex.h4
-rw-r--r--storage/federatedx/ha_federatedx.cc2
-rw-r--r--storage/innobase/dict/dict0boot.cc2
-rw-r--r--storage/innobase/dict/dict0crea.cc4
-rw-r--r--storage/innobase/fil/fil0fil.cc68
-rw-r--r--storage/innobase/fts/fts0fts.cc266
-rw-r--r--storage/innobase/fts/fts0opt.cc81
-rw-r--r--storage/innobase/handler/ha_innodb.cc155
-rw-r--r--storage/innobase/handler/ha_innodb.h15
-rw-r--r--storage/innobase/handler/handler0alter.cc14
-rw-r--r--storage/innobase/include/dict0mem.h18
-rw-r--r--storage/innobase/include/fts0fts.h24
-rw-r--r--storage/innobase/include/fts0types.h10
-rw-r--r--storage/innobase/include/os0file.h5
-rw-r--r--storage/innobase/include/os0sync.h46
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/os/os0file.cc57
-rw-r--r--storage/innobase/row/row0merge.cc5
-rw-r--r--storage/myisam/ft_boolean_search.c5
-rw-r--r--storage/myisammrg/ha_myisammrg.cc1
-rw-r--r--storage/oqgraph/ha_oqgraph.cc4
-rw-r--r--storage/oqgraph/oqgraph_judy.cc22
-rw-r--r--storage/spider/hs_client/fatal.cpp20
-rw-r--r--storage/spider/hs_client/fatal.hpp2
-rw-r--r--storage/spider/hs_client/socket.cpp2
-rw-r--r--storage/spider/spd_conn.cc34
-rw-r--r--storage/spider/spd_db_conn.cc4
-rw-r--r--storage/spider/spd_ping_table.cc4
-rw-r--r--storage/spider/spd_table.cc16
-rw-r--r--storage/spider/spd_trx.cc12
-rw-r--r--storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test4
-rw-r--r--storage/xtradb/buf/buf0dump.cc25
-rw-r--r--storage/xtradb/buf/buf0flu.cc6
-rw-r--r--storage/xtradb/dict/dict0boot.cc2
-rw-r--r--storage/xtradb/dict/dict0dict.cc2
-rw-r--r--storage/xtradb/dict/dict0stats.cc19
-rw-r--r--storage/xtradb/fil/fil0fil.cc29
-rw-r--r--storage/xtradb/fts/fts0opt.cc11
-rw-r--r--storage/xtradb/handler/ha_innodb.cc482
-rw-r--r--storage/xtradb/handler/ha_innodb.h38
-rw-r--r--storage/xtradb/handler/handler0alter.cc40
-rw-r--r--storage/xtradb/include/buf0flu.h6
-rw-r--r--storage/xtradb/include/dict0mem.h18
-rw-r--r--storage/xtradb/include/ha_prototypes.h11
-rw-r--r--storage/xtradb/include/os0file.h29
-rw-r--r--storage/xtradb/include/row0log.h5
-rw-r--r--storage/xtradb/include/row0merge.h26
-rw-r--r--storage/xtradb/include/univ.i4
-rw-r--r--storage/xtradb/lock/lock0lock.cc2
-rw-r--r--storage/xtradb/os/os0file.cc22
-rw-r--r--storage/xtradb/row/row0ftsort.cc18
-rw-r--r--storage/xtradb/row/row0log.cc46
-rw-r--r--storage/xtradb/row/row0merge.cc183
-rw-r--r--storage/xtradb/srv/srv0srv.cc32
-rw-r--r--storage/xtradb/srv/srv0start.cc6
73 files changed, 1954 insertions, 614 deletions
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index f6b42e7f360..9827f4fbe54 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -45,6 +45,7 @@ add_definitions( -DHUGE_SUPPORT -DZIP_SUPPORT -DPIVOT_SUPPORT )
# OS specific C flags, definitions and source files.
#
IF(UNIX)
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Bar: -Wfatal-errors removed (does not present in gcc on solaris10)
if(WITH_WARNINGS)
add_definitions(-Wall -Wextra -Wmissing-declarations)
@@ -71,6 +72,7 @@ IF(UNIX)
#message(STATUS "CONNECT: GCC: Some warnings disabled")
endif(WITH_WARNINGS)
+ endif()
add_definitions( -DUNIX -DLINUX -DUBUNTU )
@@ -126,37 +128,10 @@ IF(WIN32)
OPTION(CONNECT_WITH_MSXML "Compile CONNECT storage engine with MSXML support" ON)
IF(CONNECT_WITH_MSXML)
- find_library(MSXML_LIBRARY
- NAMES msxml6 msxml4 msxml3 msxml2
- PATHS
- "C:/Program Files/Microsoft SDKs/Windows/v7.0A/Lib"
- "C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib"
- "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib"
- DOC "Specify the MSXML? library here."
- )
- IF(MSXML_LIBRARY MATCHES .*msxml6[.].*)
- add_definitions(-DMSX6 -DDOMDOC_SUPPORT)
- message(STATUS "MSXML library version: msxml6")
- SET(MSXML_FOUND 1)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
- ELSEIF(MSXML_LIBRARY MATCHES .*msxml4[.].*)
- add_definitions(-DMSX4 -DDOMDOC_SUPPORT)
- message("MSXML library version: msxml4")
- SET(MSXML_FOUND 1)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
- ELSEIF(MSXML_LIBRARY MATCHES .*msxml3[.].*)
- message("MSXML library version: msxml3")
- add_definitions(-DMSX3 -DDOMDOC_SUPPORT)
- SET(MSXML_FOUND 1)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
- ELSEIF(MSXML_LIBRARY MATCHES .*msxml2[.].*)
- message("MSXML library version: msxml2")
- add_definitions(-DMXS2 -DDOMDOC_SUPPORT)
- SET(MSXML_FOUND 1)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
- ELSE()
- message(STATUS "msxml? library not found")
- ENDIF()
+ add_definitions(-DMSX6 -DDOMDOC_SUPPORT)
+ message(STATUS "MSXML library version: msxml6")
+ SET(MSXML_FOUND 1)
+ SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
ENDIF(CONNECT_WITH_MSXML)
ENDIF(WIN32)
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index 56a0fc4fd4f..460d47bcf62 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -752,7 +752,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
return RC_FX;
} else if (x == 2) {
// Remote index
- if (ptdb->ReadKey(g, op, kr))
+ if (op != OP_SAME && ptdb->ReadKey(g, op, kr))
return RC_FX;
goto rnd;
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 3fa09044a71..f5b196cb8f5 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -757,7 +757,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
sdvalout= NULL;
xmod= MODE_ANY;
istable= false;
- *partname= 0;
+ memset(partname, 0, sizeof(partname));
bzero((char*) &xinfo, sizeof(XINFO));
valid_info= false;
valid_query_id= 0;
@@ -1150,7 +1150,7 @@ char *ha_connect::GetRealString(const char *s)
{
char *sv;
- if (IsPartitioned() && s) {
+ if (IsPartitioned() && s && partname && *partname) {
sv= (char*)PlugSubAlloc(xp->g, NULL, 0);
sprintf(sv, s, partname);
PlugSubAlloc(xp->g, NULL, strlen(sv) + 1);
@@ -1173,7 +1173,9 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
: table->s->connect_string;
if (cnc.length)
- opval= GetRealString(strz(xp->g, cnc));
+ opval= strz(xp->g, cnc);
+ else
+ opval= GetListOption(xp->g, opname, options->oplist);
} else if (!stricmp(opname, "Query_String"))
opval= thd_query_string(table->in_use)->str;
@@ -2286,7 +2288,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
op= OP_EQ;
break;
case HA_READ_AFTER_KEY:
- op= (stlen >= len) ? (!i ? OP_GT : OP_LE) : OP_GE;
+ op= (stlen >= len || i > 0) ? (i > 0 ? OP_LE : OP_GT) : OP_GE;
break;
case HA_READ_KEY_OR_NEXT:
op= OP_GE;
@@ -3121,13 +3123,14 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (table->part_info) {
if (GetStringOption("Filename") || GetStringOption("Tabname")
- || GetStringOption("Connect")) {
- strcpy(partname, decode(g, strrchr(name, '#') + 1));
+ || GetStringOption("Connect")) {
+ strncpy(partname, decode(g, strrchr(name, '#') + 1), sizeof(partname) - 1);
// strcpy(partname, table->part_info->curr_part_elem->partition_name);
- part_id= &table->part_info->full_part_field_set;
+// part_id= &table->part_info->full_part_field_set;
} else // Inward table
- strcpy(partname, strrchr(name, slash) + 1);
- part_id= &table->part_info->full_part_field_set; // Temporary
+ strncpy(partname, strrchr(name, slash) + 1, sizeof(partname) - 1);
+
+ part_id= &table->part_info->full_part_field_set; // Temporary
} // endif part_info
#endif // WITH_PARTITION_STORAGE_ENGINE
} else
@@ -4054,7 +4057,7 @@ int ha_connect::delete_all_rows()
} // end of delete_all_rows
-bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
+bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
{
const char *db= (dbn && *dbn) ? dbn : NULL;
TABTYPE type=GetRealType(options);
@@ -4081,6 +4084,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
case TAB_VEC:
case TAB_JSON:
if (options->filename && *options->filename) {
+ if (!quick) {
char *s, path[FN_REFLEN], dbpath[FN_REFLEN];
#if defined(__WIN__)
s= "\\";
@@ -4099,7 +4103,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
return true;
} // endif path
-
+ }
} else
return false;
@@ -4121,10 +4125,13 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
Otherwise it's a DML, the table was normally opened, locked,
privilege were already checked, and table->grant.privilege is set.
With SQL SECURITY DEFINER, table->grant.privilege has definer's privileges.
+
+ Unless we're in prelocking mode, in this case table->grant.privilege
+ is only checked in start_stmt(), not in external_lock().
*/
if (!table || !table->mdl_ticket || table->mdl_ticket->get_type() == MDL_EXCLUSIVE)
return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0);
- if (table->grant.privilege & FILE_ACL)
+ if ((!quick && thd->lex->requires_prelocking()) || table->grant.privilege & FILE_ACL)
return false;
status_var_increment(thd->status_var.access_denied_errors);
my_error(access_denied_error_code(thd->password), MYF(0),
@@ -4308,6 +4315,9 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
PGLOBAL g= GetPlug(thd, xp);
DBUG_ENTER("ha_connect::start_stmt");
+ if (check_privileges(thd, GetTableOptionStruct(), table->s->db.str, true))
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+
// Action will depend on lock_type
switch (lock_type) {
case TL_WRITE_ALLOW_WRITE:
@@ -6142,7 +6152,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
strcpy(dbpath, name);
p= strrchr(dbpath, slash);
- strcpy(partname, ++p);
+ strncpy(partname, ++p, sizeof(partname) - 1);
strcat(strcat(strcpy(buf, p), "."), lwt);
*p= 0;
} else {
@@ -6193,7 +6203,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info && !inward)
- strcpy(partname, decode(g, strrchr(name, '#') + 1));
+ strncpy(partname, decode(g, strrchr(name, '#') + 1), sizeof(partname) - 1);
// strcpy(partname, part_info->curr_part_elem->partition_name);
#endif // WITH_PARTITION_STORAGE_ENGINE
@@ -6234,8 +6244,9 @@ int ha_connect::create(const char *name, TABLE *table_arg,
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info)
- strcpy(partname,
- decode(g, strrchr(name, (inward ? slash : '#')) + 1));
+ strncpy(partname,
+ decode(g, strrchr(name, (inward ? slash : '#')) + 1),
+ sizeof(partname) - 1);
#endif // WITH_PARTITION_STORAGE_ENGINE
if ((rc= optimize(table->in_use, NULL))) {
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 05cc872fa2a..60194ac0e3c 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -536,7 +536,7 @@ private:
DsMrr_impl ds_mrr;
protected:
- bool check_privileges(THD *thd, PTOS options, char *dbn);
+ bool check_privileges(THD *thd, PTOS options, char *dbn, bool quick=false);
MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
char *GetDBfromName(const char *name);
@@ -554,7 +554,7 @@ protected:
PVAL sdvalin4; // Used to convert date values
PVAL sdvalout; // Used to convert date values
bool istable; // True for table handler
- char partname[64]; // The partition name
+ char partname[65]; // The partition name
MODE xmod; // Table mode
XINFO xinfo; // The table info structure
bool valid_info; // True if xinfo is valid
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index 25c77cea534..7b82ba2d627 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -533,7 +533,7 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
/*********************************************************************************/
my_bool JSNX::CheckPath(PGLOBAL g)
{
- PJVAL val;
+ PJVAL val= NULL;
PJSON row = Row;
for (int i = 0; i < Nod && row; i++) {
@@ -1302,7 +1302,7 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
{
char fn[_MAX_PATH];
unsigned long i, k, m, n;
- long fl, j = -1;
+ long fl= 0, j = -1;
reslen = args->arg_count + 2;
@@ -2087,7 +2087,7 @@ my_bool json_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args,
char *json_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *, char *)
{
- char *str;
+ char *str= 0;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->Xchk) {
@@ -2621,7 +2621,7 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif Xchk
if (!CheckMemory(g, initid, args, 2, false, false, true)) {
- PJSON top;
+ PJSON top= 0;
PJVAL jvp;
PJSON jsp[2] = {NULL, NULL};
@@ -4721,7 +4721,7 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
my_bool b = true;
PJSON jsp;
PJSNX jsx;
- PJVAL jvp;
+ PJVAL jvp= 0;
PBSON bsp = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
PGLOBAL gb = GetMemPtr(g, args, 0);
@@ -4742,6 +4742,7 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!g->Xchk) {
if (CheckMemory(g, initid, args, 1, true, false, true)) {
PUSH_WARNING("CheckMemory error");
+ goto fin;
} else
jvp = MakeValue(g, args, 0);
diff --git a/storage/connect/maputil.cpp b/storage/connect/maputil.cpp
index c4e016f1511..87263b3adf6 100644
--- a/storage/connect/maputil.cpp
+++ b/storage/connect/maputil.cpp
@@ -190,8 +190,8 @@ bool CloseMemMap(void *memory, size_t dwSize)
{
if (memory) {
// All this must be redesigned
- int rc = msync(memory, dwSize, MS_SYNC);
- return (munmap(memory, dwSize) < 0) ? true : false;
+ int rc = msync((char*)memory, dwSize, MS_SYNC);
+ return (munmap((char*)memory, dwSize) < 0) ? true : false;
} else
return false;
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index ada0109a820..e9bd64cf8e6 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -959,11 +959,16 @@ void MYSQLC::FreeResult(void)
/***********************************************************************/
/* Place the cursor at the beginning of the result set. */
/***********************************************************************/
-void MYSQLC::Rewind(void)
+int MYSQLC::Rewind(PGLOBAL g, PSZ sql)
{
- if (m_Res)
- DataSeek(0);
+ int rc = RC_OK;
+ if (m_Res)
+ DataSeek(0);
+ else if (sql)
+ rc = ExecSQL(g, sql);
+
+ return rc;
} // end of Rewind
/***********************************************************************/
diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h
index fa34edd804c..79f095f5c93 100644
--- a/storage/connect/myconn.h
+++ b/storage/connect/myconn.h
@@ -80,7 +80,7 @@ class DllItem MYSQLC {
int Fetch(PGLOBAL g, int pos);
char *GetCharField(int i);
int GetFieldLength(int i);
- void Rewind(void);
+ int Rewind(PGLOBAL g, PSZ sql);
void FreeResult(void);
void Close(void);
diff --git a/storage/connect/mysql-test/connect/r/grant3.result b/storage/connect/mysql-test/connect/r/grant3.result
new file mode 100644
index 00000000000..2f9d37bdb35
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/grant3.result
@@ -0,0 +1,5 @@
+create table tcon (i int) engine=Connect table_type=DOS file_name='tcon.dos';
+create table tin (i int);
+create trigger tr after insert on tin for each row insert into tcon values (new.i);
+insert into tin values (1);
+drop table tin,tcon;
diff --git a/storage/connect/mysql-test/connect/r/mysql_index.result b/storage/connect/mysql-test/connect/r/mysql_index.result
index 4ebf10802ae..dd1864529ca 100644
--- a/storage/connect/mysql-test/connect/r/mysql_index.result
+++ b/storage/connect/mysql-test/connect/r/mysql_index.result
@@ -112,3 +112,324 @@ id msg
6 Six
DROP TABLE t2;
DROP TABLE t1;
+#
+# Make local FIX table with indices matricule and nom/prenom
+#
+CREATE TABLE t1
+(
+matricule INT(4) KEY NOT NULL field_format='Z',
+nom VARCHAR(16) NOT NULL,
+prenom VARCHAR(20) NOT NULL,
+sexe SMALLINT(1) NOT NULL COMMENT 'sexe 1:M 2:F',
+aanais INT(4) NOT NULL,
+mmnais INT(2) NOT NULL,
+ddentree DATE NOT NULL date_format='YYYYMM',
+ddnom DATE NOT NULL date_format='YYYYMM',
+brut INT(5) NOT NULL,
+net DOUBLE(8,2) NOT NULL,
+service INT(2) NOT NULL,
+sitmat CHAR(1) NOT NULL,
+formation CHAR(5) NOT NULL,
+INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='emp.txt' ENDING=2;
+#
+# Make MYSQL table with same indices
+#
+CREATE TABLE t2
+(
+matricule INT(4) KEY NOT NULL,
+nom VARCHAR(16) NOT NULL,
+prenom VARCHAR(20) NOT NULL,
+sexe SMALLINT(1) NOT NULL,
+aanais INT(4) NOT NULL,
+mmnais INT(2) NOT NULL,
+ddentree DATE NOT NULL date_format='YYYYMM',
+ddnom DATE NOT NULL date_format='YYYYMM',
+brut INT(5) NOT NULL,
+net DOUBLE(8,2) NOT NULL,
+service INT(2) NOT NULL,
+sitmat CHAR(1) NOT NULL,
+formation CHAR(5) NOT NULL,
+INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTIOn='mysql://root@localhost/test/t1';
+SELECT * FROM t2 limit 10;
+matricule nom prenom sexe aanais mmnais ddentree ddnom brut net service sitmat formation
+5745 ESCOURCHE BENEDICTE 2 1935 7 1962-12-01 1994-05-01 18345 14275.50 0 M TECHN
+9692 VICENTE LAURENCE 2 1941 8 1967-10-01 1989-01-01 16212 13032.80 0 M ANGL
+9146 NICOLAS ROGER 1 1941 6 1964-07-01 1995-02-01 34173 25098.65 0 M SANS
+2985 TESSEREAU MARIE HELENE 2 1941 9 1967-01-01 1990-01-01 19323 14933.78 0 V SANS
+3368 MOGADOR ALAIN 1 1941 1 1961-09-01 1993-11-01 43303 31420.55 0 C SANS
+7394 CHAUSSEE ERIC DENIS 1 1944 9 1965-11-01 1983-12-01 32002 23583.86 0 M ANGL
+4655 MAILLOT GEORGES 1 1945 5 1970-09-01 1986-12-01 24700 18541.64 0 C ANGL
+2825 CAMILLE NADINE 2 1956 9 1994-01-01 1993-01-01 19494 15050.45 0 M SANS
+1460 BRUYERES JEAN MARC 1 1958 8 1984-08-01 1988-05-01 20902 15980.07 0 M SANS
+4974 LONES GERARD 1 1959 10 1979-01-01 1994-12-01 16081 12916.70 0 M SANS
+SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR');
+matricule nom prenom
+1977 FOCH BERNADETTE
+5707 FOCH DENIS
+2552 FOCH FRANCK
+2634 FOCH JOCELYNE
+5765 FOCH ROBERT
+4080 FOCH SERGE
+3368 MOGADOR ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom = 'FOCH' OR nom = 'MOGADOR';
+matricule nom prenom
+1977 FOCH BERNADETTE
+5707 FOCH DENIS
+2552 FOCH FRANCK
+2634 FOCH JOCELYNE
+5765 FOCH ROBERT
+4080 FOCH SERGE
+3368 MOGADOR ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom < 'ADDAX';
+matricule nom prenom
+4552 ABBADIE MONIQUE
+307 ABBAYE ANNICK
+6627 ABBAYE GERALD
+7961 ABBE KATIA
+1340 ABBE MICHELE
+9270 ABBE SOPHIE
+2945 ABBEVILLE PASCAL
+8596 ABEBERRY PATRICK
+6399 ABEILLES RENE
+8673 ABEL JEAN PIERRE
+6124 ABELIAS DELIA
+6314 ABERDEN EVELYNE
+895 ABORD CHANTAL
+2728 ABOUT CATHERINE MARIE
+398 ABREUVOIR JEAN LUC
+1122 ACACIAS SERGE
+1644 ACARDIE BEATE
+115 ACHILLE JACQUES
+4038 ADAM JANICK
+3395 ADAM JEAN CLAUDE
+SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL';
+matricule nom prenom
+4552 ABBADIE MONIQUE
+307 ABBAYE ANNICK
+6627 ABBAYE GERALD
+7961 ABBE KATIA
+1340 ABBE MICHELE
+9270 ABBE SOPHIE
+2945 ABBEVILLE PASCAL
+8596 ABEBERRY PATRICK
+6399 ABEILLES RENE
+8673 ABEL JEAN PIERRE
+SELECT matricule, nom, prenom FROM t2 WHERE nom > 'YVON';
+matricule nom prenom
+9742 YZENGREMER MICHEL
+8738 ZILINA JEAN LOUIS
+5357 ZOLA BERNARD
+5441 ZOLA BRIGITTE
+1325 ZOLA CHRISTINE
+4859 ZORI CATHERINE
+4102 ZOUAVES ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON';
+matricule nom prenom
+5389 YVON CAROLE
+9742 YZENGREMER MICHEL
+8738 ZILINA JEAN LOUIS
+5357 ZOLA BERNARD
+5441 ZOLA BRIGITTE
+1325 ZOLA CHRISTINE
+4859 ZORI CATHERINE
+4102 ZOUAVES ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL' OR nom > 'YVON';
+matricule nom prenom
+4552 ABBADIE MONIQUE
+307 ABBAYE ANNICK
+6627 ABBAYE GERALD
+7961 ABBE KATIA
+1340 ABBE MICHELE
+9270 ABBE SOPHIE
+2945 ABBEVILLE PASCAL
+8596 ABEBERRY PATRICK
+6399 ABEILLES RENE
+8673 ABEL JEAN PIERRE
+9742 YZENGREMER MICHEL
+8738 ZILINA JEAN LOUIS
+5357 ZOLA BERNARD
+5441 ZOLA BRIGITTE
+1325 ZOLA CHRISTINE
+4859 ZORI CATHERINE
+4102 ZOUAVES ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom > 'HELEN' AND nom < 'HEROS';
+matricule nom prenom
+9096 HELENA PHILIPPE
+3309 HELENE ISABELLE
+8365 HELIOTROPES LISE
+4666 HELLEN PIERRE
+5781 HELSINKI DANIELLE
+7626 HENIN PHILIPPE
+4254 HENIN SERGE
+2673 HENNER LILIANE
+9716 HENRI JACQUES
+2085 HEOL GUY PAUL
+2579 HERANDIERE PIERRE
+7093 HERAULTS DANIEL
+4050 HERBILLON FRANCOIS
+9231 HERBILLON MADELEINE
+1291 HERMITAGE XAVIER
+6185 HERMITTE FRANCOIS
+403 HERMITTE PHILIPPE
+9749 HEROLD ISABELLE
+SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS';
+matricule nom prenom
+6199 HELEN MARTIAL
+9096 HELENA PHILIPPE
+3309 HELENE ISABELLE
+8365 HELIOTROPES LISE
+4666 HELLEN PIERRE
+5781 HELSINKI DANIELLE
+7626 HENIN PHILIPPE
+4254 HENIN SERGE
+2673 HENNER LILIANE
+9716 HENRI JACQUES
+2085 HEOL GUY PAUL
+2579 HERANDIERE PIERRE
+7093 HERAULTS DANIEL
+4050 HERBILLON FRANCOIS
+9231 HERBILLON MADELEINE
+1291 HERMITAGE XAVIER
+6185 HERMITTE FRANCOIS
+403 HERMITTE PHILIPPE
+9749 HEROLD ISABELLE
+8445 HEROS SYLVIE
+SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS' AND prenom = 'PHILIPPE';
+matricule nom prenom
+9096 HELENA PHILIPPE
+7626 HENIN PHILIPPE
+403 HERMITTE PHILIPPE
+SELECT matricule, nom, prenom FROM t2 ORDER BY nom LIMIT 10;
+matricule nom prenom
+4552 ABBADIE MONIQUE
+6627 ABBAYE GERALD
+307 ABBAYE ANNICK
+7961 ABBE KATIA
+1340 ABBE MICHELE
+9270 ABBE SOPHIE
+2945 ABBEVILLE PASCAL
+8596 ABEBERRY PATRICK
+6399 ABEILLES RENE
+8673 ABEL JEAN PIERRE
+SELECT a.nom, a.prenom, b.nom FROM t1 a STRAIGHT_JOIN t2 b ON a.prenom = b.prenom WHERE a.nom = 'FOCH' AND a.nom != b.nom;
+nom prenom nom
+FOCH SERGE ACACIAS
+FOCH ROBERT AGRIANT
+FOCH JOCELYNE ALEXIS
+FOCH DENIS AMBOISE
+FOCH SERGE ANDALUCIA
+FOCH ROBERT ANNECY
+FOCH SERGE ARCACHON
+FOCH JOCELYNE AUGUSTE
+FOCH JOCELYNE BASSE
+FOCH SERGE BEACH
+FOCH FRANCK BEARN
+FOCH SERGE BELLES
+FOCH DENIS BERARD
+FOCH DENIS BERIN
+FOCH BERNADETTE BERTIN
+FOCH DENIS BILLEHOU
+FOCH DENIS BOILEAU
+FOCH BERNADETTE BOISSY
+FOCH ROBERT BONVIN
+FOCH SERGE BOUTON
+FOCH SERGE BREUIL
+FOCH SERGE CARREFOUR
+FOCH JOCELYNE CARRERE
+FOCH JOCELYNE CHAPELLE
+FOCH SERGE CHATEAU
+FOCH ROBERT CHENIER
+FOCH SERGE COLLETTE
+FOCH DENIS CONNE
+FOCH SERGE COOLE
+FOCH DENIS COULOUBRIER
+FOCH DENIS COUTURIER
+FOCH ROBERT CURAT
+FOCH ROBERT DAUDET
+FOCH SERGE ECLUSE
+FOCH SERGE EGUILLON
+FOCH DENIS EPINETTES
+FOCH DENIS FIGOURNAS
+FOCH JOCELYNE FLEMING
+FOCH JOCELYNE GAMBADES
+FOCH ROBERT GIOTERAIE
+FOCH SERGE GOAS
+FOCH ROBERT GRAFFIANE
+FOCH SERGE GREFFIER
+FOCH ROBERT GUILLOTIERE
+FOCH SERGE HENIN
+FOCH BERNADETTE HUNTZIGER
+FOCH FRANCK ILLIERS
+FOCH DENIS ISTANBUL
+FOCH DENIS ITALIE
+FOCH SERGE JARDIN
+FOCH FRANCK JEANPIERRE
+FOCH JOCELYNE KENNEDY
+FOCH FRANCK LABBE
+FOCH DENIS LACATE
+FOCH FRANCK LACOMBE
+FOCH ROBERT LAMOTHE
+FOCH BERNADETTE LATECOERE
+FOCH BERNADETTE LEGER
+FOCH SERGE LEONIE
+FOCH FRANCK LEROY
+FOCH SERGE LOZERE
+FOCH DENIS MAROLLES
+FOCH ROBERT MARRONIERS
+FOCH SERGE MARSAT
+FOCH SERGE MONTAGNE
+FOCH FRANCK MONTALEIGNE
+FOCH DENIS MONTELIER
+FOCH DENIS MONTILS
+FOCH BERNADETTE MONTJUSTIN
+FOCH SERGE MORIZET
+FOCH ROBERT NIMES
+FOCH ROBERT NORD
+FOCH SERGE NOVEMBRE
+FOCH BERNADETTE ONZE
+FOCH SERGE ORANGERIE
+FOCH FRANCK ORVEAU
+FOCH BERNADETTE PALMAROLE
+FOCH JOCELYNE PEYBERT
+FOCH ROBERT PEYNIBLOU
+FOCH ROBERT PIECE
+FOCH JOCELYNE PIED
+FOCH ROBERT PLAGNE
+FOCH SERGE PLAISANCE
+FOCH BERNADETTE PLOUHARNEL
+FOCH DENIS POINTE
+FOCH ROBERT POMMERY
+FOCH JOCELYNE PONTAROUX
+FOCH DENIS PORTO
+FOCH ROBERT PRESIDENT
+FOCH ROBERT PUJADE
+FOCH FRANCK PURPAN
+FOCH ROBERT QUILICHINI
+FOCH DENIS REINOTS
+FOCH DENIS REMPART
+FOCH SERGE RESISTANCE
+FOCH SERGE RESTANQUES
+FOCH ROBERT RIOU
+FOCH FRANCK ROCQUENCOURT
+FOCH ROBERT ROLL
+FOCH ROBERT ROSSA
+FOCH SERGE ROSSAYS
+FOCH DENIS ROUSSIER
+FOCH FRANCK RUSSIE
+FOCH ROBERT SABLONS
+FOCH SERGE SARTRE
+FOCH SERGE SAVIGNAC
+FOCH SERGE SEGUR
+FOCH ROBERT STRASBOURG
+FOCH ROBERT TIRE
+FOCH DENIS TORTE
+FOCH DENIS TOULON
+FOCH ROBERT TUBY
+FOCH DENIS VALMANTE
+FOCH SERGE VANOEL
+FOCH ROBERT VIARMES
+FOCH SERGE WILSON
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/r/part_table.result b/storage/connect/mysql-test/connect/r/part_table.result
index 122c328fa59..f3a556ae784 100644
--- a/storage/connect/mysql-test/connect/r/part_table.result
+++ b/storage/connect/mysql-test/connect/r/part_table.result
@@ -191,6 +191,31 @@ id msg
35 thirty five
81 big
DROP TABLE t1;
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=MYSQL
+OPTION_LIST='connect=mysql://root@localhost/test/xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+Warnings:
+Warning 1105 Data repartition in 1 is unchecked
+Warning 1105 Data repartition in 2 is unchecked
+Warning 1105 Data repartition in 3 is unchecked
+SELECT * FROM t1;
+id msg
+4 four
+7 sept
+1 one
+8 eight
+40 forty
+10 ten
+11 eleven
+35 thirty five
+81 big
+DROP TABLE t1;
DROP TABLE xt1;
DROP TABLE xt2;
DROP TABLE xt3;
diff --git a/storage/connect/mysql-test/connect/t/grant3.test b/storage/connect/mysql-test/connect/t/grant3.test
new file mode 100644
index 00000000000..9f05ca796c5
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/grant3.test
@@ -0,0 +1,11 @@
+#
+# MDEV-9610 Trigger on normal table can't insert into CONNECT engine table - Access Denied
+#
+create table tcon (i int) engine=Connect table_type=DOS file_name='tcon.dos';
+create table tin (i int);
+create trigger tr after insert on tin for each row insert into tcon values (new.i);
+insert into tin values (1);
+drop table tin,tcon;
+
+let datadir=`select @@datadir`;
+remove_file $datadir/test/tcon.dos;
diff --git a/storage/connect/mysql-test/connect/t/mysql_index.test b/storage/connect/mysql-test/connect/t/mysql_index.test
index 9a162b4d8e3..81fdcad9330 100644
--- a/storage/connect/mysql-test/connect/t/mysql_index.test
+++ b/storage/connect/mysql-test/connect/t/mysql_index.test
@@ -64,3 +64,70 @@ SELECT * FROM t2;
DROP TABLE t2;
DROP TABLE t1;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--copy_file $MTR_SUITE_DIR/std_data/emp.txt $MYSQLD_DATADIR/test/emp.txt
+
+--echo #
+--echo # Make local FIX table with indices matricule and nom/prenom
+--echo #
+CREATE TABLE t1
+(
+ matricule INT(4) KEY NOT NULL field_format='Z',
+ nom VARCHAR(16) NOT NULL,
+ prenom VARCHAR(20) NOT NULL,
+ sexe SMALLINT(1) NOT NULL COMMENT 'sexe 1:M 2:F',
+ aanais INT(4) NOT NULL,
+ mmnais INT(2) NOT NULL,
+ ddentree DATE NOT NULL date_format='YYYYMM',
+ ddnom DATE NOT NULL date_format='YYYYMM',
+ brut INT(5) NOT NULL,
+ net DOUBLE(8,2) NOT NULL,
+ service INT(2) NOT NULL,
+ sitmat CHAR(1) NOT NULL,
+ formation CHAR(5) NOT NULL,
+ INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='emp.txt' ENDING=2;
+
+--echo #
+--echo # Make MYSQL table with same indices
+--echo #
+CREATE TABLE t2
+(
+ matricule INT(4) KEY NOT NULL,
+ nom VARCHAR(16) NOT NULL,
+ prenom VARCHAR(20) NOT NULL,
+ sexe SMALLINT(1) NOT NULL,
+ aanais INT(4) NOT NULL,
+ mmnais INT(2) NOT NULL,
+ ddentree DATE NOT NULL date_format='YYYYMM',
+ ddnom DATE NOT NULL date_format='YYYYMM',
+ brut INT(5) NOT NULL,
+ net DOUBLE(8,2) NOT NULL,
+ service INT(2) NOT NULL,
+ sitmat CHAR(1) NOT NULL,
+ formation CHAR(5) NOT NULL,
+ INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTIOn='mysql://root@localhost/test/t1';
+SELECT * FROM t2 limit 10;
+SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR');
+SELECT matricule, nom, prenom FROM t2 WHERE nom = 'FOCH' OR nom = 'MOGADOR';
+SELECT matricule, nom, prenom FROM t2 WHERE nom < 'ADDAX';
+SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL';
+SELECT matricule, nom, prenom FROM t2 WHERE nom > 'YVON';
+SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON';
+SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL' OR nom > 'YVON';
+SELECT matricule, nom, prenom FROM t2 WHERE nom > 'HELEN' AND nom < 'HEROS';
+SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS';
+SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS' AND prenom = 'PHILIPPE';
+SELECT matricule, nom, prenom FROM t2 ORDER BY nom LIMIT 10;
+SELECT a.nom, a.prenom, b.nom FROM t1 a STRAIGHT_JOIN t2 b ON a.prenom = b.prenom WHERE a.nom = 'FOCH' AND a.nom != b.nom;
+
+DROP TABLE t2;
+DROP TABLE t1;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/emp.txt
+--remove_file $MYSQLD_DATADIR/test/emp.fnx
diff --git a/storage/connect/mysql-test/connect/t/part_table.test b/storage/connect/mysql-test/connect/t/part_table.test
index d839337ba6f..5edd5766bd6 100644
--- a/storage/connect/mysql-test/connect/t/part_table.test
+++ b/storage/connect/mysql-test/connect/t/part_table.test
@@ -82,6 +82,21 @@ SELECT * FROM t1;
DELETE FROM t1 WHERE id in (60,72);
SELECT * FROM t1;
DROP TABLE t1;
+
+#
+# Using a connection string
+#
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=MYSQL
+OPTION_LIST='connect=mysql://root@localhost/test/xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SELECT * FROM t1;
+DROP TABLE t1;
DROP TABLE xt1;
DROP TABLE xt2;
DROP TABLE xt3;
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 47497f465e3..98a476bf94f 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -19,7 +19,7 @@
/* --------------- */
/* TABMYSQL.CPP - Source code */
/* PLGDBSEM.H - DB application declaration file */
-/* TABMYSQL.H - TABODBC classes declaration file */
+/* TABMYSQL.H - TABMYSQL classes declaration file */
/* GLOBAL.H - Global declaration file */
/* */
/* REQUIRED LIBRARIES: */
@@ -857,7 +857,9 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
/*******************************************************************/
/* Table already open, just replace it at its beginning. */
/*******************************************************************/
- Myc.Rewind();
+ if (Myc.Rewind(g, (Mode == MODE_READX) ? Query->GetStr() : NULL) != RC_OK)
+ return true;
+
N = -1;
return false;
} // endif use
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index a2d75cec8ab..69aa7e2c20e 100755
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -1279,7 +1279,7 @@ bool XINDEX::MapInit(PGLOBAL g)
IOFF *noff = (IOFF*)mbase;
// Position the memory base at the offset of this index
- mbase += noff[id].Low;
+ mbase += noff[id].v.Low;
} // endif id
// Now start the mapping process.
@@ -2347,10 +2347,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
return true;
} // endif
- NewOff.Low = (int)ftell(Xfile);
+ NewOff.v.Low = (int)ftell(Xfile);
if (trace)
- htrc("XFILE Open: NewOff.Low=%d\n", NewOff.Low);
+ htrc("XFILE Open: NewOff.v.Low=%d\n", NewOff.v.Low);
} else if (mode == MODE_WRITE) {
if (id >= 0) {
@@ -2358,10 +2358,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
memset(noff, 0, sizeof(noff));
Write(g, noff, sizeof(IOFF), MAX_INDX, rc);
fseek(Xfile, 0, SEEK_END);
- NewOff.Low = (int)ftell(Xfile);
+ NewOff.v.Low = (int)ftell(Xfile);
if (trace)
- htrc("XFILE Open: NewOff.Low=%d\n", NewOff.Low);
+ htrc("XFILE Open: NewOff.v.Low=%d\n", NewOff.v.Low);
} // endif id
@@ -2373,10 +2373,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endif MAX_INDX
if (trace)
- htrc("XFILE Open: noff[%d].Low=%d\n", id, noff[id].Low);
+ htrc("XFILE Open: noff[%d].v.Low=%d\n", id, noff[id].v.Low);
// Position the cursor at the offset of this index
- if (fseek(Xfile, noff[id].Low, SEEK_SET)) {
+ if (fseek(Xfile, noff[id].v.Low, SEEK_SET)) {
sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Xseek");
return true;
} // endif
@@ -2566,14 +2566,14 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
return true;
} // endif
- NewOff.Low = (int)rc;
- NewOff.High = (int)high;
+ NewOff.v.Low = (int)rc;
+ NewOff.v.High = (int)high;
} else if (mode == MODE_WRITE) {
if (id >= 0) {
// New not sep index file. Write the header.
memset(noff, 0, sizeof(noff));
rc = WriteFile(Hfile, noff, sizeof(noff), &drc, NULL);
- NewOff.Low = (int)drc;
+ NewOff.v.Low = (int)drc;
} // endif id
} else if (mode == MODE_READ && id >= 0) {
@@ -2586,8 +2586,8 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endif rc
// Position the cursor at the offset of this index
- rc = SetFilePointer(Hfile, noff[id].Low,
- (PLONG)&noff[id].High, FILE_BEGIN);
+ rc = SetFilePointer(Hfile, noff[id].v.Low,
+ (PLONG)&noff[id].v.High, FILE_BEGIN);
if (rc == INVALID_SET_FILE_POINTER) {
sprintf(g->Message, MSG(FUNC_ERRNO), GetLastError(), "SetFilePointer");
@@ -2649,7 +2649,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
if (id >= 0) {
// New not sep index file. Write the header.
memset(noff, 0, sizeof(noff));
- NewOff.Low = write(Hfile, &noff, sizeof(noff));
+ NewOff.v.Low = write(Hfile, &noff, sizeof(noff));
} // endif id
if (trace)
diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h
index 51b678992ea..ef2e934e5ee 100644
--- a/storage/connect/xindex.h
+++ b/storage/connect/xindex.h
@@ -66,9 +66,9 @@ typedef struct index_def : public BLOCK {
typedef struct index_off {
union {
#if defined(WORDS_BIGENDIAN)
- struct {int High; int Low;};
+ struct {int High; int Low;} v;
#else // !WORDS_BIGENDIAN
- struct {int Low; int High;};
+ struct {int Low; int High;} v;
#endif //!WORDS_BIGENDIAN
longlong Val; // File position
}; // end of union
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index 890d1bff292..aae26758c78 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -1319,7 +1319,7 @@ bool ha_federatedx::create_where_from_key(String *to,
break;
}
DBUG_PRINT("info", ("federatedx HA_READ_AFTER_KEY %d", i));
- if (store_length >= length) /* end key */
+ if (store_length >= length || i > 0) /* end key */
{
if (emit_key_part_name(&tmp, key_part))
goto err;
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index 0dff05567d7..80724372f27 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -468,7 +468,7 @@ dict_boot(void)
} else {
ib_logf(IB_LOG_LEVEL_WARN,
"Change buffer not empty when --innodb-read-only "
- "is set! but srv_force_recovery = %d, ignoring.",
+ "is set! but srv_force_recovery = %lu, ignoring.",
srv_force_recovery);
}
}
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 4a8dcd2f840..a5af8208135 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -1187,7 +1187,7 @@ dict_create_index_step(
>= UNIV_FORMAT_B);
node->index = dict_index_get_if_in_cache_low(index_id);
- ut_a(err == DB_SUCCESS ? node->index != NULL : node->index == NULL);
+ ut_a((node->index == NULL) == (err != DB_SUCCESS));
if (err != DB_SUCCESS) {
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 22abf592adc..bf7a53778f4 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2015, Oracle and/or its affiliates.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates.
Copyright (c) 2013, 2016, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -3186,8 +3186,6 @@ fil_create_link_file(
const char* tablename, /*!< in: tablename */
const char* filepath) /*!< in: pathname of tablespace */
{
- os_file_t file;
- ibool success;
dberr_t err = DB_SUCCESS;
char* link_filepath;
char* prev_filepath = fil_read_link_file(tablename);
@@ -3205,16 +3203,25 @@ fil_create_link_file(
}
link_filepath = fil_make_isl_name(tablename);
- /* Note that OS_FILE_READ_WRITE_CACHED used here to avoid
- unnecessary errors on O_DIRECT, link files are not really
- a data files. */
- file = os_file_create_simple_no_error_handling(
- innodb_file_data_key, link_filepath,
- OS_FILE_CREATE, OS_FILE_READ_WRITE_CACHED, &success, 0);
- if (!success) {
- /* The following call will print an error message */
- ulint error = os_file_get_last_error(true);
+ /** Check if the file already exists. */
+ FILE* file = NULL;
+ ibool exists;
+ os_file_type_t ftype;
+
+ bool success = os_file_status(link_filepath, &exists, &ftype);
+
+ ulint error = 0;
+ if (success && !exists) {
+ file = fopen(link_filepath, "w");
+ if (file == NULL) {
+ /* This call will print its own error message */
+ error = os_file_get_last_error(true);
+ }
+ } else {
+ error = OS_FILE_ALREADY_EXISTS;
+ }
+ if (error != 0) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Cannot create file ", stderr);
@@ -3239,13 +3246,17 @@ fil_create_link_file(
return(err);
}
- if (!os_file_write(link_filepath, file, filepath, 0,
- strlen(filepath))) {
+ ulint rbytes = fwrite(filepath, 1, strlen(filepath), file);
+ if (rbytes != strlen(filepath)) {
+ os_file_get_last_error(true);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "cannot write link file "
+ "%s",filepath);
err = DB_ERROR;
}
/* Close the file, we only need it at startup */
- os_file_close(file);
+ fclose(file);
mem_free(link_filepath);
@@ -5262,12 +5273,15 @@ retry:
os_offset_t offset
= ((os_offset_t) (start_page_no - file_start_page_no))
* page_size;
+
+ const char* name = node->name == NULL ? space->name : node->name;
+
#ifdef UNIV_HOTBACKUP
- success = os_file_write(node->name, node->handle, buf,
+ success = os_file_write(name, node->handle, buf,
offset, page_size * n_pages);
#else
success = os_aio(OS_FILE_WRITE, 0, OS_AIO_SYNC,
- node->name, node->handle, buf,
+ name, node->handle, buf,
offset, page_size * n_pages, page_size,
node, NULL, 0);
#endif /* UNIV_HOTBACKUP */
@@ -5904,30 +5918,22 @@ fil_io(
ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
+ const char* name = node->name == NULL ? space->name : node->name;
+
#ifdef UNIV_HOTBACKUP
/* In mysqlbackup do normal i/o, not aio */
if (type == OS_FILE_READ) {
ret = os_file_read(node->handle, buf, offset, len);
} else {
ut_ad(!srv_read_only_mode);
- ret = os_file_write(node->name, node->handle, buf,
+ ret = os_file_write(name, node->handle, buf,
offset, len);
}
#else
/* Queue the aio request */
- ret = os_aio(
- type,
- is_log,
- mode | wake_later,
- node->name,
- node->handle,
- buf,
- offset,
- len,
- zip_size ? zip_size : UNIV_PAGE_SIZE,
- node,
- message,
- write_size);
+ ret = os_aio(type, is_log, mode | wake_later, name, node->handle, buf,
+ offset, len, zip_size ? zip_size : UNIV_PAGE_SIZE, node,
+ message, write_size);
#endif /* UNIV_HOTBACKUP */
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index ee06f9432b8..95740da78d5 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -260,16 +260,18 @@ static const char* fts_config_table_insert_values_sql =
"INSERT INTO \"%s\" VALUES ('"
FTS_TABLE_STATE "', '0');\n";
-/****************************************************************//**
-Run SYNC on the table, i.e., write out data from the cache to the
+/** Run SYNC on the table, i.e., write out data from the cache to the
FTS auxiliary INDEX table and clear the cache at the end.
-@return DB_SUCCESS if all OK */
+@param[in,out] sync sync state
+@param[in] unlock_cache whether unlock cache lock when write node
+@param[in] wait whether wait when a sync is in progress
+@return DB_SUCCESS if all OK */
static
dberr_t
fts_sync(
-/*=====*/
- fts_sync_t* sync) /*!< in: sync state */
- __attribute__((nonnull));
+ fts_sync_t* sync,
+ bool unlock_cache,
+ bool wait);
/****************************************************************//**
Release all resources help by the words rb tree e.g., the node ilist. */
@@ -653,6 +655,7 @@ fts_cache_create(
mem_heap_zalloc(heap, sizeof(fts_sync_t)));
cache->sync->table = table;
+ cache->sync->event = os_event_create();
/* Create the index cache vector that will hold the inverted indexes. */
cache->indexes = ib_vector_create(
@@ -1207,6 +1210,7 @@ fts_cache_destroy(
mutex_free(&cache->optimize_lock);
mutex_free(&cache->deleted_lock);
mutex_free(&cache->doc_id_lock);
+ os_event_free(cache->sync->event);
if (cache->stopword_info.cached_stopword) {
rbt_free(cache->stopword_info.cached_stopword);
@@ -1435,7 +1439,7 @@ fts_cache_add_doc(
ib_vector_last(word->nodes));
}
- if (fts_node == NULL
+ if (fts_node == NULL || fts_node->synced
|| fts_node->ilist_size > FTS_ILIST_MAX_SIZE
|| doc_id < fts_node->last_doc_id) {
@@ -2886,35 +2890,28 @@ fts_doc_ids_free(
}
/*********************************************************************//**
-Do commit-phase steps necessary for the insertion of a new row.
-@return DB_SUCCESS or error code */
-static __attribute__((nonnull, warn_unused_result))
-dberr_t
+Do commit-phase steps necessary for the insertion of a new row. */
+void
fts_add(
/*====*/
fts_trx_table_t*ftt, /*!< in: FTS trx table */
fts_trx_row_t* row) /*!< in: row */
{
dict_table_t* table = ftt->table;
- dberr_t error = DB_SUCCESS;
doc_id_t doc_id = row->doc_id;
ut_a(row->state == FTS_INSERT || row->state == FTS_MODIFY);
fts_add_doc_by_id(ftt, doc_id, row->fts_indexes);
- if (error == DB_SUCCESS) {
- mutex_enter(&table->fts->cache->deleted_lock);
- ++table->fts->cache->added;
- mutex_exit(&table->fts->cache->deleted_lock);
+ mutex_enter(&table->fts->cache->deleted_lock);
+ ++table->fts->cache->added;
+ mutex_exit(&table->fts->cache->deleted_lock);
- if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
- && doc_id >= table->fts->cache->next_doc_id) {
- table->fts->cache->next_doc_id = doc_id + 1;
- }
+ if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
+ && doc_id >= table->fts->cache->next_doc_id) {
+ table->fts->cache->next_doc_id = doc_id + 1;
}
-
- return(error);
}
/*********************************************************************//**
@@ -3025,7 +3022,7 @@ fts_modify(
error = fts_delete(ftt, row);
if (error == DB_SUCCESS) {
- error = fts_add(ftt, row);
+ fts_add(ftt, row);
}
return(error);
@@ -3114,7 +3111,7 @@ fts_commit_table(
switch (row->state) {
case FTS_INSERT:
- error = fts_add(ftt, row);
+ fts_add(ftt, row);
break;
case FTS_MODIFY:
@@ -3554,16 +3551,34 @@ fts_add_doc_by_id(
get_doc->index_cache,
doc_id, doc.tokens);
+ bool need_sync = false;
+ if ((cache->total_size > fts_max_cache_size / 10
+ || fts_need_sync)
+ && !cache->sync->in_progress) {
+ need_sync = true;
+ }
+
rw_lock_x_unlock(&table->fts->cache->lock);
DBUG_EXECUTE_IF(
"fts_instrument_sync",
- fts_sync(cache->sync);
+ fts_optimize_request_sync_table(table);
+ os_event_wait(cache->sync->event);
+ );
+
+ DBUG_EXECUTE_IF(
+ "fts_instrument_sync_debug",
+ fts_sync(cache->sync, true, true);
);
- if (cache->total_size > fts_max_cache_size
- || fts_need_sync) {
- fts_sync(cache->sync);
+ DEBUG_SYNC_C("fts_instrument_sync_request");
+ DBUG_EXECUTE_IF(
+ "fts_instrument_sync_request",
+ fts_optimize_request_sync_table(table);
+ );
+
+ if (need_sync) {
+ fts_optimize_request_sync_table(table);
}
mtr_start(&mtr);
@@ -3934,16 +3949,17 @@ fts_sync_add_deleted_cache(
return(error);
}
-/*********************************************************************//**
-Write the words and ilist to disk.
+/** Write the words and ilist to disk.
+@param[in,out] trx transaction
+@param[in] index_cache index cache
+@param[in] unlock_cache whether unlock cache when write node
@return DB_SUCCESS if all went well else error code */
static __attribute__((nonnull, warn_unused_result))
dberr_t
fts_sync_write_words(
-/*=================*/
- trx_t* trx, /*!< in: transaction */
- fts_index_cache_t*
- index_cache) /*!< in: index cache */
+ trx_t* trx,
+ fts_index_cache_t* index_cache,
+ bool unlock_cache)
{
fts_table_t fts_table;
ulint n_nodes = 0;
@@ -3951,8 +3967,8 @@ fts_sync_write_words(
const ib_rbt_node_t* rbt_node;
dberr_t error = DB_SUCCESS;
ibool print_error = FALSE;
-#ifdef FTS_DOC_STATS_DEBUG
dict_table_t* table = index_cache->index->table;
+#ifdef FTS_DOC_STATS_DEBUG
ulint n_new_words = 0;
#endif /* FTS_DOC_STATS_DEBUG */
@@ -3965,7 +3981,7 @@ fts_sync_write_words(
since we want to free the memory used during caching. */
for (rbt_node = rbt_first(index_cache->words);
rbt_node;
- rbt_node = rbt_first(index_cache->words)) {
+ rbt_node = rbt_next(index_cache->words, rbt_node)) {
ulint i;
ulint selected;
@@ -3998,27 +4014,47 @@ fts_sync_write_words(
}
#endif /* FTS_DOC_STATS_DEBUG */
- n_nodes += ib_vector_size(word->nodes);
-
- /* We iterate over all the nodes even if there was an error,
- this is to free the memory of the fts_node_t elements. */
+ /* We iterate over all the nodes even if there was an error */
for (i = 0; i < ib_vector_size(word->nodes); ++i) {
fts_node_t* fts_node = static_cast<fts_node_t*>(
ib_vector_get(word->nodes, i));
+ if (fts_node->synced) {
+ continue;
+ } else {
+ fts_node->synced = true;
+ }
+
+ /*FIXME: we need to handle the error properly. */
if (error == DB_SUCCESS) {
+ if (unlock_cache) {
+ rw_lock_x_unlock(
+ &table->fts->cache->lock);
+ }
error = fts_write_node(
trx,
&index_cache->ins_graph[selected],
&fts_table, &word->text, fts_node);
- }
- ut_free(fts_node->ilist);
- fts_node->ilist = NULL;
+ DEBUG_SYNC_C("fts_write_node");
+ DBUG_EXECUTE_IF("fts_write_node_crash",
+ DBUG_SUICIDE(););
+
+ DBUG_EXECUTE_IF("fts_instrument_sync_sleep",
+ os_thread_sleep(1000000);
+ );
+
+ if (unlock_cache) {
+ rw_lock_x_lock(
+ &table->fts->cache->lock);
+ }
+ }
}
+ n_nodes += ib_vector_size(word->nodes);
+
if (error != DB_SUCCESS && !print_error) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error (%s) writing "
@@ -4027,9 +4063,6 @@ fts_sync_write_words(
print_error = TRUE;
}
-
- /* NOTE: We are responsible for free'ing the node */
- ut_free(rbt_remove_node(index_cache->words, rbt_node));
}
#ifdef FTS_DOC_STATS_DEBUG
@@ -4330,7 +4363,7 @@ fts_sync_index(
ut_ad(rbt_validate(index_cache->words));
- error = fts_sync_write_words(trx, index_cache);
+ error = fts_sync_write_words(sync->trx, index_cache, sync->unlock_cache);
#ifdef FTS_DOC_STATS_DEBUG
/* FTS_RESOLVE: the word counter info in auxiliary table "DOC_ID"
@@ -4346,6 +4379,36 @@ fts_sync_index(
return(error);
}
+/** Check if index cache has been synced completely
+@param[in,out] sync sync state
+@param[in,out] index_cache index cache
+@return true if index is synced, otherwise false. */
+static
+bool
+fts_sync_index_check(
+ fts_sync_t* sync,
+ fts_index_cache_t* index_cache)
+{
+ const ib_rbt_node_t* rbt_node;
+
+ for (rbt_node = rbt_first(index_cache->words);
+ rbt_node != NULL;
+ rbt_node = rbt_next(index_cache->words, rbt_node)) {
+
+ fts_tokenizer_word_t* word;
+ word = rbt_value(fts_tokenizer_word_t, rbt_node);
+
+ fts_node_t* fts_node;
+ fts_node = static_cast<fts_node_t*>(ib_vector_last(word->nodes));
+
+ if (!fts_node->synced) {
+ return(false);
+ }
+ }
+
+ return(true);
+}
+
/*********************************************************************//**
Commit the SYNC, change state of processed doc ids etc.
@return DB_SUCCESS if all OK */
@@ -4422,21 +4485,53 @@ fts_sync_rollback(
trx_t* trx = sync->trx;
fts_cache_t* cache = sync->table->fts->cache;
+ for (ulint i = 0; i < ib_vector_size(cache->indexes); ++i) {
+ ulint j;
+ fts_index_cache_t* index_cache;
+
+ index_cache = static_cast<fts_index_cache_t*>(
+ ib_vector_get(cache->indexes, i));
+
+ for (j = 0; fts_index_selector[j].value; ++j) {
+
+ if (index_cache->ins_graph[j] != NULL) {
+
+ fts_que_graph_free_check_lock(
+ NULL, index_cache,
+ index_cache->ins_graph[j]);
+
+ index_cache->ins_graph[j] = NULL;
+ }
+
+ if (index_cache->sel_graph[j] != NULL) {
+
+ fts_que_graph_free_check_lock(
+ NULL, index_cache,
+ index_cache->sel_graph[j]);
+
+ index_cache->sel_graph[j] = NULL;
+ }
+ }
+ }
+
rw_lock_x_unlock(&cache->lock);
fts_sql_rollback(trx);
trx_free_for_background(trx);
}
-/****************************************************************//**
-Run SYNC on the table, i.e., write out data from the cache to the
+/** Run SYNC on the table, i.e., write out data from the cache to the
FTS auxiliary INDEX table and clear the cache at the end.
+@param[in,out] sync sync state
+@param[in] unlock_cache whether unlock cache lock when write node
+@param[in] wait whether wait when a sync is in progress
@return DB_SUCCESS if all OK */
static
dberr_t
fts_sync(
-/*=====*/
- fts_sync_t* sync) /*!< in: sync state */
+ fts_sync_t* sync,
+ bool unlock_cache,
+ bool wait)
{
ulint i;
dberr_t error = DB_SUCCESS;
@@ -4444,8 +4539,35 @@ fts_sync(
rw_lock_x_lock(&cache->lock);
+ /* Check if cache is being synced.
+ Note: we release cache lock in fts_sync_write_words() to
+ avoid long wait for the lock by other threads. */
+ while (sync->in_progress) {
+ rw_lock_x_unlock(&cache->lock);
+
+ if (wait) {
+ os_event_wait(sync->event);
+ } else {
+ return(DB_SUCCESS);
+ }
+
+ rw_lock_x_lock(&cache->lock);
+ }
+
+ sync->unlock_cache = unlock_cache;
+ sync->in_progress = true;
+
+ DEBUG_SYNC_C("fts_sync_begin");
fts_sync_begin(sync);
+begin_sync:
+ if (cache->total_size > fts_max_cache_size) {
+ /* Avoid the case: sync never finish when
+ insert/update keeps comming. */
+ ut_ad(sync->unlock_cache);
+ sync->unlock_cache = false;
+ }
+
for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
fts_index_cache_t* index_cache;
@@ -4460,21 +4582,43 @@ fts_sync(
if (error != DB_SUCCESS && !sync->interrupted) {
- break;
+ goto end_sync;
}
}
DBUG_EXECUTE_IF("fts_instrument_sync_interrupted",
sync->interrupted = true;
error = DB_INTERRUPTED;
+ goto end_sync;
);
+ /* Make sure all the caches are synced. */
+ for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
+ fts_index_cache_t* index_cache;
+
+ index_cache = static_cast<fts_index_cache_t*>(
+ ib_vector_get(cache->indexes, i));
+
+ if (index_cache->index->to_be_dropped
+ || fts_sync_index_check(sync, index_cache)) {
+ continue;
+ }
+
+ goto begin_sync;
+ }
+
+end_sync:
if (error == DB_SUCCESS && !sync->interrupted) {
error = fts_sync_commit(sync);
} else {
fts_sync_rollback(sync);
}
+ rw_lock_x_lock(&cache->lock);
+ sync->in_progress = false;
+ os_event_set(sync->event);
+ rw_lock_x_unlock(&cache->lock);
+
/* We need to check whether an optimize is required, for that
we make copies of the two variables that control the trigger. These
variables can change behind our back and we don't want to hold the
@@ -4489,21 +4633,25 @@ fts_sync(
return(error);
}
-/****************************************************************//**
-Run SYNC on the table, i.e., write out data from the cache to the
-FTS auxiliary INDEX table and clear the cache at the end. */
+/** Run SYNC on the table, i.e., write out data from the cache to the
+FTS auxiliary INDEX table and clear the cache at the end.
+@param[in,out] table fts table
+@param[in] unlock_cache whether unlock cache when write node
+@param[in] wait whether wait for existing sync to finish
+@return DB_SUCCESS on success, error code on failure. */
UNIV_INTERN
dberr_t
fts_sync_table(
-/*===========*/
- dict_table_t* table) /*!< in: table */
+ dict_table_t* table,
+ bool unlock_cache,
+ bool wait)
{
dberr_t err = DB_SUCCESS;
ut_ad(table->fts);
if (!dict_table_is_discarded(table) && table->fts->cache) {
- err = fts_sync(table->fts->cache->sync);
+ err = fts_sync(table->fts->cache->sync, unlock_cache, wait);
}
return(err);
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 00b3b4682c3..ccb7090c61d 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -87,6 +87,7 @@ enum fts_msg_type_t {
FTS_MSG_DEL_TABLE, /*!< Remove a table from the optimize
threads work queue */
+ FTS_MSG_SYNC_TABLE /*!< Sync fts cache of a table */
};
/** Compressed list of words that have been read from FTS INDEX
@@ -2652,6 +2653,39 @@ fts_optimize_remove_table(
os_event_free(event);
}
+/** Send sync fts cache for the table.
+@param[in] table table to sync */
+UNIV_INTERN
+void
+fts_optimize_request_sync_table(
+ dict_table_t* table)
+{
+ fts_msg_t* msg;
+ table_id_t* table_id;
+
+ /* if the optimize system not yet initialized, return */
+ if (!fts_optimize_wq) {
+ return;
+ }
+
+ /* FTS optimizer thread is already exited */
+ if (fts_opt_start_shutdown) {
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Try to sync table %s after FTS optimize"
+ " thread exiting.", table->name);
+ return;
+ }
+
+ msg = fts_optimize_create_msg(FTS_MSG_SYNC_TABLE, NULL);
+
+ table_id = static_cast<table_id_t*>(
+ mem_heap_alloc(msg->heap, sizeof(table_id_t)));
+ *table_id = table->id;
+ msg->ptr = table_id;
+
+ ib_wqueue_add(fts_optimize_wq, msg, msg->heap);
+}
+
/**********************************************************************//**
Find the slot for a particular table.
@return slot if found else NULL. */
@@ -2932,6 +2966,25 @@ fts_optimize_need_sync(
}
#endif
+/** Sync fts cache of a table
+@param[in] table_id table id */
+void
+fts_optimize_sync_table(
+ table_id_t table_id)
+{
+ dict_table_t* table = NULL;
+
+ table = dict_table_open_on_id(table_id, FALSE, DICT_TABLE_OP_NORMAL);
+
+ if (table) {
+ if (dict_table_has_fts_index(table) && table->fts->cache) {
+ fts_sync_table(table, true, false);
+ }
+
+ dict_table_close(table, FALSE, FALSE);
+ }
+}
+
/**********************************************************************//**
Optimize all FTS tables.
@return Dummy return */
@@ -3053,6 +3106,11 @@ fts_optimize_thread(
((fts_msg_del_t*) msg->ptr)->event);
break;
+ case FTS_MSG_SYNC_TABLE:
+ fts_optimize_sync_table(
+ *static_cast<table_id_t*>(msg->ptr));
+ break;
+
default:
ut_error;
}
@@ -3079,26 +3137,7 @@ fts_optimize_thread(
ib_vector_get(tables, i));
if (slot->state != FTS_STATE_EMPTY) {
- dict_table_t* table = NULL;
-
- /*slot->table may be freed, so we try to open
- table by slot->table_id.*/
- table = dict_table_open_on_id(
- slot->table_id, FALSE,
- DICT_TABLE_OP_NORMAL);
-
- if (table) {
-
- if (dict_table_has_fts_index(table)) {
- fts_sync_table(table);
- }
-
- if (table->fts) {
- fts_free(table);
- }
-
- dict_table_close(table, FALSE, FALSE);
- }
+ fts_optimize_sync_table(slot->table_id);
}
}
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index d9c2cef7d07..d8b59d4f6bd 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
@@ -3817,6 +3817,14 @@ innobase_change_buffering_inited_ok:
innobase_open_files = tc_size;
}
}
+
+ if (innobase_open_files > (long) tc_size) {
+ fprintf(stderr,
+ "innodb_open_files should not be greater"
+ " than the open_files_limit.\n");
+ innobase_open_files = tc_size;
+ }
+
srv_max_n_open_files = (ulint) innobase_open_files;
srv_innodb_status = (ibool) innobase_create_status_file;
@@ -5944,20 +5952,14 @@ table_opened:
prebuilt->clust_index_was_generated = FALSE;
if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
- sql_print_error("Table %s has a primary key in "
- "InnoDB data dictionary, but not "
- "in MySQL!", name);
+ ib_table->dict_frm_mismatch = DICT_FRM_NO_PK;
/* This mismatch could cause further problems
if not attended, bring this to the user's attention
by printing a warning in addition to log a message
in the errorlog */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_NO_SUCH_INDEX,
- "InnoDB: Table %s has a "
- "primary key in InnoDB data "
- "dictionary, but not in "
- "MySQL!", name);
+
+ ib_push_frm_error(thd, ib_table, table, 0, true);
/* If primary_key >= MAX_KEY, its (primary_key)
value could be out of bound if continue to index
@@ -6004,27 +6006,14 @@ table_opened:
}
} else {
if (primary_key != MAX_KEY) {
- sql_print_error(
- "Table %s has no primary key in InnoDB data "
- "dictionary, but has one in MySQL! If you "
- "created the table with a MySQL version < "
- "3.23.54 and did not define a primary key, "
- "but defined a unique key with all non-NULL "
- "columns, then MySQL internally treats that "
- "key as the primary key. You can fix this "
- "error by dump + DROP + CREATE + reimport "
- "of the table.", name);
+
+ ib_table->dict_frm_mismatch = DICT_NO_PK_FRM_HAS;
/* This mismatch could cause further problems
if not attended, bring this to the user attention
by printing a warning in addition to log a message
in the errorlog */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_NO_SUCH_INDEX,
- "InnoDB: Table %s has no "
- "primary key in InnoDB data "
- "dictionary, but has one in "
- "MySQL!", name);
+ ib_push_frm_error(thd, ib_table, table, 0, true);
}
prebuilt->clust_index_was_generated = TRUE;
@@ -13494,12 +13483,8 @@ ha_innobase::info_low(
}
if (table->s->keys != num_innodb_index) {
- sql_print_error("InnoDB: Table %s contains %lu "
- "indexes inside InnoDB, which "
- "is different from the number of "
- "indexes %u defined in the MySQL ",
- ib_table->name, num_innodb_index,
- table->s->keys);
+ ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS;
+ ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true);
}
if (!(flag & HA_STATUS_NO_LOCK)) {
@@ -13519,15 +13504,8 @@ ha_innobase::info_low(
dict_index_t* index = innobase_get_index(i);
if (index == NULL) {
- sql_print_error("Table %s contains fewer "
- "indexes inside InnoDB than "
- "are defined in the MySQL "
- ".frm file. Have you mixed up "
- ".frm files from different "
- "installations? See "
- REFMAN
- "innodb-troubleshooting.html\n",
- ib_table->name);
+ ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS;
+ ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true);
break;
}
@@ -13742,7 +13720,7 @@ ha_innobase::optimize(
if (innodb_optimize_fulltext_only) {
if (prebuilt->table->fts && prebuilt->table->fts->cache
&& !dict_table_is_discarded(prebuilt->table)) {
- fts_sync_table(prebuilt->table);
+ fts_sync_table(prebuilt->table, false, true);
fts_optimize_table(prebuilt->table);
}
return(HA_ADMIN_OK);
@@ -20627,3 +20605,96 @@ ib_push_warning(
my_free(buf);
va_end(args);
}
+
+/********************************************************************//**
+Helper function to push frm mismatch error to error log and
+if needed to sql-layer. */
+UNIV_INTERN
+void
+ib_push_frm_error(
+/*==============*/
+ THD* thd, /*!< in: MySQL thd */
+ dict_table_t* ib_table, /*!< in: InnoDB table */
+ TABLE* table, /*!< in: MySQL table */
+ ulint n_keys, /*!< in: InnoDB #keys */
+ bool push_warning) /*!< in: print warning ? */
+{
+ switch (ib_table->dict_frm_mismatch) {
+ case DICT_FRM_NO_PK:
+ sql_print_error("Table %s has a primary key in "
+ "InnoDB data dictionary, but not "
+ "in MySQL!"
+ " Have you mixed up "
+ ".frm files from different "
+ "installations? See "
+ REFMAN
+ "innodb-troubleshooting.html\n",
+ ib_table->name);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s has a "
+ "primary key in InnoDB data "
+ "dictionary, but not in "
+ "MySQL!", ib_table->name);
+ }
+ break;
+ case DICT_NO_PK_FRM_HAS:
+ sql_print_error(
+ "Table %s has no primary key in InnoDB data "
+ "dictionary, but has one in MySQL! If you "
+ "created the table with a MySQL version < "
+ "3.23.54 and did not define a primary key, "
+ "but defined a unique key with all non-NULL "
+ "columns, then MySQL internally treats that "
+ "key as the primary key. You can fix this "
+ "error by dump + DROP + CREATE + reimport "
+ "of the table.", ib_table->name);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s has no "
+ "primary key in InnoDB data "
+ "dictionary, but has one in "
+ "MySQL!",
+ ib_table->name);
+ }
+ break;
+
+ case DICT_FRM_INCONSISTENT_KEYS:
+ sql_print_error("InnoDB: Table %s contains %lu "
+ "indexes inside InnoDB, which "
+ "is different from the number of "
+ "indexes %u defined in the MySQL "
+ " Have you mixed up "
+ ".frm files from different "
+ "installations? See "
+ REFMAN
+ "innodb-troubleshooting.html\n",
+ ib_table->name, n_keys,
+ table->s->keys);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s contains %lu "
+ "indexes inside InnoDB, which "
+ "is different from the number of "
+ "indexes %u defined in the MySQL ",
+ ib_table->name, n_keys,
+ table->s->keys);
+ }
+ break;
+
+ case DICT_FRM_CONSISTENT:
+ default:
+ sql_print_error("InnoDB: Table %s is consistent "
+ "on InnoDB data dictionary and MySQL "
+ " FRM file.",
+ ib_table->name);
+ ut_error;
+ break;
+ }
+}
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 4f4a0b2f999..107e90b1080 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
+Copyright (c) 2013, 2016, MariaDB Corporation.
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
@@ -675,3 +675,16 @@ innobase_copy_frm_flags_from_table_share(
/*=====================================*/
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
const TABLE_SHARE* table_share); /*!< in: table share */
+
+/********************************************************************//**
+Helper function to push frm mismatch error to error log and
+if needed to sql-layer. */
+UNIV_INTERN
+void
+ib_push_frm_error(
+/*==============*/
+ THD* thd, /*!< in: MySQL thd */
+ dict_table_t* ib_table, /*!< in: InnoDB table */
+ TABLE* table, /*!< in: MySQL table */
+ ulint n_keys, /*!< in: InnoDB #keys */
+ bool push_warning); /*!< in: print warning ? */
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index c6e5f457f13..f5db3775909 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -459,6 +459,20 @@ ha_innobase::check_if_supported_inplace_alter(
}
}
+ ulint n_indexes = UT_LIST_GET_LEN((prebuilt->table)->indexes);
+
+ /* If InnoDB dictionary and MySQL frm file are not consistent
+ use "Copy" method. */
+ if (prebuilt->table->dict_frm_mismatch) {
+
+ ha_alter_info->unsupported_reason = innobase_get_err_msg(
+ ER_NO_SUCH_INDEX);
+ ib_push_frm_error(user_thd, prebuilt->table, altered_table,
+ n_indexes, true);
+
+ DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+ }
+
/* We should be able to do the operation in-place.
See if we can do it online (LOCK=NONE). */
bool online = true;
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 53a5d6cb08b..eb2a7968bc4 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -2,7 +2,7 @@
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2015, MariaDB Corporation.
+Copyright (c) 2013, 2016, MariaDB Corporation.
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
@@ -1009,6 +1009,18 @@ if table->memcached_sync_count == DICT_TABLE_IN_DDL means there's DDL running on
the table, DML from memcached will be blocked. */
#define DICT_TABLE_IN_DDL -1
+/** These are used when MySQL FRM and InnoDB data dictionary are
+in inconsistent state. */
+typedef enum {
+ DICT_FRM_CONSISTENT = 0, /*!< Consistent state */
+ DICT_FRM_NO_PK = 1, /*!< MySQL has no primary key
+ but InnoDB dictionary has
+ non-generated one. */
+ DICT_NO_PK_FRM_HAS = 2, /*!< MySQL has primary key but
+ InnoDB dictionary has not. */
+ DICT_FRM_INCONSISTENT_KEYS = 3 /*!< Key count mismatch */
+} dict_frm_t;
+
/** Data structure for a database table. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct dict_table_t{
@@ -1069,6 +1081,10 @@ struct dict_table_t{
/*!< True if the table belongs to a system
database (mysql, information_schema or
performance_schema) */
+ dict_frm_t dict_frm_mismatch;
+ /*!< !DICT_FRM_CONSISTENT==0 if data
+ dictionary information and
+ MySQL FRM information mismatch. */
#ifndef UNIV_HOTBACKUP
hash_node_t name_hash; /*!< hash chain node */
hash_node_t id_hash; /*!< hash chain node */
diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h
index d54ed281d9a..9f7b0216d9b 100644
--- a/storage/innobase/include/fts0fts.h
+++ b/storage/innobase/include/fts0fts.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -724,6 +724,13 @@ fts_optimize_remove_table(
/*======================*/
dict_table_t* table); /*!< in: table to remove */
+/** Send sync fts cache for the table.
+@param[in] table table to sync */
+UNIV_INTERN
+void
+fts_optimize_request_sync_table(
+ dict_table_t* table);
+
/**********************************************************************//**
Signal the optimize thread to prepare for shutdown. */
UNIV_INTERN
@@ -826,15 +833,18 @@ fts_drop_index_split_tables(
dict_index_t* index) /*!< in: fts instance */
__attribute__((nonnull, warn_unused_result));
-/****************************************************************//**
-Run SYNC on the table, i.e., write out data from the cache to the
-FTS auxiliary INDEX table and clear the cache at the end. */
+/** Run SYNC on the table, i.e., write out data from the cache to the
+FTS auxiliary INDEX table and clear the cache at the end.
+@param[in,out] table fts table
+@param[in] unlock_cache whether unlock cache when write node
+@param[in] wait whether wait for existing sync to finish
+@return DB_SUCCESS on success, error code on failure. */
UNIV_INTERN
dberr_t
fts_sync_table(
-/*===========*/
- dict_table_t* table) /*!< in: table */
- __attribute__((nonnull));
+ dict_table_t* table,
+ bool unlock_cache,
+ bool wait);
/****************************************************************//**
Free the query graph but check whether dict_sys->mutex is already
diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h
index 64677428331..e495fe72a60 100644
--- a/storage/innobase/include/fts0types.h
+++ b/storage/innobase/include/fts0types.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -122,7 +122,11 @@ struct fts_sync_t {
doc_id_t max_doc_id; /*!< The doc id at which the cache was
noted as being full, we use this to
set the upper_limit field */
- ib_time_t start_time; /*!< SYNC start time */
+ ib_time_t start_time; /*!< SYNC start time */
+ bool in_progress; /*!< flag whether sync is in progress.*/
+ bool unlock_cache; /*!< flag whether unlock cache when
+ write fts node */
+ os_event_t event; /*!< sync finish event */
};
/** The cache for the FTS system. It is a memory-based inverted index
@@ -165,7 +169,6 @@ struct fts_cache_t {
objects, they are recreated after
a SYNC is completed */
-
ib_alloc_t* self_heap; /*!< This heap is the heap out of
which an instance of the cache itself
was created. Objects created using
@@ -212,6 +215,7 @@ struct fts_node_t {
ulint ilist_size_alloc;
/*!< Allocated size of ilist in
bytes */
+ bool synced; /*!< flag whether the node is synced */
};
/** A tokenizer word. Contains information about one word. */
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index dff5ebd524c..dd6fd8f9940 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -128,10 +128,7 @@ enum os_file_create_t {
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
#define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */
-#define OS_FILE_READ_WRITE_CACHED 666 /* OS_FILE_READ_WRITE but never
- O_DIRECT. Only for
- os_file_create_simple_no_error_handling
- currently. */
+
/* Options for file_create */
#define OS_FILE_AIO 61
#define OS_FILE_NORMAL 62
diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h
index e192a3a6c94..95e724ec48e 100644
--- a/storage/innobase/include/os0sync.h
+++ b/storage/innobase/include/os0sync.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -466,28 +466,7 @@ amount to decrement. */
# define os_atomic_decrement_uint64(ptr, amount) \
os_atomic_decrement(ptr, amount)
-# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
-
-/** Do an atomic test-and-set.
-@param[in,out] ptr Memory location to set to non-zero
-@return the previous value */
-inline
-lock_word_t
-os_atomic_test_and_set(volatile lock_word_t* ptr)
-{
- return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE));
-}
-
-/** Do an atomic clear.
-@param[in,out] ptr Memory location to set to zero */
-inline
-void
-os_atomic_clear(volatile lock_word_t* ptr)
-{
- __atomic_clear(ptr, __ATOMIC_RELEASE);
-}
-
-# elif defined(HAVE_ATOMIC_BUILTINS)
+# if defined(IB_STRONG_MEMORY_MODEL)
/** Do an atomic test and set.
@param[in,out] ptr Memory location to set to non-zero
@@ -516,6 +495,27 @@ os_atomic_clear(volatile lock_word_t* ptr)
return(__sync_lock_test_and_set(ptr, 0));
}
+# elif defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
+
+/** Do an atomic test-and-set.
+@param[in,out] ptr Memory location to set to non-zero
+@return the previous value */
+inline
+lock_word_t
+os_atomic_test_and_set(volatile lock_word_t* ptr)
+{
+ return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE));
+}
+
+/** Do an atomic clear.
+@param[in,out] ptr Memory location to set to zero */
+inline
+void
+os_atomic_clear(volatile lock_word_t* ptr)
+{
+ __atomic_clear(ptr, __ATOMIC_RELEASE);
+}
+
# else
# error "Unsupported platform"
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index c2451fa8c21..56a257241d9 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 29
+#define INNODB_VERSION_BUGFIX 30
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 3a0bd1fc328..f71a4cf125c 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -1350,8 +1350,7 @@ os_file_create_simple_func(
access = GENERIC_READ;
- } else if (access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_WRITE_CACHED) {
+ } else if (access_type == OS_FILE_READ_WRITE) {
access = GENERIC_READ | GENERIC_WRITE;
} else {
ib_logf(IB_LOG_LEVEL_ERROR,
@@ -1455,8 +1454,7 @@ os_file_create_simple_func(
#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
- && (access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_WRITE_CACHED)
+ && (access_type == OS_FILE_READ_WRITE)
&& os_file_lock(file, name)) {
*success = FALSE;
@@ -1470,31 +1468,6 @@ os_file_create_simple_func(
return(file);
}
-/** Disable OS I/O caching on the file if the file type and server
-configuration requires it.
-@param file handle to the file
-@param name name of the file, for diagnostics
-@param mode_str operation on the file, for diagnostics
-@param type OS_LOG_FILE or OS_DATA_FILE
-@param access_type if OS_FILE_READ_WRITE_CACHED, then caching will be disabled
-unconditionally, ignored otherwise */
-static
-void
-os_file_set_nocache_if_needed(os_file_t file, const char* name,
- const char *mode_str, ulint type,
- ulint access_type)
-{
- if (srv_read_only_mode || access_type == OS_FILE_READ_WRITE_CACHED) {
- return;
- }
-
- if (type == OS_DATA_FILE
- && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
- || (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC))) {
- os_file_set_nocache(file, name, mode_str);
- }
-}
-
/****************************************************************//**
NOTE! Use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
@@ -1550,8 +1523,7 @@ os_file_create_simple_no_error_handling_func(
access = GENERIC_READ;
} else if (srv_read_only_mode) {
access = GENERIC_READ;
- } else if (access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_WRITE_CACHED) {
+ } else if (access_type == OS_FILE_READ_WRITE) {
access = GENERIC_READ | GENERIC_WRITE;
} else if (access_type == OS_FILE_READ_ALLOW_DELETE) {
@@ -1623,8 +1595,7 @@ os_file_create_simple_no_error_handling_func(
} else {
ut_a(access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_ALLOW_DELETE
- || access_type == OS_FILE_READ_WRITE_CACHED);
+ || access_type == OS_FILE_READ_ALLOW_DELETE);
create_flag = O_RDWR;
}
@@ -1656,16 +1627,18 @@ os_file_create_simple_no_error_handling_func(
/* This function is always called for data files, we should disable
OS caching (O_DIRECT) here as we do in os_file_create_func(), so
we open the same file in the same mode, see man page of open(2). */
- if (*success) {
- os_file_set_nocache_if_needed(file, name, mode_str,
- OS_DATA_FILE, access_type);
+ if (!srv_read_only_mode
+ && *success
+ && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
+ || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {
+
+ os_file_set_nocache(file, name, mode_str);
}
#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
- && (access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_WRITE_CACHED)
+ && (access_type == OS_FILE_READ_WRITE)
&& os_file_lock(file, name)) {
*success = FALSE;
@@ -2033,9 +2006,13 @@ os_file_create_func(
} while (retry);
/* We disable OS caching (O_DIRECT) only on data files */
+ if (!srv_read_only_mode
+ && *success
+ && type != OS_LOG_FILE
+ && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
+ || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {
- if (*success) {
- os_file_set_nocache_if_needed(file, name, mode_str, type, 0);
+ os_file_set_nocache(file, name, mode_str);
}
#ifdef USE_FILE_LOCK
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 294facf9723..9b5b1574280 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -2169,7 +2169,8 @@ wait_again:
if (max_doc_id && err == DB_SUCCESS) {
/* Sync fts cache for other fts indexes to keep all
fts indexes consistent in sync_doc_id. */
- err = fts_sync_table(const_cast<dict_table_t*>(new_table));
+ err = fts_sync_table(const_cast<dict_table_t*>(new_table),
+ false, true);
if (err == DB_SUCCESS) {
fts_update_next_doc_id(
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index 6befe3b2d7a..766f8411ca1 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
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
@@ -197,7 +197,8 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param,
ftbw= (FTB_WORD *)alloc_root(&ftb_param->ftb->mem_root,
sizeof(FTB_WORD) +
(info->trunc ? HA_MAX_KEY_BUFF :
- word_len * ftb_param->ftb->charset->mbmaxlen +
+ (word_len + 1) *
+ ftb_param->ftb->charset->mbmaxlen +
HA_FT_WLEN +
ftb_param->ftb->info->s->rec_reflength));
ftbw->len= word_len + 1;
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 05d5ef1d6ca..bb2ba283f36 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -1,4 +1,5 @@
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates
+ Copyright (c) 2009, 2016, MariaDB
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
diff --git a/storage/oqgraph/ha_oqgraph.cc b/storage/oqgraph/ha_oqgraph.cc
index de92da57b56..bafa2ad20f2 100644
--- a/storage/oqgraph/ha_oqgraph.cc
+++ b/storage/oqgraph/ha_oqgraph.cc
@@ -1136,6 +1136,10 @@ int ha_oqgraph::info(uint flag)
int ha_oqgraph::extra(enum ha_extra_function operation)
{
+ if (graph->get_thd() != ha_thd()) {
+ DBUG_PRINT( "oq-debug", ("rnd_pos g->table->in_use: 0x%lx <-- current_thd 0x%lx", (long) graph->get_thd(), (long) current_thd));
+ graph->set_thd(current_thd);
+ }
return edges->file->extra(operation);
}
diff --git a/storage/oqgraph/oqgraph_judy.cc b/storage/oqgraph/oqgraph_judy.cc
index 020cab57ed2..44c7e28e268 100644
--- a/storage/oqgraph/oqgraph_judy.cc
+++ b/storage/oqgraph/oqgraph_judy.cc
@@ -23,6 +23,28 @@
*/
#include "oqgraph_judy.h"
+
+/*
+ Currently the only active code that can return error is:
+ judy_bitset::reset()/J1U()
+ judy_bitset::setbit()/J1S()
+
+ In most cases errors are either about wrong parameters passed to Judy
+ functions or internal structures corruption. These definitely deserve
+ abnormal process termination instead of exit() as it is done by original
+ JUDYERROR.
+
+ TODO: there's one exception that should be handled properly though: OOM.
+*/
+#include <stdio.h>
+#define JUDYERROR(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID) \
+ { \
+ (void) fprintf(stderr, "File '%s', line %d: %s(), " \
+ "JU_ERRNO_* == %d, ID == %d\n", \
+ CallerFile, CallerLine, \
+ JudyFunc, JudyErrno, JudyErrID); \
+ abort(); \
+ }
#include <Judy.h>
void open_query::judy_bitset::clear()
diff --git a/storage/spider/hs_client/fatal.cpp b/storage/spider/hs_client/fatal.cpp
index bec031153e4..260a2e75372 100644
--- a/storage/spider/hs_client/fatal.cpp
+++ b/storage/spider/hs_client/fatal.cpp
@@ -26,26 +26,6 @@ const int opt_syslog = LOG_ERR | LOG_PID | LOG_CONS;
*/
void
-fatal_exit(const String& message)
-{
- fprintf(stderr, "FATAL_EXIT: %s\n", message.ptr());
-/*
- syslog(opt_syslog, "FATAL_EXIT: %s", message.ptr());
-*/
- _exit(1);
-}
-
-void
-fatal_exit(const char *message)
-{
- fprintf(stderr, "FATAL_EXIT: %s\n", message);
-/*
- syslog(opt_syslog, "FATAL_EXIT: %s", message);
-*/
- _exit(1);
-}
-
-void
fatal_abort(const String& message)
{
fprintf(stderr, "FATAL_COREDUMP: %s\n", message.ptr());
diff --git a/storage/spider/hs_client/fatal.hpp b/storage/spider/hs_client/fatal.hpp
index a75c56bddad..e1190ae49c1 100644
--- a/storage/spider/hs_client/fatal.hpp
+++ b/storage/spider/hs_client/fatal.hpp
@@ -22,8 +22,6 @@
namespace dena {
-void fatal_exit(const String& message);
-void fatal_exit(const char *message);
void fatal_abort(const String& message);
void fatal_abort(const char *message);
diff --git a/storage/spider/hs_client/socket.cpp b/storage/spider/hs_client/socket.cpp
index 2082d1f024e..c61b39d140f 100644
--- a/storage/spider/hs_client/socket.cpp
+++ b/storage/spider/hs_client/socket.cpp
@@ -67,7 +67,7 @@ socket_args::set(const config& conf)
message.append(node);
message.q_append(":", sizeof(":") - 1);
message.append(port);
- fatal_exit(message);
+ fatal_abort(message);
}
}
}
diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc
index c5c47064403..2f7fdb62ad4 100644
--- a/storage/spider/spd_conn.cc
+++ b/storage/spider/spd_conn.cc
@@ -2706,7 +2706,7 @@ void *spider_bg_sts_action(
SPIDER_TRX *trx;
int error_num = 0, roop_count;
ha_spider spider;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
int *need_mons;
SPIDER_CONN **conns;
uint *conn_link_idx;
@@ -2733,7 +2733,7 @@ void *spider_bg_sts_action(
my_thread_init();
DBUG_ENTER("spider_bg_sts_action");
/* init start */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
if (!(need_mons = (int *)
spider_bulk_malloc(spider_current_trx, 21, MYF(MY_WME),
@@ -2777,7 +2777,7 @@ void *spider_bg_sts_action(
share->bg_sts_init = FALSE;
pthread_mutex_unlock(&share->sts_mutex);
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -2801,7 +2801,7 @@ void *spider_bg_sts_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -2866,7 +2866,7 @@ void *spider_bg_sts_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -2897,7 +2897,7 @@ void *spider_bg_sts_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3088,7 +3088,7 @@ void *spider_bg_crd_action(
int error_num = 0, roop_count;
ha_spider spider;
TABLE table;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
int *need_mons;
SPIDER_CONN **conns;
uint *conn_link_idx;
@@ -3115,7 +3115,7 @@ void *spider_bg_crd_action(
my_thread_init();
DBUG_ENTER("spider_bg_crd_action");
/* init start */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
if (!(need_mons = (int *)
spider_bulk_malloc(spider_current_trx, 22, MYF(MY_WME),
@@ -3159,7 +3159,7 @@ void *spider_bg_crd_action(
share->bg_crd_init = FALSE;
pthread_mutex_unlock(&share->crd_mutex);
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3183,7 +3183,7 @@ void *spider_bg_crd_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3252,7 +3252,7 @@ void *spider_bg_crd_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3283,7 +3283,7 @@ void *spider_bg_crd_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3417,7 +3417,7 @@ int spider_create_mon_threads(
{
char link_idx_str[SPIDER_SQL_INT_LEN];
int link_idx_str_length;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string conv_name_str(share->table_name_length +
SPIDER_SQL_INT_LEN + 1);
conv_name_str.set_charset(system_charset_info);
@@ -3748,7 +3748,7 @@ int spider_conn_first_link_idx(
int roop_count, active_links = 0;
longlong balance_total = 0, balance_val;
double rand_val;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
int *link_idxs, link_idx;
long *balances;
#else
@@ -3756,7 +3756,7 @@ int spider_conn_first_link_idx(
long balances[link_count];
#endif
DBUG_ENTER("spider_conn_first_link_idx");
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
if (!(link_idxs = (int *)
spider_bulk_malloc(spider_current_trx, 24, MYF(MY_WME),
&link_idxs, sizeof(int) * link_count,
@@ -3782,7 +3782,7 @@ int spider_conn_first_link_idx(
if (active_links == 0)
{
DBUG_PRINT("info",("spider all links are failed"));
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider_current_trx, link_idxs, MYF(MY_WME));
#endif
DBUG_RETURN(-1);
@@ -3811,7 +3811,7 @@ int spider_conn_first_link_idx(
}
DBUG_PRINT("info",("spider first link_idx=%d", link_idxs[roop_count]));
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
link_idx = link_idxs[roop_count];
spider_free(spider_current_trx, link_idxs, MYF(MY_WME));
DBUG_RETURN(link_idx);
diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc
index 9f46e55ca09..c29172a474a 100644
--- a/storage/spider/spd_db_conn.cc
+++ b/storage/spider/spd_db_conn.cc
@@ -9294,7 +9294,7 @@ int spider_db_udf_ping_table(
{
int init_sql_alloc_size =
spider_param_init_sql_alloc_size(trx->thd, share->init_sql_alloc_size);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string sql_str(init_sql_alloc_size);
sql_str.set_charset(system_charset_info);
spider_string where_str(init_sql_alloc_size);
@@ -9517,7 +9517,7 @@ int spider_db_udf_ping_table_mon_next(
SPIDER_SHARE *share = table_mon->share;
int init_sql_alloc_size =
spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string sql_str(init_sql_alloc_size);
sql_str.set_charset(thd->variables.character_set_client);
#else
diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc
index 41c5c240dd3..f59f7760359 100644
--- a/storage/spider/spd_ping_table.cc
+++ b/storage/spider/spd_ping_table.cc
@@ -241,7 +241,7 @@ void spider_release_ping_table_mon_list(
DBUG_PRINT("info", ("spider link_idx=%d", link_idx));
link_idx_str_length = my_sprintf(link_idx_str, (link_idx_str, "%010d",
link_idx));
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string conv_name_str(conv_name_length + link_idx_str_length + 1);
conv_name_str.set_charset(system_charset_info);
#else
@@ -1362,7 +1362,7 @@ int spider_ping_table_mon_from_table(
link_idx_str_length = my_sprintf(link_idx_str, (link_idx_str, "%010d",
link_idx));
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string conv_name_str(conv_name_length + link_idx_str_length + 1);
conv_name_str.set_charset(system_charset_info);
*((char *)(conv_name_str.ptr() + conv_name_length + link_idx_str_length)) =
diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc
index fa712575610..54dd1089b7e 100644
--- a/storage/spider/spd_table.cc
+++ b/storage/spider/spd_table.cc
@@ -3703,7 +3703,7 @@ int spider_create_conn_keys(
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
char *tmp_hs_r_name, *tmp_hs_w_name;
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
uint *conn_keys_lengths;
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
uint *hs_r_conn_keys_lengths;
@@ -3717,7 +3717,7 @@ int spider_create_conn_keys(
#endif
#endif
DBUG_ENTER("spider_create_conn_keys");
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
if (!(conn_keys_lengths =
(uint *) spider_bulk_alloc_mem(spider_current_trx, 44,
__func__, __FILE__, __LINE__, MYF(MY_WME),
@@ -3806,7 +3806,7 @@ int spider_create_conn_keys(
#endif
NullS))
) {
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider_current_trx, conn_keys_lengths, MYF(MY_WME));
#endif
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -3823,7 +3823,7 @@ int spider_create_conn_keys(
sizeof(uint) * share->all_link_count);
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider_current_trx, conn_keys_lengths, MYF(MY_WME));
#endif
@@ -4676,7 +4676,7 @@ SPIDER_SHARE *spider_get_share(
share->link_count, SPIDER_LINK_STATUS_OK);
if (search_link_idx == -1)
{
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 48, MYF(MY_WME),
@@ -4702,7 +4702,7 @@ SPIDER_SHARE *spider_get_share(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM,
ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider->trx, db, MYF(MY_WME));
#endif
*error_num = ER_SPIDER_ALL_LINKS_FAILED_NUM;
@@ -5100,7 +5100,7 @@ SPIDER_SHARE *spider_get_share(
share->link_count, SPIDER_LINK_STATUS_OK);
if (search_link_idx == -1)
{
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 50, MYF(MY_WME),
@@ -5123,7 +5123,7 @@ SPIDER_SHARE *spider_get_share(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM,
ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider->trx, db, MYF(MY_WME));
#endif
*error_num = ER_SPIDER_ALL_LINKS_FAILED_NUM;
diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc
index d7127fa0084..18b6fd5ec89 100644
--- a/storage/spider/spd_trx.cc
+++ b/storage/spider/spd_trx.cc
@@ -3710,7 +3710,7 @@ int spider_check_trx_and_get_conn(
{
TABLE *table = spider->get_table();
TABLE_SHARE *table_share = table->s;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME),
@@ -3732,7 +3732,7 @@ int spider_check_trx_and_get_conn(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM,
ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(trx, db, MYF(MY_WME));
#endif
DBUG_RETURN(ER_SPIDER_ALL_LINKS_FAILED_NUM);
@@ -3869,7 +3869,7 @@ int spider_check_trx_and_get_conn(
{
TABLE *table = spider->get_table();
TABLE_SHARE *table_share = table->s;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME),
@@ -3891,7 +3891,7 @@ int spider_check_trx_and_get_conn(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_LINK_MON_JUST_NG_NUM,
ER_SPIDER_LINK_MON_JUST_NG_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(trx, db, MYF(MY_WME));
#endif
DBUG_RETURN(ER_SPIDER_LINK_MON_JUST_NG_NUM);
@@ -4015,7 +4015,7 @@ int spider_check_trx_and_get_conn(
{
TABLE *table = spider->get_table();
TABLE_SHARE *table_share = table->s;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME),
@@ -4037,7 +4037,7 @@ int spider_check_trx_and_get_conn(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_LINK_MON_JUST_NG_NUM,
ER_SPIDER_LINK_MON_JUST_NG_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(trx, db, MYF(MY_WME));
#endif
DBUG_RETURN(ER_SPIDER_LINK_MON_JUST_NG_NUM);
diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
index f25206d8861..40ccbcc0aed 100644
--- a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
+++ b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
@@ -74,8 +74,8 @@ set_cflags_if_supported(
if (CMAKE_CXX_FLAGS MATCHES -fno-implicit-templates)
# must append this because mysql sets -fno-implicit-templates and we need to override it
- check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_-fimplicit-templates)
- if (HAVE_CXX_-fimplicit-templates)
+ check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_IMPLICIT_TEMPLATES)
+ if (HAVE_CXX_IMPLICIT_TEMPLATES)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fimplicit-templates")
endif ()
endif()
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result
index d3273437f77..9faf04b6a10 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result
@@ -182,14 +182,14 @@ a b c d e f
3 30 200 2000 20000 200000
explain select * from t1 where b > "0";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index b b NULL NULL NULL; Using where; Using index
+1 SIMPLE t1 # b b NULL NULL NULL; Using where; Using index
select * from t1 where b > "0";
a b c d e f
2 20 100 1000 10000 100000
3 30 200 2000 20000 200000
explain select * from t1 where d > "0";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index d d NULL NULL NULL; Using where; Using index
+1 SIMPLE t1 # d d NULL NULL NULL; Using where; Using index
select * from t1 where d > "0";
a b c d e f
2 20 100 1000 10000 100000
diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test
index 3a30919a8ff..f3e494e0dd4 100644
--- a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test
+++ b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test
@@ -82,11 +82,11 @@ alter table t1 add key d(d,a) clustering=yes, add key b(b) clustering=yes;
explain select * from t1 where c > "0";
select * from t1 where c > "0";
---replace_column 7 NULL 9 NULL;
+--replace_column 4 # 7 NULL 9 NULL;
explain select * from t1 where b > "0";
select * from t1 where b > "0";
---replace_column 7 NULL 9 NULL;
+--replace_column 4 # 7 NULL 9 NULL;
explain select * from t1 where d > "0";
select * from t1 where d > "0";
diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc
index 7bce480e652..a68bb8a1344 100644
--- a/storage/xtradb/buf/buf0dump.cc
+++ b/storage/xtradb/buf/buf0dump.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -163,6 +163,25 @@ buf_load_status(
va_end(ap);
}
+/** Returns the directory path where the buffer pool dump file will be created.
+@return directory path */
+static
+const char*
+get_buf_dump_dir()
+{
+ const char* dump_dir;
+
+ /* The dump file should be created in the default data directory if
+ innodb_data_home_dir is set as an empty string. */
+ if (strcmp(srv_data_home, "") == 0) {
+ dump_dir = fil_path_to_mysql_datadir;
+ } else {
+ dump_dir = srv_data_home;
+ }
+
+ return(dump_dir);
+}
+
/*****************************************************************//**
Perform a buffer pool dump into the file specified by
innodb_buffer_pool_filename. If any errors occur then the value of
@@ -186,7 +205,7 @@ buf_dump(
int ret;
ut_snprintf(full_filename, sizeof(full_filename),
- "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
+ "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR,
srv_buf_dump_filename);
ut_snprintf(tmp_filename, sizeof(tmp_filename),
@@ -471,7 +490,7 @@ buf_load()
buf_load_abort_flag = FALSE;
ut_snprintf(full_filename, sizeof(full_filename),
- "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
+ "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR,
srv_buf_dump_filename);
buf_load_status(STATUS_NOTICE,
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index 5d64b75784a..2440637ccca 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -72,12 +72,6 @@ UNIV_INTERN mysql_pfs_key_t buf_page_cleaner_thread_key;
UNIV_INTERN mysql_pfs_key_t buf_lru_manager_thread_key;
#endif /* UNIV_PFS_THREAD */
-/** If LRU list of a buf_pool is less than this size then LRU eviction
-should not happen. This is because when we do LRU flushing we also put
-the blocks on free list. If LRU list is very small then we can end up
-in thrashing. */
-#define BUF_LRU_MIN_LEN 256
-
/* @} */
/******************************************************************//**
diff --git a/storage/xtradb/dict/dict0boot.cc b/storage/xtradb/dict/dict0boot.cc
index 59f210fcab9..138d3131e09 100644
--- a/storage/xtradb/dict/dict0boot.cc
+++ b/storage/xtradb/dict/dict0boot.cc
@@ -474,7 +474,7 @@ dict_boot(void)
} else {
ib_logf(IB_LOG_LEVEL_WARN,
"Change buffer not empty when --innodb-read-only "
- "is set! but srv_force_recovery = %d, ignoring.",
+ "is set! but srv_force_recovery = %lu, ignoring.",
srv_force_recovery);
}
}
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index 206038d36c9..a147fbbc671 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -1116,7 +1116,7 @@ dict_init(void)
&dict_operation_lock, SYNC_DICT_OPERATION);
if (!srv_read_only_mode) {
- dict_foreign_err_file = os_file_create_tmpfile();
+ dict_foreign_err_file = os_file_create_tmpfile(NULL);
ut_a(dict_foreign_err_file);
mutex_create(dict_foreign_err_mutex_key,
diff --git a/storage/xtradb/dict/dict0stats.cc b/storage/xtradb/dict/dict0stats.cc
index 12ead09d829..5c283f693d5 100644
--- a/storage/xtradb/dict/dict0stats.cc
+++ b/storage/xtradb/dict/dict0stats.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2009, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2009, 2015, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -1488,7 +1488,6 @@ on the leaf page.
when comparing records
@param[out] n_diff number of distinct records
@param[out] n_external_pages number of external pages
-@param[in,out] mtr mini-transaction
@return number of distinct records on the leaf page */
static
void
@@ -1496,8 +1495,7 @@ dict_stats_analyze_index_below_cur(
const btr_cur_t* cur,
ulint n_prefix,
ib_uint64_t* n_diff,
- ib_uint64_t* n_external_pages,
- mtr_t* mtr)
+ ib_uint64_t* n_external_pages)
{
dict_index_t* index;
ulint space;
@@ -1511,6 +1509,7 @@ dict_stats_analyze_index_below_cur(
ulint* offsets2;
ulint* offsets_rec;
ulint size;
+ mtr_t mtr;
index = btr_cur_get_index(cur);
@@ -1549,12 +1548,14 @@ dict_stats_analyze_index_below_cur(
function without analyzing any leaf pages */
*n_external_pages = 0;
+ mtr_start(&mtr);
+
/* descend to the leaf level on the B-tree */
for (;;) {
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH,
NULL /* no guessed block */,
- BUF_GET, __FILE__, __LINE__, mtr);
+ BUF_GET, __FILE__, __LINE__, &mtr);
page = buf_block_get_frame(block);
@@ -1576,6 +1577,8 @@ dict_stats_analyze_index_below_cur(
ut_a(*n_diff > 0);
if (*n_diff == 1) {
+ mtr_commit(&mtr);
+
/* page has all keys equal and the end of the page
was reached by dict_stats_scan_page(), no need to
descend to the leaf level */
@@ -1600,7 +1603,7 @@ dict_stats_analyze_index_below_cur(
}
/* make sure we got a leaf page as a result from the above loop */
- ut_ad(btr_page_get_level(page, mtr) == 0);
+ ut_ad(btr_page_get_level(page, &mtr) == 0);
/* scan the leaf page and find the number of distinct keys,
when looking only at the first n_prefix columns; also estimate
@@ -1617,6 +1620,7 @@ dict_stats_analyze_index_below_cur(
__func__, page_no, n_diff);
#endif
+ mtr_commit(&mtr);
mem_heap_free(heap);
}
@@ -1826,8 +1830,7 @@ dict_stats_analyze_index_for_n_prefix(
dict_stats_analyze_index_below_cur(btr_pcur_get_btr_cur(&pcur),
n_prefix,
&n_diff_on_leaf_page,
- &n_external_pages,
- mtr);
+ &n_external_pages);
/* We adjust n_diff_on_leaf_page here to avoid counting
one record twice - once as the last on some page and once
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 2da234ad094..bc30211032b 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -5293,12 +5293,15 @@ retry:
os_offset_t offset
= ((os_offset_t) (start_page_no - file_start_page_no))
* page_size;
+
+ const char* name = node->name == NULL ? space->name : node->name;
+
#ifdef UNIV_HOTBACKUP
- success = os_file_write(node->name, node->handle, buf,
+ success = os_file_write(name, node->handle, buf,
offset, page_size * n_pages);
#else
success = os_aio(OS_FILE_WRITE, 0, OS_AIO_SYNC,
- node->name, node->handle, buf,
+ name, node->handle, buf,
offset, page_size * n_pages, page_size,
node, NULL, space_id, NULL, 0);
#endif /* UNIV_HOTBACKUP */
@@ -5962,22 +5965,12 @@ _fil_io(
}
}
+ const char* name = node->name == NULL ? space->name : node->name;
+
/* Queue the aio request */
- ret = os_aio(
- type,
- is_log,
- mode | wake_later,
- node->name,
- node->handle,
- buf,
- offset,
- len,
- zip_size ? zip_size : UNIV_PAGE_SIZE,
- node,
- message,
- space_id,
- trx,
- write_size);
+ ret = os_aio(type, is_log, mode | wake_later, name, node->handle, buf,
+ offset, len, zip_size ? zip_size : UNIV_PAGE_SIZE, node,
+ message, space_id, trx, write_size);
#else
/* In mysqlbackup do normal i/o, not aio */
@@ -5985,7 +5978,7 @@ _fil_io(
ret = os_file_read(node->handle, buf, offset, len);
} else {
ut_ad(!srv_read_only_mode);
- ret = os_file_write(node->name, node->handle, buf,
+ ret = os_file_write(name, node->handle, buf,
offset, len);
}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/fts/fts0opt.cc b/storage/xtradb/fts/fts0opt.cc
index 0703b050848..00b3b4682c3 100644
--- a/storage/xtradb/fts/fts0opt.cc
+++ b/storage/xtradb/fts/fts0opt.cc
@@ -580,7 +580,7 @@ fts_zip_read_word(
#ifdef UNIV_DEBUG
ulint i;
#endif
- byte len = 0;
+ short len = 0;
void* null = NULL;
byte* ptr = word->f_str;
int flush = Z_NO_FLUSH;
@@ -590,7 +590,7 @@ fts_zip_read_word(
return(NULL);
}
- zip->zp->next_out = &len;
+ zip->zp->next_out = reinterpret_cast<byte*>(&len);
zip->zp->avail_out = sizeof(len);
while (zip->status == Z_OK && zip->zp->avail_out > 0) {
@@ -688,11 +688,12 @@ fts_fetch_index_words(
fts_zip_t* zip = static_cast<fts_zip_t*>(user_arg);
que_node_t* exp = sel_node->select_list;
dfield_t* dfield = que_node_get_val(exp);
- byte len = (byte) dfield_get_len(dfield);
+ short len = static_cast<short>(dfield_get_len(dfield));
void* data = dfield_get_data(dfield);
/* Skip the duplicate words. */
- if (zip->word.f_len == len && !memcmp(zip->word.f_str, data, len)) {
+ if (zip->word.f_len == static_cast<ulint>(len)
+ && !memcmp(zip->word.f_str, data, len)) {
return(TRUE);
}
@@ -706,7 +707,7 @@ fts_fetch_index_words(
ut_a(zip->zp->next_in == NULL);
/* The string is prefixed by len. */
- zip->zp->next_in = &len;
+ zip->zp->next_in = reinterpret_cast<byte*>(&len);
zip->zp->avail_in = sizeof(len);
/* Compress the word, create output blocks as necessary. */
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 065f1bd2ca0..5a86f5662cc 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -617,7 +617,6 @@ ib_cb_t innodb_api_cb[] = {
(ib_cb_t) ib_trx_read_only
};
-
static void innodb_remember_check_sysvar_funcs();
mysql_var_check_func check_sysvar_enum;
@@ -652,6 +651,67 @@ ha_create_table_option innodb_table_option_list[]=
HA_TOPTION_END
};
+/**
+ Test a file path whether it is same as mysql data directory path.
+
+ @param path null terminated character string
+
+ @return
+ @retval TRUE The path is different from mysql data directory.
+ @retval FALSE The path is same as mysql data directory.
+*/
+static bool is_mysql_datadir_path(const char *path)
+{
+ if (path == NULL)
+ return false;
+
+ char mysql_data_dir[FN_REFLEN], path_dir[FN_REFLEN];
+ convert_dirname(path_dir, path, NullS);
+ convert_dirname(mysql_data_dir, mysql_unpacked_real_data_home, NullS);
+ size_t mysql_data_home_len= dirname_length(mysql_data_dir);
+ size_t path_len = dirname_length(path_dir);
+
+ if (path_len < mysql_data_home_len)
+ return true;
+
+ if (!lower_case_file_system)
+ return(memcmp(mysql_data_dir, path_dir, mysql_data_home_len));
+
+ return(files_charset_info->coll->strnncoll(files_charset_info,
+ (uchar *) path_dir, path_len,
+ (uchar *) mysql_data_dir,
+ mysql_data_home_len,
+ TRUE));
+}
+
+
+static int mysql_tmpfile_path(const char *path, const char *prefix)
+{
+ DBUG_ASSERT(path != NULL);
+ DBUG_ASSERT((strlen(path) + strlen(prefix)) <= FN_REFLEN);
+
+ char filename[FN_REFLEN];
+ File fd = create_temp_file(filename, path, prefix,
+#ifdef __WIN__
+ O_BINARY | O_TRUNC | O_SEQUENTIAL |
+ O_SHORT_LIVED |
+#endif /* __WIN__ */
+ O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
+ MYF(MY_WME));
+ if (fd >= 0) {
+#ifndef __WIN__
+ /*
+ This can be removed once the following bug is fixed:
+ Bug #28903 create_temp_file() doesn't honor O_TEMPORARY option
+ (file not removed) (Unix)
+ */
+ unlink(filename);
+#endif /* !__WIN__ */
+ }
+
+ return fd;
+}
+
/*************************************************************//**
Check whether valid argument given to innodb_ft_*_stopword_table.
This function is registered as a callback with MySQL.
@@ -667,6 +727,108 @@ innodb_stopword_table_validate(
for update function */
struct st_mysql_value* value); /*!< in: incoming string */
+/** Validate passed-in "value" is a valid directory name.
+This function is registered as a callback with MySQL.
+@param[in,out] thd thread handle
+@param[in] var pointer to system variable
+@param[out] save immediate result for update
+@param[in] value incoming string
+@return 0 for valid name */
+static
+int
+innodb_tmpdir_validate(
+ THD* thd,
+ struct st_mysql_sys_var* var,
+ void* save,
+ struct st_mysql_value* value)
+{
+
+ char* alter_tmp_dir;
+ char* innodb_tmp_dir;
+ char buff[OS_FILE_MAX_PATH];
+ int len = sizeof(buff);
+ char tmp_abs_path[FN_REFLEN + 2];
+
+ ut_ad(save != NULL);
+ ut_ad(value != NULL);
+
+ if (check_global_access(thd, FILE_ACL)) {
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "InnoDB: FILE Permissions required");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+
+ alter_tmp_dir = (char*) value->val_str(value, buff, &len);
+
+ if (!alter_tmp_dir) {
+ *static_cast<const char**>(save) = alter_tmp_dir;
+ return(0);
+ }
+
+ if (strlen(alter_tmp_dir) > FN_REFLEN) {
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "Path length should not exceed %d bytes", FN_REFLEN);
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+
+ my_realpath(tmp_abs_path, alter_tmp_dir, 0);
+ size_t tmp_abs_len = strlen(tmp_abs_path);
+
+ if (my_access(tmp_abs_path, F_OK)) {
+
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "InnoDB: Path doesn't exist.");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ } else if (my_access(tmp_abs_path, R_OK | W_OK)) {
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "InnoDB: Server doesn't have permission in "
+ "the given location.");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+
+ MY_STAT stat_info_dir;
+
+ if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) {
+ if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) {
+
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "Given path is not a directory. ");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+ }
+
+ if (!is_mysql_datadir_path(tmp_abs_path)) {
+
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "InnoDB: Path Location should not be same as "
+ "mysql data directory location.");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+
+ innodb_tmp_dir = static_cast<char*>(
+ thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1));
+ *static_cast<const char**>(save) = innodb_tmp_dir;
+ return(0);
+}
+
/** "GEN_CLUST_INDEX" is the name reserved for InnoDB default
system clustered index when there is no primary key. */
const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX";
@@ -796,6 +958,11 @@ static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG,
"This is to cause replication prefetch IO. ATTENTION: the transaction started after enabled is affected.",
NULL, NULL, FALSE);
+static MYSQL_THDVAR_STR(tmpdir,
+ PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_MEMALLOC,
+ "Directory for temporary non-tablespace files.",
+ innodb_tmpdir_validate, NULL, NULL);
+
static ibool innodb_have_lzo=IF_LZO(1, 0);
static ibool innodb_have_lz4=IF_LZ4(1, 0);
static ibool innodb_have_lzma=IF_LZMA(1, 0);
@@ -1492,6 +1659,28 @@ normalize_table_name_low(
ibool set_lower_case); /* in: TRUE if we want to set
name to lower case */
+/*************************************************************//**
+Checks if buffer pool is big enough to enable backoff algorithm.
+InnoDB empty free list algorithm backoff requires free pages
+from LRU for the best performance.
+buf_LRU_buf_pool_running_out cancels query if 1/4 of
+buffer pool belongs to LRU or freelist.
+At the same time buf_flush_LRU_list_batch
+keeps up to BUF_LRU_MIN_LEN in LRU.
+In order to avoid deadlock baclkoff requires buffer pool
+to be at least 4*BUF_LRU_MIN_LEN,
+but flush peformance is bad because of trashing
+and additional BUF_LRU_MIN_LEN pages are requested.
+@return true if it's possible to enable backoff. */
+static
+bool
+innodb_empty_free_list_algorithm_backoff_allowed(
+ srv_empty_free_list_t
+ algorithm, /*!< in: desired algorithm
+ from srv_empty_free_list_t */
+ long long buf_pool_pages); /*!< in: total number
+ of pages inside buffer pool */
+
#ifdef NOT_USED
/*************************************************************//**
Removes old archived transaction log files.
@@ -1780,6 +1969,26 @@ thd_supports_xa(
return(THDVAR(thd, support_xa));
}
+/** Get the value of innodb_tmpdir.
+@param[in] thd thread handle, or NULL to query
+ the global innodb_tmpdir.
+@retval NULL if innodb_tmpdir="" */
+UNIV_INTERN
+const char*
+thd_innodb_tmpdir(
+ THD* thd)
+{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(false));
+#endif /* UNIV_SYNC_DEBUG */
+
+ const char* tmp_dir = THDVAR(thd, tmpdir);
+ if (tmp_dir != NULL && *tmp_dir == '\0') {
+ tmp_dir = NULL;
+ }
+
+ return(tmp_dir);
+}
/******************************************************************//**
Check the status of fake changes mode (innodb_fake_changes)
@return true if fake change mode is enabled. */
@@ -2360,13 +2569,14 @@ innobase_get_lower_case_table_names(void)
return(lower_case_table_names);
}
-/*********************************************************************//**
-Creates a temporary file.
+/** Create a temporary file in the location specified by the parameter
+path. If the path is null, then it will be created in tmpdir.
+@param[in] path location for creating temporary file
@return temporary file descriptor, or < 0 on error */
UNIV_INTERN
int
-innobase_mysql_tmpfile(void)
-/*========================*/
+innobase_mysql_tmpfile(
+ const char* path)
{
#ifdef WITH_INNODB_DISALLOW_WRITES
os_event_wait(srv_allow_writes_event);
@@ -2379,7 +2589,11 @@ innobase_mysql_tmpfile(void)
return(-1);
);
- fd = mysql_tmpfile("ib");
+ if (path == NULL) {
+ fd = mysql_tmpfile("ib");
+ } else {
+ fd = mysql_tmpfile_path(path, "ib");
+ }
if (fd >= 0) {
/* Copy the file descriptor, so that the additional resources
@@ -3408,6 +3622,13 @@ ha_innobase::reset_template(void)
ut_ad(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
ut_ad(prebuilt->magic_n2 == prebuilt->magic_n);
+ /* Force table to be freed in close_thread_table(). */
+ DBUG_EXECUTE_IF("free_table_in_fts_query",
+ if (prebuilt->in_fts_query) {
+ table->m_needs_reopen = true;
+ }
+ );
+
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
prebuilt->in_fts_query = 0;
@@ -4076,6 +4297,22 @@ innobase_change_buffering_inited_ok:
#ifdef HAVE_POSIX_FALLOCATE
srv_use_posix_fallocate = (ibool) innobase_use_fallocate;
#endif
+
+ /* Do not enable backoff algorithm for small buffer pool. */
+ if (!innodb_empty_free_list_algorithm_backoff_allowed(
+ static_cast<srv_empty_free_list_t>(
+ srv_empty_free_list_algorithm),
+ innobase_buffer_pool_size / srv_page_size)) {
+ sql_print_information(
+ "InnoDB: innodb_empty_free_list_algorithm "
+ "has been changed to legacy "
+ "because of small buffer pool size. "
+ "In order to use backoff, "
+ "increase buffer pool at least up to 20MB.\n");
+ srv_empty_free_list_algorithm
+ = SRV_EMPTY_FREE_LIST_LEGACY;
+ }
+
srv_use_atomic_writes = (ibool) innobase_use_atomic_writes;
if (innobase_use_atomic_writes) {
ib_logf(IB_LOG_LEVEL_INFO, "using atomic writes.");
@@ -5718,7 +5955,7 @@ building based on the assumption that there is no concurrent
index creation/drop and DMLs that requires index lookup. All table
handle will be closed before the index creation/drop.
@return TRUE if index translation table built successfully */
-static
+UNIV_INTERN
ibool
innobase_build_index_translation(
/*=============================*/
@@ -6270,20 +6507,14 @@ table_opened:
prebuilt->clust_index_was_generated = FALSE;
if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
- sql_print_error("Table %s has a primary key in "
- "InnoDB data dictionary, but not "
- "in MySQL!", name);
+ ib_table->dict_frm_mismatch = DICT_FRM_NO_PK;
/* This mismatch could cause further problems
if not attended, bring this to the user's attention
by printing a warning in addition to log a message
in the errorlog */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_NO_SUCH_INDEX,
- "InnoDB: Table %s has a "
- "primary key in InnoDB data "
- "dictionary, but not in "
- "MySQL!", name);
+
+ ib_push_frm_error(thd, ib_table, table, 0, true);
/* If primary_key >= MAX_KEY, its (primary_key)
value could be out of bound if continue to index
@@ -6330,27 +6561,14 @@ table_opened:
}
} else {
if (primary_key != MAX_KEY) {
- sql_print_error(
- "Table %s has no primary key in InnoDB data "
- "dictionary, but has one in MySQL! If you "
- "created the table with a MySQL version < "
- "3.23.54 and did not define a primary key, "
- "but defined a unique key with all non-NULL "
- "columns, then MySQL internally treats that "
- "key as the primary key. You can fix this "
- "error by dump + DROP + CREATE + reimport "
- "of the table.", name);
+
+ ib_table->dict_frm_mismatch = DICT_NO_PK_FRM_HAS;
/* This mismatch could cause further problems
if not attended, bring this to the user attention
by printing a warning in addition to log a message
in the errorlog */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_NO_SUCH_INDEX,
- "InnoDB: Table %s has no "
- "primary key in InnoDB data "
- "dictionary, but has one in "
- "MySQL!", name);
+ ib_push_frm_error(thd, ib_table, table, 0, true);
}
prebuilt->clust_index_was_generated = TRUE;
@@ -13960,12 +14178,8 @@ ha_innobase::info_low(
}
if (table->s->keys != num_innodb_index) {
- sql_print_error("InnoDB: Table %s contains %lu "
- "indexes inside InnoDB, which "
- "is different from the number of "
- "indexes %u defined in the MySQL ",
- ib_table->name, num_innodb_index,
- table->s->keys);
+ ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS;
+ ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true);
}
if (!(flag & HA_STATUS_NO_LOCK)) {
@@ -13985,15 +14199,8 @@ ha_innobase::info_low(
dict_index_t* index = innobase_get_index(i);
if (index == NULL) {
- sql_print_error("Table %s contains fewer "
- "indexes inside InnoDB than "
- "are defined in the MySQL "
- ".frm file. Have you mixed up "
- ".frm files from different "
- "installations? See "
- REFMAN
- "innodb-troubleshooting.html\n",
- ib_table->name);
+ ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS;
+ ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true);
break;
}
@@ -18762,8 +18969,6 @@ innobase_fts_close_ranking(
{
fts_result_t* result;
- ((NEW_FT_INFO*) fts_hdl)->ft_prebuilt->in_fts_query = false;
-
result = ((NEW_FT_INFO*) fts_hdl)->ft_result;
fts_query_free_result(result);
@@ -19473,6 +19678,7 @@ static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid)
return 0;
}
+
static void
wsrep_fake_trx_id(
/*==================*/
@@ -19488,6 +19694,88 @@ wsrep_fake_trx_id(
#endif /* WITH_WSREP */
+
+/*************************************************************//**
+Empty free list algorithm.
+Checks if buffer pool is big enough to enable backoff algorithm.
+InnoDB empty free list algorithm backoff requires free pages
+from LRU for the best performance.
+buf_LRU_buf_pool_running_out cancels query if 1/4 of
+buffer pool belongs to LRU or freelist.
+At the same time buf_flush_LRU_list_batch
+keeps up to BUF_LRU_MIN_LEN in LRU.
+In order to avoid deadlock baclkoff requires buffer pool
+to be at least 4*BUF_LRU_MIN_LEN,
+but flush peformance is bad because of trashing
+and additional BUF_LRU_MIN_LEN pages are requested.
+@return true if it's possible to enable backoff. */
+static
+bool
+innodb_empty_free_list_algorithm_backoff_allowed(
+ srv_empty_free_list_t algorithm, /*!< in: desired algorithm
+ from srv_empty_free_list_t */
+ long long buf_pool_pages) /*!< in: total number
+ of pages inside buffer pool */
+{
+ return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1)
+ || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF);
+}
+
+/*************************************************************//**
+Empty free list algorithm. This function is registered as
+a callback with MySQL.
+@return 0 for valid algorithm */
+static
+int
+innodb_srv_empty_free_list_algorithm_validate(
+/*===========================*/
+ THD* thd, /*!< in: thread handle */
+ struct st_mysql_sys_var* var, /*!< in: pointer to system
+ variable */
+ void* save, /*!< out: immediate result
+ for update function */
+ struct st_mysql_value* value) /*!< in: incoming string */
+{
+ const char* algorithm_name;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ int len = sizeof(buff);
+ ulint algo;
+ srv_empty_free_list_t algorithm;
+
+ algorithm_name = value->val_str(value, buff, &len);
+
+ if (!algorithm_name) {
+ return(1);
+ }
+
+ for (algo = 0; algo < array_elements(
+ innodb_empty_free_list_algorithm_names
+ ) - 1;
+ algo++) {
+ if (!innobase_strcasecmp(
+ algorithm_name,
+ innodb_empty_free_list_algorithm_names[algo]))
+ break;
+ }
+
+ if (algo == array_elements( innodb_empty_free_list_algorithm_names) - 1)
+ return(1);
+
+ algorithm = static_cast<srv_empty_free_list_t>(algo);
+ if (!innodb_empty_free_list_algorithm_backoff_allowed(
+ algorithm,
+ innobase_buffer_pool_size / srv_page_size)) {
+ sql_print_warning(
+ "InnoDB: innodb_empty_free_list_algorithm "
+ "= 'backoff' requires at least"
+ " 20MB buffer pool.\n");
+ return(1);
+ }
+
+ *reinterpret_cast<ulong*>(save) = static_cast<ulong>(algorithm);
+ return(0);
+}
+
/* plugin options */
static MYSQL_SYSVAR_ENUM(checksum_algorithm, srv_checksum_algorithm,
@@ -20038,7 +20326,7 @@ static MYSQL_SYSVAR_ENUM(empty_free_list_algorithm,
"The algorithm to use for empty free list handling. Allowed values: "
"LEGACY: Original Oracle MySQL 5.6 handling with single page flushes; "
"BACKOFF: (default) Wait until cleaner produces a free page.",
- NULL, NULL, SRV_EMPTY_FREE_LIST_BACKOFF,
+ innodb_srv_empty_free_list_algorithm_validate, NULL, SRV_EMPTY_FREE_LIST_BACKOFF,
&innodb_empty_free_list_algorithm_typelib);
static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
@@ -21078,6 +21366,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(corrupt_table_action),
MYSQL_SYSVAR(fake_changes),
MYSQL_SYSVAR(locking_fake_changes),
+ MYSQL_SYSVAR(tmpdir),
MYSQL_SYSVAR(use_stacktrace),
MYSQL_SYSVAR(force_primary_key),
MYSQL_SYSVAR(fatal_semaphore_wait_threshold),
@@ -21822,3 +22111,96 @@ ib_push_warning(
my_free(buf);
va_end(args);
}
+
+/********************************************************************//**
+Helper function to push frm mismatch error to error log and
+if needed to sql-layer. */
+UNIV_INTERN
+void
+ib_push_frm_error(
+/*==============*/
+ THD* thd, /*!< in: MySQL thd */
+ dict_table_t* ib_table, /*!< in: InnoDB table */
+ TABLE* table, /*!< in: MySQL table */
+ ulint n_keys, /*!< in: InnoDB #keys */
+ bool push_warning) /*!< in: print warning ? */
+{
+ switch (ib_table->dict_frm_mismatch) {
+ case DICT_FRM_NO_PK:
+ sql_print_error("Table %s has a primary key in "
+ "InnoDB data dictionary, but not "
+ "in MySQL!"
+ " Have you mixed up "
+ ".frm files from different "
+ "installations? See "
+ REFMAN
+ "innodb-troubleshooting.html\n",
+ ib_table->name);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s has a "
+ "primary key in InnoDB data "
+ "dictionary, but not in "
+ "MySQL!", ib_table->name);
+ }
+ break;
+ case DICT_NO_PK_FRM_HAS:
+ sql_print_error(
+ "Table %s has no primary key in InnoDB data "
+ "dictionary, but has one in MySQL! If you "
+ "created the table with a MySQL version < "
+ "3.23.54 and did not define a primary key, "
+ "but defined a unique key with all non-NULL "
+ "columns, then MySQL internally treats that "
+ "key as the primary key. You can fix this "
+ "error by dump + DROP + CREATE + reimport "
+ "of the table.", ib_table->name);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s has no "
+ "primary key in InnoDB data "
+ "dictionary, but has one in "
+ "MySQL!",
+ ib_table->name);
+ }
+ break;
+
+ case DICT_FRM_INCONSISTENT_KEYS:
+ sql_print_error("InnoDB: Table %s contains %lu "
+ "indexes inside InnoDB, which "
+ "is different from the number of "
+ "indexes %u defined in the MySQL "
+ " Have you mixed up "
+ ".frm files from different "
+ "installations? See "
+ REFMAN
+ "innodb-troubleshooting.html\n",
+ ib_table->name, n_keys,
+ table->s->keys);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s contains %lu "
+ "indexes inside InnoDB, which "
+ "is different from the number of "
+ "indexes %u defined in the MySQL ",
+ ib_table->name, n_keys,
+ table->s->keys);
+ }
+ break;
+
+ case DICT_FRM_CONSISTENT:
+ default:
+ sql_print_error("InnoDB: Table %s is consistent "
+ "on InnoDB data dictionary and MySQL "
+ " FRM file.",
+ ib_table->name);
+ ut_error;
+ break;
+ }
+}
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index 2027a593140..ea4be1fb2e0 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
+Copyright (c) 2013, 2016, MariaDB Corporation.
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
@@ -696,3 +696,39 @@ innobase_copy_frm_flags_from_table_share(
/*=====================================*/
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
const TABLE_SHARE* table_share); /*!< in: table share */
+
+/*******************************************************************//**
+This function builds a translation table in INNOBASE_SHARE
+structure for fast index location with mysql array number from its
+table->key_info structure. This also provides the necessary translation
+between the key order in mysql key_info and Innodb ib_table->indexes if
+they are not fully matched with each other.
+Note we do not have any mutex protecting the translation table
+building based on the assumption that there is no concurrent
+index creation/drop and DMLs that requires index lookup. All table
+handle will be closed before the index creation/drop.
+@return TRUE if index translation table built successfully */
+UNIV_INTERN
+ibool
+innobase_build_index_translation(
+/*=============================*/
+ const TABLE* table, /*!< in: table in MySQL data
+ dictionary */
+ dict_table_t* ib_table, /*!< in: table in Innodb data
+ dictionary */
+ INNOBASE_SHARE* share); /*!< in/out: share structure
+ where index translation table
+ will be constructed in. */
+
+/********************************************************************//**
+Helper function to push frm mismatch error to error log and
+if needed to sql-layer. */
+UNIV_INTERN
+void
+ib_push_frm_error(
+/*==============*/
+ THD* thd, /*!< in: MySQL thd */
+ dict_table_t* ib_table, /*!< in: InnoDB table */
+ TABLE* table, /*!< in: MySQL table */
+ ulint n_keys, /*!< in: InnoDB #keys */
+ bool push_warning); /*!< in: print warning ? */
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index ea02463010c..1e57f6c5293 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -463,6 +463,20 @@ ha_innobase::check_if_supported_inplace_alter(
}
}
+ ulint n_indexes = UT_LIST_GET_LEN((prebuilt->table)->indexes);
+
+ /* If InnoDB dictionary and MySQL frm file are not consistent
+ use "Copy" method. */
+ if (prebuilt->table->dict_frm_mismatch) {
+
+ ha_alter_info->unsupported_reason = innobase_get_err_msg(
+ ER_NO_SUCH_INDEX);
+ ib_push_frm_error(user_thd, prebuilt->table, altered_table,
+ n_indexes, true);
+
+ DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+ }
+
/* We should be able to do the operation in-place.
See if we can do it online (LOCK=NONE). */
bool online = true;
@@ -2777,6 +2791,10 @@ prepare_inplace_alter_table_dict(
ctx->num_to_add_index = ha_alter_info->index_add_count;
+ ut_ad(ctx->prebuilt->trx->mysql_thd != NULL);
+ const char* path = thd_innodb_tmpdir(
+ ctx->prebuilt->trx->mysql_thd);
+
index_defs = innobase_create_key_defs(
ctx->heap, ha_alter_info, altered_table, ctx->num_to_add_index,
num_fts_index,
@@ -3130,8 +3148,10 @@ prepare_inplace_alter_table_dict(
error = DB_OUT_OF_MEMORY;
goto error_handling;);
rw_lock_x_lock(&ctx->add_index[a]->lock);
+
bool ok = row_log_allocate(ctx->add_index[a],
- NULL, true, NULL, NULL);
+ NULL, true, NULL,
+ NULL, path);
rw_lock_x_unlock(&ctx->add_index[a]->lock);
if (!ok) {
@@ -3157,7 +3177,7 @@ prepare_inplace_alter_table_dict(
clust_index, ctx->new_table,
!(ha_alter_info->handler_flags
& Alter_inplace_info::ADD_PK_INDEX),
- ctx->add_cols, ctx->col_map);
+ ctx->add_cols, ctx->col_map, path);
rw_lock_x_unlock(&clust_index->lock);
if (!ok) {
@@ -4159,6 +4179,7 @@ ok_exit:
files and merge sort. */
DBUG_EXECUTE_IF("innodb_OOM_inplace_alter",
error = DB_OUT_OF_MEMORY; goto oom;);
+
error = row_merge_build_indexes(
prebuilt->trx,
prebuilt->table, ctx->new_table,
@@ -6194,6 +6215,21 @@ foreign_fail:
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
+ /* Rebuild index translation table now for temporary tables if we are
+ restoring secondary keys, as ha_innobase::open will not be called for
+ the next access. */
+ if (dict_table_is_temporary(ctx0->new_table)
+ && ctx0->num_to_add_index > 0) {
+ ut_ad(!ctx0->num_to_drop_index);
+ ut_ad(!ctx0->num_to_drop_fk);
+ if (!innobase_build_index_translation(altered_table,
+ ctx0->new_table,
+ share)) {
+ MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
+ DBUG_RETURN(true);
+ }
+ }
+
/* TODO: The following code could be executed
while allowing concurrent access to the table
(MDL downgrade). */
diff --git a/storage/xtradb/include/buf0flu.h b/storage/xtradb/include/buf0flu.h
index 87ce7d88bdf..c8a329251fa 100644
--- a/storage/xtradb/include/buf0flu.h
+++ b/storage/xtradb/include/buf0flu.h
@@ -312,6 +312,12 @@ buf_flush_flush_list_in_progress(void)
/*==================================*/
__attribute__((warn_unused_result));
+/** If LRU list of a buf_pool is less than this size then LRU eviction
+should not happen. This is because when we do LRU flushing we also put
+the blocks on free list. If LRU list is very small then we can end up
+in thrashing. */
+#define BUF_LRU_MIN_LEN 256
+
/******************************************************************//**
Start a buffer flush batch for LRU or flush list */
ibool
diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h
index 9c43829cecf..a55d5316969 100644
--- a/storage/xtradb/include/dict0mem.h
+++ b/storage/xtradb/include/dict0mem.h
@@ -2,7 +2,7 @@
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2015, MariaDB Corporation.
+Copyright (c) 2013, 2016, MariaDB Corporation.
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
@@ -1025,6 +1025,18 @@ if table->memcached_sync_count == DICT_TABLE_IN_DDL means there's DDL running on
the table, DML from memcached will be blocked. */
#define DICT_TABLE_IN_DDL -1
+/** These are used when MySQL FRM and InnoDB data dictionary are
+in inconsistent state. */
+typedef enum {
+ DICT_FRM_CONSISTENT = 0, /*!< Consistent state */
+ DICT_FRM_NO_PK = 1, /*!< MySQL has no primary key
+ but InnoDB dictionary has
+ non-generated one. */
+ DICT_NO_PK_FRM_HAS = 2, /*!< MySQL has primary key but
+ InnoDB dictionary has not. */
+ DICT_FRM_INCONSISTENT_KEYS = 3 /*!< Key count mismatch */
+} dict_frm_t;
+
/** Data structure for a database table. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct dict_table_t{
@@ -1085,6 +1097,10 @@ struct dict_table_t{
/*!< True if the table belongs to a system
database (mysql, information_schema or
performance_schema) */
+ dict_frm_t dict_frm_mismatch;
+ /*!< !DICT_FRM_CONSISTENT==0 if data
+ dictionary information and
+ MySQL FRM information mismatch. */
#ifndef UNIV_HOTBACKUP
hash_node_t name_hash; /*!< hash chain node */
hash_node_t id_hash; /*!< hash chain node */
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index a9c003d5bb1..212a47a7a9b 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2006, 2015, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -356,6 +356,15 @@ thd_supports_xa(
THD* thd); /*!< in: thread handle, or NULL to query
the global innodb_supports_xa */
+/** Get status of innodb_tmpdir.
+@param[in] thd thread handle, or NULL to query
+ the global innodb_tmpdir.
+@retval NULL if innodb_tmpdir="" */
+UNIV_INTERN
+const char*
+thd_innodb_tmpdir(
+ THD* thd);
+
/******************************************************************//**
Check the status of fake changes mode (innodb_fake_changes)
@return true if fake change mode is enabled. */
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index c15d896caa6..c890f96b0e1 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -457,14 +457,19 @@ UNIV_INTERN
void
os_io_init_simple(void);
/*===================*/
-/***********************************************************************//**
-Creates a temporary file. This function is like tmpfile(3), but
-the temporary file is created in the MySQL temporary directory.
-@return temporary file handle, or NULL on error */
+
+/** Create a temporary file. This function is like tmpfile(3), but
+the temporary file is created in the given parameter path. If the path
+is null then it will create the file in the mysql server configuration
+parameter (--tmpdir).
+@param[in] path location for creating temporary file
+@return temporary file handle, or NULL on error */
+UNIV_INTERN
FILE*
-os_file_create_tmpfile(void);
-/*========================*/
+os_file_create_tmpfile(
+ const char* path);
+
#endif /* !UNIV_HOTBACKUP */
/***********************************************************************//**
The os_file_opendir() function opens a directory stream corresponding to the
@@ -1314,14 +1319,14 @@ os_file_get_status(
file can be opened in RW mode */
#if !defined(UNIV_HOTBACKUP)
-/*********************************************************************//**
-Creates a temporary file that will be deleted on close.
-This function is defined in ha_innodb.cc.
-@return temporary file descriptor, or < 0 on error */
+/** Create a temporary file in the location specified by the parameter
+path. If the path is null, then it will be created in tmpdir.
+@param[in] path location for creating temporary file
+@return temporary file descriptor, or < 0 on error */
UNIV_INTERN
int
-innobase_mysql_tmpfile(void);
-/*========================*/
+innobase_mysql_tmpfile(
+ const char* path);
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/include/row0log.h b/storage/xtradb/include/row0log.h
index f105838eece..e127504c484 100644
--- a/storage/xtradb/include/row0log.h
+++ b/storage/xtradb/include/row0log.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
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
@@ -55,8 +55,9 @@ row_log_allocate(
const dtuple_t* add_cols,
/*!< in: default values of
added columns, or NULL */
- const ulint* col_map)/*!< in: mapping of old column
+ const ulint* col_map,/*!< in: mapping of old column
numbers to new ones, or NULL if !table */
+ const char* path) /*!< in: where to create temporary file */
__attribute__((nonnull(1), warn_unused_result));
/******************************************************//**
diff --git a/storage/xtradb/include/row0merge.h b/storage/xtradb/include/row0merge.h
index 3e3459b8703..53164b5197f 100644
--- a/storage/xtradb/include/row0merge.h
+++ b/storage/xtradb/include/row0merge.h
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, MariaDB Corporation.
+Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, 2016, MariaDB Corporation.
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
@@ -187,14 +187,14 @@ void
row_merge_drop_temp_indexes(void);
/*=============================*/
-/*********************************************************************//**
-Creates temporary merge files, and if UNIV_PFS_IO defined, register
-the file descriptor with Performance Schema.
+/** Create temporary merge files in the given paramater path, and if
+UNIV_PFS_IO defined, register the file descriptor with Performance Schema.
+@param[in] path location for creating temporary merge files.
@return File descriptor */
UNIV_INTERN
int
-row_merge_file_create_low(void)
-/*===========================*/
+row_merge_file_create_low(
+ const char* path)
__attribute__((warn_unused_result));
/*********************************************************************//**
Destroy a merge file. And de-register the file from Performance Schema
@@ -372,15 +372,17 @@ row_merge_buf_empty(
/*================*/
row_merge_buf_t* buf) /*!< in,own: sort buffer */
__attribute__((warn_unused_result, nonnull));
-/*********************************************************************//**
-Create a merge file.
+
+/** Create a merge file in the given location.
+@param[out] merge_file merge file structure
+@param[in] path location for creating temporary file
@return file descriptor, or -1 on failure */
UNIV_INTERN
int
row_merge_file_create(
-/*==================*/
- merge_file_t* merge_file) /*!< out: merge file structure */
- __attribute__((nonnull));
+ merge_file_t* merge_file,
+ const char* path);
+
/*********************************************************************//**
Merge disk files.
@return DB_SUCCESS or error code */
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index f4a0da12476..b0fe3f020d2 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -45,10 +45,10 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 28
+#define INNODB_VERSION_BUGFIX 29
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 76.1
+#define PERCONA_INNODB_VERSION 76.2
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc
index c3044daafad..7364c10c08e 100644
--- a/storage/xtradb/lock/lock0lock.cc
+++ b/storage/xtradb/lock/lock0lock.cc
@@ -639,7 +639,7 @@ lock_sys_create(
lock_sys->rec_num = 0;
if (!srv_read_only_mode) {
- lock_latest_err_file = os_file_create_tmpfile();
+ lock_latest_err_file = os_file_create_tmpfile(NULL);
ut_a(lock_latest_err_file);
}
}
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index 2bb094e115d..4010ef10359 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -991,19 +991,21 @@ os_io_init_simple(void)
#endif
}
-/***********************************************************************//**
-Creates a temporary file. This function is like tmpfile(3), but
-the temporary file is created in the MySQL temporary directory.
-@return temporary file handle, or NULL on error */
+/** Create a temporary file. This function is like tmpfile(3), but
+the temporary file is created in the given parameter path. If the path
+is null then it will create the file in the mysql server configuration
+parameter (--tmpdir).
+@param[in] path location for creating temporary file
+@return temporary file handle, or NULL on error */
UNIV_INTERN
FILE*
-os_file_create_tmpfile(void)
-/*========================*/
+os_file_create_tmpfile(
+ const char* path)
{
- FILE* file = NULL;
- int fd;
WAIT_ALLOW_WRITES();
- fd = innobase_mysql_tmpfile();
+
+ FILE* file = NULL;
+ int fd = innobase_mysql_tmpfile(path);
ut_ad(!srv_read_only_mode);
@@ -4067,7 +4069,7 @@ os_aio_native_aio_supported(void)
return(FALSE);
} else if (!srv_read_only_mode) {
/* Now check if tmpdir supports native aio ops. */
- fd = innobase_mysql_tmpfile();
+ fd = innobase_mysql_tmpfile(NULL);
if (fd < 0) {
ib_logf(IB_LOG_LEVEL_WARN,
diff --git a/storage/xtradb/row/row0ftsort.cc b/storage/xtradb/row/row0ftsort.cc
index c7a5b51ef55..ac0dc844b1b 100644
--- a/storage/xtradb/row/row0ftsort.cc
+++ b/storage/xtradb/row/row0ftsort.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, MariaDB Corporation.
+Copyright (c) 2010, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, 2016, MariaDB Corporation.
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
@@ -240,6 +240,9 @@ row_fts_psort_info_init(
crypt_data = NULL;
}
+ ut_ad(trx->mysql_thd != NULL);
+ const char* path = thd_innodb_tmpdir(trx->mysql_thd);
+
/* There will be FTS_NUM_AUX_INDEX number of "sort buckets" for
each parallel sort thread. Each "sort bucket" holds records for
a particular "FTS index partition" */
@@ -261,8 +264,8 @@ row_fts_psort_info_init(
psort_info[j].merge_buf[i] = row_merge_buf_create(
dup->index);
- if (row_merge_file_create(psort_info[j].merge_file[i])
- < 0) {
+ if (row_merge_file_create(psort_info[j].merge_file[i],
+ path) < 0) {
goto func_exit;
}
@@ -662,6 +665,11 @@ fts_parallel_tokenization(
dberr_t error = DB_SUCCESS;
fil_space_crypt_t* crypt_data = NULL;
+ ut_ad(psort_info->psort_common->trx->mysql_thd != NULL);
+
+ const char* path = thd_innodb_tmpdir(
+ psort_info->psort_common->trx->mysql_thd);
+
ut_ad(psort_info);
buf = psort_info->merge_buf;
@@ -905,7 +913,7 @@ exit:
continue;
}
- tmpfd[i] = row_merge_file_create_low();
+ tmpfd[i] = row_merge_file_create_low(path);
if (tmpfd[i] < 0) {
error = DB_OUT_OF_MEMORY;
goto func_exit;
diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc
index b0c6f881f81..f0b200459dd 100644
--- a/storage/xtradb/row/row0log.cc
+++ b/storage/xtradb/row/row0log.cc
@@ -198,8 +198,25 @@ struct row_log_t {
or by index->lock X-latch only */
row_log_buf_t head; /*!< reader context; protected by MDL only;
modifiable by row_log_apply_ops() */
+ const char* path; /*!< where to create temporary file during
+ log operation */
};
+/** Create the file or online log if it does not exist.
+@param[in,out] log online rebuild log
+@return file descriptor. */
+static __attribute__((warn_unused_result))
+int
+row_log_tmpfile(
+ row_log_t* log)
+{
+ DBUG_ENTER("row_log_tmpfile");
+ if (log->fd < 0) {
+ log->fd = row_merge_file_create_low(log->path);
+ }
+
+ DBUG_RETURN(log->fd);
+}
/** Allocate the memory for the log buffer.
@param[in,out] log_buf Buffer used for log operation
@@ -344,6 +361,12 @@ row_log_online_op(
log->tail.buf, avail_size);
}
UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size);
+
+ if (row_log_tmpfile(log) < 0) {
+ log->error = DB_OUT_OF_MEMORY;
+ goto err_exit;
+ }
+
ret = os_file_write(
"(modification log)",
OS_FILE_FROM_FD(log->fd),
@@ -454,6 +477,12 @@ row_log_table_close_func(
log->tail.buf, avail);
}
UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size);
+
+ if (row_log_tmpfile(log) < 0) {
+ log->error = DB_OUT_OF_MEMORY;
+ goto err_exit;
+ }
+
ret = os_file_write(
"(modification log)",
OS_FILE_FROM_FD(log->fd),
@@ -473,6 +502,7 @@ write_failed:
log->tail.total += size;
UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf);
+err_exit:
mutex_exit(&log->mutex);
os_atomic_increment_ulint(&onlineddl_rowlog_rows, 1);
@@ -2544,7 +2574,8 @@ corruption:
if (index->online_log->head.blocks) {
#ifdef HAVE_FTRUNCATE
/* Truncate the file in order to save space. */
- if (ftruncate(index->online_log->fd, 0) == -1) {
+ if (index->online_log->fd != -1
+ && ftruncate(index->online_log->fd, 0) == -1) {
perror("ftruncate");
}
#endif /* HAVE_FTRUNCATE */
@@ -2860,8 +2891,9 @@ row_log_allocate(
const dtuple_t* add_cols,
/*!< in: default values of
added columns, or NULL */
- const ulint* col_map)/*!< in: mapping of old column
+ const ulint* col_map,/*!< in: mapping of old column
numbers to new ones, or NULL if !table */
+ const char* path) /*!< in: where to create temporary file */
{
row_log_t* log;
DBUG_ENTER("row_log_allocate");
@@ -2880,11 +2912,7 @@ row_log_allocate(
DBUG_RETURN(false);
}
- log->fd = row_merge_file_create_low();
- if (log->fd < 0) {
- ut_free(log);
- DBUG_RETURN(false);
- }
+ log->fd = -1;
mutex_create(index_online_log_key, &log->mutex,
SYNC_INDEX_ONLINE_LOG);
log->blobs = NULL;
@@ -2899,6 +2927,7 @@ row_log_allocate(
log->tail.block = log->head.block = NULL;
log->head.blocks = log->head.bytes = 0;
log->head.total = 0;
+ log->path = path;
dict_index_set_online_status(index, ONLINE_INDEX_CREATION);
index->online_log = log;
@@ -3376,7 +3405,8 @@ corruption:
if (index->online_log->head.blocks) {
#ifdef HAVE_FTRUNCATE
/* Truncate the file in order to save space. */
- if (ftruncate(index->online_log->fd, 0) == -1) {
+ if (index->online_log->fd != -1
+ && ftruncate(index->online_log->fd, 0) == -1) {
perror("ftruncate");
}
#endif /* HAVE_FTRUNCATE */
diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc
index 8d7fcd7388c..b45c7f2171b 100644
--- a/storage/xtradb/row/row0merge.cc
+++ b/storage/xtradb/row/row0merge.cc
@@ -1389,47 +1389,95 @@ row_merge_write_eof(
return(&block[0]);
}
-/********************************************************************//**
-Reads clustered index of the table and create temporary files
+/** Create a temporary file if it has not been created already.
+@param[in,out] tmpfd temporary file handle
+@param[in] path path to create temporary file
+@return file descriptor, or -1 on failure */
+static __attribute__((warn_unused_result))
+int
+row_merge_tmpfile_if_needed(
+ int* tmpfd,
+ const char* path)
+{
+ if (*tmpfd < 0) {
+ *tmpfd = row_merge_file_create_low(path);
+ }
+
+ return(*tmpfd);
+}
+
+/** Create a temporary file for merge sort if it was not created already.
+@param[in,out] file merge file structure
+@param[in,out] tmpfd temporary file structure
+@param[in] nrec number of records in the file
+@param[in] path path to create temporary files
+@return file descriptor, or -1 on failure */
+static __attribute__((warn_unused_result))
+int
+row_merge_file_create_if_needed(
+ merge_file_t* file,
+ int* tmpfd,
+ ulint nrec,
+ const char* path)
+{
+ ut_ad(file->fd < 0 || *tmpfd >=0);
+ if (file->fd < 0 && row_merge_file_create(file, path) >= 0) {
+ if (row_merge_tmpfile_if_needed(tmpfd, path) < 0) {
+ return(-1);
+ }
+
+ file->n_rec = nrec;
+ }
+
+ ut_ad(file->fd < 0 || *tmpfd >=0);
+ return(file->fd);
+}
+
+/** Reads clustered index of the table and create temporary files
containing the index entries for the indexes to be built.
-@return DB_SUCCESS or error */
+@param[in] trx transaction
+@param[in,out] table MySQL table object, for reporting erroneous
+ records
+@param[in] old_table table where rows are read from
+@param[in] new_table table where indexes are created; identical to
+ old_table unless creating a PRIMARY KEY
+@param[in] online true if creating indexes online
+@param[in] index indexes to be created
+@param[in] fts_sort_idx full-text index to be created, or NULL
+@param[in] psort_info parallel sort info for fts_sort_idx creation,
+ or NULL
+@param[in] files temporary files
+@param[in] key_numbers MySQL key numbers to create
+@param[in] n_index number of indexes to create
+@param[in] add_cols default values of added columns, or NULL
+@param[in] col_map mapping of old column numbers to new ones, or
+ NULL if old_table == new_table
+@param[in] add_autoinc number of added AUTO_INCREMENT columns, or
+ ULINT_UNDEFINED if none is added
+@param[in,out] sequence autoinc sequence
+@param[in,out] block file buffer
+@param[in,out] tmpfd temporary file handle
+return DB_SUCCESS or error */
static __attribute__((nonnull(1,2,3,4,6,9,10,16), warn_unused_result))
dberr_t
row_merge_read_clustered_index(
-/*===========================*/
- trx_t* trx, /*!< in: transaction */
- struct TABLE* table, /*!< in/out: MySQL table object,
- for reporting erroneous records */
- const dict_table_t* old_table,/*!< in: table where rows are
- read from */
- const dict_table_t* new_table,/*!< in: table where indexes are
- created; identical to old_table
- unless creating a PRIMARY KEY */
- bool online, /*!< in: true if creating indexes
- online */
- dict_index_t** index, /*!< in: indexes to be created */
+ trx_t* trx,
+ struct TABLE* table,
+ const dict_table_t* old_table,
+ const dict_table_t* new_table,
+ bool online,
+ dict_index_t** index,
dict_index_t* fts_sort_idx,
- /*!< in: full-text index to be created,
- or NULL */
fts_psort_t* psort_info,
- /*!< in: parallel sort info for
- fts_sort_idx creation, or NULL */
- merge_file_t* files, /*!< in: temporary files */
+ merge_file_t* files,
const ulint* key_numbers,
- /*!< in: MySQL key numbers to create */
- ulint n_index,/*!< in: number of indexes to create */
+ ulint n_index,
const dtuple_t* add_cols,
- /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map,/*!< in: mapping of old column
- numbers to new ones, or NULL
- if old_table == new_table */
+ const ulint* col_map,
ulint add_autoinc,
- /*!< in: number of added
- AUTO_INCREMENT column, or
- ULINT_UNDEFINED if none is added */
- ib_sequence_t& sequence,/*!< in/out: autoinc sequence */
- row_merge_block_t* block, /*!< in/out: file buffer */
+ ib_sequence_t& sequence,
+ row_merge_block_t* block,
+ int* tmpfd,
float pct_cost, /*!< in: percent of task weight
out of total alter job */
fil_space_crypt_t* crypt_data,/*!< in: crypt data or NULL */
@@ -1477,6 +1525,9 @@ row_merge_read_clustered_index(
DEBUG_FTS_SORT_PRINT("FTS_SORT: Start Create Index\n");
#endif
+ ut_ad(trx->mysql_thd != NULL);
+ const char* path = thd_innodb_tmpdir(trx->mysql_thd);
+
/* Create and initialize memory for record buffers */
merge_buf = static_cast<row_merge_buf_t**>(
@@ -1954,13 +2005,26 @@ write_buffers:
dict_index_get_lock(buf->index));
}
- row_merge_buf_write(buf, file, block);
+ if (buf->n_tuples > 0) {
- if (!row_merge_write(file->fd, file->offset++, block,
- crypt_data, crypt_block, new_table->space)) {
- err = DB_TEMP_FILE_WRITE_FAILURE;
- trx->error_key_num = i;
- break;
+ if (row_merge_file_create_if_needed(
+ file, tmpfd, buf->n_tuples, path) < 0) {
+ err = DB_OUT_OF_MEMORY;
+ trx->error_key_num = i;
+ break;
+ }
+
+ ut_ad(file->n_rec > 0);
+
+ row_merge_buf_write(buf, file, block);
+
+ if (!row_merge_write(file->fd, file->offset++,
+ block, crypt_data, crypt_block,
+ new_table->space)) {
+ err = DB_TEMP_FILE_WRITE_FAILURE;
+ trx->error_key_num = i;
+ break;
+ }
}
UNIV_MEM_INVALID(&block[0], srv_sort_buf_size);
@@ -2016,6 +2080,7 @@ write_buffers:
func_exit:
mtr_commit(&mtr);
+
mem_heap_free(row_heap);
if (nonnull) {
@@ -3344,14 +3409,15 @@ row_merge_drop_temp_indexes(void)
trx_free_for_background(trx);
}
-/*********************************************************************//**
-Creates temporary merge files, and if UNIV_PFS_IO defined, register
-the file descriptor with Performance Schema.
-@return file descriptor, or -1 on failure */
+
+/** Create temporary merge files in the given paramater path, and if
+UNIV_PFS_IO defined, register the file descriptor with Performance Schema.
+@param[in] path location for creating temporary merge files.
+@return File descriptor */
UNIV_INTERN
int
-row_merge_file_create_low(void)
-/*===========================*/
+row_merge_file_create_low(
+ const char* path)
{
int fd;
#ifdef UNIV_PFS_IO
@@ -3365,7 +3431,7 @@ row_merge_file_create_low(void)
"Innodb Merge Temp File",
__FILE__, __LINE__);
#endif
- fd = innobase_mysql_tmpfile();
+ fd = innobase_mysql_tmpfile(path);
#ifdef UNIV_PFS_IO
register_pfs_file_open_end(locker, fd);
#endif
@@ -3378,16 +3444,18 @@ row_merge_file_create_low(void)
return(fd);
}
-/*********************************************************************//**
-Create a merge file.
+
+/** Create a merge file in the given location.
+@param[out] merge_file merge file structure
+@param[in] path location for creating temporary file
@return file descriptor, or -1 on failure */
UNIV_INTERN
int
row_merge_file_create(
-/*==================*/
- merge_file_t* merge_file) /*!< out: merge file structure */
+ merge_file_t* merge_file,
+ const char* path)
{
- merge_file->fd = row_merge_file_create_low();
+ merge_file->fd = row_merge_file_create_low(path);
merge_file->offset = 0;
merge_file->n_rec = 0;
@@ -3958,10 +4026,6 @@ row_merge_build_indexes(
total_dynamic_cost = COST_BUILD_INDEX_DYNAMIC * n_indexes;
for (i = 0; i < n_indexes; i++) {
- if (row_merge_file_create(&merge_files[i]) < 0) {
- error = DB_OUT_OF_MEMORY;
- goto func_exit;
- }
if (indexes[i]->type & DICT_FTS) {
ibool opt_doc_id_size = FALSE;
@@ -3990,13 +4054,6 @@ row_merge_build_indexes(
}
}
- tmpfd = row_merge_file_create_low();
-
- if (tmpfd < 0) {
- error = DB_OUT_OF_MEMORY;
- goto func_exit;
- }
-
/* Reset the MySQL row buffer that is used when reporting
duplicate keys. */
innobase_rec_reset(table);
@@ -4025,7 +4082,7 @@ row_merge_build_indexes(
trx, table, old_table, new_table, online, indexes,
fts_sort_idx, psort_info, merge_files, key_numbers,
n_indexes, add_cols, col_map,
- add_autoinc, sequence, block, pct_cost,
+ add_autoinc, sequence, block, &tmpfd, pct_cost,
crypt_data, crypt_block);
pct_progress += pct_cost;
@@ -4119,7 +4176,7 @@ wait_again:
#ifdef FTS_INTERNAL_DIAG_PRINT
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n");
#endif
- } else if (UNIV_LIKELY(merge_files[i].n_rec)) {
+ } else if (merge_files[i].fd != -1) {
char buf[3 * NAME_LEN];
char *bufend;
row_merge_dup_t dup = {
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index 794b119a090..c98bfc85086 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
@@ -2243,6 +2243,8 @@ exit_func:
/*********************************************************************//**
A thread which prints warnings about semaphore waits which have lasted
too long. These can be used to track bugs which cause hangs.
+Note: In order to make sync_arr_wake_threads_if_sema_free work as expected,
+we should avoid waiting any mutexes in this function!
@return a dummy parameter */
extern "C" UNIV_INTERN
os_thread_ret_t
@@ -2282,23 +2284,21 @@ loop:
/* Try to track a strange bug reported by Harald Fuchs and others,
where the lsn seems to decrease at times */
- /* We have to use nowait to ensure we don't block */
- new_lsn= log_get_lsn_nowait();
-
- if (new_lsn && new_lsn < old_lsn) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: old log sequence number " LSN_PF
- " was greater\n"
- "InnoDB: than the new log sequence number " LSN_PF "!\n"
- "InnoDB: Please submit a bug report"
- " to http://bugs.mysql.com\n",
- old_lsn, new_lsn);
- ut_ad(0);
- }
+ if (log_peek_lsn(&new_lsn)) {
+ if (new_lsn < old_lsn) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: old log sequence number " LSN_PF
+ " was greater\n"
+ "InnoDB: than the new log sequence number " LSN_PF "!\n"
+ "InnoDB: Please submit a bug report"
+ " to http://bugs.mysql.com\n",
+ old_lsn, new_lsn);
+ ut_ad(0);
+ }
- if (new_lsn)
old_lsn = new_lsn;
+ }
if (difftime(time(NULL), srv_last_monitor_time) > 60) {
/* We referesh InnoDB Monitor values so that averages are
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index 17f9e53e76f..2455dc1c9a9 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -2000,7 +2000,7 @@ innobase_start_or_create_for_mysql(void)
}
} else {
srv_monitor_file_name = NULL;
- srv_monitor_file = os_file_create_tmpfile();
+ srv_monitor_file = os_file_create_tmpfile(NULL);
if (!srv_monitor_file) {
return(DB_ERROR);
@@ -2010,7 +2010,7 @@ innobase_start_or_create_for_mysql(void)
mutex_create(srv_dict_tmpfile_mutex_key,
&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
- srv_dict_tmpfile = os_file_create_tmpfile();
+ srv_dict_tmpfile = os_file_create_tmpfile(NULL);
if (!srv_dict_tmpfile) {
return(DB_ERROR);
@@ -2019,7 +2019,7 @@ innobase_start_or_create_for_mysql(void)
mutex_create(srv_misc_tmpfile_mutex_key,
&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
- srv_misc_tmpfile = os_file_create_tmpfile();
+ srv_misc_tmpfile = os_file_create_tmpfile(NULL);
if (!srv_misc_tmpfile) {
return(DB_ERROR);