Below is the list of changes that have just been committed into a local
5.1 repository of mikron. When mikron does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2111 06/02/08 15:14:15 mikron@stripped +3 -0
WL 2826: Error handling for ALTER TABLE for partitioning
Most of the code for handling the table log is in place now, except
the action part at recovery and proper error handling in some places.
sql/sql_table.cc
1.305 06/02/08 15:14:02 mikron@stripped +332 -151
Most of the code for handling the table log is in place now, except
the action part at recovery and proper error handling in some places.
sql/mysqld.cc
1.531 06/02/08 15:14:02 mikron@stripped +1 -1
Added call to execute table log recovery
sql/mysql_priv.h
1.384 06/02/08 15:14:01 mikron@stripped +11 -8
Removed internal methods from external table log interface
Added and changed interface
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: mikron
# Host: c-9b0be253.1238-1-64736c10.cust.bredbandsbolaget.se
# Root: /Users/mikron/wl2826
--- 1.383/sql/mysql_priv.h 2006-02-07 16:26:23 +01:00
+++ 1.384/sql/mysql_priv.h 2006-02-08 15:14:01 +01:00
@@ -1168,21 +1168,24 @@
char entry_type;
} TABLE_LOG_ENTRY;
+typedef struct st_table_log_memory_entry
+{
+ uint entry_pos;
+ TABLE_LOG_MEMORY *next_log_entry;
+ TABLE_LOG_MEMORY *prev_log_entry;
+ TABLE_LOG_MEMORY *next_active_log_entry;
+} TABLE_LOG_MEMORY_ENTRY;
bool write_table_log_entry(TABLE_LOG_ENTRY *table_log_entry,
- uint next_entry,
- uint *entry_written);
-bool write_execute_table_log_entry(uint first_entry, uint *exec_entry);
-uint read_table_log_header();
-bool read_table_log_entry(uint read_entry, TABLE_LOG_ENTRY *table_log_entry);
-bool init_table_log();
+ TABLE_LOG_MEMORY_ENTRY **active_entry);
+bool write_execute_table_log_entry(uint first_entry,
+ TABLE_LOG_MEMORY_ENTRY **active_entry);
+void release_table_log_memory_entry(TABLE_LOG_MEMORY_ENTRY *log_entry);
void release_table_log();
void execute_table_log_recovery();
bool execute_table_log_entry(uint first_entry);
-bool execute_table_log_action(TABLE_LOG_ENTRY *table_log_entry);
void lock_global_table_log();
void unlock_global_table_log();
-bool sync_table_log();
bool write_log_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt, bool install_flag);
bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt);
--- 1.530/sql/mysqld.cc 2006-02-03 16:41:14 +01:00
+++ 1.531/sql/mysqld.cc 2006-02-08 15:14:02 +01:00
@@ -3676,7 +3676,7 @@
unireg_abort(1);
}
}
-
+ execute_table_log_recovery();
init_events();
create_shutdown_thread();
--- 1.304/sql/sql_table.cc 2006-02-07 16:26:23 +01:00
+++ 1.305/sql/sql_table.cc 2006-02-08 15:14:02 +01:00
@@ -265,22 +265,19 @@
and there is a global struct that contains information about its current
state.
+ History:
+ First version written in 2006 by Mikael Ronstrom
--------------------------------------------------------------------------
*/
-typedef struct st_table_log_memory_entry
-{
- uint entry_pos;
-} TABLE_LOG_MEMORY_ENTRY;
-
typedef struct st_global_table_log
{
char file_entry[IO_SIZE];
char file_name_str[FN_REFLEN];
char *file_name;
- List<TABLE_LOG_MEMORY_ENTRY> free_entries;
- List<TABLE_LOG_MEMORY_ENTRY> log_entries;
+ TABLE_LOG_MEMORY_ENTRY *first_free;
+ TABLE_LOG_MEMORY_ENTRY *first_used;
uint no_entries;
File file_id;
uint name_len;
@@ -301,6 +298,7 @@
FALSE Success
*/
+static
bool
sync_table_log()
{
@@ -308,7 +306,10 @@
DBUG_ENTER("sync_table_log");
if (my_sync(global_table_log.file_id, MYF(0)))
+ {
+ /* Write to error log */
error= TRUE;
+ }
DBUG_RETURN(error);
}
@@ -317,8 +318,6 @@
Write one entry from table log file
SYNOPSIS
write_table_log_file_entry()
- file_id File identifier
- file_entry Memory area to read entry into
entry_no Entry number to read
RETURN VALUES
TRUE Error
@@ -327,10 +326,12 @@
static
bool
-write_table_log_file_entry(File file_id, byte *file_entry, uint entry_no)
+write_table_log_file_entry(uint entry_no)
{
bool error= FALSE;
- DBUG_ENTER("read_table_log_file_entry");
+ File file_id= global_table_log.file_id;
+ char *file_entry= (char*)global_table_log.file_entry;
+ DBUG_ENTER("write_table_log_file_entry");
if (my_pwrite(file_id, file_entry, IO_SIZE, IO_SIZE * entry_no, MYF(0)))
error= TRUE;
@@ -339,64 +340,6 @@
/*
- SYNOPSIS
- write_table_log_entry()
- table_log_entry Information about log entry
- out:entry_written Entry information written into
-
- RETURN VALUES
- TRUE Error
- FALSE Success
-
- DESCRIPTION
- A careful write of the table log is performed to ensure that we can
- handle crashes occurring during CREATE and ALTER TABLE processing.
-*/
-
-bool
-write_table_log_entry(TABLE_LOG_ENTRY *table_log_entry,
- uint *entry_written)
-{
- bool write_header, error;
- DBUG_ENTER("write_table_log_entry");
-
- global_table_log.file_entry[0]= 'i';
- global_table_log.file_entry[1]= table_log_entry->action_type;
- int4store(&global_table_log.file_entry[2],
- table_log_entry->next_entry);
- strcpy(&global_table_log.file_entry[6], table_log_entry->name);
- if (table_log_entry.action_type == 'r')
- global_table_log.file_entry[6 + NAMELEN]= 0;
- else
- strcpy(&global_table_log.file_entry[6 + NAMELEN],
- table_log_entry->from_name);
- strcpy(&global_table_log.file_entry[6 + (2*NAMELEN)],
- table_log_entry->handler_type);
- if (global_table_log.free_entries.is_empty())
- {
- global_table_log.no_entries++;
- entry_no= global_table_log.no_entries;
- write_header= TRUE;
- }
- else
- {
- TABLE_LOG_MEMORY *tmp= global_table_log.free_entries.pop();
- global_table_log.log_entries.push_back(tmp);
- entry_no= tmp->entry_pos;
- write_header= FALSE;
- }
- error= FALSE;
- if (write_table_log_entry(global_table_log.file_id,
- global_table_log.file_entry,
- entry_no))
- error= TRUE;
- else if (write_header || !(write_table_log_header()))
- error= TRUE;
- DBUG_RETURN(error);
-}
-
-
-/*
Write table log header
SYNOPSIS
write_table_log_header()
@@ -405,10 +348,12 @@
FALSE Success
*/
+static
bool
write_table_log_header()
{
uint16 const_var;
+ bool error= FALSE;
DBUG_ENTER("write_table_log_header");
int4store(&global_table_log.file_entry[0], global_table_log.no_entries);
@@ -416,36 +361,9 @@
int2store(&global_table_log.file_entry[4], const_var);
const_var= 32;
int2store(&global_table_log.file_entry[6], const_var);
- DBUG_RETURN(FALSE);
-}
-
-
-/*
- Write final entry in the table log
- SYNOPSIS
- write_execute_table_log_entry()
- first_entry First entry in linked list of entries
- to execute, if 0 = NULL it means that
- the entry is removed and the entries
- are put into the free list.
- in:out:exec_entry Entry to execute, 0 = NULL if the entry
- is written first time and needs to be
- returned. In this case the entry written
- is returned in this parameter
- RETURN VALUES
- TRUE Error
- FALSE Success
-
- DESCRIPTION
- This is the last write in the table log. The previous log entries have
- already been written but not yet synched to disk.
-*/
-
-bool
-write_execute_table_log_entry(uint first_entry, uint *exec_entry)
-{
- DBUG_ENTER("write_execute_table_log_entry");
- DBUG_RETURN(FALSE);
+ if (write_table_log_file_entry(0UL))
+ error= TRUE;
+ DBUG_RETURN(error);
}
@@ -453,8 +371,6 @@
Read one entry from table log file
SYNOPSIS
read_table_log_file_entry()
- file_id File identifier
- file_entry Memory area to read entry into
entry_no Entry number to read
RETURN VALUES
TRUE Error
@@ -463,9 +379,11 @@
static
bool
-read_table_log_file_entry(File file_id, byte *file_entry, uint entry_no)
+read_table_log_file_entry(uint entry_no)
{
bool error= FALSE;
+ File file_id= global_table_log.file_id;
+ char *file_entry= (char*)global_table_log.file_entry;
DBUG_ENTER("read_table_log_file_entry");
if (my_pread(file_id, file_entry, IO_SIZE, IO_SIZE * entry_no, MYF(0)))
@@ -475,6 +393,23 @@
/*
+ Create table log file name
+ SYNOPSIS
+ create_table_log_file_name()
+ file_name Filename setup
+ RETURN VALUES
+ NONE
+*/
+
+static
+void
+create_table_log_file_name(char *file_name)
+{
+ strxmov(file_name, mysql_data_home, "/", "table_log.log", NullS);
+}
+
+
+/*
Read header of table log file
SYNOPSIS
read_table_log_header()
@@ -487,22 +422,28 @@
of entries in the table log.
*/
+static
uint
read_table_log_header()
{
- char *file_entry= (char*)&global_table_log.file_entry;
+ char *file_entry= (char*)global_table_log.file_entry;
+ char file_name[FN_REFLEN];
DBUG_ENTER("read_table_log_header");
- if (read_table_log_file_entry(global_table_log.file_id,
- (char*)&file_entry, 0UL))
+ bzero(file_entry, sizeof(global_table_log.file_entry));
+ create_table_log_file_name(file_name);
{
- DBUG_RETURN(0);
+ if (read_table_log_file_entry(0UL))
+ {
+ /* Write message into error log */
+ }
}
entry_no= uint4korr(&file_entry[0]);
global_table_log.name_len= uint2korr(&file_entry[4]);
global_table_log.handler_type_len= uint2korr(&file_entry[6]);
- global_table_log.free_entries.clear();
- global_table_log.log_entries.clear();
+ global_table_log.first_free= NULL;
+ global_table_log.first_used= NULL;
global_table_log.no_entries= 0;
VOID(pthread_mutex_init(&LOCK_gtl, MY_MUTEX_INIT_FAST));
DBUG_RETURN(entry_no);
@@ -525,7 +466,23 @@
bool
read_table_log_entry(uint read_entry, TABLE_LOG_ENTRY *table_log_entry)
{
+ char *file_entry= (char*)&global_table_log.file_entry;
DBUG_ENTER("read_table_log_entry");
+
+ if (read_table_log_file_entry(global_table_log.file_id,
+ (char*)&file_entry, read_entry))
+ {
+ /* Error handling */
+ DBUG_RETURN(TRUE);
+ }
+ table_log_entry->entry_type= file_entry[0];
+ table_log_entry->action_type= file_entry[1];
+ table_log_entry->next_entry= uint4korr(&file_entry[2]);
+ table_log_entry->name= &file_entry[6];
+ index= 6 + global_table_log->name_len;
+ table_log_entry->from_name= &file_entry[index];
+ index+= global_table_log->name_len;
+ table_log_entry->handler_type= &file_entry[index];
DBUG_RETURN(FALSE);
}
@@ -542,94 +499,235 @@
number of entries to zero.
*/
+static
bool
init_table_log()
{
bool error= FALSE;
+ char file_name[FN_REFLEN];
DBUG_ENTER("init_table_log");
- VOID(my_delete(global_table_log.file_name));
- global_table_log.file_id= my_open(global_table_log.file_name,
- 0, 0, MYF(0));
+ create_table_log_file_name(file_name);
+ VOID(my_delete(file_name));
+ if ((global_table_log.file_id= my_create(file_name,
+ CREATE_MODE,
+ create_flags, MYF(0))) < 0)
+ {
+ /* Couldn't create table log file, this is serious error */
+ abort();
+ }
if (write_table_log_header())
+ {
+ /* Write to error log */
error= TRUE;
+ }
DBUG_RETURN(error);
}
/*
- Release all memory allocated to the table log
+ Execute one action in a table log entry
SYNOPSIS
- release_table_log()
+ execute_table_log_action()
+ table_log_entry Information in action entry to execute
RETURN VALUES
- NONE
+ TRUE Error
+ FALSE Success
*/
-void
-release_table_log()
+static
+bool
+execute_table_log_action(TABLE_LOG_ENTRY *table_log_entry)
{
- DBUG_ENTER("release_table_log");
-
- VOID(pthread_mutex_destroy(&LOCK_gtl));
- DBUG_RETURN_VOID;
+ DBUG_ENTER("execute_table_log_action");
+ DBUG_RETURN(FALSE);
}
/*
- Lock mutex for global table log
+ Get a free entry in the table log
SYNOPSIS
- lock_global_table_log()
+ get_free_table_log_entry()
+ out:active_entry A table log memory entry returned
RETURN VALUES
- NONE
+ TRUE Error
+ FALSE Success
*/
-void
-lock_global_table_log()
+static
+bool
+get_free_table_log_entry(TABLE_LOG_MEMORY_ENTRY **active_entry)
{
- DBUG_ENTER("lock_global_table_log");
+ bool write_header;
+ TABLE_LOG_MEMORY_ENTRY *used_entry;
+ TABLE_LOG_MEMORY_ENTRY *first_used= global_table_log.first_used;
+ if (global_table_log.first_free == NULL)
+ {
+ if (!(used_entry= my_malloc(sizeof(TABLE_LOG_MEMORY_ENTRY))))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ global_table_log.no_entries++;
+ used_entry->entry_no= entry_no= global_table_log.no_entries;
+ write_header= TRUE;
+ }
+ else
+ {
+ used_entry= global_table_log.first_free;
+ global_table_log.first_free= used_entry->next_log_entry;
+ entry_no= first_free->entry_pos;
+ used_entry= first_free;
+ write_header= FALSE;
+ }
+ /*
+ Move from free list to used list
+ */
+ used_entry->next_log_entry= first_used;
+ used_entry->prev_log_entry= NULL;
+ global_table_log.first_used= used_entry;
+ if (first_used)
+ first_used->prev_log_entry= used_entry;
- VOID(pthread_mutex_lock(&LOCK_gtl));
- DBUG_RETURN_VOID;
+ *active_entry= used_entry;
}
/*
- Unlock mutex for global table log
+ External interface methods for the Table log Module
+ ---------------------------------------------------
+*/
+
+/*
SYNOPSIS
- unlock_global_table_log()
+ write_table_log_entry()
+ table_log_entry Information about log entry
+ out:entry_written Entry information written into
+
RETURN VALUES
- NONE
+ TRUE Error
+ FALSE Success
+
+ DESCRIPTION
+ A careful write of the table log is performed to ensure that we can
+ handle crashes occurring during CREATE and ALTER TABLE processing.
*/
-void
-unlock_global_table_log()
+bool
+write_table_log_entry(TABLE_LOG_ENTRY *table_log_entry,
+ TABLE_LOG_MEMORY_ENTRY **active_entry)
{
- DBUG_ENTER("unlock_global_table_log");
+ bool error;
+ DBUG_ENTER("write_table_log_entry");
- VOID(pthread_mutex_unlock(&LOCK_gtl));
- DBUG_RETURN_VOID;
+ global_table_log.file_entry[0]= 'i';
+ global_table_log.file_entry[1]= table_log_entry->action_type;
+ int4store(&global_table_log.file_entry[2],
+ table_log_entry->next_entry);
+ strcpy(&global_table_log.file_entry[6], table_log_entry->name);
+ if (table_log_entry.action_type == 'r')
+ global_table_log.file_entry[6 + NAMELEN]= 0;
+ else
+ strcpy(&global_table_log.file_entry[6 + NAMELEN],
+ table_log_entry->from_name);
+ strcpy(&global_table_log.file_entry[6 + (2*NAMELEN)],
+ table_log_entry->handler_type);
+ if (get_free_table_log_entry(active_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ error= FALSE;
+ if (write_table_log_file_entry(global_table_log.file_id,
+ global_table_log.file_entry,
+ (*active_entry)->entry_pos))
+ error= TRUE;
+ else if (write_header || !(write_table_log_header()))
+ error= TRUE;
+ if (error)
+ release_table_log_memory_entry(*active_entry);
+ DBUG_RETURN(error);
}
/*
- Execute one action in a table log entry
+ Write final entry in the table log
SYNOPSIS
- execute_table_log_action()
- table_log_entry Information in action entry to execute
+ write_execute_table_log_entry()
+ first_entry First entry in linked list of entries
+ to execute, if 0 = NULL it means that
+ the entry is removed and the entries
+ are put into the free list.
+ in:out:exec_entry Entry to execute, 0 = NULL if the entry
+ is written first time and needs to be
+ returned. In this case the entry written
+ is returned in this parameter
RETURN VALUES
- TRUE Error
- FALSE Success
-*/
+ TRUE Error
+ FALSE Success
+
+ DESCRIPTION
+ This is the last write in the table log. The previous log entries have
+ already been written but not yet synched to disk.
+*/
bool
-execute_table_log_action(TABLE_LOG_ENTRY *table_log_entry)
+write_execute_table_log_entry(uint first_entry,
+ TABLE_LOG_MEMORY_ENTRY **active_entry)
{
- DBUG_ENTER("execute_table_log_action");
+ char *file_entry= (char*)global_table_log.file_entry;
+ DBUG_ENTER("write_execute_table_log_entry");
+
+ VOID(sync_table_log());
+ file_entry[0]= 'e';
+ file_entry[1]= 0; /* Ignored for execute entries */
+ int4store(&file_entry[2], first_entry);
+ file_entry[6]= 0;
+ file_entry[6 + NAMELEN]= 0;
+ file_entry[6 + 2*NAMELEN]= 0;
+ if (get_free_table_log_entry(active_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ if (write_table_log_file_entry((*active_entry)->entry_pos))
+ {
+ release_table_log_memory_entry(*active_entry);
+ DBUG_RETURN(TRUE);
+ }
+ VOID(sync_table_log());
DBUG_RETURN(FALSE);
}
/*
+ Release a log memory entry
+ SYNOPSIS
+ release_table_log_memory_entry()
+ log_memory_entry Log memory entry to release
+ RETURN VALUES
+ NONE
+*/
+
+void
+release_table_log_memory_entry(TABLE_LOG_MEMORY_ENTRY *log_entry)
+{
+ TABLE_LOG_MEMORY_ENTRY *first_free= global_table_log.first_free;
+ TABLE_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
+ TABLE_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
+ DBUG_ENTER("release_table_log_memory_entry");
+
+ global_table_log.first_free= log_entry;
+ log_entry->next_log_entry= first_free;
+
+ if (prev_log_entry)
+ prev_log_entry->next_log_entry= next_log_entry;
+ else
+ global_table_log.first_used= next_log_entry;
+ if (next_log_entry)
+ next_log_entry->prev_log_entry= prev_log_entry;
+ DBUG_RETURN_VOID;
+}
+
+
+/*
Execute one entry in the table log. Executing an entry means executing
a linked list of actions.
SYNOPSIS
@@ -640,6 +738,7 @@
FALSE Success
*/
+static
bool
execute_table_log_entry(uint first_entry)
{
@@ -649,19 +748,24 @@
do
{
- read_table_log_entry(read_entry, &table_log_entry);
+ if (read_table_log_entry(read_entry, &table_log_entry))
+ {
+ DBUG_ASSERT(0);
+ /* Write to error log and continue with next log entry */
+ break;
+ }
DBUG_ASSERT(table_log_entry.entry_type == 'i');
if (execute_table_log_action(&table_log_entry))
{
- /* error handling */
- DBUG_RETURN(TRUE);
+ DBUG_ASSERT(0);
+ /* Write to error log and continue with next log entry */
+ break;
}
read_entry= table_log_entry.next_entry;
} while (read_entry);
DBUG_RETURN(FALSE);
}
-
/*
Execute the table log at recovery of MySQL Server
SYNOPSIS
@@ -680,17 +784,94 @@
no_entries= read_log_header();
for (i= 0; i < no_entries; i++)
{
- read_table_log_entry(i, &table_log_entry);
+ if (read_table_log_entry(i, &table_log_entry))
+ {
+ DBUG_ASSERT(0);
+ /* Write to error log */
+ break;
+ }
if (table_log_entry.entry_type == 'e')
{
if (execute_table_log_entry(table_log_entry.next_entry))
{
- /* error handling */
+ /*
+ Currently errors are either crashing or ignored so we should
+ never end up here
+ */
+ abort();
DBUG_RETURN_VOID;
}
}
}
- init_table_log();
+ VOID(init_table_log());
+ DBUG_RETURN_VOID;
+}
+
+
+/*
+ Release all memory allocated to the table log
+ SYNOPSIS
+ release_table_log()
+ RETURN VALUES
+ NONE
+*/
+
+void
+release_table_log()
+{
+ TABLE_LOG_MEMORY_ENTRY *free_list= global_table_log.first_free;
+ TABLE_LOG_MEMORY_ENTRY *used_list= global_table_log.first_used;
+ DBUG_ENTER("release_table_log");
+
+ VOID(pthread_mutex_destroy(&LOCK_gtl));
+ while (used_list)
+ {
+ TABLE_LOG_MEMORY_ENTRY tmp= used_list;
+ my_free(used_list, MYF(0));
+ used_list= tmp->next_log_entry;
+ }
+ while (free_list)
+ {
+ TABLE_LOG_MEMORY_ENTRY tmp= free_list;
+ my_free(free_list, MYF(0));
+ free_list= tmp->next_log_entry;
+ }
+ DBUG_RETURN_VOID;
+}
+
+
+/*
+ Lock mutex for global table log
+ SYNOPSIS
+ lock_global_table_log()
+ RETURN VALUES
+ NONE
+*/
+
+void
+lock_global_table_log()
+{
+ DBUG_ENTER("lock_global_table_log");
+
+ VOID(pthread_mutex_lock(&LOCK_gtl));
+ DBUG_RETURN_VOID;
+}
+
+
+/*
+ Unlock mutex for global table log
+ SYNOPSIS
+ unlock_global_table_log()
+ RETURN VALUES
+ NONE
+*/
+
+void
+unlock_global_table_log()
+{
+ DBUG_ENTER("unlock_global_table_log");
+
+ VOID(pthread_mutex_unlock(&LOCK_gtl));
DBUG_RETURN_VOID;
}
| Thread |
|---|
| • bk commit into 5.1 tree (mikron:1.2111) | mikael | 9 Feb |