Commit 52191ea4 authored by unknown's avatar unknown

importing Sanja's changes to the control file, with my changes on them.


mysys/my_pread.c:
  print errno in case of error
storage/maria/control_file.c:
  importing Sanja's changes, with my minor changes on them :)
storage/maria/control_file.h:
  importing Sanja's changes, with my minor changes on them :)
parent 1c25f0ce
......@@ -155,7 +155,8 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset,
Count-=writenbytes;
offset+=writenbytes;
}
DBUG_PRINT("error",("Write only %d bytes",writenbytes));
DBUG_PRINT("error",("Write only %d bytes, error: %d",
writenbytes, my_errno));
#ifndef NO_BACKGROUND
#ifdef THREAD
if (my_thread_var->abort)
......
......@@ -4,74 +4,162 @@
Does not compile yet.
*/
#include "maria_def.h"
/* Here is the implementation of this module */
/* Control file is 512 bytes (a disk sector), to be as atomic as possible */
/* should be sector size for atomic write operation */
#define STAT_FILE_FILENO_SIZE 4
#define STAT_FILE_FILEOFFSET_SIZE 4
#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)
LSN last_checkpoint_lsn_at_startup;
uint32 last_logno_at_startup;
/*
Control file is less then 512 bytes (a disk sector),
to be as atomic as possible
*/
static int control_file_fd;
int control_file_fd;
/*
Initialize control file subsystem
SYNOPSIS
control_file_create_or_open()
Looks for the control file. If absent, it's a fresh start, create file.
If present, read it to find out last checkpoint's LSN and last log.
Called at engine's start.
RETURN
0 - OK
1 - Error
*/
int control_file_create_or_open()
{
char buffer[4];
char buffer[STAT_FILE_MAX_SIZE];
char name[FN_REFLEN];
MY_STAT stat_buff;
/* name is concatenation of Maria's home dir and "control" */
if ((control_file_fd= my_open(name, O_RDWR)) < 0)
if (fn_format(name, "control", maria_data_root, "", MYF(MY_WME)) == NullS)
return 1;
if ((control_file_fd= my_open(name,
O_CREAT | O_BINARY | /*O_DIRECT |*/ O_RDWR,
MYF(MY_WME))) < 0)
return 1;
/*
TODO: from "man fsync" on Linux:
"fsync does not necessarily ensure that the entry in the direc- tory
containing the file has also reached disk. For that an explicit
fsync on the file descriptor of the directory is also needed."
So if we just created the file we should sync the directory.
Maybe there should be a flag of my_create() to do this.
*/
if (my_stat(name, &stat_buff, MYF(MY_WME)) == NULL)
return 1;
if (stat_buff.st_size < STAT_FILE_MAX_SIZE)
{
/* failure, try to create it */
if ((control_file_fd= my_create(name, O_RDWR)) < 0)
return 1;
/*
So this is a start from scratch, 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 or not restored, and we should not
go on with life at this point.
For now we trust (this is alpha version), but for beta if would be great
to verify.
File shorter than expected (either we just created it, or a previous run
crashed between creation and first write); do first write.
*/
char buffer[STAT_FILE_MAX_SIZE];
/*
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
or not restored, and we should not go on with life at this point).
TODO: For now we trust (this is alpha version), but for beta if would
be great to verify.
We could have a tool which can rebuild the control file, by reading the
directory of logs, finding the newest log, reading it to find last
checkpoint... Slow but can save your db.
*/
last_checkpoint_lsn_at_startup= 0;
last_log_name_at_startup= NULL;
return 0;
last_checkpoint_lsn_at_startup.file_no= CONTROL_FILE_IMPOSSIBLE_LOGNO;
last_checkpoint_lsn_at_startup.rec_offset= 0;
last_logno_at_startup= CONTROL_FILE_IMPOSSIBLE_LOGNO;
/* init the file with these "undefined" values */
return control_file_write_and_force(last_checkpoint_lsn_at_startup,
last_logno_at_startup);
}
/* Already existing file, read it */
if (my_read(control_file_fd, buffer, 8, MYF(MY_FNABP)))
return 1;
last_checkpoint_lsn_at_startup= uint8korr(buffer);
if (last_log_name_at_startup= my_malloc(512-8+1))
return 1;
if (my_read(control_file_fd, last_log_name_at_startup, 512-8), MYF(MY_FNABP))
if (my_read(control_file_fd, buffer, STAT_FILE_MAX_SIZE,
MYF(MY_FNABP | MY_WME)))
return 1;
last_log_name[512-8]= 0; /* end zero to be nice */
last_checkpoint_lsn_at_startup.file_no= uint4korr(buffer);
last_checkpoint_lsn_at_startup.rec_offset= uint4korr(buffer +
STAT_FILE_FILENO_SIZE);
last_logno_at_startup= uint4korr(buffer + STAT_FILE_LSN_SIZE);
return 0;
}
/*
Write information durably to the control file.
SYNOPSIS
control_file_write_and_force()
checkpoint_lsn LSN of checkpoint
log_no last log file number
args_to_write bitmap of 1 (write the LSN) and 2 (write the LOGNO)
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).
RETURN
0 - OK
1 - Error
*/
int control_file_write_and_force(LSN lsn, char *log_name)
int control_file_write_and_force(LSN *checkpoint_lsn, uint32 log_no,
uint args_to_write)
{
char buffer[512];
uint start=8,end=8;
if (lsn != 0) /* LSN was specified */
char buffer[STAT_FILE_MAX_SIZE];
uint start= STAT_FILE_LSN_SIZE, end= STAT_FILE_LSN_SIZE;
/*
If LSN was specified...
rec_offset can't be 0 in real LSN, because all files have header page
*/
if ((args_to_write & 1) && checkpoint_lsn) /* write checkpoint LSN */
{
start= 0;
int8store(buffer, lsn);
int4store(buffer, checkpoint_lsn->file_no);
int4store(buffer + STAT_FILE_FILENO_SIZE, checkpoint_lsn->rec_offset);
}
if (log_name != NULL) /* log name was specified */
if (args_to_write & 2) /* write logno */
{
end= 512;
memcpy(buffer+8, log_name, 512-8);
end= STAT_FILE_MAX_SIZE;
int4store(buffer + STAT_FILE_LSN_SIZE, log_no);
}
DBUG_ASSERT(start != end);
return (my_pwrite(control_file_fd, buffer, end-start, start, MYF(MY_FNABP)) ||
my_sync(control_file_fd))
return (my_pwrite(control_file_fd, buffer + start, end - start, start,
MYF(MY_FNABP | MY_WME)) ||
my_sync(control_file_fd, MYF(MY_WME)));
}
/*
Free resources taken by control file subsystem
SYNOPSIS
control_file_end()
*/
void control_file_end()
{
my_close(control_file_fd, MYF(MY_WME));
}
......@@ -4,10 +4,25 @@
Does not compile yet.
*/
#ifndef _control_file_h
#define _control_file_h
/* indicate absence of the log file number */
#define CONTROL_FILE_IMPOSSIBLE_LOGNO 0xFFFFFFFF
/* Here is the interface of this module */
/*
LSN of the last checkoint
(if last_checkpoint_lsn_at_startup.file_no == CONTROL_FILE_IMPOSSIBLE_LOGNO
then there was never a checkpoint)
*/
extern LSN last_checkpoint_lsn_at_startup;
extern char *last_log_name_at_startup;
/*
Last log number at startup time (if last_logno_at_startup ==
CONTROL_FILE_IMPOSSIBLE_LOGNO then there is no log file yet)
*/
extern uint32 last_logno_at_startup;
/*
Looks for the control file. If absent, it's a fresh start, create file.
......@@ -21,4 +36,11 @@ int control_file_create_or_open();
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).
*/
int control_file_write_and_force(LSN lsn, char *log_name);
int control_file_write_and_force(LSN *checkpoint_lsn, uint32 log_no,
uint args_to_write);
/* Free resources taken by control file subsystem */
void control_file_end();
#endif
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