summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2003-11-03 19:11:09 +0200
committerunknown <heikki@hundin.mysql.fi>2003-11-03 19:11:09 +0200
commit8b648b03366a0037b178d5c17a728eda9cccb0e3 (patch)
tree16d8e94df9055bb6ed7e41eb7afbcdebf5b61236
parent35564d9fbb1a873247f7d85ecfdd7f475139764c (diff)
downloadmariadb-git-8b648b03366a0037b178d5c17a728eda9cccb0e3.tar.gz
Many files:
Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/buf/buf0buf.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/dict/dict0crea.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/dict/dict0dict.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/fil/fil0fil.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/fsp/fsp0fsp.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/fil0fil.h: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/fsp0fsp.h: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/log0recv.h: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/mtr0log.h: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/mtr0mtr.h: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/os0file.h: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/ut0dbg.h: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/ut0ut.h: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/ha0ha.ic: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/include/mtr0log.ic: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/log/log0log.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/log/log0recv.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/mem/mem0pool.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/os/os0file.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/pars/lexyy.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/row/row0mysql.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/row/row0sel.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/srv/srv0srv.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/srv/srv0start.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/ut/ut0rnd.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation innobase/ut/ut0ut.c: Merge with ibbackup; bug fix: .ibd files were extended 2 x the required amount; InnoDB does not create the small file inno_arch_log... any more at database creation
-rw-r--r--innobase/buf/buf0buf.c3
-rw-r--r--innobase/dict/dict0crea.c7
-rw-r--r--innobase/dict/dict0dict.c2
-rw-r--r--innobase/fil/fil0fil.c793
-rw-r--r--innobase/fsp/fsp0fsp.c90
-rw-r--r--innobase/include/fil0fil.h92
-rw-r--r--innobase/include/fsp0fsp.h8
-rw-r--r--innobase/include/ha0ha.ic4
-rw-r--r--innobase/include/log0recv.h11
-rw-r--r--innobase/include/mtr0log.h13
-rw-r--r--innobase/include/mtr0log.ic28
-rw-r--r--innobase/include/mtr0mtr.h8
-rw-r--r--innobase/include/os0file.h29
-rw-r--r--innobase/include/ut0dbg.h35
-rw-r--r--innobase/include/ut0ut.h10
-rw-r--r--innobase/log/log0log.c95
-rw-r--r--innobase/log/log0recv.c209
-rw-r--r--innobase/mem/mem0pool.c2
-rw-r--r--innobase/os/os0file.c103
-rw-r--r--innobase/pars/lexyy.c2
-rw-r--r--innobase/row/row0mysql.c9
-rw-r--r--innobase/row/row0sel.c8
-rw-r--r--innobase/srv/srv0srv.c6
-rw-r--r--innobase/srv/srv0start.c22
-rw-r--r--innobase/ut/ut0rnd.c3
-rw-r--r--innobase/ut/ut0ut.c46
26 files changed, 1215 insertions, 423 deletions
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index b403cc4df0d..946020acd11 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -297,8 +297,9 @@ buf_page_is_corrupted(
ulint old_checksum;
ulint checksum_field;
ulint old_checksum_field;
+#ifndef UNIV_HOTBACKUP
dulint current_lsn;
-
+#endif
if (mach_read_from_4(read_buf + FIL_PAGE_LSN + 4)
!= mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index 9d1ec53645d..a5077252c6a 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -301,9 +301,12 @@ dict_build_table_def_step(
- page 2 is the first inode page,
- page 3 will contain the root of the clustered index of the
table we create here. */
+
+ table->space = 0; /* reset to zero for the call below */
error = fil_create_new_single_table_tablespace(
- &(table->space), table->name, 4);
+ &(table->space), table->name,
+ FIL_IBD_FILE_INITIAL_SIZE);
if (error != DB_SUCCESS) {
return(error);
@@ -311,7 +314,7 @@ dict_build_table_def_step(
mtr_start(&mtr);
- fsp_header_init(table->space, 4, &mtr);
+ fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
mtr_commit(&mtr);
}
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 9056c974f02..0ae36eec6dc 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -2580,7 +2580,7 @@ dict_create_foreign_constraints_low(
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s.\n"
"Cannot find the table from the internal data dictionary of InnoDB.\n"
-"Create table statement:\n%.2000\n", name, sql_string);
+"Create table statement:\n%.2000s\n", name, sql_string);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index 3b729938ea7..7bfe7277afa 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -23,7 +23,10 @@ Created 10/25/1995 Heikki Tuuri
#include "fsp0fsp.h"
#include "srv0srv.h"
#include "srv0start.h"
+#include "mtr0mtr.h"
+#include "mtr0log.h"
+
/*
IMPLEMENTATION OF THE TABLESPACE MEMORY CACHE
=============================================
@@ -80,6 +83,10 @@ out of the LRU-list and keep a count of pending operations. When an operation
completes, we decrement the count and return the file node to the LRU-list if
the count drops to zero. */
+/* When mysqld is run, the default directory "." is the mysqld datadir,
+but in ibbackup we must set it explicitly */
+char* fil_path_to_mysql_datadir = (char*)".";
+
ulint fil_n_pending_log_flushes = 0;
ulint fil_n_pending_tablespace_flushes = 0;
@@ -257,6 +264,17 @@ fil_node_complete_io(
ulint type); /* in: OS_FILE_WRITE or OS_FILE_READ; marks
the node as modified if
type == OS_FILE_WRITE */
+/***********************************************************************
+Checks if a single-table tablespace for a given table name exists in the
+tablespace memory cache. */
+static
+ulint
+fil_get_space_id_for_table(
+/*=======================*/
+ /* out: space id, ULINT_UNDEFINED if not
+ found */
+ char* name); /* in: table name in the standard
+ 'databasename/tablename' format */
/***********************************************************************
@@ -474,15 +492,18 @@ fil_node_open_file(
system->n_open++;
if (node->size == 0) {
+ os_file_get_size(node->handle, &size_low, &size_high);
+
+ size_bytes = (((ib_longlong)size_high) << 32)
+ + (ib_longlong)size_low;
+#ifdef UNIV_HOTBACKUP
+ node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
+
+#else
/* It must be a single-table tablespace and we do not know the
size of the file yet */
ut_a(space->id != 0);
-
- os_file_get_size(node->handle, &size_low, &size_high);
-
- size_bytes = (((ib_longlong)size_high) << 32)
- + (ib_longlong)size_low;
if (size_bytes >= FSP_EXTENT_SIZE * UNIV_PAGE_SIZE) {
node->size = (ulint) ((size_bytes / (1024 * 1024))
@@ -490,8 +511,8 @@ fil_node_open_file(
} else {
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
}
-
- space->size = node->size;
+#endif
+ space->size += node->size;
}
if (space->purpose == FIL_TABLESPACE && space->id != 0) {
@@ -516,6 +537,7 @@ fil_node_close_file(
ut_a(node->open);
ut_a(node->n_pending == 0);
ut_a(node->n_pending_flushes == 0);
+ ut_a(node->modification_counter == node->flush_counter);
ret = os_file_close(node->handle);
ut_a(ret);
@@ -690,12 +712,13 @@ close_more:
mutex_exit(&(system->mutex));
+#ifndef UNIV_HOTBACKUP
/* Wake the i/o-handler threads to make sure pending i/o's are
performed */
os_aio_simulated_wake_handler_threads();
os_thread_sleep(20000);
-
+#endif
/* Flush tablespaces so that we can close modified files in the LRU
list */
@@ -722,6 +745,11 @@ fil_node_free(
ut_a(node->n_pending == 0);
if (node->open) {
+ /* We fool the assertion in fil_node_close_file() to think
+ there are no unflushed modifications in the file */
+
+ node->modification_counter = node->flush_counter;
+
fil_node_close_file(node, system);
}
@@ -854,8 +882,7 @@ try_again:
space->id = id;
system->tablespace_version++;
- space->tablespace_version =
- system->tablespace_version;
+ space->tablespace_version = system->tablespace_version;
space->mark = FALSE;
if (purpose == FIL_TABLESPACE && id > system->max_assigned_id) {
@@ -1005,6 +1032,29 @@ fil_space_free(
return(TRUE);
}
+#ifdef UNIV_HOTBACKUP
+/***********************************************************************
+Returns the tablespace object for a given id, or NULL if not found from the
+tablespace memory cache. */
+static
+fil_space_t*
+fil_get_space_for_id_low(
+/*=====================*/
+ /* out: tablespace object or NULL; NOTE that you must
+ own &(fil_system->mutex) to call this function! */
+ ulint id) /* in: space id */
+{
+ fil_system_t* system = fil_system;
+ fil_space_t* space;
+
+ ut_ad(system);
+
+ HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
+
+ return(space);
+}
+#endif
+
/***********************************************************************
Returns the size of the space in pages. The tablespace must be cached in the
memory cache. */
@@ -1456,6 +1506,225 @@ fil_decr_pending_ibuf_merges(
mutex_exit(&(system->mutex));
}
+/************************************************************
+Creates the database directory for a table if it does not exist yet. */
+static
+void
+fil_create_directory_for_tablename(
+/*===============================*/
+ char* name) /* in: name in the standard 'databasename/tablename'
+ format */
+{
+ char* ptr;
+ char path[OS_FILE_MAX_PATH];
+
+ sprintf(path, "%s/%s", fil_path_to_mysql_datadir, name);
+
+ ptr = path + ut_strlen(path);
+
+ while (*ptr != '/') {
+ ptr--;
+
+ ut_a(ptr >= path);
+ }
+
+ *ptr = '\0';
+
+ srv_normalize_path_for_win(path);
+
+ ut_a(os_file_create_directory(path, FALSE));
+}
+
+#ifndef UNIV_HOTBACKUP
+/************************************************************
+Writes a log record about an .ibd file create/rename/delete. */
+static
+void
+fil_op_write_log(
+/*=============*/
+ ulint type, /* in: MLOG_FILE_CREATE, MLOG_FILE_DELETE, or
+ MLOG_FILE_RENAME */
+ ulint space_id, /* in: space id */
+ char* name, /* in: table name in the familiar
+ 'databasename/tablename' format, or the file
+ path in the case of MLOG_FILE_DELETE */
+ char* new_name, /* in: if type is MLOG_FILE_RENAME, the new
+ table name in the 'databasename/tablename'
+ format */
+ mtr_t* mtr) /* in: mini-transaction handle */
+{
+ byte* log_ptr;
+
+ log_ptr = mlog_open(mtr, 30);
+
+ log_ptr = mlog_write_initial_log_record_for_file_op(type, space_id, 0,
+ log_ptr, mtr);
+ /* Let us store the strings as null-terminated for easier readability
+ and handling */
+
+ mach_write_to_2(log_ptr, ut_strlen(name) + 1);
+ log_ptr += 2;
+
+ mlog_close(mtr, log_ptr);
+
+ mlog_catenate_string(mtr, name, ut_strlen(name) + 1);
+
+ if (type == MLOG_FILE_RENAME) {
+ log_ptr = mlog_open(mtr, 30);
+ mach_write_to_2(log_ptr, ut_strlen(new_name) + 1);
+ log_ptr += 2;
+
+ mlog_close(mtr, log_ptr);
+
+ mlog_catenate_string(mtr, new_name, ut_strlen(new_name) + 1);
+ }
+}
+#endif
+
+/***********************************************************************
+Parses the body of a log record written about an .ibd file operation. That is,
+the log record part after the standard (type, space id, page no) header of the
+log record.
+
+If desired, also replays the delete or rename operation if the .ibd file
+exists and the space id in it matches. Replays the create operation if a file
+at that path does not exist yet. If the database directory for the file to be
+created does not exist, then we create the directory, too.
+
+Note that ibbackup --apply-log sets fil_path_to_mysql_datadir to point to the
+datadir that we should use in replaying the file operations. */
+
+byte*
+fil_op_log_parse_or_replay(
+/*=======================*/
+ /* out: end of log record, or NULL if the
+ record was not completely contained between
+ ptr and end_ptr */
+ byte* ptr, /* in: buffer containing the log record body,
+ or an initial segment of it, if the record does
+ not fir completely between ptr and end_ptr */
+ byte* end_ptr, /* in: buffer end */
+ ulint type, /* in: the type of this log record */
+ ibool do_replay, /* in: TRUE if we want to replay the
+ operation, and not just parse the log record */
+ ulint space_id) /* in: if do_replay is TRUE, the space id of
+ the tablespace in question; otherwise
+ ignored */
+{
+ ulint name_len;
+ ulint new_name_len;
+ char* name;
+ char* new_name = NULL;
+
+ if (end_ptr < ptr + 2) {
+
+ return(NULL);
+ }
+
+ name_len = mach_read_from_2(ptr);
+
+ ptr += 2;
+
+ if (end_ptr < ptr + name_len) {
+
+ return(NULL);
+ }
+
+ name = ptr;
+
+ ptr += name_len;
+
+ if (type == MLOG_FILE_RENAME) {
+ if (end_ptr < ptr + 2) {
+
+ return(NULL);
+ }
+
+ new_name_len = mach_read_from_2(ptr);
+
+ ptr += 2;
+
+ if (end_ptr < ptr + new_name_len) {
+
+ return(NULL);
+ }
+
+ new_name = ptr;
+
+ ptr += new_name_len;
+ }
+
+ /* We managed to parse a full log record body */
+/*
+ printf("Parsed log rec of type %lu space %lu\n"
+ "name %s\n", type, space_id, name);
+
+ if (type == MLOG_FILE_RENAME) {
+ printf("new name %s\n", new_name);
+ }
+*/
+ if (do_replay == FALSE) {
+
+ return(ptr);
+ }
+
+ /* Let us try to perform the file operation, if sensible. Note that
+ ibbackup has at this stage already read in all space id info to the
+ fil0fil.c data structures.
+
+ NOTE that our algorithm is not guaranteed to work correctly if there
+ were renames of tables during the backup. See ibbackup code for more
+ on the problem. */
+
+ if (type == MLOG_FILE_DELETE) {
+ if (fil_tablespace_exists_in_mem(space_id)) {
+ ut_a(fil_delete_tablespace(space_id));
+ }
+ } else if (type == MLOG_FILE_RENAME) {
+ if (fil_get_space_id_for_table(name) == space_id) {
+ /* Create the database directory for the new name, if
+ it does not exist yet */
+ fil_create_directory_for_tablename(new_name);
+
+ /* Rename the table if there is not yet a tablespace
+ with the same name */
+
+ if (fil_get_space_id_for_table(new_name)
+ == ULINT_UNDEFINED) {
+ ut_a(fil_rename_tablespace(name, space_id,
+ new_name));
+ } else {
+ fprintf(stderr,
+"InnoDB: Warning: in log replay cannot rename tablespace\n"
+"InnoDB: %s with id %lu to %s, because it exists already.\n",
+ name, space_id, new_name);
+ }
+ }
+ } else {
+ ut_a(type == MLOG_FILE_CREATE);
+
+ if (fil_tablespace_exists_in_mem(space_id)) {
+ /* Do nothing */
+ } else if (fil_get_space_id_for_table(name) !=
+ ULINT_UNDEFINED) {
+ /* Do nothing */
+ } else {
+ /* Create the database directory for name, if it does
+ not exist yet */
+ fil_create_directory_for_tablename(name);
+
+ ut_a(space_id != 0);
+
+ ut_a(DB_SUCCESS ==
+ fil_create_new_single_table_tablespace(
+ &space_id, name,
+ FIL_IBD_FILE_INITIAL_SIZE));
+ }
+ }
+
+ return(ptr);
+}
+
/***********************************************************************
Deletes a single-table tablespace. The tablespace must be cached in the
memory cache. */
@@ -1554,7 +1823,7 @@ try_again:
}
mutex_exit(&(system->mutex));
-
+#ifndef UNIV_HOTBACKUP
/* Invalidate in the buffer pool all pages belonging to the
tablespace. Since we have set space->is_being_deleted = TRUE, readahead
or ibuf merge can no longer read more pages of this tablespace to the
@@ -1563,6 +1832,8 @@ try_again:
fil_flush() from being applied to this tablespace. */
buf_LRU_invalidate_tablespace(id);
+#endif
+ /* printf("Deleting tablespace %s id %lu\n", space->name, id); */
success = fil_space_free(id);
@@ -1570,7 +1841,23 @@ try_again:
success = os_file_delete(path);
if (success) {
-
+ /* Write a log record about the deletion of the .ibd
+ file, so that ibbackup can replay it in the
+ --apply-log phase. We use a dummy mtr and the familiar
+ log write mechanism. */
+#ifndef UNIV_HOTBACKUP
+ {
+ mtr_t mtr;
+
+ /* When replaying the operation in ibbackup, do not try
+ to write any log record */
+ mtr_start(&mtr);
+
+ fil_op_write_log(MLOG_FILE_DELETE, id, path,
+ NULL, &mtr);
+ mtr_commit(&mtr);
+ }
+#endif
return(TRUE);
}
}
@@ -1679,8 +1966,8 @@ fil_rename_tablespace(
fil_space_t* space;
fil_node_t* node;
ulint count = 0;
+ char* path = NULL;
char old_path[OS_FILE_MAX_PATH];
- char path[OS_FILE_MAX_PATH];
ut_a(id != 0);
retry:
@@ -1752,9 +2039,10 @@ retry:
/* Check that the old name in the space is right */
- ut_a(strlen(old_name) < OS_FILE_MAX_PATH - 10);
+ ut_a(strlen(old_name) + strlen(fil_path_to_mysql_datadir)
+ < OS_FILE_MAX_PATH - 10);
- sprintf(old_path, "./%s.ibd", old_name);
+ sprintf(old_path, "%s/%s.ibd", fil_path_to_mysql_datadir, old_name);
srv_normalize_path_for_win(old_path);
@@ -1763,9 +2051,11 @@ retry:
/* Rename the tablespace and the node in the memory cache */
- ut_a(strlen(new_name) < OS_FILE_MAX_PATH - 10);
+ ut_a(strlen(new_name) + strlen(fil_path_to_mysql_datadir)
+ < OS_FILE_MAX_PATH - 10);
+ path = mem_alloc(OS_FILE_MAX_PATH);
- sprintf(path, "./%s.ibd", new_name);
+ sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, new_name);
srv_normalize_path_for_win(path);
@@ -1776,6 +2066,8 @@ retry:
goto func_exit;
}
+ /* printf("Renaming tablespace %s to %s id %lu\n", path, old_path, id);
+ */
success = os_file_rename(old_path, path);
if (!success) {
@@ -1784,11 +2076,26 @@ retry:
ut_a(fil_rename_tablespace_in_mem(space, node, old_path));
}
+
func_exit:
+ if (path) {
+ mem_free(path);
+ }
space->stop_ios = FALSE;
mutex_exit(&(system->mutex));
+#ifndef UNIV_HOTBACKUP
+ if (success) {
+ mtr_t mtr;
+
+ mtr_start(&mtr);
+
+ fil_op_write_log(MLOG_FILE_RENAME, id, old_name, new_name,
+ &mtr);
+ mtr_commit(&mtr);
+ }
+#endif
return(success);
}
@@ -1802,11 +2109,14 @@ ulint
fil_create_new_single_table_tablespace(
/*===================================*/
/* out: DB_SUCCESS or error code */
- ulint* space_id, /* out: space id */
+ ulint* space_id, /* in/out: space id; if this is != 0, then
+ this is an input parameter, otherwise
+ output */
char* tablename, /* in: the table name in the usual
databasename/tablename format of InnoDB */
ulint size) /* in: the initial size of the tablespace file
- in pages, must be > 0 */
+ in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE
+ */
{
os_file_t file;
ibool ret;
@@ -1815,9 +2125,11 @@ fil_create_new_single_table_tablespace(
ibool success;
char path[OS_FILE_MAX_PATH];
- ut_a(strlen(tablename) < OS_FILE_MAX_PATH - 10);
+ ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
- sprintf(path, "./%s.ibd", tablename);
+ ut_a(strlen(tablename) + strlen(fil_path_to_mysql_datadir)
+ < OS_FILE_MAX_PATH - 10);
+ sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, tablename);
srv_normalize_path_for_win(path);
@@ -1865,7 +2177,11 @@ fil_create_new_single_table_tablespace(
return(DB_OUT_OF_FILE_SPACE);
}
- *space_id = fil_assign_new_space_id();
+ if (*space_id == 0) {
+ *space_id = fil_assign_new_space_id();
+ }
+
+ /* printf("Creating tablespace %s id %lu\n", path, *space_id); */
if (*space_id == ULINT_UNDEFINED) {
ut_free(page);
@@ -1934,6 +2250,17 @@ fil_create_new_single_table_tablespace(
fil_node_create(path, size, *space_id, FALSE);
+#ifndef UNIV_HOTBACKUP
+ {
+ mtr_t mtr;
+
+ mtr_start(&mtr);
+
+ fil_op_write_log(MLOG_FILE_CREATE, *space_id, tablename, NULL, &mtr);
+
+ mtr_commit(&mtr);
+ }
+#endif
return(DB_SUCCESS);
}
@@ -1971,7 +2298,7 @@ fil_reset_too_high_lsns(
ut_a(strlen(name) < OS_FILE_MAX_PATH - 10);
- sprintf(filepath, "./%s.ibd", name);
+ sprintf(filepath, "%s/%s.ibd", fil_path_to_mysql_datadir, name);
srv_normalize_path_for_win(filepath);
@@ -2106,7 +2433,7 @@ fil_open_single_table_tablespace(
ut_a(strlen(name) < OS_FILE_MAX_PATH - 10);
- sprintf(filepath, "./%s.ibd", name);
+ sprintf(filepath, "%s/%s.ibd", fil_path_to_mysql_datadir, name);
srv_normalize_path_for_win(filepath);
@@ -2196,13 +2523,16 @@ fil_load_single_table_tablespace(
ulint size_low;
ulint size_high;
ib_longlong size;
-
+#ifdef UNIV_HOTBACKUP
+ fil_space_t* space;
+#endif
filepath = ut_malloc(OS_FILE_MAX_PATH);
- ut_a(strlen(dbname) + strlen(filename) < OS_FILE_MAX_PATH - 10);
+ ut_a(strlen(dbname) + strlen(filename)
+ + strlen(fil_path_to_mysql_datadir) < OS_FILE_MAX_PATH - 100);
- sprintf(filepath, "./%s/%s", dbname, filename);
-
+ sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname,
+ filename);
srv_normalize_path_for_win(filepath);
file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN,
@@ -2236,9 +2566,12 @@ fil_load_single_table_tablespace(
return;
}
- size = (((ib_longlong)size_high) << 32) + (ib_longlong)size_low;
+ /* Every .ibd file is created >= 4 pages in size. Smaller files
+ cannot be ok. */
- if (size < 4 * UNIV_PAGE_SIZE) {
+ size = (((ib_longlong)size_high) << 32) + (ib_longlong)size_low;
+#ifndef UNIV_HOTBACKUP
+ if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Error: the size of single-table tablespace file %s\n"
"InnoDB: is only %lu %lu, should be at least %lu!", filepath, size_high,
@@ -2248,24 +2581,95 @@ fil_load_single_table_tablespace(
return;
}
-
- /* Read the first page of the tablespace */
+#endif
+ /* Read the first page of the tablespace if the size big enough */
page = ut_malloc(UNIV_PAGE_SIZE);
- success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
+ if (size >= FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
+ success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
- /* We have to read the tablespace id from the file */
+ /* We have to read the tablespace id from the file */
- space_id = fsp_header_get_space_id(page);
+ space_id = fsp_header_get_space_id(page);
+ } else {
+ space_id = ULINT_UNDEFINED;
+ }
+#ifndef UNIV_HOTBACKUP
if (space_id == ULINT_UNDEFINED || space_id == 0) {
fprintf(stderr,
"InnoDB: Error: tablespace id %lu in file %s is not sensible\n", space_id,
filepath);
goto func_exit;
}
+#else
+ if (space_id == ULINT_UNDEFINED || space_id == 0) {
+ char* new_path;
+
+ fprintf(stderr,
+"InnoDB: Renaming tablespace %s of id %lu,\n"
+"InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
+"InnoDB: because its size %lld is too small (< 4 pages 16 kB each),\n"
+"InnoDB: or the space id in the file header is not sensible.\n"
+"InnoDB: This can happen in an ibbackup run, and is not dangerous.\n",
+ filepath, space_id, filepath, size);
+ os_file_close(file);
+
+ new_path = ut_malloc(OS_FILE_MAX_PATH);
+
+ sprintf(new_path, "%s_ibbackup_old_vers_", filepath);
+ ut_sprintf_timestamp_without_extra_chars(
+ new_path + ut_strlen(new_path));
+ ut_a(os_file_rename(filepath, new_path));
+
+ ut_free(page);
+ ut_free(filepath);
+ ut_free(new_path);
+
+ return;
+ }
+
+ /* A backup may contain the same space several times, if the space got
+ renamed at a sensitive time. Since it is enough to have one version of
+ the space, we rename the file if a space with the same space id
+ already exists in the tablespace memory cache. We rather rename the
+ file than delete it, because if there is a bug, we do not want to
+ destroy valuable data. */
+
+ mutex_enter(&(fil_system->mutex));
+
+ space = fil_get_space_for_id_low(space_id);
+
+ if (space) {
+ char* new_path;
+
+ fprintf(stderr,
+"InnoDB: Renaming tablespace %s of id %lu,\n"
+"InnoDB: to %s_ibbackup_old_vers_<timestamp>\n"
+"InnoDB: because space %s with the same id\n"
+"InnoDB: was scanned earlier. This can happen if you have renamed tables\n"
+"InnoDB: during an ibbackup run.\n", filepath, space_id, filepath,
+ space->name);
+ os_file_close(file);
+
+ new_path = ut_malloc(OS_FILE_MAX_PATH);
+
+ sprintf(new_path, "%s_ibbackup_old_vers_", filepath);
+ ut_sprintf_timestamp_without_extra_chars(
+ new_path + ut_strlen(new_path));
+ mutex_exit(&(fil_system->mutex));
+
+ ut_a(os_file_rename(filepath, new_path));
+ ut_free(page);
+ ut_free(filepath);
+ ut_free(new_path);
+
+ return;
+ }
+ mutex_exit(&(fil_system->mutex));
+#endif
success = fil_space_create(filepath, space_id, FIL_TABLESPACE);
if (!success) {
@@ -2305,7 +2709,7 @@ fil_load_single_table_tablespaces(void)
/* The datadir of MySQL is always the default directory of mysqld */
- dir = os_file_opendir((char*)".", TRUE);
+ dir = os_file_opendir(fil_path_to_mysql_datadir, TRUE);
if (dir == NULL) {
@@ -2317,8 +2721,8 @@ fil_load_single_table_tablespaces(void)
/* Scan all directories under the datadir. They are the database
directories of MySQL. */
- ret = os_file_readdir_next_file((char*)".", dir, &dbinfo);
-
+ ret = os_file_readdir_next_file(fil_path_to_mysql_datadir, dir,
+ &dbinfo);
while (ret == 0) {
/* printf("Looking at %s in datadir\n", dbinfo.name); */
@@ -2333,8 +2737,8 @@ fil_load_single_table_tablespaces(void)
ut_a(strlen(dbinfo.name) < OS_FILE_MAX_PATH - 10);
- sprintf(dbpath, "./%s", dbinfo.name);
-
+ sprintf(dbpath, "%s/%s", fil_path_to_mysql_datadir,
+ dbinfo.name);
srv_normalize_path_for_win(dbpath);
dbdir = os_file_opendir(dbpath, FALSE);
@@ -2378,7 +2782,8 @@ next_file_item:
}
next_datadir_item:
- ret = os_file_readdir_next_file((char*)".", dir, &dbinfo);
+ ret = os_file_readdir_next_file(fil_path_to_mysql_datadir,
+ dir, &dbinfo);
}
ut_free(dbpath);
@@ -2427,11 +2832,10 @@ fil_print_orphaned_tablespaces(void)
&& !space->mark) {
fprintf(stderr,
"InnoDB: Warning: tablespace %s of id %lu has no matching table in\n"
-"InnoDB: the InnoDB data dixtionary.\n", space->name, space->id);
+"InnoDB: the InnoDB data dictionary.\n", space->name, space->id);
}
space = UT_LIST_GET_NEXT(space_list, space);
-
}
mutex_exit(&(system->mutex));
@@ -2515,8 +2919,8 @@ there may be many tablespaces which are not yet in the memory cache. */
ibool
fil_space_for_table_exists_in_mem(
/*==============================*/
- /* out: TRUE if a matching tablespace
- exists in the memory cache */
+ /* out: TRUE if a matching tablespace exists
+ in the memory cache */
ulint id, /* in: space id */
char* name, /* in: table name in the standard
'databasename/tablename' format */
@@ -2539,7 +2943,7 @@ fil_space_for_table_exists_in_mem(
mutex_enter(&(system->mutex));
- sprintf(path, "./%s.ibd", name);
+ sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, name);
srv_normalize_path_for_win(path);
/* Look if there is a space with the same id */
@@ -2552,16 +2956,19 @@ fil_space_for_table_exists_in_mem(
HASH_SEARCH(name_hash, system->name_hash,
ut_fold_string(path), namespace,
0 == strcmp(namespace->name, path));
- if (!print_error_if_does_not_exist) {
- if (space && space == namespace) {
- if (mark_space) {
- space->mark = TRUE;
- }
+ if (space && space == namespace) {
+ /* Found */
+
+ if (mark_space) {
+ space->mark = TRUE;
+ }
- mutex_exit(&(system->mutex));
+ mutex_exit(&(system->mutex));
- return(TRUE);
- }
+ return(TRUE);
+ }
+
+ if (!print_error_if_does_not_exist) {
mutex_exit(&(system->mutex));
@@ -2602,7 +3009,8 @@ fil_space_for_table_exists_in_mem(
" InnoDB: Error: table %s\n"
"InnoDB: in InnoDB data dictionary has tablespace id %lu,\n"
"InnoDB: but tablespace with that id has name %s.\n"
-"InnoDB: Have you deleted or moved .ibd files?", name, id, space->name);
+"InnoDB: Have you deleted or moved .ibd files?\n", name, id, space->name);
+
if (namespace != NULL) {
fprintf(stderr,
"InnoDB: There is a tablespace with the right name\n"
@@ -2618,182 +3026,228 @@ fil_space_for_table_exists_in_mem(
return(FALSE);
}
- ut_a(space == namespace);
+ mutex_exit(&(system->mutex));
- if (mark_space) {
- space->mark = TRUE;
- }
+ return(FALSE);
+}
+
+/***********************************************************************
+Checks if a single-table tablespace for a given table name exists in the
+tablespace memory cache. */
+static
+ulint
+fil_get_space_id_for_table(
+/*=======================*/
+ /* out: space id, ULINT_UNDEFINED if not
+ found */
+ char* name) /* in: table name in the standard
+ 'databasename/tablename' format */
+{
+ fil_system_t* system = fil_system;
+ fil_space_t* namespace;
+ ulint id = ULINT_UNDEFINED;
+ char path[OS_FILE_MAX_PATH];
+
+ ut_ad(system);
+
+ mutex_enter(&(system->mutex));
+
+ sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, name);
+ srv_normalize_path_for_win(path);
+
+ /* Look if there is a space with the same name; the name is the
+ directory path to the file */
+
+ HASH_SEARCH(name_hash, system->name_hash,
+ ut_fold_string(path), namespace,
+ 0 == strcmp(namespace->name, path));
+ if (namespace) {
+ id = namespace->id;
+ }
mutex_exit(&(system->mutex));
- return(TRUE);
+ return(id);
}
/**************************************************************************
-Tries to extend a data file by the number of pages given. Fractions of 1 MB
-are ignored. The tablespace must be cached in the memory cache. */
+Tries to extend a data file so that it would accommodate the number of pages
+given. The tablespace must be cached in the memory cache. If the space is big
+enough already, does nothing. */
ibool
-fil_extend_last_data_file(
-/*======================*/
- /* out: TRUE if success, also if we run
- out of disk space we may return TRUE */
- ulint* actual_increase,/* out: number of pages we were able to
- extend, here the original size of the file and
- the resulting size of the file are rounded
- downwards to a full megabyte, and the
- difference expressed in pages is returned */
- ulint space_id, /* in: space id */
- ulint size, /* in: current size of the space in pages, as
- stored in the fsp header */
- ulint size_increase) /* in: try to extend this many pages */
+fil_extend_space_to_desired_size(
+/*=============================*/
+ /* out: TRUE if success */
+ ulint* actual_size, /* out: size of the space after extension;
+ if we ran out of disk space this may be lower
+ than the desired size */
+ ulint space_id, /* in: space id, must be != 0 */
+ ulint size_after_extend)/* in: desired size in pages after the
+ extension; if the current space size is bigger
+ than this already, the function does nothing */
{
fil_system_t* system = fil_system;
fil_node_t* node;
fil_space_t* space;
byte* buf2;
byte* buf;
- ibool success;
- ulint i;
+ ulint start_page_no;
+ ulint file_start_page_no;
+ ulint n_pages;
+ ulint offset_high;
+ ulint offset_low;
+ ibool success = TRUE;
fil_mutex_enter_and_prepare_for_io(space_id);
HASH_SEARCH(hash, system->spaces, space_id, space,
space->id == space_id);
ut_a(space);
+
+ if (space->size >= size_after_extend) {
+ /* Space already big enough */
+
+ *actual_size = space->size;
+
+ mutex_exit(&(system->mutex));
+
+ return(TRUE);
+ }
node = UT_LIST_GET_LAST(space->chain);
fil_node_prepare_for_io(node, system, space);
- if (UT_LIST_GET_LEN(space->chain) == 1 && node->size < size) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-"InnoDB: Fatal error: space %s id %lu size stored in header is %lu pages\n"
-"InnoDB: but actual size is only %lu pages (possibly rounded downwards)!\n"
-"InnoDB: Cannot continue operation!\n", space->name, space->id, size,
- node->size);
- exit(1);
- }
+ /* Extend 1 MB at a time */
buf2 = mem_alloc(1024 * 1024 + UNIV_PAGE_SIZE);
buf = ut_align(buf2, UNIV_PAGE_SIZE);
memset(buf, '\0', 1024 * 1024);
- for (i = 0; i < size_increase / ((1024 * 1024) / UNIV_PAGE_SIZE);
- i++) {
- /* If we use native Windows aio, then we use it also in this
- write */
+ start_page_no = space->size;
+ file_start_page_no = space->size - node->size;
+
+ while (start_page_no < size_after_extend) {
+ n_pages = size_after_extend - start_page_no;
+
+ if (n_pages > (1024 * 1024) / UNIV_PAGE_SIZE) {
+ n_pages = (1024 * 1024) / UNIV_PAGE_SIZE;
+ }
+ offset_high = (start_page_no - file_start_page_no)
+ / (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE));
+ offset_low = ((start_page_no - file_start_page_no)
+ % (4096 * ((1024 * 1024) / UNIV_PAGE_SIZE)))
+ * UNIV_PAGE_SIZE;
+#ifdef UNIV_HOTBACKUP
+ success = os_file_write(node->name, node->handle, buf,
+ offset_low, offset_high,
+ UNIV_PAGE_SIZE * n_pages);
+#else
success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
node->name, node->handle, buf,
- (node->size << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
- node->size >> (32 - UNIV_PAGE_SIZE_SHIFT),
- 1024 * 1024, NULL, NULL);
+ offset_low, offset_high,
+ UNIV_PAGE_SIZE * n_pages,
+ NULL, NULL);
+#endif
+ if (success) {
+ node->size += n_pages;
+ space->size += n_pages;
+
+ os_has_said_disk_full = FALSE;
+ } else {
+ /* Let us measure the size of the file to determine
+ how much we were able to extend it */
+
+ n_pages = ((ulint)
+ (os_file_get_size_as_iblonglong(node->handle)
+ / UNIV_PAGE_SIZE)) - node->size;
+
+ node->size += n_pages;
+ space->size += n_pages;
- if (!success) {
break;
}
- node->size += ((1024 * 1024) / UNIV_PAGE_SIZE);
- space->size += ((1024 * 1024) / UNIV_PAGE_SIZE);
-
- os_has_said_disk_full = FALSE;
+ start_page_no += n_pages;
}
mem_free(buf2);
fil_node_complete_io(node, system, OS_FILE_WRITE);
+ *actual_size = space->size;
+ /*
+ printf("Extended %s to %lu, actual size %lu pages\n", space->name,
+ size_after_extend, *actual_size); */
mutex_exit(&(system->mutex));
- *actual_increase = i * ((1024 * 1024) / UNIV_PAGE_SIZE);
-
fil_flush(space_id);
- if (space_id == 0) {
- srv_data_file_sizes[srv_n_data_files - 1] += *actual_increase;
- }
-
- return(TRUE);
+ return(success);
}
-/**************************************************************************
-Tries to extend a data file so that it would accommodate the number of pages
-given. The tablespace must be cached in the memory cache. */
+#ifdef UNIV_HOTBACKUP
+/************************************************************************
+Extends all tablespaces to the size stored in the space header. During the
+ibbackup --apply-log phase we extended the spaces on-demand so that log records
+could be appllied, but that may have left spaces still too small compared to
+the size stored in the space header. */
-ibool
-fil_extend_data_file_with_pages(
-/*============================*/
- /* out: TRUE if success */
- ulint space_id, /* in: space id, must be != 0 */
- ulint size, /* in: current size of the space in pages, as
- stored in the fsp header */
- ulint size_after_extend)/* in: desired size in pages after the
- extension, should be less than 4 GB (this
- function is primarily intended for increasing
- the data file size from < 64 pages to up to
- 64 pages) */
+void
+fil_extend_tablespaces_to_stored_len(void)
+/*======================================*/
{
- fil_system_t* system = fil_system;
- fil_node_t* node;
+ fil_system_t* system = fil_system;
fil_space_t* space;
- byte* buf2;
byte* buf;
+ ulint actual_size;
+ ulint size_in_header;
+ ulint error;
ibool success;
- ut_a(space_id != 0);
- ut_a(size_after_extend < 64 * 4096);
- ut_a(size_after_extend >= size);
+ buf = mem_alloc(UNIV_PAGE_SIZE);
- fil_mutex_enter_and_prepare_for_io(space_id);
+ mutex_enter(&(system->mutex));
- HASH_SEARCH(hash, system->spaces, space_id, space,
- space->id == space_id);
- ut_a(space);
-
- node = UT_LIST_GET_LAST(space->chain);
+ space = UT_LIST_GET_FIRST(system->space_list);
- fil_node_prepare_for_io(node, system, space);
+ while (space) {
+ ut_a(space->purpose == FIL_TABLESPACE);
- if (UT_LIST_GET_LEN(space->chain) == 1 && node->size < size) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-"InnoDB: Fatal error: space %s id %lu size stored in header is %lu pages\n"
-"InnoDB: but actual size is only %lu pages (possibly rounded downwards)!\n"
-"InnoDB: Cannot continue operation!\n", space->name, space_id, size,
- node->size);
- exit(1);
- }
+ mutex_exit(&(system->mutex)); /* no need to protect with a
+ mutex, because this is a single-
+ threaded operation */
+ error = fil_read(TRUE, space->id, 0, 0, UNIV_PAGE_SIZE, buf,
+ NULL);
+ ut_a(error == DB_SUCCESS);
- buf2 = mem_alloc((1 + size_after_extend - size) * UNIV_PAGE_SIZE);
- buf = ut_align(buf2, UNIV_PAGE_SIZE);
+ size_in_header = fsp_get_size_low(buf);
- memset(buf, '\0', (size_after_extend - size) * UNIV_PAGE_SIZE);
+ success = fil_extend_space_to_desired_size(&actual_size,
+ space->id, size_in_header);
+ if (!success) {
+ fprintf(stderr,
+"InnoDB: Error: could not extend the tablespace of %s\n"
+"InnoDB: to the size stored in header, %lu pages;\n"
+"InnoDB: size after extension %lu pages\n"
+"InnoDB: Check that you have free disk space and retry!\n", space->name,
+ size_in_header, actual_size);
+ exit(1);
+ }
- success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC,
- node->name, node->handle, buf,
- UNIV_PAGE_SIZE * size, 0,
- UNIV_PAGE_SIZE * (size_after_extend - size),
- NULL, NULL);
- if (success) {
- node->size = size_after_extend;
- space->size = size_after_extend;
+ mutex_enter(&(system->mutex));
- os_has_said_disk_full = FALSE;
+ space = UT_LIST_GET_NEXT(space_list, space);
}
- mem_free(buf2);
-
- fil_node_complete_io(node, system, OS_FILE_WRITE);
-
- mutex_exit(&(system->mutex));
-
- fil_flush(space_id);
+ mutex_exit(&(system->mutex));
- return(success);
+ mem_free(buf);
}
+#endif
/*========== RESERVE FREE EXTENTS (for a B-tree split, for example) ===*/
@@ -3123,12 +3577,23 @@ fil_io(
/* Do aio */
- ut_anp(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
- ut_anp((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
+ ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
+#ifdef UNIV_HOTBACKUP
+ /* In ibbackup do normal i/o, not aio */
+ if (type == OS_FILE_READ) {
+ ret = os_file_read(node->handle, buf, offset_low, offset_high,
+ len);
+ } else {
+ ret = os_file_write(node->name, node->handle, buf,
+ offset_low, offset_high, len);
+ }
+#else
/* Queue the aio request */
ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
offset_low, offset_high, len, node, message);
+#endif
ut_a(ret);
if (mode == OS_AIO_SYNC) {
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index 7c4d691ea13..8ceea03f34a 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -27,6 +27,10 @@ Created 11/29/1995 Heikki Tuuri
#include "dict0mem.h"
#include "log0log.h"
+
+#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header
+ within a file page */
+
/* The data structures in files are defined just as byte strings in C */
typedef byte fsp_header_t;
typedef byte xdes_t;
@@ -38,8 +42,6 @@ File space header data structure: this data structure is contained in the
first page of a space. The space for this header is reserved in every extent
descriptor page, but used only in the first. */
-#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header
- within a file page */
/*-------------------------------------*/
#define FSP_SPACE_ID 0 /* space id */
#define FSP_NOT_USED 4 /* this field contained a value up to
@@ -90,7 +92,6 @@ descriptor page, but used only in the first. */
#define FSP_FREE_ADD 4 /* this many free extents are added
to the free list from above
FSP_FREE_LIMIT at a time */
-
/* FILE SEGMENT INODE
==================
@@ -298,6 +299,19 @@ fseg_alloc_free_page_low(
FSP_UP, FSP_NO_DIR */
mtr_t* mtr); /* in: mtr handle */
+
+/**************************************************************************
+Reads the file space size stored in the header page. */
+
+ulint
+fsp_get_size_low(
+/*=============*/
+ /* out: tablespace size stored in the space header */
+ page_t* page) /* in: header page (page 0 in the tablespace) */
+{
+ return(mach_read_from_4(page + FSP_HEADER_OFFSET + FSP_SIZE));
+}
+
/**************************************************************************
Gets a pointer to the space header and x-locks its page. */
UNIV_INLINE
@@ -1034,8 +1048,9 @@ fsp_try_extend_data_file_with_pages(
fsp_header_t* header, /* in: space header */
mtr_t* mtr) /* in: mtr */
{
- ulint size;
ibool success;
+ ulint actual_size;
+ ulint size;
ut_a(space != 0);
@@ -1043,12 +1058,12 @@ fsp_try_extend_data_file_with_pages(
ut_a(page_no >= size);
- success = fil_extend_data_file_with_pages(space, size, page_no + 1);
-
- if (success) {
- mlog_write_ulint(header + FSP_SIZE, page_no + 1, MLOG_4BYTES,
- mtr);
- }
+ success = fil_extend_space_to_desired_size(&actual_size, space,
+ page_no + 1);
+ /* actual_size now has the space size in pages; it may be less than
+ we wanted if we ran out of disk space */
+
+ mlog_write_ulint(header + FSP_SIZE, actual_size, MLOG_4BYTES, mtr);
return(success);
}
@@ -1060,13 +1075,20 @@ ibool
fsp_try_extend_data_file(
/*=====================*/
/* out: FALSE if not auto-extending */
- ulint* actual_increase,/* out: actual increase in pages */
+ ulint* actual_increase,/* out: actual increase in pages, where
+ we measure the tablespace size from
+ what the header field says; it may be
+ the actual file size rounded down to
+ megabyte */
ulint space, /* in: space */
fsp_header_t* header, /* in: space header */
mtr_t* mtr) /* in: mtr */
{
ulint size;
+ ulint new_size;
+ ulint old_size;
ulint size_increase;
+ ulint actual_size;
ibool success;
*actual_increase = 0;
@@ -1078,6 +1100,8 @@ fsp_try_extend_data_file(
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
+ old_size = size;
+
if (space == 0 && srv_last_file_size_max != 0) {
if (srv_last_file_size_max
< srv_data_file_sizes[srv_n_data_files - 1]) {
@@ -1107,8 +1131,12 @@ fsp_try_extend_data_file(
success = fsp_try_extend_data_file_with_pages(
space, FSP_EXTENT_SIZE - 1,
header, mtr);
-
if (!success) {
+ new_size = mtr_read_ulint(
+ header + FSP_SIZE, MLOG_4BYTES, mtr);
+
+ *actual_increase = new_size - old_size;
+
return(FALSE);
}
@@ -1118,7 +1146,10 @@ fsp_try_extend_data_file(
if (size < 32 * FSP_EXTENT_SIZE) {
size_increase = FSP_EXTENT_SIZE;
} else {
- size_increase = 8 * FSP_EXTENT_SIZE;
+ /* Below in fsp_fill_free_list() we assume
+ that we add at most FSP_FREE_ADD extents at
+ a time */
+ size_increase = FSP_FREE_ADD * FSP_EXTENT_SIZE;
}
}
}
@@ -1128,18 +1159,17 @@ fsp_try_extend_data_file(
return(TRUE);
}
- /* Extend the data file. If we are not able to extend the full
- requested length, the function tells how many pages we were able to
- extend so that the size of the tablespace would be divisible by 1 MB
- (we possibly managed to extend more, but we only take into account
- full megabytes). */
-
- success = fil_extend_last_data_file(actual_increase, space, size,
- size_increase);
- if (success) {
- mlog_write_ulint(header + FSP_SIZE, size + *actual_increase,
+ success = fil_extend_space_to_desired_size(&actual_size, space,
+ size + size_increase);
+ /* We ignore any fragments of a full megabyte when storing the size
+ to the space header */
+
+ mlog_write_ulint(header + FSP_SIZE,
+ ut_calc_align_down(actual_size, (1024 * 1024) / UNIV_PAGE_SIZE),
MLOG_4BYTES, mtr);
- }
+ new_size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
+
+ *actual_increase = new_size - old_size;
return(TRUE);
}
@@ -1186,8 +1216,10 @@ fsp_fill_free_list(
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
}
- if (space != 0 && !init_space) {
- /* Try to increase the data file size */
+ if (space != 0 && !init_space
+ && size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
+
+ /* Try to increase the .ibd file size */
fsp_try_extend_data_file(&actual_increase, space, header, mtr);
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, mtr);
}
@@ -1222,7 +1254,7 @@ fsp_fill_free_list(
fsp_init_file_page(descr_page, mtr);
}
- /* Initialize the ibuf page in a separate
+ /* Initialize the ibuf bitmap page in a separate
mini-transaction because it is low in the latching
order, and we must be able to release its latch
before returning from the fsp routine */
@@ -1797,7 +1829,7 @@ fsp_free_seg_inode(
flst_remove(space_header + FSP_SEG_INODES_FREE,
page + FSEG_INODE_PAGE_NODE, mtr);
- fsp_free_page(space, buf_frame_get_page_no(page), mtr);
+ fsp_free_page(space, buf_frame_get_page_no(page), mtr);
}
}
@@ -3157,7 +3189,7 @@ fseg_free_step(
freed yet */
ut_a(descr);
- ut_anp(xdes_get_bit(descr, XDES_FREE_BIT, buf_frame_get_page_no(header)
+ ut_a(xdes_get_bit(descr, XDES_FREE_BIT, buf_frame_get_page_no(header)
% FSP_EXTENT_SIZE, mtr) == FALSE);
inode = fseg_inode_get(header, mtr);
diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h
index 506bc6c1870..0ed012c489a 100644
--- a/innobase/include/fil0fil.h
+++ b/innobase/include/fil0fil.h
@@ -16,6 +16,14 @@ Created 10/25/1995 Heikki Tuuri
#include "ut0byte.h"
#include "os0file.h"
+/* When mysqld is run, the default directory "." is the mysqld datadir, but in
+ibbackup we must set it explicitly; the patgh must NOT contain the trailing
+'/' or '\' */
+extern char* fil_path_to_mysql_datadir;
+
+/* Initial size of a single-table tablespace in pages */
+#define FIL_IBD_FILE_INITIAL_SIZE 4
+
/* 'null' (undefined) page offset in the context of file spaces */
#define FIL_NULL ULINT32_UNDEFINED
@@ -261,6 +269,35 @@ fil_decr_pending_ibuf_merges(
/*========================*/
ulint id); /* in: space id */
/***********************************************************************
+Parses the body of a log record written about an .ibd file operation. That is,
+the log record part after the standard (type, space id, page no) header of the
+log record.
+
+If desired, also replays the delete or rename operation if the .ibd file
+exists and the space id in it matches. Replays the create operation if a file
+at that path does not exist yet. If the database directory for the file to be
+created does not exist, then we create the directory, too.
+
+Note that ibbackup --apply-log sets fil_path_to_mysql_datadir to point to the
+datadir that we should use in replaying the file operations. */
+
+byte*
+fil_op_log_parse_or_replay(
+/*=======================*/
+ /* out: end of log record, or NULL if the
+ record was not completely contained between
+ ptr and end_ptr */
+ byte* ptr, /* in: buffer containing the log record body,
+ or an initial segment of it, if the record does
+ not fir completely between ptr and end_ptr */
+ byte* end_ptr, /* in: buffer end */
+ ulint type, /* in: the type of this log record */
+ ibool do_replay, /* in: TRUE if we want to replay the
+ operation, and not just parse the log record */
+ ulint space_id); /* in: if do_replay is TRUE, the space id of
+ the tablespace in question; otherwise
+ ignored */
+/***********************************************************************
Deletes a single-table tablespace. The tablespace must be cached in the
memory cache. */
@@ -306,16 +343,18 @@ ulint
fil_create_new_single_table_tablespace(
/*===================================*/
/* out: DB_SUCCESS or error code */
- ulint* space_id, /* out: space id */
+ ulint* space_id, /* in/out: space id; if this is != 0, then
+ this is an input parameter, otherwise
+ output */
char* tablename, /* in: the table name in the usual
databasename/tablename format of InnoDB */
ulint size); /* in: the initial size of the tablespace file
- in pages */
+ in pages, must be > 0 */
/************************************************************************
Tries to open a single-table tablespace and checks the space id is right in
it. If does not succeed, prints an error message to the .err log. This
function is used to open the tablespace when we load a table definition
-to the dictionarky cache. NOTE that we assume this operation is used under the
+to the dictionary cache. NOTE that we assume this operation is used under the
protection of the dictionary mutex, so that two users cannot race here. */
ibool
@@ -410,39 +449,32 @@ fil_space_for_table_exists_in_mem(
the .err log if a matching tablespace is
not found from memory */
/**************************************************************************
-Tries to extend a data file by the number of pages given. Fractions of 1 MB
-are ignored. The tablespace must be cached in the memory cache. */
-
-ibool
-fil_extend_last_data_file(
-/*======================*/
- /* out: TRUE if success, also if we run
- out of disk space we may return TRUE */
- ulint* actual_increase,/* out: number of pages we were able to
- extend, here the original size of the file and
- the resulting size of the file are rounded
- downwards to a full megabyte, and the
- difference expressed in pages is returned */
- ulint space_id, /* in: space id */
- ulint size, /* in: current size of the space in pages, as
- stored in the fsp header */
- ulint size_increase); /* in: try to extend this many pages */
-/**************************************************************************
Tries to extend a data file so that it would accommodate the number of pages
-given. The tablespace must be cached in the memory cache. */
+given. The tablespace must be cached in the memory cache. If the space is big
+enough already, does nothing. */
ibool
-fil_extend_data_file_with_pages(
-/*============================*/
+fil_extend_space_to_desired_size(
+/*=============================*/
/* out: TRUE if success */
+ ulint* actual_size, /* out: size of the space after extension;
+ if we ran out of disk space this may be lower
+ than the desired size */
ulint space_id, /* in: space id, must be != 0 */
- ulint size, /* in: current size of the space in pages, as
- stored in the fsp header */
ulint size_after_extend);/* in: desired size in pages after the
- extension, should be less than 4 GB (this
- function is primarily intended for increasing
- the data file size from < 64 pages to up to
- 64 pages) */
+ extension; if the current space size is bigger
+ than this already, the function does nothing */
+#ifdef UNIV_HOTBACKUP
+/************************************************************************
+Extends all tablespaces to the size stored in the space header. During the
+ibbackup --apply-log phase we extended the spaces on-demand so that log records
+could be appllied, but that may have left spaces still too small compared to
+the size stored in the space header. */
+
+void
+fil_extend_tablespaces_to_stored_len(void);
+/*======================================*/
+#endif
/***********************************************************************
Tries to reserve free extents in a file space. */
diff --git a/innobase/include/fsp0fsp.h b/innobase/include/fsp0fsp.h
index 127e01ef59f..2fcde882df7 100644
--- a/innobase/include/fsp0fsp.h
+++ b/innobase/include/fsp0fsp.h
@@ -67,6 +67,14 @@ fsp_header_get_tablespace_size(
/* out: size in pages */
ulint space); /* in: space id, must be 0 */
/**************************************************************************
+Reads the file space size stored in the header page. */
+
+ulint
+fsp_get_size_low(
+/*=============*/
+ /* out: tablespace size stored in the space header */
+ page_t* page); /* in: header page (page 0 in the tablespace) */
+/**************************************************************************
Reads the space id from the first page of a tablespace. */
ulint
diff --git a/innobase/include/ha0ha.ic b/innobase/include/ha0ha.ic
index 22da7107659..77064cdf9da 100644
--- a/innobase/include/ha0ha.ic
+++ b/innobase/include/ha0ha.ic
@@ -51,8 +51,6 @@ ha_chain_get_next(
/* out: next node, NULL if none */
ha_node_t* node) /* in: hash chain node */
{
- ut_ad(table);
-
return(node->next);
}
@@ -144,8 +142,6 @@ ha_next(
fold = node->fold;
- ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
-
node = ha_chain_get_next(node);
while (node) {
diff --git a/innobase/include/log0recv.h b/innobase/include/log0recv.h
index 0a4f56816a1..5991960e8ae 100644
--- a/innobase/include/log0recv.h
+++ b/innobase/include/log0recv.h
@@ -175,17 +175,14 @@ recv_apply_hashed_log_recs(
disk and invalidated in buffer pool: this
alternative means that no new log records
can be generated during the application */
+#ifdef UNIV_HOTBACKUP
/***********************************************************************
Applies log records in the hash table to a backup. */
void
-recv_apply_log_recs_for_backup(
-/*===========================*/
- ulint n_data_files, /* in: number of data files */
- char** data_files, /* in: array containing the paths to the
- data files */
- ulint* file_sizes); /* in: sizes of the data files in database
- pages */
+recv_apply_log_recs_for_backup(void);
+/*================================*/
+#endif
/************************************************************
Recovers from archived log files, and also from log files, if they exist. */
diff --git a/innobase/include/mtr0log.h b/innobase/include/mtr0log.h
index acbf87df447..da942dd45d7 100644
--- a/innobase/include/mtr0log.h
+++ b/innobase/include/mtr0log.h
@@ -58,6 +58,19 @@ mlog_write_initial_log_record(
byte type, /* in: log item type: MLOG_1BYTE, ... */
mtr_t* mtr); /* in: mini-transaction handle */
/************************************************************
+Writes a log record about an .ibd file create/delete/rename. */
+UNIV_INLINE
+byte*
+mlog_write_initial_log_record_for_file_op(
+/*======================================*/
+ /* out: new value of log_ptr */
+ ulint type, /* in: MLOG_FILE_CREATE, MLOG_FILE_DELETE, or
+ MLOG_FILE_RENAME */
+ ulint space_id,/* in: space id, if applicable */
+ ulint page_no,/* in: page number (not relevant currently) */
+ byte* log_ptr,/* in: pointer to mtr log which has been opened */
+ mtr_t* mtr); /* in: mtr */
+/************************************************************
Catenates 1 - 4 bytes to the mtr log. */
UNIV_INLINE
void
diff --git a/innobase/include/mtr0log.ic b/innobase/include/mtr0log.ic
index c2150660794..60a5b390be9 100644
--- a/innobase/include/mtr0log.ic
+++ b/innobase/include/mtr0log.ic
@@ -185,3 +185,31 @@ mlog_write_initial_log_record_fast(
#endif
return(log_ptr);
}
+
+/************************************************************
+Writes a log record about an .ibd file create/delete/rename. */
+UNIV_INLINE
+byte*
+mlog_write_initial_log_record_for_file_op(
+/*======================================*/
+ /* out: new value of log_ptr */
+ ulint type, /* in: MLOG_FILE_CREATE, MLOG_FILE_DELETE, or
+ MLOG_FILE_RENAME */
+ ulint space_id,/* in: space id, if applicable */
+ ulint page_no,/* in: page number (not relevant currently) */
+ byte* log_ptr,/* in: pointer to mtr log which has been opened */
+ mtr_t* mtr) /* in: mtr */
+{
+ ut_ad(log_ptr);
+
+ mach_write_to_1(log_ptr, type);
+ log_ptr++;
+
+ /* We write dummy space id and page number */
+ log_ptr += mach_write_compressed(log_ptr, space_id);
+ log_ptr += mach_write_compressed(log_ptr, page_no);
+
+ mtr->n_log_recs++;
+
+ return(log_ptr);
+}
diff --git a/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h
index 0ef25b3d1ee..c47fb54a6f8 100644
--- a/innobase/include/mtr0mtr.h
+++ b/innobase/include/mtr0mtr.h
@@ -96,7 +96,13 @@ flag value must give the length also! */
sequence of these records */
#define MLOG_DUMMY_RECORD ((byte)32) /* dummy log record used to
pad a log block full */
-#define MLOG_BIGGEST_TYPE ((byte)32) /* biggest value (used in
+#define MLOG_FILE_CREATE ((byte)33) /* log record about an .ibd
+ file creation */
+#define MLOG_FILE_RENAME ((byte)34) /* log record about an .ibd
+ file rename */
+#define MLOG_FILE_DELETE ((byte)35) /* log record about an .ibd
+ file deletion */
+#define MLOG_BIGGEST_TYPE ((byte)35) /* biggest value (used in
asserts) */
/*******************************************************************
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index d1dc9dea18b..4a9fae90f07 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -63,6 +63,7 @@ log. */
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
+#define OS_FILE_READ_ALLOW_DELETE 555 /* for ibbackup */
/* Options for file_create */
#define OS_FILE_AIO 61
@@ -199,6 +200,21 @@ os_file_readdir_next_file(
char* dirname,/* in: directory name or path */
os_file_dir_t dir, /* in: directory stream */
os_file_stat_t* info); /* in/out: buffer where the info is returned */
+/*********************************************************************
+This function attempts to create a directory named pathname. The new directory
+gets default permissions. On Unix, the permissions are (0770 & ~umask). If the
+directory exists already, nothing is done and the call succeeds, unless the
+fail_if_exists arguments is true. */
+
+ibool
+os_file_create_directory(
+/*=====================*/
+ /* out: TRUE if call succeeds, FALSE on
+ error */
+ char* pathname, /* in: directory name as null-terminated
+ string */
+ ibool fail_if_exists);/* in: if TRUE, pre-existing directory is
+ treated as an error. */
/********************************************************************
A simple function to open or create a file. */
@@ -206,7 +222,8 @@ os_file_t
os_file_create_simple(
/*==================*/
/* out, own: handle to the file, not defined if error,
- error number can be retrieved with os_get_last_error */
+ error number can be retrieved with
+ os_file_get_last_error */
char* name, /* in: name of the file or path as a null-terminated
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
@@ -221,13 +238,16 @@ os_file_t
os_file_create_simple_no_error_handling(
/*====================================*/
/* out, own: handle to the file, not defined if error,
- error number can be retrieved with os_get_last_error */
+ error number can be retrieved with
+ os_file_get_last_error */
char* name, /* in: name of the file or path as a null-terminated
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
(if does not exist, error), or OS_FILE_CREATE if a new
file is created (if exists, error) */
- ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
+ ulint access_type,/* in: OS_FILE_READ_ONLY, OS_FILE_READ_WRITE, or
+ OS_FILE_READ_ALLOW_DELETE; the last option is used by
+ a backup program reading the file */
ibool* success);/* out: TRUE if succeed, FALSE if error */
/********************************************************************
Opens an existing file or creates a new. */
@@ -236,7 +256,8 @@ os_file_t
os_file_create(
/*===========*/
/* out, own: handle to the file, not defined if error,
- error number can be retrieved with os_get_last_error */
+ error number can be retrieved with
+ os_file_get_last_error */
char* name, /* in: name of the file or path as a null-terminated
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h
index 802557099fc..fd543dc5649 100644
--- a/innobase/include/ut0dbg.h
+++ b/innobase/include/ut0dbg.h
@@ -30,39 +30,8 @@ extern ulint* ut_dbg_null_ptr;
" InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
os_thread_pf(os_thread_get_curr_id()), IB__FILE__,\
(ulint)__LINE__);\
- fprintf(stderr,\
- "InnoDB: Failing assertion: " #EXPR);\
- fprintf(stderr,\
- "\nInnoDB: We intentionally generate a memory trap.\n");\
- fprintf(stderr,\
- "InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n");\
- ut_dbg_stop_threads = TRUE;\
- dbg_i = *(ut_dbg_null_ptr);\
- if (dbg_i) {\
- ut_dbg_null_ptr = NULL;\
- }\
- }\
- if (ut_dbg_stop_threads) {\
- fprintf(stderr,\
- "InnoDB: Thread %lu stopped in file %s line %lu\n",\
- os_thread_pf(os_thread_get_curr_id()), IB__FILE__, (ulint)__LINE__);\
- os_thread_sleep(1000000000);\
- }\
-}
-
-/* This can be used if there are % characters in the assertion formula:
-if we try to printf the formula gcc would complain of illegal print
-format characters */
-#define ut_anp(EXPR)\
-{\
- ulint dbg_i;\
-\
- if (!((ulint)(EXPR) + ut_dbg_zero)) {\
- ut_print_timestamp(stderr);\
- fprintf(stderr,\
- " InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
- os_thread_pf(os_thread_get_curr_id()), IB__FILE__,\
- (ulint)__LINE__);\
+ fputs(\
+ "InnoDB: Failing assertion: " #EXPR, stderr);\
fprintf(stderr,\
"\nInnoDB: We intentionally generate a memory trap.\n");\
fprintf(stderr,\
diff --git a/innobase/include/ut0ut.h b/innobase/include/ut0ut.h
index 8ec23b23dcd..6a45d438a7f 100644
--- a/innobase/include/ut0ut.h
+++ b/innobase/include/ut0ut.h
@@ -139,7 +139,7 @@ void
ut_ulint_sort(ulint* arr, ulint* aux_arr, ulint low, ulint high);
/*============================================================*/
/************************************************************
-The following function returns a clock time in milliseconds. */
+The following function returns elapsed CPU time in milliseconds. */
ulint
ut_clock(void);
@@ -174,6 +174,14 @@ ut_sprintf_timestamp(
/*=================*/
char* buf); /* in: buffer where to sprintf */
/**************************************************************
+Sprintfs a timestamp to a buffer with no spaces and with ':' characters
+replaced by '_'. */
+
+void
+ut_sprintf_timestamp_without_extra_chars(
+/*=====================================*/
+ char* buf); /* in: buffer where to sprintf */
+/**************************************************************
Returns current year, month, day. */
void
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index 62c1dea0d41..d3309815998 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -95,14 +95,6 @@ static
void
log_io_complete_archive(void);
/*=========================*/
-/********************************************************************
-Tries to establish a big enough margin of free space in the log groups, such
-that a new log entry can be catenated without an immediate need for a
-archiving. */
-static
-void
-log_archive_margin(void);
-/*====================*/
/********************************************************************
Sets the global variable log_fsp_current_free_limit. Also makes a checkpoint,
@@ -407,7 +399,7 @@ log_pad_current_log_block(void)
log_close();
log_release();
- ut_anp((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
+ ut_a((ut_dulint_get_low(lsn) % OS_FILE_LOG_BLOCK_SIZE)
== LOG_BLOCK_HDR_SIZE);
}
@@ -745,7 +737,8 @@ log_init(void)
memset(log_sys->checkpoint_buf, '\0', OS_FILE_LOG_BLOCK_SIZE);
/*----------------------------*/
- log_sys->archiving_state = LOG_ARCH_ON;
+ /* Under MySQL, log archiving is always off */
+ log_sys->archiving_state = LOG_ARCH_OFF;
log_sys->archived_lsn = log_sys->lsn;
log_sys->next_archived_lsn = ut_dulint_zero;
@@ -754,13 +747,15 @@ log_init(void)
rw_lock_create(&(log_sys->archive_lock));
rw_lock_set_level(&(log_sys->archive_lock), SYNC_NO_ORDER_CHECK);
- log_sys->archive_buf = ut_align(
+ log_sys->archive_buf = NULL;
+
+ /* ut_align(
ut_malloc(LOG_ARCHIVE_BUF_SIZE
+ OS_FILE_LOG_BLOCK_SIZE),
- OS_FILE_LOG_BLOCK_SIZE);
- log_sys->archive_buf_size = LOG_ARCHIVE_BUF_SIZE;
+ OS_FILE_LOG_BLOCK_SIZE); */
+ log_sys->archive_buf_size = 0;
- memset(log_sys->archive_buf, '\0', LOG_ARCHIVE_BUF_SIZE);
+ /* memset(log_sys->archive_buf, '\0', LOG_ARCHIVE_BUF_SIZE); */
log_sys->archiving_on = os_event_create(NULL);
@@ -1107,8 +1102,8 @@ log_group_write_buf(
ulint i;
ut_ad(mutex_own(&(log_sys->mutex)));
- ut_anp(len % OS_FILE_LOG_BLOCK_SIZE == 0);
- ut_anp(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_a(len % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
if (new_data_offset == 0) {
write_header = TRUE;
@@ -2080,6 +2075,8 @@ log_archived_file_name_gen(
ulint id, /* in: group id */
ulint file_no)/* in: file number */
{
+ ut_a(0);
+
UT_NOT_USED(id); /* Currently we only archive the first group */
sprintf(buf, "%sib_arch_log_%010lu", srv_arch_dir, file_no);
@@ -2101,6 +2098,8 @@ log_group_archive_file_header_write(
byte* buf;
ulint dest_offset;
+ ut_a(0);
+
ut_ad(mutex_own(&(log_sys->mutex)));
ut_a(nth_file < group->n_files);
@@ -2138,6 +2137,8 @@ log_group_archive_completed_header_write(
byte* buf;
ulint dest_offset;
+ ut_a(0);
+
ut_ad(mutex_own(&(log_sys->mutex)));
ut_a(nth_file < group->n_files);
@@ -2177,15 +2178,17 @@ log_group_archive(
ulint n_files;
ulint open_mode;
+ ut_a(0);
+
ut_ad(mutex_own(&(log_sys->mutex)));
start_lsn = log_sys->archived_lsn;
- ut_anp(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_a(ut_dulint_get_low(start_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
end_lsn = log_sys->next_archived_lsn;
- ut_anp(ut_dulint_get_low(end_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_a(ut_dulint_get_low(end_lsn) % OS_FILE_LOG_BLOCK_SIZE == 0);
buf = log_sys->archive_buf;
@@ -2289,7 +2292,7 @@ loop:
group->next_archived_file_no = group->archived_file_no + n_files;
group->next_archived_offset = next_offset % group->file_size;
- ut_anp(group->next_archived_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_a(group->next_archived_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
}
/*********************************************************
@@ -2302,6 +2305,8 @@ log_archive_groups(void)
{
log_group_t* group;
+ ut_a(0);
+
ut_ad(mutex_own(&(log_sys->mutex)));
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -2325,6 +2330,8 @@ log_archive_write_complete_groups(void)
dulint end_lsn;
ulint i;
+ ut_a(0);
+
ut_ad(mutex_own(&(log_sys->mutex)));
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -2387,6 +2394,8 @@ void
log_archive_check_completion_low(void)
/*==================================*/
{
+ ut_a(0);
+
ut_ad(mutex_own(&(log_sys->mutex)));
if (log_sys->n_pending_archive_ios == 0
@@ -2423,6 +2432,8 @@ log_io_complete_archive(void)
{
log_group_t* group;
+ ut_a(0);
+
mutex_enter(&(log_sys->mutex));
group = UT_LIST_GET_FIRST(log_sys->log_groups);
@@ -2458,6 +2469,8 @@ log_archive_do(
dulint start_lsn;
dulint limit_lsn;
+ ut_a(0);
+
calc_new_limit = TRUE;
loop:
mutex_enter(&(log_sys->mutex));
@@ -2484,7 +2497,7 @@ loop:
start_lsn = log_sys->archived_lsn;
if (calc_new_limit) {
- ut_anp(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE
+ ut_a(log_sys->archive_buf_size % OS_FILE_LOG_BLOCK_SIZE
== 0);
limit_lsn = ut_dulint_add(start_lsn,
log_sys->archive_buf_size);
@@ -2584,6 +2597,8 @@ log_archive_all(void)
return;
}
+ ut_a(0);
+
present_lsn = log_sys->lsn;
mutex_exit(&(log_sys->mutex));
@@ -2621,11 +2636,17 @@ log_archive_close_groups(
ut_ad(mutex_own(&(log_sys->mutex)));
+ if (log_sys->archiving_state == LOG_ARCH_OFF) {
+
+ return;
+ }
+
+ ut_a(0);
+
group = UT_LIST_GET_FIRST(log_sys->log_groups);
trunc_len = UNIV_PAGE_SIZE
* fil_space_get_size(group->archive_space_id);
-
if (trunc_len > 0) {
ut_a(trunc_len == group->file_size);
@@ -2653,17 +2674,18 @@ log_archive_close_groups(
/********************************************************************
Writes the log contents to the archive up to the lsn when this function was
called, and stops the archiving. When archiving is started again, the archived
-log file numbers start from 2 higher, so that the archiving will
-not write again to the archived log files which exist when this function
-returns. */
+log file numbers start from 2 higher, so that the archiving will not write
+again to the archived log files which exist when this function returns. */
ulint
log_archive_stop(void)
/*==================*/
- /* out: DB_SUCCESS or DB_ERROR */
+ /* out: DB_SUCCESS or DB_ERROR */
{
ibool success;
+ ut_a(0);
+
mutex_enter(&(log_sys->mutex));
if (log_sys->archiving_state != LOG_ARCH_ON) {
@@ -2676,7 +2698,7 @@ log_archive_stop(void)
log_sys->archiving_state = LOG_ARCH_STOPPING;
mutex_exit(&(log_sys->mutex));
-
+
log_archive_all();
mutex_enter(&(log_sys->mutex));
@@ -2697,7 +2719,7 @@ log_archive_stop(void)
if appropriate */
log_archive_close_groups(TRUE);
-
+
mutex_exit(&(log_sys->mutex));
/* Make a checkpoint, so that if recovery is needed, the file numbers
@@ -2726,6 +2748,8 @@ log_archive_start(void)
/*===================*/
/* out: DB_SUCCESS or DB_ERROR */
{
+ ut_a(0);
+
mutex_enter(&(log_sys->mutex));
if (log_sys->archiving_state != LOG_ARCH_STOPPED) {
@@ -2752,6 +2776,7 @@ log_archive_noarchivelog(void)
/*==========================*/
/* out: DB_SUCCESS or DB_ERROR */
{
+ ut_a(0);
loop:
mutex_enter(&(log_sys->mutex));
@@ -2784,6 +2809,7 @@ log_archive_archivelog(void)
/*========================*/
/* out: DB_SUCCESS or DB_ERROR */
{
+ ut_a(0);
mutex_enter(&(log_sys->mutex));
if (log_sys->archiving_state == LOG_ARCH_OFF) {
@@ -2791,7 +2817,7 @@ log_archive_archivelog(void)
log_sys->archiving_state = LOG_ARCH_ON;
log_sys->archived_lsn = ut_dulint_align_down(log_sys->lsn,
- OS_FILE_LOG_BLOCK_SIZE);
+ OS_FILE_LOG_BLOCK_SIZE);
mutex_exit(&(log_sys->mutex));
return(DB_SUCCESS);
@@ -2802,6 +2828,7 @@ log_archive_archivelog(void)
return(DB_ERROR);
}
+#ifdef notdefined
/********************************************************************
Tries to establish a big enough margin of free space in the log groups, such
that a new log entry can be catenated without an immediate need for
@@ -2855,6 +2882,7 @@ loop:
goto loop;
}
}
+#endif
/************************************************************************
Checks that there is enough free space in the log to start a new query step.
@@ -2871,7 +2899,7 @@ loop:
log_checkpoint_margin();
- log_archive_margin();
+ /* log_archive_margin(); */
mutex_enter(&(log_sys->mutex));
@@ -3009,7 +3037,7 @@ loop:
goto loop;
}
- log_archive_all();
+ /* log_archive_all(); */
log_make_checkpoint_at(ut_dulint_max, TRUE);
mutex_enter(&(log_sys->mutex));
@@ -3027,15 +3055,16 @@ loop:
goto loop;
}
- arch_log_no =
+ arch_log_no = 0;
+/*
UT_LIST_GET_FIRST(log_sys->log_groups)->archived_file_no;
if (0 == UT_LIST_GET_FIRST(log_sys->log_groups)->archived_offset) {
arch_log_no--;
}
-
- log_archive_close_groups(TRUE);
+*/
+ /* log_archive_close_groups(TRUE); */
mutex_exit(&(log_sys->mutex));
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index cf9e3c89559..942dde78e35 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -721,7 +721,7 @@ recv_scan_log_seg_for_backup(
/***********************************************************************
Tries to parse a single log record body and also applies it to a page if
-specified. */
+specified. File ops are parsed, but not applied in this function. */
static
byte*
recv_parse_or_apply_log_rec_body(
@@ -798,8 +798,14 @@ recv_parse_or_apply_log_rec_body(
} else if (type == MLOG_INIT_FILE_PAGE) {
new_ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
- } else if (type <= MLOG_WRITE_STRING) {
+ } else if (type == MLOG_WRITE_STRING) {
new_ptr = mlog_parse_string(ptr, end_ptr, page);
+
+ } else if (type == MLOG_FILE_CREATE
+ || type == MLOG_FILE_RENAME
+ || type == MLOG_FILE_DELETE) {
+ new_ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
+ ULINT_UNDEFINED);
} else {
new_ptr = NULL;
@@ -1322,7 +1328,6 @@ loop:
fprintf(stderr, "%lu ",
(i * 100) / hash_get_n_cells(recv_sys->addr_hash));
-
}
}
@@ -1376,130 +1381,132 @@ loop:
}
#ifdef UNIV_HOTBACKUP
+/* This page is allocated from the buffer pool and used in the function
+below */
+page_t* recv_backup_application_page = NULL;
+
/***********************************************************************
Applies log records in the hash table to a backup. */
void
-recv_apply_log_recs_for_backup(
-/*===========================*/
- ulint n_data_files, /* in: number of data files */
- char** data_files, /* in: array containing the paths to the
- data files */
- ulint* file_sizes) /* in: sizes of the data files in database
- pages */
+recv_apply_log_recs_for_backup(void)
+/*================================*/
{
recv_addr_t* recv_addr;
- os_file_t data_file;
- ulint n_pages_total = 0;
- ulint nth_file = 0;
- ulint nth_page_in_file= 0;
+ ulint n_hash_cells;
byte* page;
+ ulint actual_size;
ibool success;
+ ulint error;
ulint i;
recv_sys->apply_log_recs = TRUE;
recv_sys->apply_batch_on = TRUE;
- page = buf_pool->frame_zero;
-
- for (i = 0; i < n_data_files; i++) {
- n_pages_total += file_sizes[i];
+ if (recv_backup_application_page == NULL) {
+ recv_backup_application_page = buf_frame_alloc();
}
- if (recv_max_parsed_page_no >= n_pages_total) {
- printf(
-"InnoDB: Error: tablespace size %lu pages, but a log record on page %lu!\n"
-"InnoDB: Are you sure you have specified all the ibdata files right in\n"
-"InnoDB: the my.cnf file you gave as the argument to ibbackup --restore?\n",
- n_pages_total, recv_max_parsed_page_no);
- }
+ page = recv_backup_application_page;
printf(
"InnoDB: Starting an apply batch of log records to the database...\n"
"InnoDB: Progress in percents: ");
- for (i = 0; i < n_pages_total; i++) {
+ n_hash_cells = hash_get_n_cells(recv_sys->addr_hash);
- if (i == 0 || nth_page_in_file == file_sizes[nth_file]) {
- if (i != 0) {
- nth_file++;
- nth_page_in_file = 0;
- os_file_flush(data_file);
- os_file_close(data_file);
- }
+ for (i = 0; i < n_hash_cells; i++) {
+ /* The address hash table is externally chained */
+ recv_addr = hash_get_nth_cell(recv_sys->addr_hash, i)->node;
- data_file = os_file_create_simple(data_files[nth_file],
- OS_FILE_OPEN,
- OS_FILE_READ_WRITE,
- &success);
- if (!success) {
+ while (recv_addr != NULL) {
+
+ if (!fil_tablespace_exists_in_mem(recv_addr->space)) {
+/*
printf(
-"InnoDB: Error: cannot open %lu'th data file\n", nth_file);
+"InnoDB: Warning: cannot apply log record to tablespace %lu page %lu,\n"
+"InnoDB: because tablespace with that id does not exist.\n",
+ recv_addr->space, recv_addr->page_no);
+*/
+ recv_addr->state = RECV_PROCESSED;
- exit(1);
+ ut_a(recv_sys->n_addrs);
+ recv_sys->n_addrs--;
+
+ goto skip_this_recv_addr;
}
- }
-
- recv_addr = recv_get_fil_addr_struct(0, i);
-
- if (recv_addr != NULL) {
- success = os_file_read(data_file, page,
- (nth_page_in_file << UNIV_PAGE_SIZE_SHIFT)
- & 0xFFFFFFFFUL,
- nth_page_in_file >> (32 - UNIV_PAGE_SIZE_SHIFT),
- UNIV_PAGE_SIZE);
+
+ /* We simulate a page read made by the buffer pool, to
+ make sure the recovery apparatus works ok, for
+ example, the buf_frame_align() function. We must init
+ the block corresponding to buf_pool->frame_zero
+ (== page). */
+
+ buf_page_init_for_backup_restore(recv_addr->space,
+ recv_addr->page_no,
+ buf_block_align(page));
+
+ /* Extend the tablespace's last file if the page_no
+ does not fall inside its bounds; we assume the last
+ file is auto-extending, and ibbackup copied the file
+ when it still was smaller */
+
+ success = fil_extend_space_to_desired_size(
+ &actual_size,
+ recv_addr->space,
+ recv_addr->page_no + 1);
if (!success) {
printf(
-"InnoDB: Error: cannot read page no %lu from %lu'th data file\n",
- nth_page_in_file, nth_file);
+"InnoDB: Fatal error: cannot extend tablespace %lu to hold %lu pages\n",
+ recv_addr->space, recv_addr->page_no);
+
+ exit(1);
+ }
+ /* Read the page from the tablespace file using the
+ fil0fil.c routines */
+
+ error = fil_io(OS_FILE_READ, TRUE, recv_addr->space,
+ recv_addr->page_no, 0, UNIV_PAGE_SIZE,
+ page, NULL);
+ if (error != DB_SUCCESS) {
+ printf(
+"InnoDB: Fatal error: cannot read from tablespace %lu page number %lu\n",
+ recv_addr->space, recv_addr->page_no);
+
exit(1);
}
-
- /* We simulate a page read made by the buffer pool,
- to make sure recovery works ok. We must init the
- block corresponding to buf_pool->frame_zero
- (== page) */
- buf_page_init_for_backup_restore(0, i,
- buf_block_align(page));
+ /* Apply the log records to this page */
+ recv_recover_page(TRUE, FALSE, page, recv_addr->space,
+ recv_addr->page_no);
- recv_recover_page(TRUE, FALSE, page, 0, i);
+ /* Write the page back to the tablespace file using the
+ fil0fil.c routines */
buf_flush_init_for_writing(page,
mach_read_from_8(page + FIL_PAGE_LSN),
- 0, i);
-
- success = os_file_write(data_files[nth_file],
- data_file, page,
- (nth_page_in_file << UNIV_PAGE_SIZE_SHIFT)
- & 0xFFFFFFFF,
- nth_page_in_file >> (32 - UNIV_PAGE_SIZE_SHIFT),
- UNIV_PAGE_SIZE);
- if (!success) {
- printf(
-"InnoDB: Error: cannot write page no %lu to %lu'th data file\n",
- nth_page_in_file, nth_file);
+ recv_addr->space, recv_addr->page_no);
- exit(1);
- }
+ error = fil_io(OS_FILE_WRITE, TRUE, recv_addr->space,
+ recv_addr->page_no, 0, UNIV_PAGE_SIZE,
+ page, NULL);
+skip_this_recv_addr:
+ recv_addr = HASH_GET_NEXT(addr_hash, recv_addr);
}
- if ((100 * i) / n_pages_total
- != (100 * (i + 1)) / n_pages_total) {
- printf("%lu ", (100 * i) / n_pages_total);
+ if ((100 * i) / n_hash_cells
+ != (100 * (i + 1)) / n_hash_cells) {
+ printf("%lu ", (100 * i) / n_hash_cells);
fflush(stdout);
}
-
- nth_page_in_file++;
}
-
- os_file_flush(data_file);
- os_file_close(data_file);
recv_sys_empty_hash();
}
+#endif
+#ifdef notdefined
/***********************************************************************
In the debug version, updates the replica of a file page, based on a log
record. */
@@ -1737,7 +1744,7 @@ recv_parse_log_rec(
return(0);
}
- /* Check that space id and page_no are sensible */
+ /* Check that page_no is sensible */
if (*page_no > 0x8FFFFFFFUL) {
@@ -1911,12 +1918,16 @@ loop:
single_rec = (ulint)*ptr & MLOG_SINGLE_REC_FLAG;
if (single_rec || *ptr == MLOG_DUMMY_RECORD) {
- /* The mtr only modified a single page */
+ /* The mtr only modified a single page, or this is a file op */
old_lsn = recv_sys->recovered_lsn;
+ /* Try to parse a log record, fetching its type, space id,
+ page no, and a pointer to the body of the log record */
+
len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
&page_no, &body);
+
if (len == 0 || recv_sys->found_corrupt_log) {
if (recv_sys->found_corrupt_log) {
@@ -1954,6 +1965,26 @@ loop:
if (type == MLOG_DUMMY_RECORD) {
/* Do nothing */
+ } else if (store_to_hash && (type == MLOG_FILE_CREATE
+ || type == MLOG_FILE_RENAME
+ || type == MLOG_FILE_DELETE)) {
+#ifdef UNIV_HOTBACKUP
+ /* In ibbackup --apply-log, replay an .ibd file
+ operation, if possible; note that
+ fil_path_to_mysql_datadir is set in ibbackup to
+ point to the datadir we should use there */
+
+ if (NULL == fil_op_log_parse_or_replay(body, end_ptr,
+ type, TRUE, space)) {
+ fprintf(stderr,
+"InnoDB: Error: file op log record of type %lu space %lu not complete in\n"
+"InnoDB: the replay phase. Path %s\n", (ulint)type, space, (char*)(body + 2));
+
+ ut_a(0);
+ }
+#endif
+ /* In normal mysqld crash recovery we do not try to
+ replay file operations */
} else if (store_to_hash) {
recv_add_to_hash_table(type, space, page_no, body,
ptr + len, old_lsn,
@@ -2915,6 +2946,8 @@ recv_reset_log_files_for_backup(
buf = ut_malloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
+ memset(buf, LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE, '\0');
+
for (i = 0; i < n_log_files; i++) {
sprintf(name, "%sib_logfile%lu", log_dir, i);
@@ -2954,7 +2987,7 @@ recv_reset_log_files_for_backup(
log_block_init_in_old_format(buf + LOG_FILE_HDR_SIZE, lsn);
log_block_set_first_rec_group(buf + LOG_FILE_HDR_SIZE,
LOG_BLOCK_HDR_SIZE);
- sprintf(name, "%sib_logfile%lu", log_dir, 0);
+ sprintf(name, "%sib_logfile%lu", log_dir, 0UL);
log_file = os_file_create_simple(name, OS_FILE_OPEN,
OS_FILE_READ_WRITE, &success);
@@ -2996,6 +3029,8 @@ log_group_recover_from_archive_file(
int input_char;
char name[10000];
+ ut_a(0);
+
try_open_again:
buf = log_sys->buf;
@@ -3173,6 +3208,8 @@ recv_recovery_from_archive_start(
ibool ret;
ulint err;
+ ut_a(0);
+
recv_sys_create();
recv_sys_init(FALSE, buf_pool_get_curr_size());
@@ -3271,6 +3308,8 @@ void
recv_recovery_from_archive_finish(void)
/*===================================*/
{
+ ut_a(0);
+
recv_recovery_from_checkpoint_finish();
recv_recovery_from_backup_on = FALSE;
diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c
index 9b1aea089d1..274daae1d4e 100644
--- a/innobase/mem/mem0pool.c
+++ b/innobase/mem/mem0pool.c
@@ -603,7 +603,7 @@ mem_pool_validate(
}
}
- ut_anp(free + pool->reserved == pool->size);
+ ut_a(free + pool->reserved == pool->size);
mutex_exit(&(pool->mutex));
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 4b9289d2b93..37f64efb27f 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -595,6 +595,51 @@ next_file:
#endif
}
+/*********************************************************************
+This function attempts to create a directory named pathname. The new directory
+gets default permissions. On Unix the permissions are (0770 & ~umask). If the
+directory exists already, nothing is done and the call succeeds, unless the
+fail_if_exists arguments is true. */
+
+ibool
+os_file_create_directory(
+/*=====================*/
+ /* out: TRUE if call succeeds, FALSE on
+ error */
+ char* pathname, /* in: directory name as null-terminated
+ string */
+ ibool fail_if_exists) /* in: if TRUE, pre-existing directory is
+ treated as an error. */
+{
+#ifdef __WIN__
+ BOOL rcode;
+
+ rcode = CreateDirectory(pathname, NULL);
+ if (!(rcode != 0 ||
+ (GetLastError() == ERROR_FILE_EXISTS && !fail_if_exists))) {
+ /* failure */
+ os_file_handle_error(NULL, pathname, "CreateDirectory");
+
+ return(FALSE);
+ }
+
+ return (TRUE);
+#else
+ int rcode;
+
+ rcode = mkdir(pathname, 0770);
+
+ if (!(rcode == 0 || (errno == EEXIST && !fail_if_exists))) {
+ /* failure */
+ os_file_handle_error(0, pathname, "mkdir");
+
+ return(FALSE);
+ }
+
+ return (TRUE);
+#endif
+}
+
/********************************************************************
A simple function to open or create a file. */
@@ -602,7 +647,8 @@ os_file_t
os_file_create_simple(
/*==================*/
/* out, own: handle to the file, not defined if error,
- error number can be retrieved with os_get_last_error */
+ error number can be retrieved with
+ os_file_get_last_error */
char* name, /* in: name of the file or path as a null-terminated
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
@@ -714,13 +760,16 @@ os_file_t
os_file_create_simple_no_error_handling(
/*====================================*/
/* out, own: handle to the file, not defined if error,
- error number can be retrieved with os_get_last_error */
+ error number can be retrieved with
+ os_file_get_last_error */
char* name, /* in: name of the file or path as a null-terminated
string */
ulint create_mode,/* in: OS_FILE_OPEN if an existing file is opened
(if does not exist, error), or OS_FILE_CREATE if a new
file is created (if exists, error) */
- ulint access_type,/* in: OS_FILE_READ_ONLY or OS_FILE_READ_WRITE */
+ ulint access_type,/* in: OS_FILE_READ_ONLY, OS_FILE_READ_WRITE, or
+ OS_FILE_READ_ALLOW_DELETE; the last option is used by
+ a backup program reading the file */
ibool* success)/* out: TRUE if succeed, FALSE if error */
{
#ifdef __WIN__
@@ -728,6 +777,7 @@ os_file_create_simple_no_error_handling(
DWORD create_flag;
DWORD access;
DWORD attributes = 0;
+ DWORD share_mode = FILE_SHARE_READ;
ut_a(name);
@@ -744,6 +794,13 @@ os_file_create_simple_no_error_handling(
access = GENERIC_READ;
} else if (access_type == OS_FILE_READ_WRITE) {
access = GENERIC_READ | GENERIC_WRITE;
+ } else if (access_type == OS_FILE_READ_ALLOW_DELETE) {
+ access = GENERIC_READ;
+ share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ
+ | FILE_SHARE_WRITE; /* A backup program has to give
+ mysqld the maximum freedom to
+ do what it likes with the
+ file */
} else {
access = 0;
ut_error;
@@ -751,8 +808,7 @@ os_file_create_simple_no_error_handling(
file = CreateFile(name,
access,
- FILE_SHARE_READ,/* file can be read also by other
- processes */
+ share_mode,
NULL, /* default security attributes */
create_flag,
attributes,
@@ -808,7 +864,8 @@ os_file_t
os_file_create(
/*===========*/
/* out, own: handle to the file, not defined if error,
- error number can be retrieved with os_get_last_error */
+ error number can be retrieved with
+ os_file_get_last_error */
char* name, /* in: name of the file or path as a null-terminated
string */
ulint create_mode, /* in: OS_FILE_OPEN if an existing file is opened
@@ -896,7 +953,7 @@ try_again:
start 2 instances of mysqld on the
SAME files, that could cause severe
database corruption! When opening
- raw disk partitions Microsoft manuals
+ raw disk partitions, Microsoft manuals
say that we must give also the write
permission. */
NULL, /* default security attributes */
@@ -1017,6 +1074,10 @@ os_file_delete(
{
#ifdef __WIN__
BOOL ret;
+ ulint count = 0;
+loop:
+ /* In Windows, deleting an .ibd file may fail if ibbackup is copying
+ it */
ret = DeleteFile((LPCTSTR)name);
@@ -1024,9 +1085,31 @@ os_file_delete(
return(TRUE);
}
- os_file_handle_error(NULL, name, "delete");
+ if (GetLastError() == ERROR_PATH_NOT_FOUND) {
+ /* If the file does not exist, we classify this as a 'mild'
+ error and return */
- return(FALSE);
+ return(FALSE);
+ }
+
+ count++;
+
+ if (count > 100 && 0 == (count % 10)) {
+ fprintf(stderr,
+"InnoDB: Warning: cannot delete file %s\n"
+"InnoDB: Are you running ibbackup to back up the file?\n", name);
+
+ os_file_get_last_error(TRUE); /* print error information */
+ }
+
+ os_thread_sleep(1000000); /* sleep for a second */
+
+ if (count > 2000) {
+
+ return(FALSE);
+ }
+
+ goto loop;
#else
int ret;
@@ -1103,6 +1186,7 @@ os_file_close(
}
os_file_handle_error(file, NULL, "close");
+
return(FALSE);
#else
int ret;
@@ -1111,6 +1195,7 @@ os_file_close(
if (ret == -1) {
os_file_handle_error(file, NULL, "close");
+
return(FALSE);
}
diff --git a/innobase/pars/lexyy.c b/innobase/pars/lexyy.c
index 71507ccd868..7c6711d2f97 100644
--- a/innobase/pars/lexyy.c
+++ b/innobase/pars/lexyy.c
@@ -1,7 +1,7 @@
/* A lexical scanner generated by flex */
/* Scanner skeleton version:
- * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ * $Header: /home/heikki/cvsroot/ib/pars/lexyy.c,v 1.2 2003/10/30 20:27:19 heikki Exp $
*/
#define FLEX_SCANNER
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 661aec3d9a9..61bb41fe3e6 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -2346,8 +2346,13 @@ row_drop_table_for_mysql(
/* Do not drop possible .ibd tablespace if something went
wrong: we do not want to delete valuable data of the user */
- if (err == DB_SUCCESS && space_id != 0
- && fil_tablespace_exists_in_mem(space_id)) {
+ if (err == DB_SUCCESS && space_id > 0) {
+ if (!fil_space_for_table_exists_in_mem(space_id, name,
+ FALSE, TRUE)) {
+ err = DB_ERROR;
+
+ goto funct_exit;
+ }
success = fil_delete_tablespace(space_id);
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index e6022abe105..0effdf20766 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -3288,7 +3288,13 @@ rec_loop:
} else if (index == clust_index) {
- if (!lock_clust_rec_cons_read_sees(rec, index,
+ /* Fetch a previous version of the row if the current
+ one is not visible in the snapshot; if we have a very
+ high force recovery level set, we try to avoid crashes
+ by skipping this lookup */
+
+ if (srv_force_recovery < 5
+ && !lock_clust_rec_cons_read_sees(rec, index,
trx->read_view)) {
err = row_sel_build_prev_vers_for_mysql(
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 2f3502f99ad..fa836fb6083 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -102,7 +102,7 @@ char** srv_log_group_home_dirs = NULL;
ulint srv_n_log_groups = ULINT_MAX;
ulint srv_n_log_files = ULINT_MAX;
ulint srv_log_file_size = ULINT_MAX; /* size in database pages */
-ibool srv_log_archive_on = TRUE;
+ibool srv_log_archive_on = FALSE;
ulint srv_log_buffer_size = ULINT_MAX; /* size in database pages */
ulint srv_flush_log_at_trx_commit = 1;
@@ -3209,11 +3209,13 @@ flush_loop:
goto loop;
}
mutex_exit(&kernel_mutex);
-
+/*
srv_main_thread_op_info =
(char*)"archiving log (if log archive is on)";
log_archive_do(FALSE, &n_bytes_archived);
+*/
+ n_bytes_archived = 0;
/* Keep looping in the background loop if still work to do */
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 83cde6e6589..59143e81049 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -553,7 +553,6 @@ open_or_create_log_file(
ulint i) /* in: log file number in group */
{
ibool ret;
- ulint arch_space_id;
ulint size;
ulint size_high;
char name[10000];
@@ -649,9 +648,10 @@ open_or_create_log_file(
fil_node_create(name, srv_log_file_size,
2 * k + SRV_LOG_SPACE_FIRST_ID, FALSE);
-
+#ifdef notdefined
/* If this is the first log group, create the file space object
- for archived logs */
+ for archived logs.
+ Under MySQL, no archiving ever done. */
if (k == 0 && i == 0) {
arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID;
@@ -661,12 +661,13 @@ open_or_create_log_file(
} else {
arch_space_id = ULINT_UNDEFINED;
}
-
+#endif
if (i == 0) {
log_group_init(k, srv_n_log_files,
srv_log_file_size * UNIV_PAGE_SIZE,
2 * k + SRV_LOG_SPACE_FIRST_ID,
- arch_space_id);
+ SRV_LOG_SPACE_FIRST_ID + 1); /* dummy arch
+ space id */
}
return(DB_SUCCESS);
@@ -1000,7 +1001,6 @@ innobase_start_or_create_for_mysql(void)
dulint max_flushed_lsn;
ulint min_arch_log_no;
ulint max_arch_log_no;
- ibool start_archive;
ulint sum_of_new_sizes;
ulint sum_of_data_file_sizes;
ulint tablespace_size_in_header;
@@ -1156,7 +1156,7 @@ NetWare. */
assume fewer threads. */
srv_max_n_threads = 10000;
} else {
- srv_max_n_threads = 1000; /* saves several MB of memory,
+ srv_max_n_threads = 1000; /* saves several MB of memory,
especially in 64-bit
computers */
}
@@ -1341,7 +1341,9 @@ NetWare. */
mutex_enter(&(log_sys->mutex));
- recv_reset_logs(max_flushed_lsn, max_arch_log_no + 1, TRUE);
+ /* Do not + 1 arch_log_no because we do not use log
+ archiving */
+ recv_reset_logs(max_flushed_lsn, max_arch_log_no, TRUE);
mutex_exit(&(log_sys->mutex));
}
@@ -1430,6 +1432,8 @@ NetWare. */
log_make_checkpoint_at(ut_dulint_max, TRUE);
+#ifdef notdefined
+ /* Archiving is always off under MySQL */
if (!srv_log_archive_on) {
ut_a(DB_SUCCESS == log_archive_noarchivelog());
} else {
@@ -1447,7 +1451,7 @@ NetWare. */
ut_a(DB_SUCCESS == log_archive_archivelog());
}
}
-
+#endif
if (!create_new_db && srv_force_recovery == 0) {
/* After a crash recovery we only check that the info in data
dictionary is consistent with what we already know about space
diff --git a/innobase/ut/ut0rnd.c b/innobase/ut/ut0rnd.c
index 3335861384f..85d2e6094c3 100644
--- a/innobase/ut/ut0rnd.c
+++ b/innobase/ut/ut0rnd.c
@@ -71,9 +71,8 @@ ut_find_prime(
/* Found a prime */
break;
- next_n: ;
+next_n: ;
}
return(n);
}
-
diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c
index be311764261..f3be1a082a2 100644
--- a/innobase/ut/ut0ut.c
+++ b/innobase/ut/ut0ut.c
@@ -63,7 +63,7 @@ ut_get_high32(
}
/************************************************************
-The following function returns a clock time in milliseconds. */
+The following function returns elapsed CPU time in milliseconds. */
ulint
ut_clock(void)
@@ -182,6 +182,50 @@ ut_sprintf_timestamp(
}
/**************************************************************
+Sprintfs a timestamp to a buffer with no spaces and with ':' characters
+replaced by '_'. */
+
+void
+ut_sprintf_timestamp_without_extra_chars(
+/*=====================================*/
+ char* buf) /* in: buffer where to sprintf */
+{
+#ifdef __WIN__
+ SYSTEMTIME cal_tm;
+
+ GetLocalTime(&cal_tm);
+
+ sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d",
+ (int)cal_tm.wYear % 100,
+ (int)cal_tm.wMonth,
+ (int)cal_tm.wDay,
+ (int)cal_tm.wHour,
+ (int)cal_tm.wMinute,
+ (int)cal_tm.wSecond);
+#else
+ struct tm cal_tm;
+ struct tm* cal_tm_ptr;
+ time_t tm;
+
+ time(&tm);
+
+#ifdef HAVE_LOCALTIME_R
+ localtime_r(&tm, &cal_tm);
+ cal_tm_ptr = &cal_tm;
+#else
+ cal_tm_ptr = localtime(&tm);
+#endif
+ sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d",
+ cal_tm_ptr->tm_year % 100,
+ cal_tm_ptr->tm_mon + 1,
+ cal_tm_ptr->tm_mday,
+ cal_tm_ptr->tm_hour,
+ cal_tm_ptr->tm_min,
+ cal_tm_ptr->tm_sec);
+#endif
+}
+
+/**************************************************************
Returns current year, month, day. */
void