@ -109,7 +109,8 @@ static char* add_identifier(THD* thd, char *to_p, const char * end_p,
tmp_name [ name_len ] = 0 ;
conv_name = tmp_name ;
}
res = strconvert ( & my_charset_filename , conv_name , system_charset_info ,
res = strconvert ( & my_charset_filename , conv_name , name_len ,
system_charset_info ,
conv_string , FN_REFLEN , & errors ) ;
if ( ! res | | errors )
{
@ -407,7 +408,7 @@ uint filename_to_tablename(const char *from, char *to, uint to_length
}
else
{
res = strconvert ( & my_charset_filename , from ,
res = strconvert ( & my_charset_filename , from , FN_REFLEN ,
system_charset_info , to , to_length , & errors ) ;
if ( errors ) // Old 5.0 name
{
@ -508,7 +509,7 @@ uint tablename_to_filename(const char *from, char *to, uint to_length)
}
DBUG_RETURN ( length ) ;
}
length = strconvert ( system_charset_info , from ,
length = strconvert ( system_charset_info , from , FN_REFLEN ,
& my_charset_filename , to , to_length , & errors ) ;
if ( check_if_legal_tablename ( to ) & &
length + 4 < to_length )
@ -564,7 +565,7 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db,
db , table_name , ext , flags ) ) ;
if ( flags & FN_IS_TMP ) // FN_FROM_IS_TMP | FN_TO_IS_TMP
strnmov ( tbbuff , table_name , sizeof ( tbbuff ) ) ;
strmake ( tbbuff , table_name , sizeof ( tbbuff ) - 1 ) ;
else
( void ) tablename_to_filename ( table_name , tbbuff , sizeof ( tbbuff ) ) ;
@ -579,8 +580,11 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db,
pos = strnmov ( pos , FN_ROOTDIR , end - pos ) ;
pos = strxnmov ( pos , end - pos , dbbuff , FN_ROOTDIR , NullS ) ;
# ifdef USE_SYMDIR
unpack_dirname ( buff , buff ) ;
pos = strend ( buff ) ;
if ( ! ( flags & SKIP_SYMDIR_ACCESS ) )
{
unpack_dirname ( buff , buff ) ;
pos = strend ( buff ) ;
}
# endif
pos = strxnmov ( pos , end - pos , tbbuff , ext , NullS ) ;
@ -687,14 +691,14 @@ mysql_mutex_t LOCK_gdl;
# define DDL_LOG_NAME_LEN_POS 4
# define DDL_LOG_IO_SIZE_POS 8
/*
Read one entry from ddl log file
SYNOPSIS
read_ddl_log_file_entry ( )
entry_no Entry number to read
RETURN VALUES
TRUE Error
FALSE Success
/**
Read one entry from ddl log file .
@ param entry_no Entry number to read
@ return Operation status
@ retval true Error
@ retval false Success
*/
static bool read_ddl_log_file_entry ( uint entry_no )
@ -713,14 +717,14 @@ static bool read_ddl_log_file_entry(uint entry_no)
}
/*
Write one entry from ddl log file
SYNOPSIS
write_ddl_log_file_entry ( )
entry_no Entry number to write
RETURN VALUES
TRUE Error
FALSE Success
/**
Write one entry to ddl log file .
@ param entry_no Entry number to write
@ return Operation status
@ retval true Error
@ retval false Success
*/
static bool write_ddl_log_file_entry ( uint entry_no )
@ -731,7 +735,7 @@ static bool write_ddl_log_file_entry(uint entry_no)
DBUG_ENTER ( " write_ddl_log_file_entry " ) ;
mysql_mutex_assert_owner ( & LOCK_gdl ) ;
if ( mysql_file_pwrite ( file_id , ( uchar * ) file_entry_buf ,
if ( mysql_file_pwrite ( file_id , file_entry_buf ,
IO_SIZE , IO_SIZE * entry_no , MYF ( MY_WME ) ) ! = IO_SIZE )
error = TRUE ;
DBUG_RETURN ( error ) ;
@ -769,7 +773,7 @@ static bool write_ddl_log_header()
int4store ( & global_ddl_log . file_entry_buf [ DDL_LOG_NUM_ENTRY_POS ] ,
global_ddl_log . num_entries ) ;
const_var = FN_LEN ;
const_var = FN_REF LEN ;
int4store ( & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_LEN_POS ] ,
( ulong ) const_var ) ;
const_var = IO_SIZE ;
@ -784,13 +788,9 @@ static bool write_ddl_log_header()
}
/*
Create ddl log file name
SYNOPSIS
create_ddl_log_file_name ( )
file_name Filename setup
RETURN VALUES
NONE
/**
Create ddl log file name .
@ param file_name Filename setup
*/
static inline void create_ddl_log_file_name ( char * file_name )
@ -799,17 +799,14 @@ static inline void create_ddl_log_file_name(char *file_name)
}
/*
Read header of ddl log file
SYNOPSIS
read_ddl_log_header ( )
RETURN VALUES
> 0 Last entry in ddl log
0 No entries in ddl log
DESCRIPTION
When we read the ddl log header we get information about maximum sizes
of names in the ddl log and we also get information about the number
of entries in the ddl log .
/**
Read header of ddl log file .
When we read the ddl log header we get information about maximum sizes
of names in the ddl log and we also get information about the number
of entries in the ddl log .
@ return Last entry in ddl log ( 0 if no entries )
*/
static uint read_ddl_log_header ( )
@ -820,6 +817,8 @@ static uint read_ddl_log_header()
bool successful_open = FALSE ;
DBUG_ENTER ( " read_ddl_log_header " ) ;
mysql_mutex_init ( key_LOCK_gdl , & LOCK_gdl , MY_MUTEX_INIT_SLOW ) ;
mysql_mutex_lock ( & LOCK_gdl ) ;
create_ddl_log_file_name ( file_name ) ;
if ( ( global_ddl_log . file_id = mysql_file_open ( key_file_global_ddl_log ,
file_name ,
@ -848,36 +847,72 @@ static uint read_ddl_log_header()
global_ddl_log . first_free = NULL ;
global_ddl_log . first_used = NULL ;
global_ddl_log . num_entries = 0 ;
mysql_mutex_init ( key_LOCK_gdl , & LOCK_gdl , MY_MUTEX_INIT_FAST ) ;
global_ddl_log . do_release = true ;
mysql_mutex_unlock ( & LOCK_gdl ) ;
DBUG_RETURN ( entry_no ) ;
}
/*
Read a ddl log entry
SYNOPSIS
read_ddl_log_entry ( )
read_entry Number of entry to read
out : entry_info Information from entry
RETURN VALUES
TRUE Error
FALSE Success
DESCRIPTION
Read a specified entry in the ddl log
/**
Convert from ddl_log_entry struct to file_entry_buf binary blob .
@ param ddl_log_entry filled in ddl_log_entry struct .
*/
bool read_ddl_log_entry ( uint read_entry , DDL_LOG_ENTRY * ddl_log_entry )
static void set_global_from_ddl_log_entry ( const DDL_LOG_ENTRY * ddl_log_entry )
{
char * file_entry_buf = ( char * ) & global_ddl_log . file_entry_buf ;
mysql_mutex_assert_owner ( & LOCK_gdl ) ;
global_ddl_log . file_entry_buf [ DDL_LOG_ENTRY_TYPE_POS ] =
( char ) DDL_LOG_ENTRY_CODE ;
global_ddl_log . file_entry_buf [ DDL_LOG_ACTION_TYPE_POS ] =
( char ) ddl_log_entry - > action_type ;
global_ddl_log . file_entry_buf [ DDL_LOG_PHASE_POS ] = 0 ;
int4store ( & global_ddl_log . file_entry_buf [ DDL_LOG_NEXT_ENTRY_POS ] ,
ddl_log_entry - > next_entry ) ;
DBUG_ASSERT ( strlen ( ddl_log_entry - > name ) < FN_REFLEN ) ;
strmake ( & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS ] ,
ddl_log_entry - > name , FN_REFLEN - 1 ) ;
if ( ddl_log_entry - > action_type = = DDL_LOG_RENAME_ACTION | |
ddl_log_entry - > action_type = = DDL_LOG_REPLACE_ACTION | |
ddl_log_entry - > action_type = = DDL_LOG_EXCHANGE_ACTION )
{
DBUG_ASSERT ( strlen ( ddl_log_entry - > from_name ) < FN_REFLEN ) ;
strmake ( & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS + FN_REFLEN ] ,
ddl_log_entry - > from_name , FN_REFLEN - 1 ) ;
}
else
global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS + FN_REFLEN ] = 0 ;
DBUG_ASSERT ( strlen ( ddl_log_entry - > handler_name ) < FN_REFLEN ) ;
strmake ( & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS + ( 2 * FN_REFLEN ) ] ,
ddl_log_entry - > handler_name , FN_REFLEN - 1 ) ;
if ( ddl_log_entry - > action_type = = DDL_LOG_EXCHANGE_ACTION )
{
DBUG_ASSERT ( strlen ( ddl_log_entry - > tmp_name ) < FN_REFLEN ) ;
strmake ( & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS + ( 3 * FN_REFLEN ) ] ,
ddl_log_entry - > tmp_name , FN_REFLEN - 1 ) ;
}
else
global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS + ( 3 * FN_REFLEN ) ] = 0 ;
}
/**
Convert from file_entry_buf binary blob to ddl_log_entry struct .
@ param [ out ] ddl_log_entry struct to fill in .
@ note Strings ( names ) are pointing to the global_ddl_log structure ,
so LOCK_gdl needs to be hold until they are read or copied .
*/
static void set_ddl_log_entry_from_global ( DDL_LOG_ENTRY * ddl_log_entry ,
const uint read_entry )
{
char * file_entry_buf = ( char * ) global_ddl_log . file_entry_buf ;
uint inx ;
uchar single_char ;
DBUG_ENTER ( " read_ddl_log_entry " ) ;
if ( read_ddl_log_file_entry ( read_entry ) )
{
DBUG_RETURN ( TRUE ) ;
}
mysql_mutex_assert_owner ( & LOCK_gdl ) ;
ddl_log_entry - > entry_pos = read_entry ;
single_char = file_entry_buf [ DDL_LOG_ENTRY_TYPE_POS ] ;
ddl_log_entry - > entry_type = ( enum ddl_log_entry_code ) single_char ;
@ -890,22 +925,51 @@ bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
ddl_log_entry - > from_name = & file_entry_buf [ inx ] ;
inx + = global_ddl_log . name_len ;
ddl_log_entry - > handler_name = & file_entry_buf [ inx ] ;
if ( ddl_log_entry - > action_type = = DDL_LOG_EXCHANGE_ACTION )
{
inx + = global_ddl_log . name_len ;
ddl_log_entry - > tmp_name = & file_entry_buf [ inx ] ;
}
else
ddl_log_entry - > tmp_name = NULL ;
}
/**
Read a ddl log entry .
Read a specified entry in the ddl log .
@ param read_entry Number of entry to read
@ param [ out ] entry_info Information from entry
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
static bool read_ddl_log_entry ( uint read_entry , DDL_LOG_ENTRY * ddl_log_entry )
{
DBUG_ENTER ( " read_ddl_log_entry " ) ;
if ( read_ddl_log_file_entry ( read_entry ) )
{
DBUG_RETURN ( TRUE ) ;
}
set_ddl_log_entry_from_global ( ddl_log_entry , read_entry ) ;
DBUG_RETURN ( FALSE ) ;
}
/*
Initialise ddl log
SYNOPSIS
init_ddl_log ( )
/**
Initialise ddl log .
DESCRIPTION
Write the header of the ddl log file and length of names . Also set
number of entries to zero .
Write the header of the ddl log file and length of names . Also set
number of entries to zero .
RETURN VALUES
TRUE Error
FALSE Success
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
static bool init_ddl_log ( )
@ -917,7 +981,7 @@ static bool init_ddl_log()
goto end ;
global_ddl_log . io_size = IO_SIZE ;
global_ddl_log . name_len = FN_LEN ;
global_ddl_log . name_len = FN_REF LEN ;
create_ddl_log_file_name ( file_name ) ;
if ( ( global_ddl_log . file_id = mysql_file_create ( key_file_global_ddl_log ,
file_name , CREATE_MODE ,
@ -1043,14 +1107,14 @@ static bool deactivate_ddl_log_entry_no_lock(uint entry_no)
}
/*
/**
Execute one action in a ddl log entry
SYNOPSIS
execute_ddl_log_action ( )
ddl_log_entry Information in action entry to execute
RETURN VALUES
TRUE Error
FALSE Success
@ param ddl_log_entry Information in action entry to execute
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
static int execute_ddl_log_action ( THD * thd , DDL_LOG_ENTRY * ddl_log_entry )
@ -1068,6 +1132,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
handlerton * hton ;
DBUG_ENTER ( " execute_ddl_log_action " ) ;
mysql_mutex_assert_owner ( & LOCK_gdl ) ;
if ( ddl_log_entry - > entry_type = = DDL_IGNORE_LOG_ENTRY_CODE )
{
DBUG_RETURN ( FALSE ) ;
@ -1132,7 +1197,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
}
if ( ( deactivate_ddl_log_entry_no_lock ( ddl_log_entry - > entry_pos ) ) )
break ;
( void ) sync_ddl_log ( ) ;
( void ) sync_ddl_log_no_lock ( ) ;
error = FALSE ;
if ( ddl_log_entry - > action_type = = DDL_LOG_DELETE_ACTION )
break ;
@ -1165,9 +1230,9 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
ddl_log_entry - > name ) )
break ;
}
if ( ( deactivate_ddl_log_entry ( ddl_log_entry - > entry_pos ) ) )
if ( ( deactivate_ddl_log_entry_no_lock ( ddl_log_entry - > entry_pos ) ) )
break ;
( void ) sync_ddl_log ( ) ;
( void ) sync_ddl_log_no_lock ( ) ;
error = FALSE ;
break ;
}
@ -1234,14 +1299,14 @@ error:
}
/*
/**
Get a free entry in the ddl log
SYNOPSIS
get_free_ddl_log_entry ( )
out : active_entry A ddl log memory entry returned
RETURN VALUES
TRUE Error
FALSE Success
@ param [ out ] active_entry A ddl log memory entry returned
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
static bool get_free_ddl_log_entry ( DDL_LOG_MEMORY_ENTRY * * active_entry ,
@ -1284,24 +1349,67 @@ static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
}
/**
Execute one entry in the ddl log .
Executing an entry means executing a linked list of actions .
@ param first_entry Reference to first action in entry
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
static bool execute_ddl_log_entry_no_lock ( THD * thd , uint first_entry )
{
DDL_LOG_ENTRY ddl_log_entry ;
uint read_entry = first_entry ;
DBUG_ENTER ( " execute_ddl_log_entry_no_lock " ) ;
mysql_mutex_assert_owner ( & LOCK_gdl ) ;
do
{
if ( read_ddl_log_entry ( read_entry , & ddl_log_entry ) )
{
/* Write to error log and continue with next log entry */
sql_print_error ( " Failed to read entry = %u from ddl log " ,
read_entry ) ;
break ;
}
DBUG_ASSERT ( ddl_log_entry . entry_type = = DDL_LOG_ENTRY_CODE | |
ddl_log_entry . entry_type = = DDL_IGNORE_LOG_ENTRY_CODE ) ;
if ( execute_ddl_log_action ( thd , & ddl_log_entry ) )
{
/* Write to error log and continue with next log entry */
sql_print_error ( " Failed to execute action for entry = %u from ddl log " ,
read_entry ) ;
break ;
}
read_entry = ddl_log_entry . next_entry ;
} while ( read_entry ) ;
DBUG_RETURN ( FALSE ) ;
}
/*
External interface methods for the DDL log Module
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
/*
SYNOPSIS
write_ddl_log_entry ( )
ddl_log_entry Information about log entry
out : entry_written Entry information written into
/**
Write a ddl log entry .
RETURN VALUES
TRUE Error
FALSE Success
A careful write of the ddl log is performed to ensure that we can
handle crashes occurring during CREATE and ALTER TABLE processing .
DESCRIPTION
A careful write of the ddl log is performed to ensure that we can
handle crashes occurring during CREATE and ALTER TABLE processing .
@ param ddl_log_entry Information about log entry
@ param [ out ] entry_written Entry information written into
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
bool write_ddl_log_entry ( DDL_LOG_ENTRY * ddl_log_entry ,
@ -1310,46 +1418,29 @@ bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
bool error , write_header ;
DBUG_ENTER ( " write_ddl_log_entry " ) ;
mysql_mutex_assert_owner ( & LOCK_gdl ) ;
if ( init_ddl_log ( ) )
{
DBUG_RETURN ( TRUE ) ;
}
global_ddl_log . file_entry_buf [ DDL_LOG_ENTRY_TYPE_POS ] =
( char ) DDL_LOG_ENTRY_CODE ;
global_ddl_log . file_entry_buf [ DDL_LOG_ACTION_TYPE_POS ] =
( char ) ddl_log_entry - > action_type ;
global_ddl_log . file_entry_buf [ DDL_LOG_PHASE_POS ] = 0 ;
int4store ( & global_ddl_log . file_entry_buf [ DDL_LOG_NEXT_ENTRY_POS ] ,
ddl_log_entry - > next_entry ) ;
DBUG_ASSERT ( strlen ( ddl_log_entry - > name ) < FN_LEN ) ;
strmake ( & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS ] ,
ddl_log_entry - > name , FN_LEN - 1 ) ;
if ( ddl_log_entry - > action_type = = DDL_LOG_RENAME_ACTION | |
ddl_log_entry - > action_type = = DDL_LOG_REPLACE_ACTION )
{
DBUG_ASSERT ( strlen ( ddl_log_entry - > from_name ) < FN_LEN ) ;
strmake ( & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS + FN_LEN ] ,
ddl_log_entry - > from_name , FN_LEN - 1 ) ;
}
else
global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS + FN_LEN ] = 0 ;
DBUG_ASSERT ( strlen ( ddl_log_entry - > handler_name ) < FN_LEN ) ;
strmake ( & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS + ( 2 * FN_LEN ) ] ,
ddl_log_entry - > handler_name , FN_LEN - 1 ) ;
set_global_from_ddl_log_entry ( ddl_log_entry ) ;
if ( get_free_ddl_log_entry ( active_entry , & write_header ) )
{
DBUG_RETURN ( TRUE ) ;
}
error = FALSE ;
DBUG_PRINT ( " ddl_log " ,
( " write type %c next %u name '%s' from_name '%s' handler '%s' " ,
( " write type %c next %u name '%s' from_name '%s' handler '%s' "
" tmp_name '%s' " ,
( char ) global_ddl_log . file_entry_buf [ DDL_LOG_ACTION_TYPE_POS ] ,
ddl_log_entry - > next_entry ,
( char * ) & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS ] ,
( char * ) & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS
+ FN_LEN ] ,
+ FN_REFLEN ] ,
( char * ) & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS
+ ( 2 * FN_LEN ) ] ) ) ;
+ ( 2 * FN_REFLEN ) ] ,
( char * ) & global_ddl_log . file_entry_buf [ DDL_LOG_NAME_POS
+ ( 3 * FN_REFLEN ) ] ) ) ;
if ( write_ddl_log_file_entry ( ( * active_entry ) - > entry_pos ) )
{
error = TRUE ;
@ -1358,7 +1449,7 @@ bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
}
if ( write_header & & ! error )
{
( void ) sync_ddl_log ( ) ;
( void ) sync_ddl_log_no_lock ( ) ;
if ( write_ddl_log_header ( ) )
error = TRUE ;
}
@ -1368,31 +1459,30 @@ bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
}
/*
Write final entry in the ddl log
SYNOPSIS
write_execute_ddl_log_entry ( )
first_entry First entry in linked list of entries
/**
@ brief Write final entry in the ddl log .
@ details This is the last write in the ddl log . The previous log entries
have already been written but not yet synched to disk .
We write a couple of log entries that describes action to perform .
This entries are set - up in a linked list , however only when a first
execute entry is put as the first entry these will be executed .
This routine writes this first .
@ param 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 .
complete Flag indicating we are simply writing
@ param complete Flag indicating we are simply writing
info about that entry has been completed
in : out : active_entry Entry to execute , 0 = NULL if the entry
@ param [ in , out ] active_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 ddl log . The previous log entries have
already been written but not yet synched to disk .
We write a couple of log entries that describes action to perform .
This entries are set - up in a linked list , however only when a first
execute entry is put as the first entry these will be executed .
This routine writes this first
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
bool write_execute_ddl_log_entry ( uint first_entry ,
@ -1403,6 +1493,7 @@ bool write_execute_ddl_log_entry(uint first_entry,
char * file_entry_buf = ( char * ) global_ddl_log . file_entry_buf ;
DBUG_ENTER ( " write_execute_ddl_log_entry " ) ;
mysql_mutex_assert_owner ( & LOCK_gdl ) ;
if ( init_ddl_log ( ) )
{
DBUG_RETURN ( TRUE ) ;
@ -1415,7 +1506,7 @@ bool write_execute_ddl_log_entry(uint first_entry,
any log entries before , we are only here to write the execute
entry to indicate it is done .
*/
( void ) sync_ddl_log ( ) ;
( void ) sync_ddl_log_no_lock ( ) ;
file_entry_buf [ DDL_LOG_ENTRY_TYPE_POS ] = ( char ) DDL_LOG_EXECUTE_CODE ;
}
else
@ -1424,14 +1515,15 @@ bool write_execute_ddl_log_entry(uint first_entry,
file_entry_buf [ DDL_LOG_PHASE_POS ] = 0 ;
int4store ( & file_entry_buf [ DDL_LOG_NEXT_ENTRY_POS ] , first_entry ) ;
file_entry_buf [ DDL_LOG_NAME_POS ] = 0 ;
file_entry_buf [ DDL_LOG_NAME_POS + FN_LEN ] = 0 ;
file_entry_buf [ DDL_LOG_NAME_POS + 2 * FN_LEN ] = 0 ;
file_entry_buf [ DDL_LOG_NAME_POS + FN_REF LEN ] = 0 ;
file_entry_buf [ DDL_LOG_NAME_POS + 2 * FN_REF LEN ] = 0 ;
if ( ! ( * active_entry ) )
{
if ( get_free_ddl_log_entry ( active_entry , & write_header ) )
{
DBUG_RETURN ( TRUE ) ;
}
write_header = TRUE ;
}
if ( write_ddl_log_file_entry ( ( * active_entry ) - > entry_pos ) )
{
@ -1439,7 +1531,7 @@ bool write_execute_ddl_log_entry(uint first_entry,
release_ddl_log_memory_entry ( * active_entry ) ;
DBUG_RETURN ( TRUE ) ;
}
( void ) sync_ddl_log ( ) ;
( void ) sync_ddl_log_no_lock ( ) ;
if ( write_header )
{
if ( write_ddl_log_header ( ) )
@ -1452,106 +1544,54 @@ bool write_execute_ddl_log_entry(uint first_entry,
}
/*
For complex rename operations we need to deactivate individual entries .
SYNOPSIS
deactivate_ddl_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 ddl 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 .
/**
Deactivate an individual entry .
@ details see deactivate_ddl_log_entry_no_lock .
@ param entry_no Entry position of record to change
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
bool deactivate_ddl_log_entry ( uint entry_no )
{
char * file_entry_buf = ( char * ) global_ddl_log . file_entry_buf ;
bool error ;
DBUG_ENTER ( " deactivate_ddl_log_entry " ) ;
if ( ! read_ddl_log_file_entry ( entry_no ) )
{
if ( file_entry_buf [ DDL_LOG_ENTRY_TYPE_POS ] = = DDL_LOG_ENTRY_CODE )
{
if ( file_entry_buf [ DDL_LOG_ACTION_TYPE_POS ] = = DDL_LOG_DELETE_ACTION | |
file_entry_buf [ DDL_LOG_ACTION_TYPE_POS ] = = DDL_LOG_RENAME_ACTION | |
( file_entry_buf [ DDL_LOG_ACTION_TYPE_POS ] = = DDL_LOG_REPLACE_ACTION & &
file_entry_buf [ DDL_LOG_PHASE_POS ] = = 1 ) )
file_entry_buf [ DDL_LOG_ENTRY_TYPE_POS ] = DDL_IGNORE_LOG_ENTRY_CODE ;
else if ( file_entry_buf [ DDL_LOG_ACTION_TYPE_POS ] = = DDL_LOG_REPLACE_ACTION )
{
DBUG_ASSERT ( file_entry_buf [ DDL_LOG_PHASE_POS ] = = 0 ) ;
file_entry_buf [ DDL_LOG_PHASE_POS ] = 1 ;
}
else
{
DBUG_ASSERT ( 0 ) ;
}
if ( write_ddl_log_file_entry ( entry_no ) )
{
sql_print_error ( " Error in deactivating log entry. Position = %u " ,
entry_no ) ;
DBUG_RETURN ( TRUE ) ;
}
}
}
else
{
sql_print_error ( " Failed in reading entry before deactivating it " ) ;
DBUG_RETURN ( TRUE ) ;
}
DBUG_RETURN ( FALSE ) ;
mysql_mutex_lock ( & LOCK_gdl ) ;
error = deactivate_ddl_log_entry_no_lock ( entry_no ) ;
mysql_mutex_unlock ( & LOCK_gdl ) ;
DBUG_RETURN ( error ) ;
}
/*
Sync ddl log file
SYNOPSIS
sync_ddl_log ( )
RETURN VALUES
TRUE Error
FALSE Success
/**
Sync ddl log file .
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
bool sync_ddl_log ( )
{
bool error = FALSE ;
bool error ;
DBUG_ENTER ( " sync_ddl_log " ) ;
if ( ( ! global_ddl_log . recovery_phase ) & &
init_ddl_log ( ) )
{
DBUG_RETURN ( TRUE ) ;
}
if ( mysql_file_sync ( global_ddl_log . file_id , MYF ( 0 ) ) )
{
/* Write to error log */
sql_print_error ( " Failed to sync ddl log " ) ;
error = TRUE ;
}
mysql_mutex_lock ( & LOCK_gdl ) ;
error = sync_ddl_log_no_lock ( ) ;
mysql_mutex_unlock ( & LOCK_gdl ) ;
DBUG_RETURN ( error ) ;
}
/*
Release a log memory entry
SYNOPSIS
release_ddl_log_memory_entry ( )
log_memory_entry Log memory entry to release
RETURN VALUES
NONE
/**
Release a log memory entry .
@ param log_memory_entry Log memory entry to release
*/
void release_ddl_log_memory_entry ( DDL_LOG_MEMORY_ENTRY * log_entry )
@ -1561,6 +1601,7 @@ void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
DDL_LOG_MEMORY_ENTRY * prev_log_entry = log_entry - > prev_log_entry ;
DBUG_ENTER ( " release_ddl_log_memory_entry " ) ;
mysql_mutex_assert_owner ( & LOCK_gdl ) ;
global_ddl_log . first_free = log_entry ;
log_entry - > next_log_entry = first_free ;
@ -1574,56 +1615,32 @@ void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
}
/*
Execute one entry in the ddl log . Executing an entry means executing
a linked list of actions .
SYNOPSIS
execute_ddl_log_entry ( )
first_entry Reference to first action in entry
RETURN VALUES
TRUE Error
FALSE Success
/**
Execute one entry in the ddl log .
Executing an entry means executing a linked list of actions .
@ param first_entry Reference to first action in entry
@ return Operation status
@ retval TRUE Error
@ retval FALSE Success
*/
bool execute_ddl_log_entry ( THD * thd , uint first_entry )
{
DDL_LOG_ENTRY ddl_log_entry ;
uint read_entry = first_entry ;
bool error ;
DBUG_ENTER ( " execute_ddl_log_entry " ) ;
mysql_mutex_lock ( & LOCK_gdl ) ;
do
{
if ( read_ddl_log_entry ( read_entry , & ddl_log_entry ) )
{
/* Write to error log and continue with next log entry */
sql_print_error ( " Failed to read entry = %u from ddl log " ,
read_entry ) ;
break ;
}
DBUG_ASSERT ( ddl_log_entry . entry_type = = DDL_LOG_ENTRY_CODE | |
ddl_log_entry . entry_type = = DDL_IGNORE_LOG_ENTRY_CODE ) ;
if ( execute_ddl_log_action ( thd , & ddl_log_entry ) )
{
/* Write to error log and continue with next log entry */
sql_print_error ( " Failed to execute action for entry = %u from ddl log " ,
read_entry ) ;
break ;
}
read_entry = ddl_log_entry . next_entry ;
} while ( read_entry ) ;
error = execute_ddl_log_entry_no_lock ( thd , first_entry ) ;
mysql_mutex_unlock ( & LOCK_gdl ) ;
DBUG_RETURN ( FALSE ) ;
DBUG_RETURN ( error ) ;
}
/*
Close the ddl log
SYNOPSIS
close_ddl_log ( )
RETURN VALUES
NONE
/**
Close the ddl log .
*/
static void close_ddl_log ( )
@ -1638,12 +1655,8 @@ static void close_ddl_log()
}
/*
Execute the ddl log at recovery of MySQL Server
SYNOPSIS
execute_ddl_log_recovery ( )
RETURN VALUES
NONE
/**
Execute the ddl log at recovery of MySQL Server .
*/
void execute_ddl_log_recovery ( )
@ -1676,6 +1689,7 @@ void execute_ddl_log_recovery()
/* this also initialize LOCK_gdl */
num_entries = read_ddl_log_header ( ) ;
mysql_mutex_lock ( & LOCK_gdl ) ;
for ( i = 1 ; i < num_entries + 1 ; i + + )
{
if ( read_ddl_log_entry ( i , & ddl_log_entry ) )
@ -1686,7 +1700,7 @@ void execute_ddl_log_recovery()
}
if ( ddl_log_entry . entry_type = = DDL_LOG_EXECUTE_CODE )
{
if ( execute_ddl_log_entry ( thd , ddl_log_entry . next_entry ) )
if ( execute_ddl_log_entry_no_lock ( thd , ddl_log_entry . next_entry ) )
{
/* Real unpleasant scenario but we continue anyways. */
continue ;
@ -1697,6 +1711,7 @@ void execute_ddl_log_recovery()
create_ddl_log_file_name ( file_name ) ;
( void ) mysql_file_delete ( key_file_global_ddl_log , file_name , MYF ( 0 ) ) ;
global_ddl_log . recovery_phase = FALSE ;
mysql_mutex_unlock ( & LOCK_gdl ) ;
delete thd ;
/* Remember that we don't have a THD */
set_current_thd ( 0 ) ;
@ -1704,24 +1719,22 @@ void execute_ddl_log_recovery()
}
/*
Release all memory allocated to the ddl log
SYNOPSIS
release_ddl_log ( )
RETURN VALUES
NONE
/**
Release all memory allocated to the ddl log .
*/
void release_ddl_log ( )
{
DDL_LOG_MEMORY_ENTRY * free_list = global_ddl_log . first_free ;
DDL_LOG_MEMORY_ENTRY * used_list = global_ddl_log . first_used ;
DDL_LOG_MEMORY_ENTRY * free_list ;
DDL_LOG_MEMORY_ENTRY * used_list ;
DBUG_ENTER ( " release_ddl_log " ) ;
if ( ! global_ddl_log . do_release )
DBUG_VOID_RETURN ;
mysql_mutex_lock ( & LOCK_gdl ) ;
free_list = global_ddl_log . first_free ;
used_list = global_ddl_log . first_used ;
while ( used_list )
{
DDL_LOG_MEMORY_ENTRY * tmp = used_list - > next_log_entry ;