183
143
Uses database and table name, and extension to create
184
a file name in drizzle_data_dir. Database and table
144
a file name in mysql_data_dir. Database and table
185
145
names are converted from system_charset_info into "fscs".
186
146
Unless flags indicate a temporary table name.
187
147
'db' is always converted.
188
148
'ext' is not converted.
190
The conversion suppression is required for ALTER Table. This
150
The conversion suppression is required for ALTER TABLE. This
191
151
statement creates intermediate tables. These are regular
192
152
(non-temporary) tables with a temporary name. Their path names must
193
153
be derivable from the table name. So we cannot use
194
154
build_tmptable_filename() for them.
197
path length on success, 0 on failure
200
uint32_t build_table_filename(char *buff, size_t bufflen, const char *db,
201
const char *table_name, const char *ext, uint32_t flags)
160
uint build_table_filename(char *buff, size_t bufflen, const char *db,
161
const char *table_name, const char *ext, uint flags)
204
163
char dbbuff[FN_REFLEN];
205
164
char tbbuff[FN_REFLEN];
166
if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
167
strnmov(tbbuff, table_name, sizeof(tbbuff));
169
VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)));
171
VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
173
char *end = buff + bufflen;
174
/* Don't add FN_ROOTDIR if mysql_data_home already includes it */
175
char *pos = strnmov(buff, mysql_data_home, bufflen);
206
176
int rootdir_len= strlen(FN_ROOTDIR);
208
if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
209
strncpy(tbbuff, table_name, sizeof(tbbuff));
211
tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
213
tablename_to_filename(db, dbbuff, sizeof(dbbuff));
214
table_path= drizzle_data_home;
215
int without_rootdir= table_path.length()-rootdir_len;
217
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
218
if (without_rootdir >= 0)
220
char *tmp= (char*)table_path.c_str()+without_rootdir;
221
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
222
table_path.append(FN_ROOTDIR);
225
table_path.append(dbbuff);
226
table_path.append(FN_ROOTDIR);
177
if (pos - rootdir_len >= buff &&
178
memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
179
pos= strnmov(pos, FN_ROOTDIR, end - pos);
180
pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
227
181
#ifdef USE_SYMDIR
182
unpack_dirname(buff, buff);
230
table_path.append(tbbuff);
231
table_path.append(ext);
233
if (bufflen < table_path.length())
236
strcpy(buff, table_path.c_str());
237
return table_path.length();
185
pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
242
Creates path to a file: drizzle_tmpdir/#sql1234_12_1.ext
192
Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
245
195
build_tmptable_filename()
246
session The thread handle.
196
thd The thread handle.
247
197
buff Where to write result in my_charset_filename.
248
198
bufflen buff size
252
202
Uses current_pid, thread_id, and tmp_table counter to create
253
a file name in drizzle_tmpdir.
203
a file name in mysql_tmpdir.
256
path length on success, 0 on failure
259
uint32_t build_tmptable_filename(Session* session, char *buff, size_t bufflen)
209
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
262
ostringstream path_str, post_tmpdir_str;
265
path_str << drizzle_tmpdir;
266
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
267
post_tmpdir_str << session->thread_id << session->tmp_table++;
268
tmp= post_tmpdir_str.str();
212
char *p= strnmov(buff, mysql_tmpdir, bufflen);
213
snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s",
214
tmp_file_prefix, current_pid,
215
thd->thread_id, thd->tmp_table++, reg_ext);
270
217
if (lower_case_table_names)
271
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
275
if (bufflen < path_str.str().length())
278
length= unpack_filename(buff, path_str.str().c_str());
219
/* Convert all except tmpdir to lower case */
220
my_casedn_str(files_charset_info, p);
223
uint length= unpack_filename(buff, buff);
228
--------------------------------------------------------------------------
233
This module is used to ensure that we can recover from crashes that occur
234
in the middle of a meta-data operation in MySQL. E.g. DROP TABLE t1, t2;
235
We need to ensure that both t1 and t2 are dropped and not only t1 and
236
also that each table drop is entirely done and not "half-baked".
238
To support this we create log entries for each meta-data statement in the
239
ddl log while we are executing. These entries are dropped when the
240
operation is completed.
242
At recovery those entries that were not completed will be executed.
244
There is only one ddl log in the system and it is protected by a mutex
245
and there is a global struct that contains information about its current
249
First version written in 2006 by Mikael Ronstrom
250
--------------------------------------------------------------------------
254
struct st_global_ddl_log
257
We need to adjust buffer size to be able to handle downgrades/upgrades
258
where IO_SIZE has changed. We'll set the buffer size such that we can
259
handle that the buffer size was upto 4 times bigger in the version
260
that wrote the DDL log.
262
char file_entry_buf[4*IO_SIZE];
263
char file_name_str[FN_REFLEN];
265
DDL_LOG_MEMORY_ENTRY *first_free;
266
DDL_LOG_MEMORY_ENTRY *first_used;
274
st_global_ddl_log() : inited(false), do_release(false) {}
277
st_global_ddl_log global_ddl_log;
279
pthread_mutex_t LOCK_gdl;
281
#define DDL_LOG_ENTRY_TYPE_POS 0
282
#define DDL_LOG_ACTION_TYPE_POS 1
283
#define DDL_LOG_PHASE_POS 2
284
#define DDL_LOG_NEXT_ENTRY_POS 4
285
#define DDL_LOG_NAME_POS 8
287
#define DDL_LOG_NUM_ENTRY_POS 0
288
#define DDL_LOG_NAME_LEN_POS 4
289
#define DDL_LOG_IO_SIZE_POS 8
292
Read one entry from ddl log file
294
read_ddl_log_file_entry()
295
entry_no Entry number to read
301
static bool read_ddl_log_file_entry(uint entry_no)
304
File file_id= global_ddl_log.file_id;
305
uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
306
ssize_t io_size= (ssize_t)global_ddl_log.io_size;
308
if (pread(file_id, file_entry_buf, io_size, io_size * entry_no) != io_size)
315
Write one entry from ddl log file
317
write_ddl_log_file_entry()
318
entry_no Entry number to read
324
static bool write_ddl_log_file_entry(uint entry_no)
327
File file_id= global_ddl_log.file_id;
328
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
330
if (pwrite(file_id, (uchar*)file_entry_buf,
331
IO_SIZE, IO_SIZE * entry_no) != IO_SIZE)
340
write_ddl_log_header()
346
static bool write_ddl_log_header()
351
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
352
global_ddl_log.num_entries);
354
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
357
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
359
if (write_ddl_log_file_entry(0UL))
361
sql_print_error("Error writing ddl log header");
364
VOID(sync_ddl_log());
370
Create ddl log file name
372
create_ddl_log_file_name()
373
file_name Filename setup
378
static inline void create_ddl_log_file_name(char *file_name)
380
strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
385
Read header of ddl log file
387
read_ddl_log_header()
389
> 0 Last entry in ddl log
390
0 No entries in ddl log
392
When we read the ddl log header we get information about maximum sizes
393
of names in the ddl log and we also get information about the number
394
of entries in the ddl log.
397
static uint read_ddl_log_header()
399
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
400
char file_name[FN_REFLEN];
402
bool successful_open= false;
404
create_ddl_log_file_name(file_name);
405
if ((global_ddl_log.file_id= my_open(file_name,
406
O_RDWR | O_BINARY, MYF(0))) >= 0)
408
if (read_ddl_log_file_entry(0UL))
410
/* Write message into error log */
411
sql_print_error("Failed to read ddl log file in recovery");
414
successful_open= true;
416
entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
417
global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
420
global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
421
assert(global_ddl_log.io_size <=
422
sizeof(global_ddl_log.file_entry_buf));
428
global_ddl_log.first_free= NULL;
429
global_ddl_log.first_used= NULL;
430
global_ddl_log.num_entries= 0;
431
VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST));
432
global_ddl_log.do_release= true;
441
read_entry Number of entry to read
442
out:entry_info Information from entry
447
Read a specified entry in the ddl log
450
bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
452
char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
456
if (read_ddl_log_file_entry(read_entry))
460
ddl_log_entry->entry_pos= read_entry;
461
single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
462
ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
463
single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
464
ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
465
ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
466
ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
467
ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
468
inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
469
ddl_log_entry->from_name= &file_entry_buf[inx];
470
inx+= global_ddl_log.name_len;
471
ddl_log_entry->handler_name= &file_entry_buf[inx];
482
Write the header of the ddl log file and length of names. Also set
483
number of entries to zero.
490
static bool init_ddl_log()
492
char file_name[FN_REFLEN];
494
if (global_ddl_log.inited)
497
global_ddl_log.io_size= IO_SIZE;
498
create_ddl_log_file_name(file_name);
499
if ((global_ddl_log.file_id= my_create(file_name,
501
O_RDWR | O_TRUNC | O_BINARY,
504
/* Couldn't create ddl log file, this is serious error */
505
sql_print_error("Failed to open ddl log file");
508
global_ddl_log.inited= true;
509
if (write_ddl_log_header())
511
VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
512
global_ddl_log.inited= false;
522
Execute one action in a ddl log entry
524
execute_ddl_log_action()
525
ddl_log_entry Information in action entry to execute
531
static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
533
bool frm_action= false;
534
LEX_STRING handler_name;
538
char to_path[FN_REFLEN];
539
char from_path[FN_REFLEN];
542
if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
546
handler_name.str= (char*)ddl_log_entry->handler_name;
547
handler_name.length= strlen(ddl_log_entry->handler_name);
548
init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
549
if (!strcmp(ddl_log_entry->handler_name, reg_ext))
553
plugin_ref plugin= ha_resolve_by_name(thd, &handler_name);
556
my_error(ER_ILLEGAL_HA, MYF(0), ddl_log_entry->handler_name);
559
hton= plugin_data(plugin, handlerton*);
560
file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
563
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
567
switch (ddl_log_entry->action_type)
569
case DDL_LOG_REPLACE_ACTION:
570
case DDL_LOG_DELETE_ACTION:
572
if (ddl_log_entry->phase == 0)
576
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
577
if ((error= my_delete(to_path, MYF(MY_WME))))
579
if (my_errno != ENOENT)
585
if ((error= file->ha_delete_table(ddl_log_entry->name)))
587
if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
591
if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
593
VOID(sync_ddl_log());
595
if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
598
assert(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
600
Fall through and perform the rename action of the replace
601
action. We have already indicated the success of the delete
602
action in the log entry by stepping up the phase.
605
case DDL_LOG_RENAME_ACTION:
610
strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
611
strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
612
if (my_rename(from_path, to_path, MYF(MY_WME)))
617
if (file->ha_rename_table(ddl_log_entry->from_name,
618
ddl_log_entry->name))
621
if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos)))
623
VOID(sync_ddl_log());
633
free_root(&mem_root, MYF(0));
639
Get a free entry in the ddl log
641
get_free_ddl_log_entry()
642
out:active_entry A ddl log memory entry returned
648
static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
651
DDL_LOG_MEMORY_ENTRY *used_entry;
652
DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
654
if (global_ddl_log.first_free == NULL)
656
if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
657
sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
659
sql_print_error("Failed to allocate memory for ddl log free list");
662
global_ddl_log.num_entries++;
663
used_entry->entry_pos= global_ddl_log.num_entries;
668
used_entry= global_ddl_log.first_free;
669
global_ddl_log.first_free= used_entry->next_log_entry;
670
*write_header= false;
673
Move from free list to used list
675
used_entry->next_log_entry= first_used;
676
used_entry->prev_log_entry= NULL;
677
global_ddl_log.first_used= used_entry;
679
first_used->prev_log_entry= used_entry;
681
*active_entry= used_entry;
687
External interface methods for the DDL log Module
688
---------------------------------------------------
693
write_ddl_log_entry()
694
ddl_log_entry Information about log entry
695
out:entry_written Entry information written into
702
A careful write of the ddl log is performed to ensure that we can
703
handle crashes occurring during CREATE and ALTER TABLE processing.
706
bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
707
DDL_LOG_MEMORY_ENTRY **active_entry)
709
bool error, write_header;
715
global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
716
(char)DDL_LOG_ENTRY_CODE;
717
global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
718
(char)ddl_log_entry->action_type;
719
global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
720
int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
721
ddl_log_entry->next_entry);
722
assert(strlen(ddl_log_entry->name) < FN_LEN);
723
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
724
ddl_log_entry->name, FN_LEN - 1);
725
if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
726
ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION)
728
assert(strlen(ddl_log_entry->from_name) < FN_LEN);
729
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN],
730
ddl_log_entry->from_name, FN_LEN - 1);
733
global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
734
assert(strlen(ddl_log_entry->handler_name) < FN_LEN);
735
strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_LEN)],
736
ddl_log_entry->handler_name, FN_LEN - 1);
737
if (get_free_ddl_log_entry(active_entry, &write_header))
742
if (write_ddl_log_file_entry((*active_entry)->entry_pos))
745
sql_print_error("Failed to write entry_no = %u",
746
(*active_entry)->entry_pos);
748
if (write_header && !error)
750
VOID(sync_ddl_log());
751
if (write_ddl_log_header())
755
release_ddl_log_memory_entry(*active_entry);
761
Write final entry in the ddl log
763
write_execute_ddl_log_entry()
764
first_entry First entry in linked list of entries
765
to execute, if 0 = NULL it means that
766
the entry is removed and the entries
767
are put into the free list.
768
complete Flag indicating we are simply writing
769
info about that entry has been completed
770
in:out:active_entry Entry to execute, 0 = NULL if the entry
771
is written first time and needs to be
772
returned. In this case the entry written
773
is returned in this parameter
779
This is the last write in the ddl log. The previous log entries have
780
already been written but not yet synched to disk.
781
We write a couple of log entries that describes action to perform.
782
This entries are set-up in a linked list, however only when a first
783
execute entry is put as the first entry these will be executed.
784
This routine writes this first
787
bool write_execute_ddl_log_entry(uint first_entry,
789
DDL_LOG_MEMORY_ENTRY **active_entry)
791
bool write_header= false;
792
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
801
We haven't synched the log entries yet, we synch them now before
802
writing the execute entry. If complete is true we haven't written
803
any log entries before, we are only here to write the execute
804
entry to indicate it is done.
806
VOID(sync_ddl_log());
807
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
810
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
811
file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
812
file_entry_buf[DDL_LOG_PHASE_POS]= 0;
813
int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
814
file_entry_buf[DDL_LOG_NAME_POS]= 0;
815
file_entry_buf[DDL_LOG_NAME_POS + FN_LEN]= 0;
816
file_entry_buf[DDL_LOG_NAME_POS + 2*FN_LEN]= 0;
817
if (!(*active_entry))
819
if (get_free_ddl_log_entry(active_entry, &write_header))
824
if (write_ddl_log_file_entry((*active_entry)->entry_pos))
826
sql_print_error("Error writing execute entry in ddl log");
827
release_ddl_log_memory_entry(*active_entry);
830
VOID(sync_ddl_log());
833
if (write_ddl_log_header())
835
release_ddl_log_memory_entry(*active_entry);
844
For complex rename operations we need to deactivate individual entries.
846
deactivate_ddl_log_entry()
847
entry_no Entry position of record to change
852
During replace operations where we start with an existing table called
853
t1 and a replacement table called t1#temp or something else and where
854
we want to delete t1 and rename t1#temp to t1 this is not possible to
855
do in a safe manner unless the ddl log is informed of the phases in
858
Delete actions are 1-phase actions that can be ignored immediately after
860
Rename actions from x to y is also a 1-phase action since there is no
861
interaction with any other handlers named x and y.
862
Replace action where drop y and x -> y happens needs to be a two-phase
863
action. Thus the first phase will drop y and the second phase will
867
bool deactivate_ddl_log_entry(uint entry_no)
869
char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
871
if (!read_ddl_log_file_entry(entry_no))
873
if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
875
if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
876
file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
877
(file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
878
file_entry_buf[DDL_LOG_PHASE_POS] == 1))
879
file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
880
else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
882
assert(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
883
file_entry_buf[DDL_LOG_PHASE_POS]= 1;
889
if (write_ddl_log_file_entry(entry_no))
891
sql_print_error("Error in deactivating log entry. Position = %u",
899
sql_print_error("Failed in reading entry before deactivating it");
919
if ((!global_ddl_log.recovery_phase) &&
924
if (my_sync(global_ddl_log.file_id, MYF(0)))
926
/* Write to error log */
927
sql_print_error("Failed to sync ddl log");
935
Release a log memory entry
937
release_ddl_log_memory_entry()
938
log_memory_entry Log memory entry to release
943
void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
945
DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
946
DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
947
DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
949
global_ddl_log.first_free= log_entry;
950
log_entry->next_log_entry= first_free;
953
prev_log_entry->next_log_entry= next_log_entry;
955
global_ddl_log.first_used= next_log_entry;
957
next_log_entry->prev_log_entry= prev_log_entry;
963
Execute one entry in the ddl log. Executing an entry means executing
964
a linked list of actions.
966
execute_ddl_log_entry()
967
first_entry Reference to first action in entry
973
bool execute_ddl_log_entry(THD *thd, uint first_entry)
975
DDL_LOG_ENTRY ddl_log_entry;
976
uint read_entry= first_entry;
978
pthread_mutex_lock(&LOCK_gdl);
981
if (read_ddl_log_entry(read_entry, &ddl_log_entry))
983
/* Write to error log and continue with next log entry */
984
sql_print_error("Failed to read entry = %u from ddl log",
988
assert(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
989
ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
991
if (execute_ddl_log_action(thd, &ddl_log_entry))
993
/* Write to error log and continue with next log entry */
994
sql_print_error("Failed to execute action for entry = %u from ddl log",
998
read_entry= ddl_log_entry.next_entry;
999
} while (read_entry);
1000
pthread_mutex_unlock(&LOCK_gdl);
1013
static void close_ddl_log()
1015
if (global_ddl_log.file_id >= 0)
1017
VOID(my_close(global_ddl_log.file_id, MYF(MY_WME)));
1018
global_ddl_log.file_id= (File) -1;
1025
Execute the ddl log at recovery of MySQL Server
1027
execute_ddl_log_recovery()
1032
void execute_ddl_log_recovery()
1034
uint num_entries, i;
1036
DDL_LOG_ENTRY ddl_log_entry;
1037
char file_name[FN_REFLEN];
1040
Initialise global_ddl_log struct
1042
bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
1043
global_ddl_log.inited= false;
1044
global_ddl_log.recovery_phase= true;
1045
global_ddl_log.io_size= IO_SIZE;
1046
global_ddl_log.file_id= (File) -1;
1049
To be able to run this from boot, we allocate a temporary THD
1053
thd->thread_stack= (char*) &thd;
1054
thd->store_globals();
1056
num_entries= read_ddl_log_header();
1057
for (i= 1; i < num_entries + 1; i++)
1059
if (read_ddl_log_entry(i, &ddl_log_entry))
1061
sql_print_error("Failed to read entry no = %u from ddl log",
1065
if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
1067
if (execute_ddl_log_entry(thd, ddl_log_entry.next_entry))
1069
/* Real unpleasant scenario but we continue anyways. */
1075
create_ddl_log_file_name(file_name);
1076
VOID(my_delete(file_name, MYF(0)));
1077
global_ddl_log.recovery_phase= false;
1079
/* Remember that we don't have a THD */
1080
my_pthread_setspecific_ptr(THR_THD, 0);
1086
Release all memory allocated to the ddl log
1093
void release_ddl_log()
1095
DDL_LOG_MEMORY_ENTRY *free_list= global_ddl_log.first_free;
1096
DDL_LOG_MEMORY_ENTRY *used_list= global_ddl_log.first_used;
1098
if (!global_ddl_log.do_release)
1101
pthread_mutex_lock(&LOCK_gdl);
1104
DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
1105
my_free(used_list, MYF(0));
1110
DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
1111
my_free(free_list, MYF(0));
1115
global_ddl_log.inited= 0;
1116
pthread_mutex_unlock(&LOCK_gdl);
1117
VOID(pthread_mutex_destroy(&LOCK_gdl));
1118
global_ddl_log.do_release= false;
1124
---------------------------------------------------------------------------
1127
--------------------
1129
---------------------------------------------------------------------------
286
session Thread object
287
1137
clear_error is clear_error to be called
288
1138
query Query to log
289
1139
query_length Length of query
4918
5958
goto err_with_placeholders;
4921
quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
5961
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
4924
if (session->locked_tables && new_name == table_name && new_db == db)
5964
if (thd->locked_tables && new_name == table_name && new_db == db)
4926
session->in_lock_tables= 1;
4927
error= reopen_tables(session, 1, 1);
4928
session->in_lock_tables= 0;
5966
thd->in_lock_tables= 1;
5967
error= reopen_tables(thd, 1, 1);
5968
thd->in_lock_tables= 0;
4930
5970
goto err_with_placeholders;
4932
pthread_mutex_unlock(&LOCK_open);
4934
session->set_proc_info("end");
4936
write_bin_log(session, true, session->query, session->query_length);
4938
if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
5972
VOID(pthread_mutex_unlock(&LOCK_open));
5974
thd_proc_info(thd, "end");
5976
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
5977
thd->query, thd->query_length,
5980
assert(!(mysql_bin_log.is_open() &&
5981
thd->current_stmt_binlog_row_based &&
5982
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
5983
write_bin_log(thd, true, thd->query, thd->query_length);
5985
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
4941
5988
For the alter table to be properly flushed to the logs, we
4942
5989
have to open the new table. If not, we get a problem on server
4943
5990
shutdown. But we do not need to attach MERGE children.
4945
char table_path[FN_REFLEN];
4947
build_table_filename(table_path, sizeof(table_path), new_db, table_name, "", 0);
4948
t_table= open_temporary_table(session, table_path, new_db, tmp_name, false, OTM_OPEN);
5992
char path[FN_REFLEN];
5994
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
5995
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
4951
5998
intern_close_table(t_table);
5999
my_free(t_table, MYF(0));
4955
errmsg_printf(ERRMSG_LVL_WARN,
4956
_("Could not open table %s.%s after rename\n"),
6002
sql_print_warning("Could not open table %s.%s after rename\n",
4958
6004
ha_flush_logs(old_db_type);
4960
6006
table_list->table=0; // For query cache
4962
if (session->locked_tables && (new_name != table_name || new_db != db))
6008
if (thd->locked_tables && (new_name != table_name || new_db != db))
4965
If are we under LOCK TABLES and did ALTER Table with RENAME we need
6011
If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
4966
6012
to remove placeholders for the old table and for the target table
4967
6013
from the list of open tables and table cache. If we are not under
4968
6014
LOCK TABLES we can rely on close_thread_tables() doing this job.
4970
6016
pthread_mutex_lock(&LOCK_open);
4971
unlink_open_table(session, table, false);
4972
unlink_open_table(session, name_lock, false);
6017
unlink_open_table(thd, table, false);
6018
unlink_open_table(thd, name_lock, false);
4973
6019
pthread_mutex_unlock(&LOCK_open);
4978
* Field::store() may have called my_error(). If this is
4979
* the case, we must not send an ok packet, since
4980
* Diagnostics_area::is_set() will fail an assert.
4982
if (! session->is_error())
4984
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
4985
(ulong) (copied + deleted), (ulong) deleted,
4986
(ulong) session->cuted_fields);
4987
session->my_ok(copied + deleted, 0L, tmp_name);
4988
session->some_tables_deleted=0;
4993
/* my_error() was called. Return true (which means error...) */
6023
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
6024
(ulong) (copied + deleted), (ulong) deleted,
6025
(ulong) thd->cuted_fields);
6026
my_ok(thd, copied + deleted, 0L, tmp_name);
6027
thd->some_tables_deleted=0;
5000
6033
/* close_temporary_table() frees the new_table pointer. */
5001
close_temporary_table(session, new_table, 1, 1);
6034
close_temporary_table(thd, new_table, 1, 1);
5004
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
6037
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));