summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorunknown <guilhem@gbichot3.local>2006-09-11 16:12:31 +0200
committerunknown <guilhem@gbichot3.local>2006-09-11 16:12:31 +0200
commit26fb36067a97b21e12fc2704fd08f9ddfd231ded (patch)
tree789515e41bec65d1095796a5923f0a27f9c13091 /storage
parente321f8eb29e8c3baf67cf0f745261dababf36877 (diff)
downloadmariadb-git-26fb36067a97b21e12fc2704fd08f9ddfd231ded.tar.gz
WL#3234 Maria control file manager.
Fitting ma_control_file_test into the mytap unittest framework: new directories: - unittest/storage/ for unit tests of any storage engine - unittest/storage/maria for ... Maria, containing ma_control_file-t. Later, older tests like ma_test*, ma_test_all (but which is Unix dependent in its current form) could move here too. The plugins macro enable building of unittest/storage/X for any enabled engine X which has such a directory. If Falcon wants to have unit tests there too, I may have to merge this patch into 5.x one day. config/ac-macros/plugins.m4: If a storage engine has a directory in unittest/storage, build this directory. configure.in: build storage engines' unit tests. storage/maria/Makefile.am: ma_control_file_test moves to unittest/storage/maria storage/maria/ma_control_file.c: more error codes when opening the control file fails. ma_control_file_end() may now return an error if my_close() failed. storage/maria/ma_control_file.h: more error codes when opening the control file fails. unittest/Makefile.am: adding unit tests for storage engines. Note that unit.pl simply recurses into "storage", so if a unit test for storage engine X has been built previously, and now you re-configure (without making clean) to disable this engine, then the unit test of X will not be rebuilt but will still be present in storage/X, so will be run. unittest/storage/maria/ma_control_file-t.c: Making the test fit the mytap framework (return all the way up the stack instead of assert(); use the mytap functions plan(), ok() etc). Adding test of file too short/long. unittest/storage/maria/Makefile.am: a_control_file-t is added to the Maria unit tests. Later, older tests (ma_test1 etc) could also move here. unittest/storage/Makefile.am: New BitKeeper file ``unittest/storage/Makefile.am''
Diffstat (limited to 'storage')
-rw-r--r--storage/maria/Makefile.am10
-rw-r--r--storage/maria/ma_control_file.c77
-rw-r--r--storage/maria/ma_control_file.h15
-rw-r--r--storage/maria/ma_control_file_test.c312
4 files changed, 67 insertions, 347 deletions
diff --git a/storage/maria/Makefile.am b/storage/maria/Makefile.am
index f5678a55266..10204226742 100644
--- a/storage/maria/Makefile.am
+++ b/storage/maria/Makefile.am
@@ -47,7 +47,7 @@ maria_pack_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-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
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 ha_maria.h
@@ -89,12 +89,6 @@ ma_sp_test_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
-ma_control_file_test_DEPENDENCIES= $(LIBRARIES)
-ma_control_file_test_LDADD= @CLIENT_EXTRA_LDFLAGS@ libmaria.a \
- $(top_builddir)/storage/myisam/libmyisam.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/strings/libmystrings.a @ZLIB_LIBS@
libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ma_rnext.c ma_rnext_same.c \
ma_search.c ma_page.c ma_key.c ma_locking.c \
@@ -113,7 +107,7 @@ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ha_maria.cc \
ma_rt_index.c ma_rt_key.c ma_rt_mbr.c ma_rt_split.c \
ma_sp_key.c ma_control_file.c
-CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA? maria_control
+CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA?
SUFFIXES = .sh
diff --git a/storage/maria/ma_control_file.c b/storage/maria/ma_control_file.c
index 5861246baf9..5fbb0a084df 100644
--- a/storage/maria/ma_control_file.c
+++ b/storage/maria/ma_control_file.c
@@ -41,7 +41,7 @@ uint32 last_logno;
Control file is less then 512 bytes (a disk sector),
to be as atomic as possible
*/
-static int control_file_fd;
+static int control_file_fd= -1;
static void lsn8store(char *buffer, const LSN *lsn)
{
@@ -87,15 +87,16 @@ static char simple_checksum(char *buffer, uint size)
RETURN
0 - OK
- 1 - Error
+ 1 - Error (in which case the file is left closed)
*/
-int ma_control_file_create_or_open()
+CONTROL_FILE_ERROR ma_control_file_create_or_open()
{
char buffer[CONTROL_FILE_SIZE];
char name[FN_REFLEN];
MY_STAT stat_buff;
my_bool create_file;
int open_flags= O_BINARY | /*O_DIRECT |*/ O_RDWR;
+ int error= CONTROL_FILE_UNKNOWN_ERROR;
DBUG_ENTER("ma_control_file_create_or_open");
/*
@@ -106,16 +107,19 @@ int ma_control_file_create_or_open()
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" */
- if (fn_format(name, "control", maria_data_root, "", MYF(MY_WME)) == NullS)
- DBUG_RETURN(1);
+ if (control_file_fd >= 0) /* already open */
+ DBUG_RETURN(0);
+
+ if (fn_format(name, CONTROL_FILE_BASE_NAME,
+ maria_data_root, "", MYF(MY_WME)) == NullS)
+ DBUG_RETURN(CONTROL_FILE_UNKNOWN_ERROR);
create_file= test(my_access(name,F_OK));
if (create_file)
{
if ((control_file_fd= my_create(name, 0, open_flags, MYF(0))) < 0)
- DBUG_RETURN(1);
+ DBUG_RETURN(CONTROL_FILE_UNKNOWN_ERROR);
/*
TODO: from "man fsync" on Linux:
"fsync does not necessarily ensure that the entry in the directory
@@ -127,10 +131,10 @@ int ma_control_file_create_or_open()
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.
@@ -138,7 +142,7 @@ int ma_control_file_create_or_open()
LSN imposs_lsn= CONTROL_FILE_IMPOSSIBLE_LSN;
uint32 imposs_logno= CONTROL_FILE_IMPOSSIBLE_FILENO;
-
+
/* init the file with these "undefined" values */
DBUG_RETURN(ma_control_file_write_and_force(&imposs_lsn, imposs_logno,
CONTROL_FILE_UPDATE_ALL));
@@ -147,12 +151,12 @@ int ma_control_file_create_or_open()
/* Otherwise, file exists */
if ((control_file_fd= my_open(name, open_flags, MYF(MY_WME))) < 0)
- DBUG_RETURN(1);
-
+ goto err;
+
if (my_stat(name, &stat_buff, MYF(MY_WME)) == NULL)
- DBUG_RETURN(1);
+ goto err;
- if ((uint)stat_buff.st_size != CONTROL_FILE_SIZE)
+ if ((uint)stat_buff.st_size < CONTROL_FILE_SIZE)
{
/*
Given that normally we write only a sector and it's atomic, the only
@@ -165,31 +169,43 @@ int ma_control_file_create_or_open()
disk/filesystem has a problem.
So let's be rigid.
*/
- my_message(0, "wrong file size", MYF(0)); /* TODO: improve errors */
- my_error(HA_ERR_CRASHED, MYF(0), name);
- DBUG_RETURN(1);
+ my_message(0, "too small file", MYF(0)); /* TODO: improve errors */
+ error= CONTROL_FILE_TOO_SMALL;
+ goto err;
+ }
+
+ if ((uint)stat_buff.st_size > CONTROL_FILE_SIZE)
+ {
+ my_message(0, "too big file", MYF(0)); /* TODO: improve errors */
+ error= CONTROL_FILE_TOO_BIG;
+ goto err;
}
if (my_read(control_file_fd, buffer, CONTROL_FILE_SIZE,
MYF(MY_FNABP | MY_WME)))
- DBUG_RETURN(1);
+ goto err;
if (memcmp(buffer + CONTROL_FILE_MAGIC_STRING_OFFSET,
CONTROL_FILE_MAGIC_STRING, CONTROL_FILE_MAGIC_STRING_SIZE))
{
my_message(0, "bad magic string", MYF(0));
- DBUG_RETURN(1);
+ error= CONTROL_FILE_BAD_MAGIC_STRING;
+ goto err;
}
if (simple_checksum(buffer + CONTROL_FILE_LSN_OFFSET,
CONTROL_FILE_SIZE - CONTROL_FILE_LSN_OFFSET) !=
buffer[CONTROL_FILE_CHECKSUM_OFFSET])
{
my_message(0, "checksum mismatch", MYF(0));
- DBUG_RETURN(1);
+ error= CONTROL_FILE_BAD_CHECKSUM;
+ goto err;
}
last_checkpoint_lsn= lsn8korr(buffer + CONTROL_FILE_LSN_OFFSET);
last_logno= uint4korr(buffer + CONTROL_FILE_FILENO_OFFSET);
DBUG_RETURN(0);
+err:
+ ma_control_file_end();
+ DBUG_RETURN(error);
}
@@ -227,6 +243,8 @@ int ma_control_file_write_and_force(const LSN *checkpoint_lsn, uint32 logno,
my_bool update_checkpoint_lsn= FALSE, update_logno= FALSE;
DBUG_ENTER("ma_control_file_write_and_force");
+ DBUG_ASSERT(control_file_fd >= 0); /* must be open */
+
memcpy(buffer + CONTROL_FILE_MAGIC_STRING_OFFSET,
CONTROL_FILE_MAGIC_STRING, CONTROL_FILE_MAGIC_STRING_SIZE);
@@ -259,7 +277,7 @@ int ma_control_file_write_and_force(const LSN *checkpoint_lsn, uint32 logno,
0, MYF(MY_FNABP | MY_WME)) ||
my_sync(control_file_fd, MYF(MY_WME)))
DBUG_RETURN(1);
-
+
/* TODO: you need some protection to be able to write last_* global vars */
if (update_checkpoint_lsn)
last_checkpoint_lsn= *checkpoint_lsn;
@@ -277,15 +295,26 @@ int ma_control_file_write_and_force(const LSN *checkpoint_lsn, uint32 logno,
ma_control_file_end()
*/
-void ma_control_file_end()
+int ma_control_file_end()
{
+ int close_error;
DBUG_ENTER("ma_control_file_end");
- my_close(control_file_fd, MYF(MY_WME));
+
+ if (control_file_fd < 0) /* already closed */
+ DBUG_RETURN(0);
+
+ close_error= my_close(control_file_fd, MYF(MY_WME));
+ /*
+ As my_close() frees structures even if close() fails, we do the same,
+ i.e. we mark the file as closed in all cases.
+ */
+ control_file_fd= -1;
/*
As this module owns these variables, closing the module forbids access to
them (just a safety):
*/
last_checkpoint_lsn= CONTROL_FILE_IMPOSSIBLE_LSN;
last_logno= CONTROL_FILE_IMPOSSIBLE_FILENO;
- DBUG_VOID_RETURN;
+
+ DBUG_RETURN(close_error);
}
diff --git a/storage/maria/ma_control_file.h b/storage/maria/ma_control_file.h
index 5f5581137b7..5ac6f158183 100644
--- a/storage/maria/ma_control_file.h
+++ b/storage/maria/ma_control_file.h
@@ -24,6 +24,7 @@ typedef struct st_lsn {
#define maria_data_root "."
#endif
+#define CONTROL_FILE_BASE_NAME "maria_control"
/*
indicate absence of the log file number; first log is always number 1, 0 is
impossible.
@@ -55,7 +56,15 @@ extern uint32 last_logno;
If present, read it to find out last checkpoint's LSN and last log.
Called at engine's start.
*/
-int ma_control_file_create_or_open();
+typedef enum enum_control_file_error {
+ CONTROL_FILE_OK= 0,
+ CONTROL_FILE_TOO_SMALL,
+ CONTROL_FILE_TOO_BIG,
+ CONTROL_FILE_BAD_MAGIC_STRING,
+ CONTROL_FILE_BAD_CHECKSUM,
+ CONTROL_FILE_UNKNOWN_ERROR /* any other error */
+} CONTROL_FILE_ERROR;
+CONTROL_FILE_ERROR ma_control_file_create_or_open();
/*
Write information durably to the control file.
@@ -66,10 +75,10 @@ int ma_control_file_create_or_open();
#define CONTROL_FILE_UPDATE_ONLY_LSN 1
#define CONTROL_FILE_UPDATE_ONLY_LOGNO 2
int ma_control_file_write_and_force(const LSN *checkpoint_lsn, uint32 logno,
- uint objs_to_write);
+ uint objs_to_write);
/* Free resources taken by control file subsystem */
-void ma_control_file_end();
+int ma_control_file_end();
#endif
diff --git a/storage/maria/ma_control_file_test.c b/storage/maria/ma_control_file_test.c
deleted file mode 100644
index b99c61da4fb..00000000000
--- a/storage/maria/ma_control_file_test.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Unit test of the control file module of the Maria engine */
-
-/* TODO: make it fit the mytap framework */
-
-/*
- Note that it is not possible to test the durability of the write (can't
- pull the plug programmatically :)
-*/
-
-#include "maria.h"
-#include "ma_control_file.h"
-#include <my_getopt.h>
-
-char file_name[FN_REFLEN];
-int fd= -1;
-
-static void clean_files();
-static void run_test_normal();
-static void run_test_abnormal();
-static void usage();
-static void get_options(int argc, char *argv[]);
-
-int main(int argc,char *argv[])
-{
- MY_INIT(argv[0]);
-
- get_options(argc,argv);
-
- clean_files();
- run_test_normal();
- run_test_abnormal();
-
- fprintf(stderr, "All tests succeeded\n");
- exit(0); /* all ok, if some test failed, we will have aborted */
-}
-
-/*
- Abort unless given expression is non-zero.
-
- SYNOPSIS
- DIE_UNLESS(expr)
-
- DESCRIPTION
- We can't use any kind of system assert as we need to
- preserve tested invariants in release builds as well.
-
- NOTE
- This is infamous copy-paste from mysql_client_test.c;
- we should instead put it in some include in one single place.
-*/
-
-#define DIE_UNLESS(expr) \
- ((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
-#define DIE_IF(expr) \
- ((void) (!(expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
-#define DIE(expr) \
- die(__FILE__, __LINE__, #expr)
-
-void die(const char *file, int line, const char *expr)
-{
- fprintf(stderr, "%s:%d: check failed: '%s'\n", file, line, expr);
- abort();
-}
-
-
-static void clean_files()
-{
- DIE_IF(fn_format(file_name, "control", maria_data_root, "", MYF(MY_WME)) ==
- NullS);
- my_delete(file_name, MYF(0)); /* maybe file does not exist, ignore error */
-}
-
-
-static void run_test_normal()
-{
- LSN checkpoint_lsn;
- uint32 logno;
- uint objs_to_write;
- uint i;
- char buffer[17];
-
- /* TEST0: Instance starts from scratch (control file does not exist) */
- DIE_UNLESS(ma_control_file_create_or_open() == 0);
- /* Check that the module reports no information */
- DIE_UNLESS(last_logno == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(last_checkpoint_lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(last_checkpoint_lsn.rec_offset == CONTROL_FILE_IMPOSSIBLE_LOG_OFFSET);
-
- /* TEST1: Simulate creation of one log */
-
- objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
- logno= 123;
- DIE_UNLESS(ma_control_file_write_and_force(NULL, logno,
- objs_to_write) == 0);
- /* Check that last_logno was updated */
- DIE_UNLESS(last_logno == logno);
- /* Simulate shutdown */
- ma_control_file_end();
- /* Verify amnesia */
- DIE_UNLESS(last_logno == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(last_checkpoint_lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(last_checkpoint_lsn.rec_offset == CONTROL_FILE_IMPOSSIBLE_LOG_OFFSET);
- /* And restart */
- DIE_UNLESS(ma_control_file_create_or_open() == 0);
- DIE_UNLESS(last_logno == logno);
-
- /* TEST2: Simulate creation of 5 logs */
-
- objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
- logno= 100;
- for (i= 0; i<5; i++)
- {
- logno*= 3;
- DIE_UNLESS(ma_control_file_write_and_force(NULL, logno,
- objs_to_write) == 0);
- }
- ma_control_file_end();
- DIE_UNLESS(last_logno == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(last_checkpoint_lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(last_checkpoint_lsn.rec_offset == CONTROL_FILE_IMPOSSIBLE_LOG_OFFSET);
- DIE_UNLESS(ma_control_file_create_or_open() == 0);
- DIE_UNLESS(last_logno == logno);
-
- /*
- TEST3: Simulate one checkpoint, one log creation, two checkpoints, one
- log creation.
- */
-
- objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
- checkpoint_lsn= (LSN){5, 10000};
- logno= 10;
- DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
- objs_to_write) == 0);
- /* check that last_logno was not updated */
- DIE_UNLESS(last_logno != logno);
- /* Check that last_checkpoint_lsn was updated */
- DIE_UNLESS(last_checkpoint_lsn.file_no == checkpoint_lsn.file_no);
- DIE_UNLESS(last_checkpoint_lsn.rec_offset == checkpoint_lsn.rec_offset);
-
- objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
- checkpoint_lsn= (LSN){5, 20000};
- logno= 17;
- DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
- objs_to_write) == 0);
- /* Check that checkpoint LSN was not updated */
- DIE_UNLESS(last_checkpoint_lsn.rec_offset != checkpoint_lsn.rec_offset);
- objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
- checkpoint_lsn= (LSN){17, 20000};
- DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
- objs_to_write) == 0);
- objs_to_write= CONTROL_FILE_UPDATE_ONLY_LSN;
- checkpoint_lsn= (LSN){17, 45000};
- DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
- objs_to_write) == 0);
- objs_to_write= CONTROL_FILE_UPDATE_ONLY_LOGNO;
- logno= 19;
- DIE_UNLESS(ma_control_file_write_and_force(&checkpoint_lsn, logno,
- objs_to_write) == 0);
-
- ma_control_file_end();
- DIE_UNLESS(last_logno == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(last_checkpoint_lsn.file_no == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(last_checkpoint_lsn.rec_offset == CONTROL_FILE_IMPOSSIBLE_LOG_OFFSET);
- DIE_UNLESS(ma_control_file_create_or_open() == 0);
- DIE_UNLESS(last_logno == logno);
- DIE_UNLESS(last_checkpoint_lsn.file_no == checkpoint_lsn.file_no);
- DIE_UNLESS(last_checkpoint_lsn.rec_offset == checkpoint_lsn.rec_offset);
-
- /*
- TEST4: actually check by ourselves the content of the file.
- Note that constants (offsets) are hard-coded here, precisely to prevent
- someone from changing them in the control file module and breaking
- 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,
- O_BINARY | O_RDWR,
- MYF(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);
- i= uint4korr(buffer+5);
- DIE_UNLESS(i == last_checkpoint_lsn.file_no);
- i= uint4korr(buffer+9);
- DIE_UNLESS(i == last_checkpoint_lsn.rec_offset);
- i= uint4korr(buffer+13);
- DIE_UNLESS(i == last_logno);
-
-
- /* TEST5: Simulate stop/start/nothing/stop/start */
-
- ma_control_file_end();
- DIE_UNLESS(last_logno == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(ma_control_file_create_or_open() == 0);
- ma_control_file_end();
- DIE_UNLESS(last_logno == CONTROL_FILE_IMPOSSIBLE_FILENO);
- DIE_UNLESS(ma_control_file_create_or_open() == 0);
- DIE_UNLESS(last_logno == logno);
- DIE_UNLESS(last_checkpoint_lsn.file_no == checkpoint_lsn.file_no);
- DIE_UNLESS(last_checkpoint_lsn.rec_offset == checkpoint_lsn.rec_offset);
-
-}
-
-static void run_test_abnormal()
-{
- char buffer[4];
- /* Corrupt the control file */
- DIE_IF((fd= my_open(file_name,
- O_BINARY | O_RDWR,
- MYF(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);
-
- /* Check that control file module sees the problem */
- DIE_IF(ma_control_file_create_or_open() == 0);
-
- /* Note that control file is left corrupted at this point */
-}
-
-
-static struct my_option my_long_options[] =
-{
-#ifndef DBUG_OFF
- {"debug", '#', "Debug log.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#endif
- {"help", '?', "Display help and exit",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"version", 'V', "Print version number and exit",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
-};
-
-
-static void version()
-{
- printf("ma_control_file_test: unit test for the control file "
- "module of the Maria storage engine. Ver 1.0 \n");
-}
-
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- switch(optid) {
- case 'V':
- version();
- exit(0);
- case '#':
- DBUG_PUSH (argument);
- break;
- case '?':
- version();
- usage();
- exit(0);
- }
- return 0;
-}
-
-
-/* Read options */
-
-static void get_options(int argc, char *argv[])
-{
- int ho_error;
-
- if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
- exit(ho_error);
-
- return;
-} /* get options */
-
-
-static void usage()
-{
- printf("Usage: %s [options]\n\n", my_progname);
- my_print_help(my_long_options);
- my_print_variables(my_long_options);
-}