summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavi Arnaut <davi.arnaut@oracle.com>2010-07-26 12:54:20 -0300
committerDavi Arnaut <davi.arnaut@oracle.com>2010-07-26 12:54:20 -0300
commite4cbcaf942796e5ba1f865485ea56c3903cf2fb8 (patch)
tree7351d5d892130fe6f95d96337a08097268d2e199
parent0a8021610d08718c614c3cd62332a6b4a8c2cabc (diff)
downloadmariadb-git-e4cbcaf942796e5ba1f865485ea56c3903cf2fb8.tar.gz
Bug#45377: ARCHIVE tables aren't discoverable after OPTIMIZE
The problem was that the optimize method of the ARCHIVE storage engine was not preserving the FRM embedded in the ARZ file when rewriting the ARZ file for optimization. The ARCHIVE engine stores the FRM in the ARZ file so it can be transferred from machine to machine without also copying the FRM -- the engine restores the embedded FRM during discovery. The solution is to copy over the FRM when rewriting the ARZ file. In addition, some initial error checking is performed to ensure garbage is not copied over. mysql-test/t/archive.test: Add test case for Bug#45377. storage/archive/azio.c: Add error checking to ensure that the I/O operations are successful. storage/archive/ha_archive.cc: Copy over the embedded FRM.
-rw-r--r--mysql-test/r/archive.result26
-rw-r--r--mysql-test/t/archive.test21
-rw-r--r--storage/archive/azio.c22
-rw-r--r--storage/archive/ha_archive.cc37
-rw-r--r--storage/archive/ha_archive.h1
5 files changed, 95 insertions, 12 deletions
diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result
index 685e1e5ba4b..028c8b32f87 100644
--- a/mysql-test/r/archive.result
+++ b/mysql-test/r/archive.result
@@ -12775,3 +12775,29 @@ a
1
2
DROP TABLE t1;
+#
+# Bug#45377: ARCHIVE tables aren't discoverable after OPTIMIZE
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a int) ENGINE=ARCHIVE;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=ARCHIVE DEFAULT CHARSET=latin1
+INSERT INTO t1 VALUES (1);
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+FLUSH TABLES;
+INSERT INTO t1 VALUES (2);
+SELECT * FROM t1 ORDER BY a;
+a
+1
+2
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=ARCHIVE DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
index a3665e5f455..c3a080612a9 100644
--- a/mysql-test/t/archive.test
+++ b/mysql-test/t/archive.test
@@ -1701,3 +1701,24 @@ SELECT * FROM t1;
REPAIR TABLE t1 EXTENDED;
SELECT * FROM t1;
DROP TABLE t1;
+
+
+--echo #
+--echo # Bug#45377: ARCHIVE tables aren't discoverable after OPTIMIZE
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a int) ENGINE=ARCHIVE;
+SHOW CREATE TABLE t1;
+INSERT INTO t1 VALUES (1);
+OPTIMIZE TABLE t1;
+let $MYSQLD_DATADIR= `select @@datadir`;
+remove_file $MYSQLD_DATADIR/test/t1.frm;
+FLUSH TABLES;
+INSERT INTO t1 VALUES (2);
+SELECT * FROM t1 ORDER BY a;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/storage/archive/azio.c b/storage/archive/azio.c
index c1dd6e6f38c..1e2753027dc 100644
--- a/storage/archive/azio.c
+++ b/storage/archive/azio.c
@@ -31,7 +31,7 @@ int az_open(azio_stream *s, const char *path, int Flags, File fd);
int do_flush(azio_stream *file, int flush);
int get_byte(azio_stream *s);
void check_header(azio_stream *s);
-void write_header(azio_stream *s);
+int write_header(azio_stream *s);
int destroy(azio_stream *s);
void putLong(File file, uLong x);
uLong getLong(azio_stream *s);
@@ -155,7 +155,7 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd)
}
-void write_header(azio_stream *s)
+int write_header(azio_stream *s)
{
char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
char *ptr= buffer;
@@ -191,8 +191,8 @@ void write_header(azio_stream *s)
*(ptr + AZ_DIRTY_POS)= (unsigned char)s->dirty; /* Start of Data Block Index Block */
/* Always begin at the begining, and end there as well */
- my_pwrite(s->file, (uchar*) buffer, AZHEADER_SIZE + AZMETA_BUFFER_SIZE, 0,
- MYF(0));
+ return my_pwrite(s->file, (uchar*) buffer, AZHEADER_SIZE + AZMETA_BUFFER_SIZE,
+ 0, MYF(MY_NABP)) ? 1 : 0;
}
/* ===========================================================================
@@ -838,19 +838,19 @@ int azwrite_frm(azio_stream *s, char *blob, unsigned int length)
s->frm_length= length;
s->start+= length;
- my_pwrite(s->file, (uchar*) blob, s->frm_length, s->frm_start_pos, MYF(0));
-
- write_header(s);
- my_seek(s->file, 0, MY_SEEK_END, MYF(0));
+ if (my_pwrite(s->file, (uchar*) blob, s->frm_length,
+ s->frm_start_pos, MYF(MY_NABP)) ||
+ write_header(s) ||
+ (my_seek(s->file, 0, MY_SEEK_END, MYF(0)) == MY_FILEPOS_ERROR))
+ return 1;
return 0;
}
int azread_frm(azio_stream *s, char *blob)
{
- my_pread(s->file, (uchar*) blob, s->frm_length, s->frm_start_pos, MYF(0));
-
- return 0;
+ return my_pread(s->file, (uchar*) blob, s->frm_length,
+ s->frm_start_pos, MYF(MY_NABP)) ? 1 : 0;
}
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 63848370ff1..ef907b035b5 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -613,6 +613,34 @@ int ha_archive::close(void)
}
+/**
+ Copy a frm blob between streams.
+
+ @param src The source stream.
+ @param dst The destination stream.
+
+ @return Zero on success, non-zero otherwise.
+*/
+
+int ha_archive::frm_copy(azio_stream *src, azio_stream *dst)
+{
+ int rc= 0;
+ char *frm_ptr;
+
+ if (!(frm_ptr= (char *) my_malloc(src->frm_length, MYF(0))))
+ return HA_ERR_OUT_OF_MEM;
+
+ /* Write file offset is set to the end of the file. */
+ if (azread_frm(src, frm_ptr) ||
+ azwrite_frm(dst, frm_ptr, src->frm_length))
+ rc= my_errno ? my_errno : HA_ERR_INTERNAL_ERROR;
+
+ my_free(frm_ptr);
+
+ return rc;
+}
+
+
/*
We create our data file here. The format is pretty simple.
You can read about the format of the data file above.
@@ -1345,10 +1373,10 @@ int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
*/
int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
- DBUG_ENTER("ha_archive::optimize");
int rc= 0;
azio_stream writer;
char writer_filename[FN_REFLEN];
+ DBUG_ENTER("ha_archive::optimize");
init_archive_reader();
@@ -1366,6 +1394,13 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR|O_BINARY)))
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ /*
+ Transfer the embedded FRM so that the file can be discoverable.
+ Write file offset is set to the end of the file.
+ */
+ if ((rc= frm_copy(&archive, &writer)))
+ goto error;
+
/*
An extended rebuild is a lot more effort. We open up each row and re-record it.
Any dead rows are removed (aka rows that may have been partially recorded).
diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h
index 94842203f16..b258b403c3c 100644
--- a/storage/archive/ha_archive.h
+++ b/storage/archive/ha_archive.h
@@ -75,6 +75,7 @@ class ha_archive: public handler
archive_record_buffer *create_record_buffer(unsigned int length);
void destroy_record_buffer(archive_record_buffer *r);
+ int frm_copy(azio_stream *src, azio_stream *dst);
public:
ha_archive(handlerton *hton, TABLE_SHARE *table_arg);