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.2124 06/02/10 22:36:01 mikron@stripped +5 -0
WL 2826: Error handling of ALTER TABLE for partitioning
Make lots of fixes to handle the most complex case of reorganising
of partitions where two-phased processes are needed in some cases.
sql/sql_table.cc
1.314 06/02/10 22:35:48 mikron@stripped +146 -68
More constants with somewhat descriptive names
Moved around some methods between internal part and external part
Added new method to handle inactivation of log entries
sql/sql_partition.cc
1.45 06/02/10 22:35:48 mikron@stripped +97 -6
Fix change of partitions
sql/mysql_priv.h
1.390 06/02/10 22:35:47 mikron@stripped +13 -0
Converted 'd', 'e' and so forth to constants with somewhat more
descriptive names
Added method to inactivate log entries
sql/handler.h
1.187 06/02/10 22:35:47 mikron@stripped +3 -1
Added new entry to partition_element to keep track of log entry for
a partition during ALTER TABLE that reorganises existing partitions.
sql/ha_partition.cc
1.31 06/02/10 22:35:47 mikron@stripped +68 -64
Rewrote the rename partitions and drop partitions to align with how
the table log handles things.
# 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-370be253.1238-1-64736c10.cust.bredbandsbolaget.se
# Root: /Users/mikron/wl2826
--- 1.186/sql/handler.h 2006-02-09 20:13:16 +01:00
+++ 1.187/sql/handler.h 2006-02-10 22:35:47 +01:00
@@ -667,6 +667,7 @@
ulonglong part_min_rows;
char *partition_name;
char *tablespace_name;
+ TABLE_LOG_MEMORY_ENTRY *log_entry;
longlong range_value;
char* part_comment;
char* data_file_name;
@@ -677,7 +678,8 @@
partition_element()
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
- tablespace_name(NULL), range_value(0), part_comment(NULL),
+ tablespace_name(NULL), log_entry(0),
+ range_value(0), part_comment(NULL),
data_file_name(NULL), index_file_name(NULL),
engine_type(NULL),part_state(PART_NORMAL),
nodegroup_id(UNDEF_NODEGROUP)
--- 1.389/sql/mysql_priv.h 2006-02-09 19:02:51 +01:00
+++ 1.390/sql/mysql_priv.h 2006-02-10 22:35:47 +01:00
@@ -1177,6 +1177,8 @@
uint next_entry;
char action_type;
char entry_type;
+ char phase;
+ char not_used;
} TABLE_LOG_ENTRY;
typedef struct st_table_log_memory_entry
@@ -1187,11 +1189,22 @@
struct st_table_log_memory_entry *next_active_log_entry;
} TABLE_LOG_MEMORY_ENTRY;
+#define TLOG_EXECUTE_CODE 'e'
+#define TLOG_LOG_ENTRY_CODE 'l'
+#define TLOG_IGNORE_LOG_ENTRY_CODE 'i'
+
+#define TLOG_DELETE_ACTION_CODE 'd'
+#define TLOG_RENAME_ACTION_CODE 'r'
+#define TLOG_REPLACE_ACTION_CODE 's'
+
+#define TLOG_HANDLER_TYPE_LEN 32
+
bool write_table_log_entry(TABLE_LOG_ENTRY *table_log_entry,
TABLE_LOG_MEMORY_ENTRY **active_entry);
bool write_execute_table_log_entry(uint first_entry,
bool complete,
TABLE_LOG_MEMORY_ENTRY **active_entry);
+bool inactivate_table_log_entry(uint entry_no);
void release_table_log_memory_entry(TABLE_LOG_MEMORY_ENTRY *log_entry);
void release_table_log();
void execute_table_log_recovery();
--- 1.313/sql/sql_table.cc 2006-02-10 19:32:34 +01:00
+++ 1.314/sql/sql_table.cc 2006-02-10 22:35:48 +01:00
@@ -289,28 +289,38 @@
pthread_mutex_t LOCK_gtl;
+#define TLOG_ENTRY_TYPE_POS 0
+#define TLOG_ACTION_TYPE_POS 1
+#define TLOG_PHASE_POS 2
+#define TLOG_NEXT_ENTRY_POS 4
+
+#define TLOG_NO_ENTRY_POS 0
+#define TLOG_NAME_LEN_POS 4
+#define TLOG_HANDLER_TYPE_POS 8
+#define TLOG_IO_SIZE_POS 12
/*
- Sync table log file
+ Read one entry from table log file
SYNOPSIS
- sync_table_log()
+ read_table_log_file_entry()
+ entry_no Entry number to read
RETURN VALUES
- TRUE Error
- FALSE Success
+ TRUE Error
+ FALSE Success
*/
static
bool
-sync_table_log()
+read_table_log_file_entry(uint entry_no)
{
bool error= FALSE;
- DBUG_ENTER("sync_table_log");
+ File file_id= global_table_log.file_id;
+ char *file_entry= (char*)global_table_log.file_entry;
+ uint io_size= global_table_log.io_size;
+ DBUG_ENTER("read_table_log_file_entry");
- if (my_sync(global_table_log.file_id, MYF(0)))
- {
- /* Write to error log */
+ if (my_pread(file_id, file_entry, io_size, io_size * entry_no, MYF(0)))
error= TRUE;
- }
DBUG_RETURN(error);
}
@@ -358,13 +368,17 @@
bool error= FALSE;
DBUG_ENTER("write_table_log_header");
- int4store(&global_table_log.file_entry[0], global_table_log.no_entries);
+ int4store(&global_table_log.file_entry[TLOG_NO_ENTRY_POS],
+ global_table_log.no_entries);
const_var= FN_LEN;
- int2store(&global_table_log.file_entry[4], const_var);
- const_var= 32;
- int2store(&global_table_log.file_entry[6], const_var);
+ int4store(&global_table_log.file_entry[TLOG_NAME_LEN_POS],
+ const_var);
+ const_var= TLOG_HANDLER_TYPE_LEN;
+ int4store(&global_table_log.file_entry[TLOG_HANDLER_TYPE_POS],
+ const_var);
const_var= IO_SIZE;
- int4store(&global_table_log.file_entry[8], const_var);
+ int4store(&global_table_log.file_entry[TLOG_IO_SIZE_POS],
+ const_var);
if (write_table_log_file_entry(0UL))
error= TRUE;
if (!error)
@@ -374,32 +388,6 @@
/*
- Read one entry from table log file
- SYNOPSIS
- read_table_log_file_entry()
- entry_no Entry number to read
- RETURN VALUES
- TRUE Error
- FALSE Success
-*/
-
-static
-bool
-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;
- uint io_size= global_table_log.io_size;
- DBUG_ENTER("read_table_log_file_entry");
-
- if (my_pread(file_id, file_entry, io_size, io_size * entry_no, MYF(0)))
- error= TRUE;
- DBUG_RETURN(error);
-}
-
-
-/*
Create table log file name
SYNOPSIS
create_table_log_file_name()
@@ -450,11 +438,12 @@
else
successful_open= TRUE;
}
- 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]);
+ entry_no= uint4korr(&file_entry[TLOG_NO_ENTRY_POS]);
+ global_table_log.name_len= uint4korr(&file_entry[TLOG_NAME_LEN_POS]);
+ global_table_log.handler_type_len=
+ uint4korr(&file_entry[TLOG_HANDLER_TYPE_POS]);
if (successful_open)
- global_table_log.io_size= uint4korr(&file_entry[8]);
+ global_table_log.io_size= uint4korr(&file_entry[TLOG_IO_SIZE_POS]);
global_table_log.first_free= NULL;
global_table_log.first_used= NULL;
global_table_log.no_entries= 0;
@@ -488,11 +477,12 @@
/* 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];
- inx= 6 + global_table_log.name_len;
+ table_log_entry->entry_type= file_entry[TLOG_ENTRY_TYPE_POS];
+ table_log_entry->action_type= file_entry[TLOG_ACTION_TYPE_POS];
+ table_log_entry->phase= file_entry[TLOG_PHASE_POS];
+ table_log_entry->next_entry= uint4korr(&file_entry[TLOG_NEXT_ENTRY_POS]);
+ table_log_entry->name= &file_entry[TLOG_NAME_POS];
+ inx= TLOG_NAME_POS + global_table_log.name_len;
table_log_entry->from_name= &file_entry[inx];
inx+= global_table_log.name_len;
table_log_entry->handler_type= &file_entry[inx];
@@ -637,23 +627,27 @@
bool error, write_header;
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],
+ global_table_log.file_entry[TLOG_ENTRY_TYPE_POS]= TLOG_LOG_ENTRY_CODE;
+ global_table_log.file_entry[TLOG_ACTION_TYPE_POS]=
+ table_log_entry->action_type;
+ global_table_log.file_entry[TLOG_PHASE_POS]= 0;
+ int4store(&global_table_log.file_entry[TLOG_NEXT_ENTRY_POS],
table_log_entry->next_entry);
DBUG_ASSERT(strlen(table_log_entry->name) < FN_LEN);
- strncpy(&global_table_log.file_entry[6], table_log_entry->name, FN_LEN);
- if (table_log_entry->action_type == 'r')
+ strncpy(&global_table_log.file_entry[TLOG_NAME_POS],
+ table_log_entry->name, FN_LEN);
+ if (table_log_entry->action_type == TLOG_RENAME_ACTION_CODE ||
+ table_log_entry->action_type == TLOG_REPLACE_ACTION_CODE)
{
DBUG_ASSERT(strlen(table_log_entry->from_name) < FN_LEN);
- strncpy(&global_table_log.file_entry[6 + FN_LEN],
+ strncpy(&global_table_log.file_entry[TLOG_NAME_POS + FN_LEN],
table_log_entry->from_name, FN_LEN);
}
else
- global_table_log.file_entry[6 + FN_LEN]= 0;
+ global_table_log.file_entry[TLOG_NAME_POS + FN_LEN]= 0;
DBUG_ASSERT(strlen(table_log_entry->handler_type) < FN_LEN);
- strncpy(&global_table_log.file_entry[6 + (2*FN_LEN)],
- table_log_entry->handler_type, FN_LEN);
+ strncpy(&global_table_log.file_entry[TLOG_NAME_POS + (2*FN_LEN)],
+ table_log_entry->handler_type, FN_LEN);
if (get_free_table_log_entry(active_entry, &write_header))
{
DBUG_RETURN(TRUE);
@@ -705,15 +699,16 @@
if (!complete)
{
VOID(sync_table_log());
- file_entry[0]= 'e';
+ file_entry[TLOG_ENTRY_TYPE_POS]= TLOG_EXECUTE_CODE;
}
else
- file_entry[0]= 'i';
- file_entry[1]= 0; /* Ignored for execute entries */
- int4store(&file_entry[2], first_entry);
- file_entry[6]= 0;
- file_entry[6 + FN_LEN]= 0;
- file_entry[6 + 2*FN_LEN]= 0;
+ file_entry[TLOG_ENTRY_TYPE_POS]= TLOG_IGNORE_LOG_ENTRY_CODE;
+ file_entry[TLOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
+ file_entry[TLOG_PHASE_POS]= 0;
+ int4store(&file_entry[TLOG_NEXT_ENTRY_POS], first_entry);
+ file_entry[TLOG_NAME_POS]= 0;
+ file_entry[TLOG_NAME_POS + FN_LEN]= 0;
+ file_entry[TLOG_NAME_POS + 2*FN_LEN]= 0;
if (!(*active_entry))
{
if (get_free_table_log_entry(active_entry, &write_header))
@@ -740,6 +735,88 @@
/*
+ For complex rename operations we need to inactivate individual entries.
+ SYNOPSIS
+ inactivate_table_log_entry()
+ entry_no Entry position of record to change
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+ DESCRIPTION
+ During replace operations where we start with an existing table called
+ t1 and a replacement table called t1#temp or something else and where
+ we want to delete t1 and rename t1#temp to t1 this is not possible to
+ do in a safe manner unless the table log is informed of the phases in
+ the change.
+
+ Delete actions are 1-phase actions that can be ignored immediately after
+ being executed.
+ Rename actions from x to y is also a 1-phase action since there is no
+ interaction with any other handlers named x and y.
+ Replace action where drop y and x -> y happens needs to be a two-phase
+ action. Thus the first phase will drop y and the second phase will
+ rename x -> y.
+*/
+
+bool
+inactivate_table_log_entry(uint entry_no)
+{
+ bool error= TRUE;
+ const char *file_entry= (const char*)global_table_log.file_entry
+ DBUG_ENTER("inactivate_table_log_entry");
+
+ if (!read_table_log_file_entry(entry_no))
+ {
+ if (file_entry[TLOG_ENTRY_POS] == TLOG_LOG_ENTRY_CODE)
+ {
+ if (file_entry[TLOG_ACTION_TYPE_POS] == TLOG_DELETE_ACTION_CODE ||
+ file_entry[TLOG_ACTION_TYPE_POS] == TLOG_RENAME_ACTION_CODE ||
+ (file_entry[TLOG_ACTION_TYPE_POS] == TLOG_REPLACE_ACTION_CODE &&
+ file_entry[TLOG_PHASE_POS] == 1))
+ file_entry[TLOG_ENTRY_TYPE_POS]= TLOG_IGNORE_LOG_ENTRY_POS;
+ else if (file_entry[TLOG_ACTION_TYPE_POS] == TLOG_REPLACE_ACTION_CODE)
+ {
+ DBUG_ASSERT(file_entry[TLOG_PHASE_POS] == 0);
+ file_entry[TLOG_PHASE_POS]= 1;
+ }
+ else
+ {
+ DBUG_ASSERT(0);
+ }
+ if (!write_table_log_file_entry(entry_no))
+ error= FALSE;
+ }
+ }
+ DBUG_RETURN(error);
+}
+
+
+/*
+ Sync table log file
+ SYNOPSIS
+ sync_table_log()
+ RETURN VALUES
+ TRUE Error
+ FALSE Success
+*/
+
+static
+bool
+sync_table_log()
+{
+ bool error= FALSE;
+ DBUG_ENTER("sync_table_log");
+
+ if (my_sync(global_table_log.file_id, MYF(0)))
+ {
+ /* Write to error log */
+ error= TRUE;
+ }
+ DBUG_RETURN(error);
+}
+
+
+/*
Release a log memory entry
SYNOPSIS
release_table_log_memory_entry()
@@ -795,7 +872,8 @@
/* Write to error log and continue with next log entry */
break;
}
- DBUG_ASSERT(table_log_entry.entry_type == 'i');
+ DBUG_ASSERT(table_log_entry.entry_type == TLOG_LOG_ENTRY_CODE ||
+ table_log_entry.entry_type == TLOG_IGNORE_LOG_ENTRY_CODE);
if (execute_table_log_action(&table_log_entry))
{
DBUG_ASSERT(0);
@@ -831,7 +909,7 @@
/* Write to error log */
break;
}
- if (table_log_entry.entry_type == 'e')
+ if (table_log_entry.entry_type == TLOG_EXECUTE_CODE)
{
if (execute_table_log_entry(table_log_entry.next_entry))
{
--- 1.30/sql/ha_partition.cc 2006-02-09 20:24:58 +01:00
+++ 1.31/sql/ha_partition.cc 2006-02-10 22:35:47 +01:00
@@ -577,7 +577,6 @@
int ha_partition::drop_partitions(const char *path)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
- List_iterator<partition_element> temp_it(m_part_info->temp_partitions);
char part_name_buff[FN_REFLEN];
uint no_parts= m_part_info->partitions.elements;
uint part_count= 0;
@@ -585,37 +584,18 @@
uint i= 0;
uint name_variant;
int error= 0;
- bool reorged_parts= (m_reorged_parts > 0);
- bool temp_partitions= (m_part_info->temp_partitions.elements > 0);
DBUG_ENTER("ha_partition::drop_partitions");
- if (temp_partitions)
- no_parts= m_part_info->temp_partitions.elements;
do
{
- partition_element *part_elem;
- if (temp_partitions)
- {
- /*
- We need to remove the reorganised partitions that were put in the
- temp_partitions-list.
- */
- part_elem= temp_it++;
- DBUG_ASSERT(part_elem->part_state == PART_TO_BE_DROPPED);
- }
- else
- part_elem= part_it++;
- if (part_elem->part_state == PART_TO_BE_DROPPED ||
- part_elem->part_state == PART_IS_CHANGED)
+ partition_element *part_elem= part_it++;
+ if (part_elem->part_state == PART_TO_BE_DROPPED)
{
handler *file;
/*
This part is to be dropped, meaning the part or all its subparts.
*/
name_variant= NORMAL_PART_NAME;
- if (part_elem->part_state == PART_IS_CHANGED ||
- (part_elem->part_state == PART_TO_BE_DROPPED && temp_partitions))
- name_variant= RENAMED_PART_NAME;
if (m_is_sub_partitioned)
{
List_iterator<partition_element> sub_it(part_elem->subpartitions);
@@ -627,10 +607,7 @@
create_subpartition_name(part_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name, name_variant);
- if (reorged_parts)
- file= m_reorged_file[part_count++];
- else
- file= m_file[part];
+ file= m_file[part];
DBUG_PRINT("info", ("Drop subpartition %s", part_name_buff));
error+= file->delete_table((const char *) part_name_buff);
} while (++j < no_subparts);
@@ -640,10 +617,7 @@
create_partition_name(part_name_buff, path,
part_elem->partition_name, name_variant,
TRUE);
- if (reorged_parts)
- file= m_reorged_file[part_count++];
- else
- file= m_file[i];
+ file= m_file[i];
DBUG_PRINT("info", ("Drop partition %s", part_name_buff));
error+= file->delete_table((const char *) part_name_buff);
}
@@ -695,6 +669,14 @@
if (temp_partitions)
{
+ /*
+ These are the reorganised partitions that have already been copied.
+ We delete the partitions and log the delete by inactivating the
+ delete log entry in the table log. We only need to synchronise
+ these writes before moving to the next loop since there is no
+ interaction among reorganised partitions, they cannot have the
+ same name.
+ */
do
{
part_elem= temp_it++;
@@ -705,39 +687,57 @@
{
sub_elem= sub_it++;
file= m_reorged_file[part_count++];
- create_subpartition_name(part_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- RENAMED_PART_NAME);
create_subpartition_name(norm_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name,
NORMAL_PART_NAME);
- DBUG_PRINT("info", ("Rename subpartition from %s to %s",
- norm_name_buff, part_name_buff));
- error+= file->rename_table((const char *) norm_name_buff,
- (const char *) part_name_buff);
+ DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
+ if (file->delete_table((const char *) norm_name_buff) ||
+ inactivate_table_log_entry(sub_elem->log_entry->entry_pos))
+ error= 1;
+ else
+ sub_elem->log_entry= NULL; /* Indicate success */
} while (++j < no_subparts);
}
else
{
file= m_reorged_file[part_count++];
- create_partition_name(part_name_buff, path,
- part_elem->partition_name, RENAMED_PART_NAME,
- TRUE);
create_partition_name(norm_name_buff, path,
part_elem->partition_name, NORMAL_PART_NAME,
TRUE);
- DBUG_PRINT("info", ("Rename partition from %s to %s",
- norm_name_buff, part_name_buff));
- error+= file->rename_table((const char *) norm_name_buff,
- (const char *) part_name_buff);
+ DBUG_PRINT("info", ("Delete partition %s", norm_name_buff));
+ if (file->delete_table((const char *) norm_name_buff) ||
+ inactivate_table_log_entry(sub_elem->log_entry->entry_pos))
+ error= 1;
+ else
+ sub_elem->log_entry= NULL; /* Indicate success */
}
} while (++i < temp_partitions);
+ VOID(sync_table_log());
}
i= 0;
do
{
+ /*
+ When state is PART_IS_CHANGED it means that we have created a new
+ TEMP partition that is to be renamed to normal partition name and
+ we are to delete the old partition with currently the normal name.
+
+ We perform this operation by
+ 1) Delete old partition with normal partition name
+ 2) Signal this in table log entry
+ 3) Synch table log to ensure we have consistency in crashes
+ 4) Rename temporary partition name to normal partition name
+ 5) Signal this to table log entry
+ It is not necessary to synch the last state since a new rename
+ should not corrupt things if there was no temporary partition.
+
+ The only other parts we need to cater for are new parts that
+ replace reorganised parts. The reorganised parts were deleted
+ by the code above that goes through the temp_partitions list.
+ Thus the synch above makes it safe to simply perform step 4 and 5
+ for those entries.
+ */
part_elem= part_it++;
if (part_elem->part_state == PART_IS_CHANGED ||
(part_elem->part_state == PART_IS_ADDED && temp_partitions))
@@ -759,14 +759,11 @@
if (part_elem->part_state == PART_IS_CHANGED)
{
file= m_reorged_file[part_count++];
- create_subpartition_name(part_name_buff, path,
- part_elem->partition_name,
- sub_elem->partition_name,
- RENAMED_PART_NAME);
- DBUG_PRINT("info", ("Rename subpartition from %s to %s",
- norm_name_buff, part_name_buff));
- error+= file->rename_table((const char *) norm_name_buff,
- (const char *) part_name_buff);
+ DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
+ if (file->delete_table((const char *) norm_name_buff) ||
+ inactivate_table_log_entry(sub_elem->log_entry->entry_pos))
+ error= 1;
+ VOID(synch_table_log());
}
file= m_new_file[part];
create_subpartition_name(part_name_buff, path,
@@ -775,8 +772,12 @@
TEMP_PART_NAME);
DBUG_PRINT("info", ("Rename subpartition from %s to %s",
part_name_buff, norm_name_buff));
- error+= file->rename_table((const char *) part_name_buff,
- (const char *) norm_name_buff);
+ if (file->rename_table((const char *) norm_name_buff,
+ (const char *) part_name_buff) ||
+ inactivate_table_log_entry(sub_elem->log_entry->entry_pos))
+ error= 1;
+ else
+ sub_elem->log_entry= NULL;
} while (++j < no_subparts);
}
else
@@ -787,13 +788,11 @@
if (part_elem->part_state == PART_IS_CHANGED)
{
file= m_reorged_file[part_count++];
- create_partition_name(part_name_buff, path,
- part_elem->partition_name, RENAMED_PART_NAME,
- TRUE);
- DBUG_PRINT("info", ("Rename partition from %s to %s",
- norm_name_buff, part_name_buff));
- error+= file->rename_table((const char *) norm_name_buff,
- (const char *) part_name_buff);
+ DBUG_PRINT("info", ("Delete subpartition %s", norm_name_buff));
+ if (file->delete_table((const char *) norm_name_buff) ||
+ inactivate_table_log_entry(part_elem->log_entry->entry_pos))
+ error= 1;
+ VOID(synch_table_log());
}
file= m_new_file[i];
create_partition_name(part_name_buff, path,
@@ -801,11 +800,16 @@
TRUE);
DBUG_PRINT("info", ("Rename partition from %s to %s",
part_name_buff, norm_name_buff));
- error+= file->rename_table((const char *) part_name_buff,
- (const char *) norm_name_buff);
+ if (file->rename_table((const char *) norm_name_buff,
+ (const char *) part_name_buff) ||
+ inactivate_table_log_entry(part_elem->log_entry->entry_pos))
+ error= 1;
+ else
+ part_elem->log_entry= NULL;
}
}
} while (++i < no_parts);
+ VOID(synch_table_log());
DBUG_RETURN(error);
}
--- 1.44/sql/sql_partition.cc 2006-02-10 12:30:37 +01:00
+++ 1.45/sql/sql_partition.cc 2006-02-10 22:35:48 +01:00
@@ -5135,9 +5135,9 @@
DBUG_ENTER("write_log_rename_frm");
if (rename_flag)
- table_log_entry.action_type= 'r';
+ table_log_entry.action_type= TLOG_RENAME_ACTION_CODE;
else
- table_log_entry.action_type= 'd';
+ table_log_entry.action_type= TLOG_DELETE_ACTION_CODE;
table_log_entry.next_entry= next_entry;
table_log_entry.handler_type= "frm";
table_log_entry.name= to_path;
@@ -5160,6 +5160,18 @@
RETURN VALUES
TRUE Error
FALSE Success
+ DESCRIPTION
+ This code is used to perform safe ADD PARTITION for HASH partitions
+ and COALESCE for HASH partitions and REORGANIZE for any type of
+ partitions.
+ We prepare entries for all partitions except the reorganised partitions
+ in REORGANIZE partition, those are handled by
+ write_log_dropped_partitions. For those partitions that are replaced
+ special care is needed to ensure that this is performed correctly and
+ this requires a two-phased approach with this log as a helper for this.
+
+ This code is closely intertwined with the code in rename_partitions in
+ the partition handler.
*/
static
@@ -5167,7 +5179,84 @@
write_log_changed_partitions(ALTER_PARTITION_PARAM_TYPE *lpt,
uint *next_entry, const char *path)
{
+ TABLE_LOG_ENTRY table_log_entry;
+ partition_info *part_info= lpt->part_info;
+ TABLE_LOG_MEMORY_ENTRY *log_entry;
+ char tmp_path[FN_LEN];
+ char normal_path[FN_LEN];
+ List_iterator<partition_element> part_it(part_info->partitions);
+ uint temp_partitions= part_info->temp_partitions.elements;
+ uint no_elements= part_info->partitions.elements;
+ uint i= 0;
DBUG_ENTER("write_log_changed_partitions");
+
+ do
+ {
+ partition_element *part_elem= part_it++;
+ if (part_elem->part_state == PART_IS_CHANGED ||
+ (part_elem->part_state == PART_IS_ADDED && temp_partitions))
+ {
+ if (is_sub_partitioned(part_info))
+ {
+ List_iterator<partition_element> sub_it(part_elem->subpartitions);
+ uint no_subparts= part_info->no_subparts;
+ uint j= 0;
+ do
+ {
+ partition_element *sub_elem= sub_it++;
+ table_log_entry.next_entry= *next_entry;
+ table_log_entry.handler_type=
+ ha_resolve_storage_engine_name(sub_elem->engine_type);
+ create_subpartition_name(tmp_path, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ TEMP_PART_NAME);
+ create_subpartition_name(normal_path, path,
+ part_elem->partition_name,
+ sub_elem->partition_name,
+ NORMAL_PART_NAME);
+ table_log_entry.name= norm_path;
+ table_log_entry.from_name= tmp_path;
+ if (part_elem->part_state == PART_IS_CHANGED)
+ table_log_entry->action_type= TLOG_REPLACE_ACTION_CODE;
+ else
+ table_log_entry->action_type= TLOG_RENAME_ACTION_CODE;
+ if (write_table_log_entry(&table_log_entry, &log_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ *next_entry= log_entry->entry_pos;
+ sub_elem->log_entry= log_entry;
+ insert_part_info_log_entry_list(part_info, log_entry);
+ } while (++j < no_subparts);
+ }
+ else
+ {
+ table_log_entry.next_entry= *next_entry;
+ table_log_entry.handler_type=
+ ha_resolve_storage_engine_name(part_elem->engine_type);
+ create_partition_name(tmp_path, path,
+ part_elem->partition_name,
+ TEMP_PART_NAME, TRUE);
+ create_partition_name(normal_path, path,
+ part_elem->partition_name,
+ NORMAL_PART_NAME, TRUE);
+ table_log_entry.name= normal_path;
+ table_log_entry.from_name= tmp_path;
+ if (part_elem->part_state == PART_IS_CHANGED)
+ table_log_entry->action_type= TLOG_REPLACE_ACTION_CODE;
+ else
+ table_log_entry->action_type= TLOG_RENAME_ACTION_CODE;
+ if (write_table_log_entry(&table_log_entry, &log_entry))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ *next_entry= log_entry->entry_pos;
+ part_elem->table_log_entry= log_entry;
+ insert_part_info_log_entry_list(part_info, log_entry);
+ }
+ }
+ } while (++i < no_elements)
DBUG_RETURN(FALSE);
}
@@ -5200,7 +5289,7 @@
uint i= 0;
DBUG_ENTER("write_log_dropped_partitions");
- table_log_entry.action_type= 'd';
+ table_log_entry.action_type= TLOG_DELETE_ACTION_CODE;
if (temp_list)
no_elements= no_temp_partitions;
while (no_elements--)
@@ -5242,6 +5331,8 @@
DBUG_RETURN(TRUE);
}
*next_entry= log_entry->entry_pos;
+ if (temp_list)
+ sub_elem->table_log_entry= log_entry;
insert_part_info_log_entry_list(part_info, log_entry);
} while (++j < no_subparts);
}
@@ -5259,6 +5350,8 @@
DBUG_RETURN(TRUE);
}
*next_entry= log_entry->entry_pos;
+ if (temp_list)
+ part_elem->table_log_entry= log_entry;
insert_part_info_log_entry_list(part_info, log_entry);
}
}
@@ -5961,10 +6054,8 @@
ERROR_INJECT_CRASH("crash_change_partition_8") ||
(close_open_tables_and_downgrade(lpt), FALSE) ||
ERROR_INJECT_CRASH("crash_change_partition_9") ||
- mysql_drop_partitions(lpt) ||
- ERROR_INJECT_CRASH("crash_change_partition_10") ||
write_log_completed(lpt) ||
- ERROR_INJECT_CRASH("crash_change_partition_11") ||
+ ERROR_INJECT_CRASH("crash_change_partition_10") ||
(mysql_wait_completed_table(lpt, table), FALSE))
{
abort();
| Thread |
|---|
| • bk commit into 5.1 tree (mikron:1.2124) | mikael | 13 Feb |