Commit 8f7aa290 authored by unknown's avatar unknown

WL#3234 "Maria - control file manager":

added checksum of the file. Now we have size + magic string + checksum
to detect that all is ok.
Plus misc fixes for "make dist" to work and the resulting tarball to build


include/Makefile.am:
  adding pagecache.h to help the tarball build.
  The model of pagecache.h, keycache.h, is in pkginclude_HEADERS,
  wonder why. Adding pagecache.h to noinst_HEADERS for now.
storage/maria/Makefile.am:
  adding ma_control_file.h to help the tarball build
storage/maria/ma_control_file.c:
  adding a simple checksum to the control file.
  We protect against corruption of this file like this:
  - test size
  - test magic string at start
  - test checksum
  I also add some simple my_message() errors (to be changed to a better
  reporting later).
storage/maria/ma_control_file.h:
  comments
storage/maria/ma_control_file_test.c:
  test of wrong checksum in control file
storage/maria/CMakeLists.txt:
  just to make "make dist" happy for now.
parent 6590935a
...@@ -33,7 +33,7 @@ noinst_HEADERS = config-win.h config-netware.h \ ...@@ -33,7 +33,7 @@ noinst_HEADERS = config-win.h config-netware.h \
mysql_version.h.in my_handler.h my_time.h decimal.h \ mysql_version.h.in my_handler.h my_time.h decimal.h \
my_vle.h my_user.h my_atomic.h atomic/nolock.h \ my_vle.h my_user.h my_atomic.h atomic/nolock.h \
atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \ atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \
my_libwrap.h my_libwrap.h pagecache.h
# mysql_version.h are generated # mysql_version.h are generated
CLEANFILES = mysql_version.h my_config.h readline openssl CLEANFILES = mysql_version.h my_config.h readline openssl
......
# empty for the moment; will fill it when we build under Windows
...@@ -28,7 +28,9 @@ bin_PROGRAMS = maria_chk maria_pack maria_ftdump ...@@ -28,7 +28,9 @@ bin_PROGRAMS = maria_chk maria_pack maria_ftdump
maria_chk_DEPENDENCIES= $(LIBRARIES) maria_chk_DEPENDENCIES= $(LIBRARIES)
maria_pack_DEPENDENCIES=$(LIBRARIES) maria_pack_DEPENDENCIES=$(LIBRARIES)
noinst_PROGRAMS = ma_test1 ma_test2 ma_test3 ma_rt_test ma_sp_test ma_control_file_test noinst_PROGRAMS = ma_test1 ma_test2 ma_test3 ma_rt_test ma_sp_test ma_control_file_test
noinst_HEADERS = maria_def.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h ma_sp_defs.h ma_fulltext.h ma_ftdefs.h ma_ft_test1.h ma_ft_eval.h noinst_HEADERS = maria_def.h ma_rt_index.h ma_rt_key.h ma_rt_mbr.h \
ma_sp_defs.h ma_fulltext.h ma_ftdefs.h ma_ft_test1.h ma_ft_eval.h \
ma_control_file.h
ma_test1_DEPENDENCIES= $(LIBRARIES) ma_test1_DEPENDENCIES= $(LIBRARIES)
ma_test2_DEPENDENCIES= $(LIBRARIES) ma_test2_DEPENDENCIES= $(LIBRARIES)
ma_test3_DEPENDENCIES= $(LIBRARIES) ma_test3_DEPENDENCIES= $(LIBRARIES)
......
This diff is collapsed.
...@@ -62,9 +62,9 @@ int ma_control_file_create_or_open(); ...@@ -62,9 +62,9 @@ int ma_control_file_create_or_open();
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).
*/ */
#define CONTROL_FILE_WRITE_ALL 0 /* write all 3 objects */ #define CONTROL_FILE_UPDATE_ALL 0
#define CONTROL_FILE_WRITE_ONLY_LSN 1 #define CONTROL_FILE_UPDATE_ONLY_LSN 1
#define CONTROL_FILE_WRITE_ONLY_LOGNO 2 #define CONTROL_FILE_UPDATE_ONLY_LOGNO 2
int ma_control_file_write_and_force(const LSN *checkpoint_lsn, uint32 logno, int ma_control_file_write_and_force(const LSN *checkpoint_lsn, uint32 logno,
uint objs_to_write); uint objs_to_write);
......
...@@ -45,7 +45,8 @@ int main(int argc,char *argv[]) ...@@ -45,7 +45,8 @@ int main(int argc,char *argv[])
clean_files(); clean_files();
run_test_normal(); run_test_normal();
run_test_abnormal(); run_test_abnormal();
fprintf(stderr, "All tests succeeded\n");
exit(0); /* all ok, if some test failed, we will have aborted */ exit(0); /* all ok, if some test failed, we will have aborted */
} }
...@@ -92,7 +93,7 @@ static void run_test_normal() ...@@ -92,7 +93,7 @@ static void run_test_normal()
uint32 logno; uint32 logno;
uint objs_to_write; uint objs_to_write;
uint i; uint i;
char buffer[4]; char buffer[17];
/* TEST0: Instance starts from scratch (control file does not exist) */ /* TEST0: Instance starts from scratch (control file does not exist) */
DIE_UNLESS(ma_control_file_create_or_open() == 0); DIE_UNLESS(ma_control_file_create_or_open() == 0);
...@@ -103,7 +104,7 @@ static void run_test_normal() ...@@ -103,7 +104,7 @@ static void run_test_normal()
/* TEST1: Simulate creation of one log */ /* TEST1: Simulate creation of one log */
objs_to_write= CONTROL_FILE_WRITE_ONLY_LOGNO; objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
logno= 123; logno= 123;
DIE_UNLESS(ma_control_file_write_and_force(NULL, logno, DIE_UNLESS(ma_control_file_write_and_force(NULL, logno,
objs_to_write) == 0); objs_to_write) == 0);
...@@ -121,7 +122,7 @@ static void run_test_normal() ...@@ -121,7 +122,7 @@ static void run_test_normal()
/* TEST2: Simulate creation of 5 logs */ /* TEST2: Simulate creation of 5 logs */
objs_to_write= CONTROL_FILE_WRITE_ONLY_LOGNO; objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
logno= 100; logno= 100;
for (i= 0; i<5; i++) for (i= 0; i<5; i++)
{ {
...@@ -141,7 +142,7 @@ static void run_test_normal() ...@@ -141,7 +142,7 @@ static void run_test_normal()
log creation. log creation.
*/ */
objs_to_write= CONTROL_FILE_WRITE_ONLY_LSN; objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
checkpoint_lsn= (LSN){5, 10000}; checkpoint_lsn= (LSN){5, 10000};
logno= 10; logno= 10;
DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno, DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
...@@ -152,22 +153,22 @@ static void run_test_normal() ...@@ -152,22 +153,22 @@ static void run_test_normal()
DIE_UNLESS(last_checkpoint_lsn.file_no == checkpoint_lsn.file_no); DIE_UNLESS(last_checkpoint_lsn.file_no == checkpoint_lsn.file_no);
DIE_UNLESS(last_checkpoint_lsn.rec_offset == checkpoint_lsn.rec_offset); DIE_UNLESS(last_checkpoint_lsn.rec_offset == checkpoint_lsn.rec_offset);
objs_to_write= CONTROL_FILE_WRITE_ONLY_LOGNO; objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
checkpoint_lsn= (LSN){5, 20000}; checkpoint_lsn= (LSN){5, 20000};
logno= 17; logno= 17;
DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno, DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
objs_to_write) == 0); objs_to_write) == 0);
/* Check that checkpoint LSN was not updated */ /* Check that checkpoint LSN was not updated */
DIE_UNLESS(last_checkpoint_lsn.rec_offset != checkpoint_lsn.rec_offset); DIE_UNLESS(last_checkpoint_lsn.rec_offset != checkpoint_lsn.rec_offset);
objs_to_write= CONTROL_FILE_WRITE_ONLY_LSN; objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
checkpoint_lsn= (LSN){17, 20000}; checkpoint_lsn= (LSN){17, 20000};
DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno, DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
objs_to_write) == 0); objs_to_write) == 0);
objs_to_write= CONTROL_FILE_WRITE_ONLY_LSN; objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
checkpoint_lsn= (LSN){17, 45000}; checkpoint_lsn= (LSN){17, 45000};
DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno, DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
objs_to_write) == 0); objs_to_write) == 0);
objs_to_write= CONTROL_FILE_WRITE_ONLY_LOGNO; objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
logno= 19; logno= 19;
DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno, DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
objs_to_write) == 0); objs_to_write) == 0);
...@@ -186,18 +187,21 @@ static void run_test_normal() ...@@ -186,18 +187,21 @@ static void run_test_normal()
Note that constants (offsets) are hard-coded here, precisely to prevent Note that constants (offsets) are hard-coded here, precisely to prevent
someone from changing them in the control file module and breaking someone from changing them in the control file module and breaking
backward-compatibility. backward-compatibility.
TODO: when we reach the format-freeze state, we may even just do a
comparison with a raw binary string, to not depend on any uint4korr
future change/breakage.
*/ */
DIE_IF((fd= my_open(file_name, DIE_IF((fd= my_open(file_name,
O_BINARY | O_RDWR, O_BINARY | O_RDWR,
MYF(MY_WME))) < 0); MYF(MY_WME))) < 0);
DIE_IF(my_read(fd, buffer, 16, MYF(MY_FNABP | MY_WME)) != 0); DIE_IF(my_read(fd, buffer, 17, MYF(MY_FNABP | MY_WME)) != 0);
DIE_IF(my_close(fd, MYF(MY_WME)) != 0); DIE_IF(my_close(fd, MYF(MY_WME)) != 0);
i= uint4korr(buffer+4); i= uint4korr(buffer+5);
DIE_UNLESS(i == last_checkpoint_lsn.file_no); DIE_UNLESS(i == last_checkpoint_lsn.file_no);
i= uint4korr(buffer+8); i= uint4korr(buffer+9);
DIE_UNLESS(i == last_checkpoint_lsn.rec_offset); DIE_UNLESS(i == last_checkpoint_lsn.rec_offset);
i= uint4korr(buffer+12); i= uint4korr(buffer+13);
DIE_UNLESS(i == last_logno); DIE_UNLESS(i == last_logno);
...@@ -217,15 +221,33 @@ static void run_test_normal() ...@@ -217,15 +221,33 @@ static void run_test_normal()
static void run_test_abnormal() static void run_test_abnormal()
{ {
char buffer[4];
/* Corrupt the control file */ /* Corrupt the control file */
DIE_IF((fd= my_open(file_name, DIE_IF((fd= my_open(file_name,
O_BINARY | O_RDWR, O_BINARY | O_RDWR,
MYF(MY_WME))) < 0); MYF(MY_WME))) < 0);
DIE_IF(my_write(fd, "papa", 4, MYF(MY_FNABP | MY_WME)) != 0); DIE_IF(my_pread(fd, buffer, 4, 0, MYF(MY_FNABP | MY_WME)) != 0);
DIE_IF(my_pwrite(fd, "papa", 4, 0, MYF(MY_FNABP | MY_WME)) != 0);
DIE_IF(my_close(fd, MYF(MY_WME)) != 0);
/* Check that control file module sees the problem */
DIE_IF(ma_control_file_create_or_open() == 0);
/* Restore it and corrupt it differently */
DIE_IF((fd= my_open(file_name,
O_BINARY | O_RDWR,
MYF(MY_WME))) < 0);
/* Restore magic string */
DIE_IF(my_pwrite(fd, buffer, 4, 0, MYF(MY_FNABP | MY_WME)) != 0);
DIE_IF(my_pread(fd, buffer, 1, 4, MYF(MY_FNABP | MY_WME)) != 0);
buffer[1]= buffer[0]+3; /* mangle checksum */
DIE_IF(my_pwrite(fd, buffer+1, 1, 4, MYF(MY_FNABP | MY_WME)) != 0);
DIE_IF(my_close(fd, MYF(MY_WME)) != 0); DIE_IF(my_close(fd, MYF(MY_WME)) != 0);
/* Check that control file module sees the problem */ /* Check that control file module sees the problem */
DIE_IF(ma_control_file_create_or_open() == 0); DIE_IF(ma_control_file_create_or_open() == 0);
/* Note that control file is left corrupted at this point */
} }
......
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