diff options
-rw-r--r-- | BitKeeper/etc/logging_ok | 1 | ||||
-rw-r--r-- | Docs/manual.texi | 40 | ||||
-rw-r--r-- | client/mysqlcheck.c | 82 | ||||
-rw-r--r-- | client/mysqldump.c | 137 | ||||
-rw-r--r-- | client/mysqltest.c | 1 | ||||
-rw-r--r-- | innobase/include/univ.i | 5 | ||||
-rw-r--r-- | innobase/os/os0file.c | 32 | ||||
-rw-r--r-- | innobase/os/os0sync.c | 1 | ||||
-rw-r--r-- | mysql-test/mysql-test-run.sh | 2 | ||||
-rw-r--r-- | mysql-test/r/binlog-backup-restore.result | 5 | ||||
-rw-r--r-- | mysql-test/t/binlog-backup-restore.test | 18 | ||||
-rw-r--r-- | sql/ha_innobase.cc | 10 | ||||
-rw-r--r-- | sql/log.cc | 48 | ||||
-rw-r--r-- | sql/log_event.cc | 32 | ||||
-rw-r--r-- | sql/log_event.h | 14 | ||||
-rw-r--r-- | sql/mysqlbinlog.cc | 6 | ||||
-rw-r--r-- | sql/slave.cc | 146 | ||||
-rw-r--r-- | sql/slave.h | 15 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_repl.cc | 13 | ||||
-rw-r--r-- | sql/sql_repl.h | 3 |
21 files changed, 458 insertions, 156 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index 0cf09ad6901..a2d07539822 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -5,3 +5,4 @@ monty@donna.mysql.fi monty@work.mysql.com sasha@mysql.sashanet.com serg@serg.mysql.com +paul@central.snake.net diff --git a/Docs/manual.texi b/Docs/manual.texi index 1790454e951..f42e6362d5d 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -29340,6 +29340,9 @@ index operations (querying/dumping/statistics). @itemize @bullet @item Make all operations with @code{FULLTEXT} index @strong{faster}. @item Support for braces @code{()} in boolean full-text search. +@item Phrase search, proximity operators +@item Boolean search can work without @code{FULLTEXT} index +(yes, @strong{very} slow). @item Support for "always-index words". They could be any strings the user wants to treat as words, examples are "C++", "AS/400", "TCP/IP", etc. @item Support for full-text search in @code{MERGE} tables. @@ -32555,6 +32558,10 @@ used.) @item -q, --quick Don't buffer query, dump directly to stdout. Uses @code{mysql_use_result()} to do this. +@item -r, --result-file=... +Direct output to a given file. This option should be used in MSDOS, +because it prevents new line '\n' from being converted to '\n\r' (new +line + carriage return). @item -S /path/to/socket, --socket=/path/to/socket The socket file to use when connecting to @code{localhost} (which is the default host). @@ -42995,6 +43002,8 @@ import-/export-files. (Freeware). By Ansgar Becker. @item @uref{http://www.mysql.com/Downloads/Win32/W9xstop.zip,Utility from Artronic to stop MySQL on win9x}. +@item @uref{http://bardo.hyperlink.cz/mysqlmon,a light weight GUI client for Windows}. + @item @uref{http://dbtools.vila.bol.com.br/, Dbtools} A tool to manage @strong{MySQL} databases. Currently only for Windows. Some features: @@ -43233,7 +43242,7 @@ An authentication module for the Cyrus IMAP server. By Aaron Newsome. @appendixsec Converters @itemize @bullet -item @uref{http://www.mysql.com/Downloads/Contrib/mssql2mysql.txt, mssql2mysql.txt} +@item @uref{http://www.mysql.com/Downloads/Contrib/mssql2mysql.txt, mssql2mysql.txt} Converter from MS-SQL to MySQL. By Michael Kofler. @uref{http://www.kofler.cc/mysql/mssql2mysql.html, mssql2mysql home page}. @@ -43938,9 +43947,9 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}. @itemize @bullet @item -Added @code{SQL_CALC_FOUND_ROWS} and @code{FOUND_ROWS()}. This make it -possible to know how many rows a query would have returned if one hadn't -used @code{LIMIT}. +Added @code{SQL_CALC_FOUND_ROWS} and @code{FOUND_ROWS()}. This makes it +possible to know how many rows a query would have returned +without a @code{LIMIT} clause. @item Changed output format of @code{SHOW OPEN TABLES}. @item @@ -44050,7 +44059,7 @@ together with a group functions and a @code{WHERE} that didn't match any rows. @item New program @code{mysqlcheck}. @item -Added database name to output for admin commands like @code{CHECK}, +Added database name to output for administrative commands like @code{CHECK}, @code{REPAIR}, @code{OPTIMIZE}. @item Lots of portability fixes for InnoDB. @@ -44061,7 +44070,7 @@ will use index on @code{key_part1} instead of @code{filesort}. @item Fixed bug when doing @code{LOCK TABLE to_table WRITE,...; INSERT INTO to_table... SELECT ...} -when to_table was empty. +when @code{to_table} was empty. @item Fixed bug with @code{LOCK TABLE} and BDB tables. @end itemize @@ -44087,35 +44096,35 @@ Fixed bug when using indexes on @code{CHAR(255) NULL} columns. Slave thread will now be started even if @code{master-host} is not set, as long as @code{server-id} is set and valid @code{master.info} is present @item -Partial updates ( terminated with kill) are now logged with a special error +Partial updates (terminated with kill) are now logged with a special error code to the binary log. Slave will refuse to execute them if the error code indicates the update was terminated abnormally, and will have to be recovered with @code{SET SQL_SLAVE_SKIP_COUNTER=1; SLAVE START} after a manual sanity -check/correction of data integrity +check/correction of data integrity. @item Fixed bug that erroneously logged a drop of internal temporary table -on thread termination to the binary log - bug affected replication +on thread termination to the binary log - bug affected replication. @item Fixed a bug in @code{REGEXP()} on 64-bit machines. @item @code{UPDATE} and @code{DELETE} with @code{WHERE unique_key_part IS NULL} didn't update/delete all rows. @item -Disabled @code{INSERT DELAYED} for tables that supports transactions. +Disabled @code{INSERT DELAYED} for tables that support transactions. @item Fixed bug when using date functions on @code{TEXT}/@code{BLOB} column with wrong date format. @item -UDF's now also works on windows. (Patch by Ralph Mason) +UDFs now also work on Windows. (Patch by Ralph Mason) @item Fixed bug in @code{ALTER TABLE} and @code{LOAD DATA INFILE} that disabled -key-sorting. These command should now be faster in most cases. +key-sorting. These commands should now be faster in most cases. @item Fixed performance bug where reopened tables (tables that had been waiting for @code{FLUSH} or @code{REPAIR}) would not use indexes for the next query. @item -Fixed problem with @code{ALTER TABLE} to Innobase tables on Freebsd. +Fixed problem with @code{ALTER TABLE} to Innobase tables on FreeBSD. @item Added @code{mysqld} variables @code{myisam_max_sort_file_size} and @code{myisam_max_extra_sort_file_size}. @@ -44134,8 +44143,9 @@ Added @code{--skip-safemalloc} option to @code{mysqld}. @appendixsubsec Changes in release 3.23.36 @itemize @bullet @item -Fixed a bug that allowed you to use database names with @code{.}. This -fixes a serious security issue when @code{mysqld} is run as root. +Fixed a bug that allowed you to use database names containing a @samp{.} +character. This fixes a serious security issue when @code{mysqld} is run +as root. @item Fixed bug when thread creation failed (could happen when doing a LOT of connections in a short time). diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index f8ad5d813cd..3d4d4597ef5 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -16,7 +16,7 @@ /* By Jani Tolonen, 2001-04-20, MySQL Development Team */ -#define CHECK_VERSION "1.00" +#define CHECK_VERSION "1.01" #include <global.h> #include <my_sys.h> @@ -40,22 +40,24 @@ static MYSQL mysql_connection, *sock = 0; static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0, opt_compress = 0, opt_databases = 0, opt_fast = 0, opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0, - opt_silent = 0, ignore_errors = 0; + opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0; static uint verbose = 0, opt_mysql_port=0; static my_string opt_mysql_unix_port = 0; static char *opt_password = 0, *current_user = 0, *default_charset = 0, *current_host = 0; static int first_error = 0; +DYNAMIC_ARRAY tables4repair; enum operations {DO_CHECK, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE}; enum options {OPT_CHARSETS_DIR=256, OPT_COMPRESS, OPT_DEFAULT_CHARSET, - OPT_TABLES}; + OPT_TABLES, OPT_AUTO_REPAIR}; static struct option long_options[] = { {"all-databases", no_argument, 0, 'A'}, {"all-in-1", no_argument, 0, '1'}, + {"auto-repair", no_argument, 0, OPT_AUTO_REPAIR}, {"analyze", no_argument, 0, 'a'}, {"character-sets-dir", required_argument, 0, OPT_CHARSETS_DIR}, {"check", no_argument, 0, 'c'}, @@ -122,13 +124,19 @@ static void usage(void) puts("By Jani Tolonen, 2001-04-20, MySQL Development Team\n"); puts("This software comes with ABSOLUTELY NO WARRANTY. This is free"); puts("software and you are welcome to modify and redistribute it"); - puts("under the GPL license\n"); + puts("under the GPL license.\n"); puts("This program can be used to CHECK (-c,-m,-C), REPAIR (-r), ANALYZE (-a)"); puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be"); - puts("used same time. It works on MyISAM and in some cases on BDB tables"); + puts("used same time. It works on MyISAM and in some cases on BDB tables."); puts("Please consult the MySQL manual for latest information about the"); - puts("above. The options above are exclusive to each other, which means"); - puts("that the last option will be used, if several was specified.\n"); + puts("above. The options -c,-r,-a and -o are exclusive to each other, which"); + puts("means that the last option will be used, if several was specified.\n"); + puts("The option -c will be used by default, if none was specified. You"); + puts("can change the default behavior by making a symbolic link, or"); + puts("copying this file somewhere with another name, the alternatives are:"); + puts("mysqlrepair: The default option will be -r"); + puts("mysqlanalyze: The default option will be -a"); + puts("mysqloptimize: The default option will be -o\n"); printf("Usage: %s [OPTIONS] database [tables]\n", my_progname); printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n", my_progname); @@ -140,6 +148,9 @@ static void usage(void) all queries in 1 query separately for each database.\n\ Table names will be in a comma separeted list.\n\ -a, --analyze Analyze given tables.\n\ + --auto-repair If a checked table is corrupted, automatically fix\n\ + it. Repairing will be done after all tables have\n\ + been checked, if corrupted ones were found.\n\ -#, --debug=... Output debug log. Often this is 'd:t:o,filename'\n\ --character-sets-dir=...\n\ Directory where character sets are\n\ @@ -197,12 +208,18 @@ printf("\ print_defaults("my", load_default_groups); } /* usage */ - + static int get_options(int *argc, char ***argv) { int c, option_index; my_bool tty_password = 0; + if (*argc == 1) + { + usage(); + exit(0); + } + load_defaults("my", load_default_groups, argc, argv); while ((c = getopt_long(*argc, *argv, "#::p::h:u:P:S:BaAcCdeFfmqorsvVw:?I1", long_options, &option_index)) != EOF) @@ -217,6 +234,9 @@ static int get_options(int *argc, char ***argv) case 'A': opt_alldbs = 1; break; + case OPT_AUTO_REPAIR: + opt_auto_repair = 1; + break; case OPT_DEFAULT_CHARSET: default_charset = optarg; break; @@ -315,7 +335,20 @@ static int get_options(int *argc, char ***argv) } } if (!what_to_do) - what_to_do = DO_CHECK; + { + int pnlen = strlen(my_progname); + + if (pnlen < 6) // name too short + what_to_do = DO_CHECK; + else if (!strcmp("repair", my_progname + pnlen - 6)) + what_to_do = DO_REPAIR; + else if (!strcmp("analyze", my_progname + pnlen - 7)) + what_to_do = DO_ANALYZE; + else if (!strcmp("optimize", my_progname + pnlen - 8)) + what_to_do = DO_OPTIMIZE; + else + what_to_do = DO_CHECK; + } if (default_charset) { if (set_default_charset_by_name(default_charset, MYF(MY_WME))) @@ -517,7 +550,7 @@ static void print_result() { MYSQL_RES *res; MYSQL_ROW row; - char prev[1024]; + char prev[NAME_LEN*2+2]; int i; res = mysql_use_result(sock); @@ -531,7 +564,11 @@ static void print_result() if (status && changed) printf("%-50s %s", row[0], row[3]); else if (!status && changed) + { printf("%s\n%-9s: %s", row[0], row[2], row[3]); + if (what_to_do != DO_REPAIR && opt_auto_repair) + insert_dynamic(&tables4repair, row[0]); + } else printf("%-9s: %s", row[2], row[3]); strmov(prev, row[0]); @@ -610,6 +647,13 @@ int main(int argc, char **argv) if (dbConnect(current_host, current_user, opt_password)) exit(EX_MYSQLERR); + if (opt_auto_repair && + init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64)) + { + first_error = 1; + goto end; + } + if (opt_alldbs) process_all_databases(); /* Only one database and selected table(s) */ @@ -618,8 +662,24 @@ int main(int argc, char **argv) /* One or more databases, all tables */ else process_databases(argv); + if (opt_auto_repair) + { + uint i; + + if (!opt_silent && tables4repair.elements) + puts("\nRepairing tables"); + what_to_do = DO_REPAIR; + for (i = 0; i < tables4repair.elements ; i++) + { + char *name= (char*) dynamic_array_ptr(&tables4repair, i); + handle_request_for_tables(name, strlen(name)); + } + } + end: dbDisconnect(current_host); + if (opt_auto_repair) + delete_dynamic(&tables4repair); my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); my_end(0); - return(first_error); + return(first_error!=0); } /* main */ diff --git a/client/mysqldump.c b/client/mysqldump.c index ce6c64aa00e..aa5a29e45e3 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -37,7 +37,7 @@ ** Tõnu Samuel <tonu@please.do.not.remove.this.spam.ee> **/ -#define DUMP_VERSION "8.13" +#define DUMP_VERSION "8.14" #include <global.h> #include <my_sys.h> @@ -73,7 +73,8 @@ static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick=0, extended_insert = 0, lock_tables=0,ignore_errors=0,flush_logs=0,replace=0, ignore=0,opt_drop=0,opt_keywords=0,opt_lock=0,opt_compress=0, opt_delayed=0,create_options=0,opt_quoted=0,opt_databases=0, - opt_alldbs=0,opt_create_db=0,opt_first_slave=0; + opt_alldbs=0,opt_create_db=0,opt_first_slave=0, + opt_resultfile=0; static MYSQL mysql_connection,*sock=0; static char insert_pat[12 * 1024],*opt_password=0,*current_user=0, *current_host=0,*path=0,*fields_terminated=0, @@ -127,6 +128,7 @@ static struct option long_options[] = {"port", required_argument, 0, 'P'}, {"quick", no_argument, 0, 'q'}, {"quote-names", no_argument, 0, 'Q'}, + {"result-file", required_argument, 0, 'r'}, {"set-variable", required_argument, 0, 'O'}, {"socket", required_argument, 0, 'S'}, #include "sslopt-longopts.h" @@ -227,6 +229,10 @@ puts("\ -P, --port=... Port number to use for connection.\n\ -q, --quick Don't buffer query, dump directly to stdout.\n\ -Q, --quote-names Quote table and column names with `\n\ + -r, --result-file=... Direct output to a given file. This option should be\n\ + used in MSDOS, because it prevents new line '\\n'\n\ + from being converted to '\\n\\r' (newline + carriage\n\ + return).\n\ -S, --socket=... Socket file to use for connection.\n\ --tables Overrides option --databases (-B).\n"); #include "sslopt-usage.h" @@ -283,10 +289,12 @@ static int get_options(int *argc,char ***argv) { int c,option_index; my_bool tty_password=0; + FILE *resultfile; load_defaults("my",load_default_groups,argc,argv); set_all_changeable_vars(changeable_vars); - while ((c=getopt_long(*argc,*argv,"#::p::h:u:O:P:S:T:EBaAcCdefFlnqtvVw:?Ix", + while ((c=getopt_long(*argc,*argv, + "#::p::h:u:O:P:r:S:T:EBaAcCdefFlnqtvVw:?Ix", long_options, &option_index)) != EOF) { switch(c) { @@ -346,6 +354,15 @@ static int get_options(int *argc,char ***argv) case 'P': opt_mysql_port= (unsigned int) atoi(optarg); break; + case 'r': + if (!(resultfile = my_fopen(optarg, O_WRONLY, MYF(MY_WME)))) + { + printf("Couldn't open result-file %s, aborting!\n", optarg); + exit(1); + } + opt_resultfile = 1; + stdout = resultfile; + break; case 'S': opt_mysql_unix_port= optarg; break; @@ -625,8 +642,8 @@ static uint getTableStructure(char *table, char* db) O_WRONLY, MYF(MY_WME)); if (!sql_file) /* If file couldn't be opened */ { - safe_exit(EX_MYSQLERR); - DBUG_RETURN(0); + safe_exit(EX_MYSQLERR); + DBUG_RETURN(0); } write_heder(sql_file, db); } @@ -734,20 +751,20 @@ static uint getTableStructure(char *table, char* db) if (!tFlag) { if (opt_keywords) - fprintf(sql_file, " %s.%s %s", table_name, - quote_name(row[SHOW_FIELDNAME],name_buff), row[SHOW_TYPE]); + fprintf(sql_file, " %s.%s %s", table_name, + quote_name(row[SHOW_FIELDNAME],name_buff), row[SHOW_TYPE]); else - fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME],name_buff), - row[SHOW_TYPE]); + fprintf(sql_file, " %s %s", quote_name(row[SHOW_FIELDNAME], + name_buff), row[SHOW_TYPE]); if (row[SHOW_DEFAULT]) { - fputs(" DEFAULT ", sql_file); - unescape(sql_file,row[SHOW_DEFAULT],lengths[SHOW_DEFAULT]); + fputs(" DEFAULT ", sql_file); + unescape(sql_file,row[SHOW_DEFAULT],lengths[SHOW_DEFAULT]); } if (!row[SHOW_NULL][0]) - fputs(" NOT NULL", sql_file); + fputs(" NOT NULL", sql_file); if (row[SHOW_EXTRA][0]) - fprintf(sql_file, " %s",row[SHOW_EXTRA]); + fprintf(sql_file, " %s",row[SHOW_EXTRA]); } } numFields = (uint) mysql_num_rows(tableRes); @@ -761,9 +778,9 @@ static uint getTableStructure(char *table, char* db) if (mysql_query(sock, buff)) { fprintf(stderr, "%s: Can't get keys for table '%s' (%s)\n", - my_progname, table, mysql_error(sock)); + my_progname, table, mysql_error(sock)); if (sql_file != stdout) - my_fclose(sql_file, MYF(MY_WME)); + my_fclose(sql_file, MYF(MY_WME)); safe_exit(EX_MYSQLERR); DBUG_RETURN(0); } @@ -776,16 +793,16 @@ static uint getTableStructure(char *table, char* db) { if (atoi(row[3]) == 1) { - keynr++; - #ifdef FORCE_PRIMARY_KEY - if (atoi(row[1]) == 0 && primary_key == INT_MAX) - primary_key=keynr; - #endif - if (!strcmp(row[2],"PRIMARY")) - { - primary_key=keynr; - break; - } + keynr++; +#ifdef FORCE_PRIMARY_KEY + if (atoi(row[1]) == 0 && primary_key == INT_MAX) + primary_key=keynr; +#endif + if (!strcmp(row[2],"PRIMARY")) + { + primary_key=keynr; + break; + } } } mysql_data_seek(tableRes,0); @@ -794,21 +811,21 @@ static uint getTableStructure(char *table, char* db) { if (atoi(row[3]) == 1) { - if (keynr++) - putc(')', sql_file); - if (atoi(row[1])) /* Test if duplicate key */ - /* Duplicate allowed */ - fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff)); - else if (keynr == primary_key) - fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */ - else - fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff)); + if (keynr++) + putc(')', sql_file); + if (atoi(row[1])) /* Test if duplicate key */ + /* Duplicate allowed */ + fprintf(sql_file, ",\n KEY %s (",quote_name(row[2],name_buff)); + else if (keynr == primary_key) + fputs(",\n PRIMARY KEY (",sql_file); /* First UNIQUE is primary */ + else + fprintf(sql_file, ",\n UNIQUE %s (",quote_name(row[2],name_buff)); } else - putc(',', sql_file); + putc(',', sql_file); fputs(quote_name(row[4],name_buff), sql_file); if (row[7]) - fprintf(sql_file, " (%s)",row[7]); /* Sub key */ + fprintf(sql_file, " (%s)",row[7]); /* Sub key */ } if (keynr) putc(')', sql_file); @@ -820,28 +837,28 @@ static uint getTableStructure(char *table, char* db) sprintf(buff,"show table status like '%s'",table); if (mysql_query(sock, buff)) { - if (mysql_errno(sock) != ER_PARSE_ERROR) - { /* If old MySQL version */ - if (verbose) - fprintf(stderr, - "# Warning: Couldn't get status information for table '%s' (%s)\n", - table,mysql_error(sock)); - } + if (mysql_errno(sock) != ER_PARSE_ERROR) + { /* If old MySQL version */ + if (verbose) + fprintf(stderr, + "# Warning: Couldn't get status information for table '%s' (%s)\n", + table,mysql_error(sock)); + } } else if (!(tableRes=mysql_store_result(sock)) || - !(row=mysql_fetch_row(tableRes))) + !(row=mysql_fetch_row(tableRes))) { - fprintf(stderr, - "Error: Couldn't read status information for table '%s' (%s)\n", - table,mysql_error(sock)); + fprintf(stderr, + "Error: Couldn't read status information for table '%s' (%s)\n", + table,mysql_error(sock)); } else { - fputs("/*!",sql_file); - print_value(sql_file,tableRes,row,"type=","Type",0); - print_value(sql_file,tableRes,row,"","Create_options",0); - print_value(sql_file,tableRes,row,"comment=","Comment",1); - fputs(" */",sql_file); + fputs("/*!",sql_file); + print_value(sql_file,tableRes,row,"type=","Type",0); + print_value(sql_file,tableRes,row,"","Create_options",0); + print_value(sql_file,tableRes,row,"comment=","Comment",1); + fputs(" */",sql_file); } mysql_free_result(tableRes); /* Is always safe to free */ } @@ -967,7 +984,7 @@ static void dumpTable(uint numFields, char *table) printf("# WHERE: %s\n",where); strxmov(strend(query), " WHERE ",where,NullS); } - puts("#\n"); + fputs("#\n\n", stdout); if (mysql_query(sock, query)) { @@ -1090,7 +1107,7 @@ static void dumpTable(uint numFields, char *table) else { if (row_break) - puts(";"); + fputs(";\n", stdout); row_break=1; /* This is first row */ fputs(insert_pat,stdout); fputs(extended_row.str,stdout); @@ -1098,12 +1115,10 @@ static void dumpTable(uint numFields, char *table) } } else - { - puts(");"); - } + fputs(");\n", stdout); } if (extended_insert && row_break) - puts(";"); /* If not empty table */ + fputs(";\n", stdout); /* If not empty table */ fflush(stdout); if (mysql_errno(sock)) { @@ -1118,7 +1133,7 @@ static void dumpTable(uint numFields, char *table) return; } if (opt_lock) - puts("UNLOCK TABLES;"); + fputs("UNLOCK TABLES;\n", stdout); mysql_free_result(res); } } /* dumpTable */ @@ -1365,7 +1380,9 @@ int main(int argc, char **argv) } } dbDisconnect(current_host); - puts(""); + fputs("\n", stdout); + if (opt_resultfile) + my_fclose(stdout, MYF(0)); my_free(opt_password, MYF(MY_ALLOW_ZERO_PTR)); if (extended_insert) dynstr_free(&extended_row); diff --git a/client/mysqltest.c b/client/mysqltest.c index dd2d6340bf1..5eaefe165d7 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1766,6 +1766,7 @@ static void init_var_hash() die("Variable hash initialization failed"); var_from_env("MASTER_MYPORT", "9306"); var_from_env("SLAVE_MYPORT", "9307"); + var_from_env("MYSQL_TEST_DIR", ""); } int main(int argc, char** argv) diff --git a/innobase/include/univ.i b/innobase/include/univ.i index 5e74b7eb09b..46ba508f784 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -9,6 +9,7 @@ Created 1/20/1994 Heikki Tuuri #ifndef univ_i #define univ_i + #if (defined(_WIN32) || defined(_WIN64)) #define __WIN__ #include <windows.h> @@ -20,6 +21,10 @@ be defined: #define CRITICAL_SECTION ulint */ +#ifdef _NT_ +#define __NT__ +#endif + #else /* The Unix version */ diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index 8e9b8482259..804a63507ce 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -163,7 +163,6 @@ os_file_handle_error( os_file_t file, /* in: file pointer */ char* name) /* in: name of a file or NULL */ { - int input_char; ulint err; UT_NOT_USED(file); @@ -172,32 +171,19 @@ os_file_handle_error( if (err == OS_FILE_DISK_FULL) { ask_again: - printf("\n"); + fprintf(stderr, "\n"); if (name) { - printf( - "Innobase encountered a problem with file %s.\n", + fprintf(stderr, + "InnoDB: Encountered a problem with file %s.\n", name); } - printf("Disk is full. Try to clean the disk to free space\n"); - printf("before answering the following: How to continue?\n"); - printf("(Y == freed some space: try again)\n"); - printf("(N == crash the database: will restart it)?\n"); -ask_with_no_question: - input_char = getchar(); - - if (input_char == (int) 'N') { - ut_error; - - return(FALSE); - } else if (input_char == (int) 'Y') { + fprintf(stderr, + "InnoDB: Cannot continue operation.\n" + "InnoDB: Disk is full. Try to clean the disk to free space.\n" + "InnoDB: Delete possible created file and restart.\n"); - return(TRUE); - } else if (input_char == (int) '\n') { + exit(1); - goto ask_with_no_question; - } else { - goto ask_again; - } } else if (err == OS_FILE_AIO_RESOURCES_RESERVED) { return(TRUE); @@ -1413,7 +1399,7 @@ try_again: return(TRUE); } - goto error_handling; + err = 1; /* Fall through the next if */ } #endif if (err == 0) { diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c index 4c283431575..c5dd603100d 100644 --- a/innobase/os/os0sync.c +++ b/innobase/os/os0sync.c @@ -247,6 +247,7 @@ os_event_wait_time( return(OS_SYNC_TIME_EXCEEDED); } else { ut_error; + return(1000000); /* dummy value to eliminate compiler warn. */ } #else UT_NOT_USED(time); diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 1281e368015..ece2e42f40b 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -492,7 +492,7 @@ start_slave() --core \ --tmpdir=$MYSQL_TMP_DIR \ --language=english \ - --skip-innodb \ + --skip-innodb --skip-slave-start \ $SMALL_SERVER \ $EXTRA_SLAVE_OPT $EXTRA_SLAVE_MYSQLD_OPT" if [ x$DO_DDD = x1 ] diff --git a/mysql-test/r/binlog-backup-restore.result b/mysql-test/r/binlog-backup-restore.result new file mode 100644 index 00000000000..ebfe8217906 --- /dev/null +++ b/mysql-test/r/binlog-backup-restore.result @@ -0,0 +1,5 @@ +n +11 +12 +13 +14 diff --git a/mysql-test/t/binlog-backup-restore.test b/mysql-test/t/binlog-backup-restore.test new file mode 100644 index 00000000000..546782c5825 --- /dev/null +++ b/mysql-test/t/binlog-backup-restore.test @@ -0,0 +1,18 @@ +reset master; +drop table if exists t1; +create table t1(n int); +insert into t1 values (1),(2),(3),(4); +flush logs; +update t1 set n = n + 10; +save_master_pos; +flush tables with read lock; +system rm -rf var/tmp/backup; +system mkdir -p var/tmp/backup; +system cp var/master-data/master-bin.* var/tmp/backup; +unlock tables; +drop table t1; +eval change master to master_host='$MYSQL_TEST_DIR/var/tmp/backup/master-bin'; +slave start; +sync_with_master; +select * from t1; + diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index f263f693103..72857fc953f 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -1868,7 +1868,7 @@ corresponding row to buf. */ int ha_innobase::index_first( /*=====================*/ - /* out: 0, HA_ERR_KEY_NOT_FOUND, + /* out: 0, HA_ERR_END_OF_FILE, or error code */ mysql_byte* buf) /* in/out: buffer for the row */ { @@ -1879,6 +1879,12 @@ ha_innobase::index_first( error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY); + /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ + + if (error == HA_ERR_KEY_NOT_FOUND) { + error = HA_ERR_END_OF_FILE; + } + DBUG_RETURN(error); } @@ -1899,7 +1905,7 @@ ha_innobase::index_last( error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY); - /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ + /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ if (error == HA_ERR_KEY_NOT_FOUND) { error = HA_ERR_END_OF_FILE; diff --git a/sql/log.cc b/sql/log.cc index 4ae9fa79d5b..4cd93261973 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -103,7 +103,7 @@ MYSQL_LOG::~MYSQL_LOG() void MYSQL_LOG::set_index_file_name(const char* index_file_name) { if (index_file_name) - fn_format(this->index_file_name,index_file_name,mysql_data_home,"-index", + fn_format(this->index_file_name,index_file_name,mysql_data_home,".index", 4); else this->index_file_name[0] = 0; @@ -129,6 +129,32 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) return 0; } +bool MYSQL_LOG::open_index( int options) +{ + return (index_file < 0 && + (index_file = my_open(index_file_name, options | O_BINARY , + MYF(MY_WME))) < 0); +} + +void MYSQL_LOG::init(enum_log_type log_type_arg) +{ + log_type = log_type_arg; + if (!inited) + { + inited=1; + (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW); + (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW); + } +} + +void MYSQL_LOG::close_index() +{ + if(index_file >= 0) + { + my_close(index_file, MYF(0)); + index_file = -1; + } +} void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, const char *new_name) @@ -137,17 +163,11 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, char buff[512]; File file= -1; bool do_magic; - - if (!inited) - { - inited=1; - (void) pthread_mutex_init(&LOCK_log,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW); - if (log_type_arg == LOG_BIN && *fn_ext(log_name)) + + if (!inited && log_type_arg == LOG_BIN && *fn_ext(log_name)) no_rotate = 1; - } + init(log_type_arg); - log_type=log_type_arg; if (!(name=my_strdup(log_name,MYF(MY_WME)))) goto err; if (new_name) @@ -208,10 +228,7 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, clean up if failed */ if ((do_magic && my_b_write(&log_file, (byte*) BINLOG_MAGIC, 4)) || - (index_file < 0 && - (index_file = my_open(index_file_name, - O_APPEND | O_BINARY | O_RDWR | O_CREAT, - MYF(MY_WME))) < 0)) + open_index(O_APPEND | O_RDWR | O_CREAT)) goto err; Start_log_event s; bool error; @@ -224,8 +241,7 @@ void MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, pthread_mutex_unlock(&LOCK_index); if (error) { - my_close(index_file,MYF(0)); - index_file= -1; + close_index(); goto err; } } diff --git a/sql/log_event.cc b/sql/log_event.cc index d643952c5b0..5fc5f7f0e62 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -280,7 +280,7 @@ void Log_event::print_timestamp(FILE* file, time_t* ts) } -void Start_log_event::print(FILE* file, bool short_form) +void Start_log_event::print(FILE* file, bool short_form, char* last_db) { if (short_form) return; @@ -293,7 +293,7 @@ void Start_log_event::print(FILE* file, bool short_form) fflush(file); } -void Stop_log_event::print(FILE* file, bool short_form) +void Stop_log_event::print(FILE* file, bool short_form, char* last_db) { if (short_form) return; @@ -303,7 +303,7 @@ void Stop_log_event::print(FILE* file, bool short_form) fflush(file); } -void Rotate_log_event::print(FILE* file, bool short_form) +void Rotate_log_event::print(FILE* file, bool short_form, char* last_db) { if (short_form) return; @@ -441,7 +441,7 @@ Query_log_event::Query_log_event(const char* buf, int event_len): *((char*)query+q_len) = 0; } -void Query_log_event::print(FILE* file, bool short_form) +void Query_log_event::print(FILE* file, bool short_form, char* last_db) { char buff[40],*end; // Enough for SET TIMESTAMP if (!short_form) @@ -451,7 +451,15 @@ void Query_log_event::print(FILE* file, bool short_form) (ulong) thread_id, (ulong) exec_time, error_code); } - if (db && db[0]) + bool same_db = 0; + + if(db && last_db) + { + if(!(same_db = !memcmp(last_db, db, db_len))) + memcpy(last_db, db, db_len + 1); + } + + if (db && db[0] && !same_db) fprintf(file, "use %s;\n", db); end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); *end++=';'; @@ -507,7 +515,7 @@ int Intvar_log_event::write_data(IO_CACHE* file) return my_b_write(file, (byte*) buf, sizeof(buf)); } -void Intvar_log_event::print(FILE* file, bool short_form) +void Intvar_log_event::print(FILE* file, bool short_form, char* last_db) { char llbuff[22]; if(!short_form) @@ -625,7 +633,7 @@ void Load_log_event::copy_log_event(const char *buf, ulong data_len) } -void Load_log_event::print(FILE* file, bool short_form) +void Load_log_event::print(FILE* file, bool short_form, char* last_db) { if (!short_form) { @@ -634,7 +642,15 @@ void Load_log_event::print(FILE* file, bool short_form) thread_id, exec_time); } - if(db && db[0]) + bool same_db = 0; + + if(db && last_db) + { + if(!(same_db = !memcmp(last_db, db, db_len))) + memcpy(last_db, db, db_len + 1); + } + + if(db && db[0] && !same_db) fprintf(file, "use %s;\n", db); fprintf(file, "LOAD DATA INFILE '%s' ", fname); diff --git a/sql/log_event.h b/sql/log_event.h index 0f4945bae3c..41f847e8d92 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -100,7 +100,7 @@ public: virtual ~Log_event() {} virtual int get_data_size() { return 0;} - virtual void print(FILE* file, bool short_form = 0) = 0; + virtual void print(FILE* file, bool short_form = 0, char* last_db = 0) = 0; void print_timestamp(FILE* file, time_t *ts = 0); void print_header(FILE* file); @@ -169,7 +169,7 @@ public: ; } - void print(FILE* file, bool short_form = 0); + void print(FILE* file, bool short_form = 0, char* last_db = 0); }; #define DUMPFILE_FLAG 0x1 @@ -312,7 +312,7 @@ public: ; } - void print(FILE* file, bool short_form = 0); + void print(FILE* file, bool short_form = 0, char* last_db = 0); }; extern char server_version[SERVER_VERSION_LENGTH]; @@ -350,7 +350,7 @@ public: // sizeof(binlog_version) + sizeof(server_version) sizeof(created) return 2 + sizeof(server_version) + 4; } - void print(FILE* file, bool short_form = 0); + void print(FILE* file, bool short_form = 0, char* last_db = 0); }; class Intvar_log_event: public Log_event @@ -369,7 +369,7 @@ public: int write_data(IO_CACHE* file); - void print(FILE* file, bool short_form = 0); + void print(FILE* file, bool short_form = 0, char* last_db = 0); }; class Stop_log_event: public Log_event @@ -388,7 +388,7 @@ public: } ~Stop_log_event() {} Log_event_type get_type_code() { return STOP_EVENT;} - void print(FILE* file, bool short_form = 0); + void print(FILE* file, bool short_form = 0, char* last_db = 0); }; class Rotate_log_event: public Log_event @@ -416,7 +416,7 @@ public: int get_data_size() { return ident_len;} int write_data(IO_CACHE* file); - void print(FILE* file, bool short_form = 0); + void print(FILE* file, bool short_form = 0, char* last_db = 0); }; #endif diff --git a/sql/mysqlbinlog.cc b/sql/mysqlbinlog.cc index 60989615390..05ff166cd49 100644 --- a/sql/mysqlbinlog.cc +++ b/sql/mysqlbinlog.cc @@ -291,6 +291,7 @@ static void dump_remote_table(NET* net, const char* db, const char* table) static void dump_remote_log_entries(const char* logname) { char buf[128]; + char last_db[FN_REFLEN+1] = ""; uint len; NET* net = &mysql->net; if(!position) position = 4; // protect the innocent from spam @@ -324,7 +325,7 @@ Unfortunately, no sweepstakes today, adjusted position to 4\n"); len - 1); if(ev) { - ev->print(stdout, short_form); + ev->print(stdout, short_form, last_db); if(ev->get_type_code() == LOAD_EVENT) dump_remote_file(net, ((Load_log_event*)ev)->fname); delete ev; @@ -339,6 +340,7 @@ static void dump_local_log_entries(const char* logname) File fd = -1; IO_CACHE cache,*file= &cache; ulonglong rec_count = 0; + char last_db[FN_REFLEN+1] = ""; if (logname && logname[0] != '-') { @@ -398,7 +400,7 @@ Could not read entry at offset %s : Error in log format or read error", if (!short_form) printf("# at %s\n",llstr(old_off,llbuff)); - ev->print(stdout, short_form); + ev->print(stdout, short_form, last_db); } rec_count++; delete ev; diff --git a/sql/slave.cc b/sql/slave.cc index aded6d558fc..1ca8324e204 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -20,6 +20,7 @@ #include <myisam.h> #include "mini_client.h" #include "slave.h" +#include "sql_repl.h" #include <thr_alarm.h> #include <my_dir.h> @@ -441,6 +442,101 @@ int fetch_nx_table(THD* thd, MASTER_INFO* mi) return error; } +void MASTER_INFO::close_virtual_master() +{ + vm_binlog.close_index(); + end_io_cache(&vm_cache); + if(vm_fd >= 0) + { + my_close(vm_fd, MYF(0)); + vm_fd = -1; + } +} + +int MASTER_INFO::setup_virtual_master() +{ + vm_binlog.init(LOG_BIN); + vm_binlog.set_index_file_name(host); + if(vm_binlog.open_index(O_RDONLY)) + { + sql_print_error("virtual master: could not open index file '%s': \ + (%d)", host, my_errno); + return 1; + } + + if(vm_binlog.find_first_log(&vm_linfo,log_file_name)) + { + sql_print_error("virtual master: could not find first log"); + return 1; + } + + if(open_log()) + return 1; + + return 0; +} + +int MASTER_INFO::open_log() +{ + const char* errmsg = "Unknown error"; + if(vm_fd >= 0) + { + end_io_cache(&vm_cache); + my_close(vm_fd, MYF(0)); + } + + // if backup-up logs have relative paths, assume they are relative to + // the directory that has the log index, not cwd + char logname_buf[FN_REFLEN+1], *logname; + if(vm_linfo.log_file_name[0] == FN_LIBCHAR) + logname = vm_linfo.log_file_name; + else + { + char* end = strnmov(logname_buf, host, + sizeof(logname_buf)); + for(; *end != FN_LIBCHAR; --end); // we will always find it, first + // char of host is always FN_LIBCHAR for virtual master + + strncpy(end + 1, vm_linfo.log_file_name, + sizeof(logname_buf) - (end - logname_buf)); + logname = logname_buf; + } + + if((vm_fd = open_binlog(&vm_cache, logname, &errmsg)) < 0) + { + sql_print_error("virtual master: error opening binlog '%s': %s", + vm_linfo.log_file_name, errmsg); + return 1; + } + + strncpy(log_file_name, vm_linfo.log_file_name, sizeof(log_file_name)); + return 0; +} + +uint MASTER_INFO::read_event() +{ + for(;!(vm_ev = Log_event::read_log_event(&vm_cache, 0));) + { + if(!vm_cache.error) // eof - try next log + { + switch(vm_binlog.find_next_log(&vm_linfo)) + { + case LOG_INFO_EOF: + return 0; + case 0: + if(open_log()) + return packet_error; + continue; + default: + sql_print_error("virtual master: could not read next log"); + return packet_error; + } + } + } + + return vm_ev->get_data_size() + LOG_EVENT_HEADER_LEN; +} + void end_master_info(MASTER_INFO* mi) { if(mi->fd >= 0) @@ -450,6 +546,8 @@ void end_master_info(MASTER_INFO* mi) mi->fd = -1; } mi->inited = 0; + if(mi->virtual_master) + mi->close_virtual_master(); } int init_master_info(MASTER_INFO* mi) @@ -545,6 +643,7 @@ int init_master_info(MASTER_INFO* mi) } mi->inited = 1; + mi->virtual_master = (mi->host[0] == FN_LIBCHAR); // now change the cache from READ to WRITE - must do this // before flush_master_info reinit_io_cache(&mi->file, WRITE_CACHE, 0L,0,1); @@ -742,6 +841,9 @@ static int safe_sleep(THD* thd, int sec) static int request_dump(MYSQL* mysql, MASTER_INFO* mi) { + if(mi->virtual_master) + return 0; + char buf[FN_REFLEN + 10]; int len; int binlog_flags = 0; // for now @@ -795,6 +897,9 @@ command"); static uint read_event(MYSQL* mysql, MASTER_INFO *mi) { + if(mi->virtual_master) + return mi->read_event(); + uint len = packet_error; // for convinience lets think we start by // being in the interrupted state :-) @@ -860,16 +965,18 @@ point. If you are sure that your master is ok, run this query manually on the\ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) { - Log_event * ev = Log_event::read_log_event((const char*)net->read_pos + 1, - event_len); + Log_event * ev = (mi->virtual_master) ? mi->vm_ev : + Log_event::read_log_event((const char*)net->read_pos + 1, + event_len) ; char llbuff[22]; if (ev) { int type_code = ev->get_type_code(); - if (ev->server_id == ::server_id || slave_skip_counter) + if ((!mi->virtual_master && ev->server_id == ::server_id) + || slave_skip_counter) { - if(type_code == LOAD_EVENT) + if(type_code == LOAD_EVENT && !mi->virtual_master) skip_load_data_infile(net); mi->inc_pos(event_len); @@ -971,6 +1078,14 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) case LOAD_EVENT: { + if(mi->virtual_master) + { + delete ev; + sql_print_error("LOAD DATA INFILE does not yet work with virtual \ +master. Perform in manually, then restart slave with SET SQL_SKIP_COUNTER=1;\ +SLAVE START"); + return 1; + } Load_log_event* lev = (Load_log_event*)ev; init_sql_alloc(&thd->mem_root, 8192,0); thd->db = rewrite_db((char*)lev->db); @@ -993,7 +1108,8 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) // the table will be opened in mysql_load if(table_rules_on && !tables_ok(thd, &tables)) { - skip_load_data_infile(net); + if(!mi->virtual_master) + skip_load_data_infile(net); } else { @@ -1057,7 +1173,8 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) { // we will just ask the master to send us /dev/null if we do not // want to load the data :-) - skip_load_data_infile(net); + if(!mi->virtual_master) + skip_load_data_infile(net); } thd->net.vio = 0; @@ -1293,9 +1410,21 @@ try again, log '%s' at postion %s", RPL_LOG_NAME, sql_print_error("Slave thread killed while reading event"); goto err; } + + if(!event_len && glob_mi.virtual_master) + { + sql_print_error("Virtual master replication finished"); + goto err; + } if (event_len == packet_error) { + if(glob_mi.virtual_master) + { + sql_print_error("Virtual master replication encountered \ +error while reading event, replication terminated"); + goto err; + } thd->proc_info = "Waiting to reconnect after a failed read"; if(mysql->net.vio) vio_close(mysql->net.vio); @@ -1403,6 +1532,8 @@ position %s", static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) { + if(mi->virtual_master) + return mi->setup_virtual_master(); int slave_was_killed; #ifndef DBUG_OFF events_till_disconnect = disconnect_slave_event_count; @@ -1432,6 +1563,9 @@ static int safe_connect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) static int safe_reconnect(THD* thd, MYSQL* mysql, MASTER_INFO* mi) { + if(mi->virtual_master) + return mi->setup_virtual_master(); + int slave_was_killed; char llbuff[22]; diff --git a/sql/slave.h b/sql/slave.h index 311368a4b82..d04c0c13c23 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -16,8 +16,14 @@ typedef struct st_master_info pthread_mutex_t lock; pthread_cond_t cond; bool inited; + bool virtual_master; // for replay of binlogs from a directory + MYSQL_LOG vm_binlog; + LOG_INFO vm_linfo; + IO_CACHE vm_cache; + int vm_fd; + Log_event* vm_ev; - st_master_info():pending(0),fd(-1),inited(0) + st_master_info():pending(0),fd(-1),inited(0),virtual_master(0),vm_fd(-1) { host[0] = 0; user[0] = 0; password[0] = 0; pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST); @@ -28,6 +34,8 @@ typedef struct st_master_info { pthread_mutex_destroy(&lock); pthread_cond_destroy(&cond); + if(virtual_master) + close_virtual_master(); } inline void inc_pending(ulonglong val) { @@ -51,6 +59,11 @@ typedef struct st_master_info } int wait_for_pos(THD* thd, String* log_name, ulonglong log_pos); + int setup_virtual_master(); + void close_virtual_master(); + uint read_event(); + int open_log(); + } MASTER_INFO; typedef struct st_table_rule_ent diff --git a/sql/sql_class.h b/sql/sql_class.h index cb08b8a9df4..438898ca294 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -71,9 +71,12 @@ public: ~MYSQL_LOG(); pthread_mutex_t* get_log_lock() { return &LOCK_log; } void set_index_file_name(const char* index_file_name = 0); + void init(enum_log_type log_type_arg); void open(const char *log_name,enum_log_type log_type, const char *new_name=0); void new_file(void); + bool open_index(int options); + void close_index(); bool write(THD *thd, enum enum_server_command command,const char *format,...); bool write(THD *thd, const char *query, uint query_length, time_t query_start=0); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 05e64670df5..ed41bf53692 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -132,7 +132,7 @@ static int send_file(THD *thd) } -static File open_log(IO_CACHE *log, const char *log_file_name, +File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg) { File file; @@ -294,7 +294,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, ulong pos, ushort flags) goto err; } - if ((file=open_log(&log, log_file_name, &errmsg)) < 0) + if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0) goto err; if(pos < 4) @@ -483,7 +483,7 @@ sweepstakes if you report the bug"; // fake Rotate_log event just in case it did not make it to the log // otherwise the slave make get confused about the offset - if ((file=open_log(&log, log_file_name, &errmsg)) < 0 || + if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 || fake_rotate_event(net, packet, log_file_name, &errmsg)) goto err; @@ -694,7 +694,12 @@ int change_master(THD* thd) glob_mi.pos = lex_mi->pos; if(lex_mi->host) - strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host)); + { + if(glob_mi.virtual_master) + glob_mi.close_virtual_master(); + strmake(glob_mi.host, lex_mi->host, sizeof(glob_mi.host)); + glob_mi.virtual_master = (glob_mi.host[0] == FN_LIBCHAR); + } if(lex_mi->user) strmake(glob_mi.user, lex_mi->user, sizeof(glob_mi.user)); if(lex_mi->password) diff --git a/sql/sql_repl.h b/sql/sql_repl.h index f8a67f51aa2..68f2b4ba6c4 100644 --- a/sql/sql_repl.h +++ b/sql/sql_repl.h @@ -9,6 +9,9 @@ extern uint32 server_id; extern bool server_id_supplied; extern I_List<i_string> binlog_do_db, binlog_ignore_db; +File open_binlog(IO_CACHE *log, const char *log_file_name, + const char **errmsg); + int start_slave(THD* thd = 0, bool net_report = 1); int stop_slave(THD* thd = 0, bool net_report = 1); int change_master(THD* thd); |