Commit 8a2901a7 authored by unknown's avatar unknown

write a magic string "MACF" (MAria Control File) at the start of the control file.

lsn8store, lsn8korr.


storage/maria/control_file.h:
  parameter changes name
parent 52191ea4
...@@ -9,11 +9,20 @@ ...@@ -9,11 +9,20 @@
/* Here is the implementation of this module */ /* Here is the implementation of this module */
/* should be sector size for atomic write operation */ /*
#define STAT_FILE_FILENO_SIZE 4 a control file contains 3 objects: magic string, LSN of last checkpoint,
#define STAT_FILE_FILEOFFSET_SIZE 4 number of last log.
#define STAT_FILE_LSN_SIZE (STAT_FILE_FILENO_SIZE + STAT_FILE_FILEOFFSET_SIZE) */
#define STAT_FILE_MAX_SIZE (STAT_FILE_LSN_SIZE + STAT_FILE_FILENO_SIZE)
/* total size should be < sector size for atomic write operation */
#define CONTROL_FILE_MAGIC_STRING "MACF"
#define CONTROL_FILE_MAGIC_STRING_OFFSET 0
#define CONTROL_FILE_MAGIC_STRING_SIZE sizeof(CONTROL_FILE_MAGIC_STRING)
#define CONTROL_FILE_LSN_OFFSET (CONTROL_FILE_MAGIC_STRING_OFFSET + CONTROL_FILE_MAGIC_STRING_SIZE)
#define CONTROL_FILE_LSN_SIZE (4+4)
#define CONTROL_FILE_FILENO_OFFSET (CONTROL_FILE_LSN_OFFSET + CONTROL_FILE_LSN_SIZE)
#define CONTROL_FILE_FILENO_SIZE 4
#define CONTROL_FILE_MAX_SIZE (CONTROL_FILE_FILENO_OFFSET + CONTROL_FILE_FILENO_SIZE)
LSN last_checkpoint_lsn_at_startup; LSN last_checkpoint_lsn_at_startup;
...@@ -26,6 +35,19 @@ uint32 last_logno_at_startup; ...@@ -26,6 +35,19 @@ uint32 last_logno_at_startup;
*/ */
static int control_file_fd; static int control_file_fd;
static void lsn8store(char *buffer, LSN *lsn)
{
int4store(buffer, lsn->file_no);
int4store(buffer + CONTROL_FILE_FILENO_SIZE, lsn->rec_offset);
}
static LSN lsn8korr(char *buffer)
{
LSN tmp;
tmp.file_no= uint4korr(buffer);
tmp.rec_offset= uint4korr(buffer + CONTROL_FILE_FILENO_SIZE);
return tmp;
}
/* /*
Initialize control file subsystem Initialize control file subsystem
...@@ -43,10 +65,18 @@ static int control_file_fd; ...@@ -43,10 +65,18 @@ static int control_file_fd;
*/ */
int control_file_create_or_open() int control_file_create_or_open()
{ {
char buffer[STAT_FILE_MAX_SIZE]; char buffer[CONTROL_FILE_MAX_SIZE];
char name[FN_REFLEN]; char name[FN_REFLEN];
MY_STAT stat_buff; MY_STAT stat_buff;
/*
If you change sizes in the #defines, you at least have to change the
"*store" and "*korr" calls in this file, and can even create backward
compatibility problems. Beware!
*/
DBUG_ASSERT(CONTROL_FILE_LSN_SIZE == (4+4));
DBUG_ASSERT(CONTROL_FILE_FILENO_SIZE == 4);
/* name is concatenation of Maria's home dir and "control" */ /* name is concatenation of Maria's home dir and "control" */
if (fn_format(name, "control", maria_data_root, "", MYF(MY_WME)) == NullS) if (fn_format(name, "control", maria_data_root, "", MYF(MY_WME)) == NullS)
return 1; return 1;
...@@ -68,13 +98,13 @@ int control_file_create_or_open() ...@@ -68,13 +98,13 @@ int control_file_create_or_open()
if (my_stat(name, &stat_buff, MYF(MY_WME)) == NULL) if (my_stat(name, &stat_buff, MYF(MY_WME)) == NULL)
return 1; return 1;
if (stat_buff.st_size < STAT_FILE_MAX_SIZE) if (stat_buff.st_size < CONTROL_FILE_MAX_SIZE)
{ {
/* /*
File shorter than expected (either we just created it, or a previous run File shorter than expected (either we just created it, or a previous run
crashed between creation and first write); do first write. crashed between creation and first write); do first write.
*/ */
char buffer[STAT_FILE_MAX_SIZE]; char buffer[CONTROL_FILE_MAX_SIZE];
/* /*
To be safer we should make sure that there are no logs or data/index To be safer we should make sure that there are no logs or data/index
files around (indeed it could be that the control file alone was deleted files around (indeed it could be that the control file alone was deleted
...@@ -87,67 +117,83 @@ int control_file_create_or_open() ...@@ -87,67 +117,83 @@ int control_file_create_or_open()
directory of logs, finding the newest log, reading it to find last directory of logs, finding the newest log, reading it to find last
checkpoint... Slow but can save your db. checkpoint... Slow but can save your db.
*/ */
last_checkpoint_lsn_at_startup.file_no= CONTROL_FILE_IMPOSSIBLE_LOGNO; last_checkpoint_lsn_at_startup.file_no= CONTROL_FILE_IMPOSSIBLE_FILENO;
last_checkpoint_lsn_at_startup.rec_offset= 0; last_checkpoint_lsn_at_startup.rec_offset= 0;
last_logno_at_startup= CONTROL_FILE_IMPOSSIBLE_LOGNO; last_logno_at_startup= CONTROL_FILE_IMPOSSIBLE_FILENO;
/* init the file with these "undefined" values */ /* init the file with these "undefined" values */
return control_file_write_and_force(last_checkpoint_lsn_at_startup, return control_file_write_and_force(last_checkpoint_lsn_at_startup,
last_logno_at_startup); last_logno_at_startup,
CONTROL_FILE_WRITE_ALL);
} }
/* Already existing file, read it */ /* Already existing file, read it */
if (my_read(control_file_fd, buffer, STAT_FILE_MAX_SIZE, if (my_read(control_file_fd, buffer, CONTROL_FILE_MAX_SIZE,
MYF(MY_FNABP | MY_WME))) MYF(MY_FNABP | MY_WME)))
return 1; return 1;
last_checkpoint_lsn_at_startup.file_no= uint4korr(buffer); if (memcmp(buffer + CONTROL_FILE_MAGIC_STRING_OFFSET,
last_checkpoint_lsn_at_startup.rec_offset= uint4korr(buffer + CONTROL_FILE_MAGIC_STRING, CONTROL_FILE_MAGIC_STRING_SIZE))
STAT_FILE_FILENO_SIZE); return 1;
last_logno_at_startup= uint4korr(buffer + STAT_FILE_LSN_SIZE); last_checkpoint_lsn_at_startup= lsn8korr(buffer + CONTROL_FILE_LSN_OFFSET);
last_logno_at_startup= uint4korr(buffer + CONTROL_FILE_FILENO_OFFSET);
return 0; return 0;
} }
#define CONTROL_FILE_WRITE_ALL 0 /* write all 3 objects */
#define CONTROL_FILE_WRITE_ONLY_LSN 1
#define CONTROL_FILE_WRITE_ONLY_LOGNO 2
/* /*
Write information durably to the control file. Write information durably to the control file.
SYNOPSIS SYNOPSIS
control_file_write_and_force() control_file_write_and_force()
checkpoint_lsn LSN of checkpoint checkpoint_lsn LSN of last checkpoint
log_no last log file number log_no last log file number
args_to_write bitmap of 1 (write the LSN) and 2 (write the LOGNO) objs_to_write what we should write
Called when we have created a new log (after syncing this log's creation) Called when we have created a new log (after syncing this log's creation)
and when we have written a checkpoint (after syncing this log record). and when we have written a checkpoint (after syncing this log record).
NOTE
We always want to do one single my_pwrite() here to be as atomic as
possible.
RETURN RETURN
0 - OK 0 - OK
1 - Error 1 - Error
*/ */
int control_file_write_and_force(LSN *checkpoint_lsn, uint32 log_no, int control_file_write_and_force(LSN *checkpoint_lsn, uint32 log_no,
uint args_to_write) uint objs_to_write)
{ {
char buffer[STAT_FILE_MAX_SIZE]; char buffer[CONTROL_FILE_MAX_SIZE];
uint start= STAT_FILE_LSN_SIZE, end= STAT_FILE_LSN_SIZE; uint start, size;
/* memcpy(buffer + CONTROL_FILE_MAGIC_STRING_OFFSET,
If LSN was specified... CONTROL_FILE_MAGIC_STRING, CONTROL_FILE_MAGIC_STRING_SIZE);
/* write checkpoint LSN */
rec_offset can't be 0 in real LSN, because all files have header page if (checkpoint_lsn)
*/ lsn8store(buffer + CONTROL_FILE_LSN_OFFSET, checkpoint_lsn);
if ((args_to_write & 1) && checkpoint_lsn) /* write checkpoint LSN */ /* write logno */
int4store(buffer + CONTROL_FILE_FILENO_OFFSET, log_no);
if (objs_to_write == CONTROL_FILE_WRITE_ALL)
{
start= CONTROL_FILE_MAGIC_STRING_OFFSET;
size= CONTROL_FILE_MAX_SIZE;
}
else if (objs_to_write == CONTROL_FILE_WRITE_ONLY_LSN)
{ {
start= 0; start= CONTROL_FILE_LSN_OFFSET;
int4store(buffer, checkpoint_lsn->file_no); size= CONTROL_FILE_LSN_SIZE;
int4store(buffer + STAT_FILE_FILENO_SIZE, checkpoint_lsn->rec_offset);
} }
if (args_to_write & 2) /* write logno */ else if (objs_to_write == CONTROL_FILE_WRITE_ONLY_LOGNO)
{ {
end= STAT_FILE_MAX_SIZE; start= CONTROL_FILE_FILENO_OFFSET;
int4store(buffer + STAT_FILE_LSN_SIZE, log_no); size= CONTROL_FILE_FILENO_SIZE;
} }
DBUG_ASSERT(start != end); else /* incorrect value of objs_to_write */
return (my_pwrite(control_file_fd, buffer + start, end - start, start, DBUG_ASSERT(0);
MYF(MY_FNABP | MY_WME)) || return (my_pwrite(control_file_fd, buffer + start, size,
start, MYF(MY_FNABP | MY_WME)) ||
my_sync(control_file_fd, MYF(MY_WME))); my_sync(control_file_fd, MYF(MY_WME)));
} }
......
...@@ -37,7 +37,7 @@ int control_file_create_or_open(); ...@@ -37,7 +37,7 @@ int control_file_create_or_open();
and when we have written a checkpoint (after syncing this log record). and when we have written a checkpoint (after syncing this log record).
*/ */
int control_file_write_and_force(LSN *checkpoint_lsn, uint32 log_no, int control_file_write_and_force(LSN *checkpoint_lsn, uint32 log_no,
uint args_to_write); uint objs_to_write);
/* Free resources taken by control file subsystem */ /* Free resources taken by control file subsystem */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment