Hi Anurag,
On Tue, Nov 10, 2009 at 12:29:43PM +0000, Anurag Shekhar wrote:
> #At file:///home/anurag/mysqlsrc/mysql-5.1-bugteam-47012/ based on
> revid:luis.soares@stripped
>
> 3173 Anurag Shekhar 2009-11-10
> Bug #47012 archive tables are not upgradeable, and server crashes
> on any access
>
> Archive engine for 5.1 (and latter) version uses a modified
> version of zlib (azlib). These two version are incompatible
> so a proper upgrade is needed before tables created in 5.0
> can be used reliable.
>
> This upgrade can be performed using repair. But due to lack
> of test and close proximity with GA dates this patch addressed
> only the crashing issue. Any attempt to repair will be blocked.
Hmm... 5.1 is GA.
>
> Eventually repair can be allowed to run through (which will also
> cause an upgrade from older version to newer) but only after a
But only after a ?
> @ mysql-test/r/archive.result
> Updated result file for test case for bug#47012
> @ mysql-test/std_data/bug47012.ARM
> part of archive table (t1) created in mysql 5.0
> @ mysql-test/std_data/bug47012.ARZ
> part of archive table (t1) created in mysql 5.0
> @ mysql-test/std_data/bug47012.frm
> part of archive table (t1) created in mysql 5.0
> @ mysql-test/t/archive.test
> Added test case for 47012
For BUG#47012.
> @ storage/archive/azio.c
> Fixed a minor issues (minor version over writing version in
> stream structure)
> Removed assertion when an older version is found. Instead
> setting the currect version (2) in s->version
> If an unknown version is found marked it as currupt.
> @ storage/archive/ha_archive.cc
>
Please remove the above empty line.
> Detecting the archive version in getShare and marking
get_share
> it as need to upgrade.
> Blocking open if the archive needs an upgrade. This
> can be allwoed in case of open for repair to upgrade
allowed
...skip...
> === modified file 'mysql-test/t/archive.test'
> --- a/mysql-test/t/archive.test 2009-09-10 06:58:13 +0000
> +++ b/mysql-test/t/archive.test 2009-11-10 12:29:37 +0000
> @@ -1623,3 +1623,23 @@ INSERT INTO t1 VALUES('aaaaaaaaaaaaaaaaa
> SELECT COUNT(t1.a) FROM t1, t1 a, t1 b, t1 c, t1 d, t1 e;
> DROP TABLE t1;
> SET @@join_buffer_size= @save_join_buffer_size;
> +
> +#
> +# BUG#47012 archive tables are not upgradeable, and server crashes on any access
> +#
> +let $MYSQLD_DATADIR= `SELECT @@datadir`;
> +copy_file std_data/bug47012.frm $MYSQLD_DATADIR/test/t1.frm;
> +copy_file std_data/bug47012.ARZ $MYSQLD_DATADIR/test/t1.ARZ;
> +copy_file std_data/bug47012.ARM $MYSQLD_DATADIR/test/t1.ARM;
> +
> +--error ER_TABLE_NEEDS_UPGRADE
> +SHOW CREATE TABLE t1;
> +
> +--error ER_TABLE_NEEDS_UPGRADE
> +SELECT * FROM t1;
> +
> +--error ER_TABLE_NEEDS_UPGRADE
> +INSERT INTO t1 (col1, col2) VALUES (1, "value");
> +
> +REPAIR TABLE t1;
> +DROP TABLE t1;
Hmm... are you sure that the .ARZ file is removed here?
> === modified file 'storage/archive/azio.c'
> --- a/storage/archive/azio.c 2009-02-13 16:41:47 +0000
> +++ b/storage/archive/azio.c 2009-11-10 12:29:37 +0000
...skip...
> @@ -352,10 +352,20 @@ void read_header(azio_stream *s, unsigne
> s->comment_length= (unsigned int)uint4korr(buffer + AZ_COMMENT_LENGTH_POS);
> s->dirty= (unsigned int)buffer[AZ_DIRTY_POS];
> }
> - else
> + else if (buffer[0] == gz_magic[0] && buffer[1] == gz_magic[1])
> {
> - DBUG_ASSERT(buffer[0] == az_magic[0] && buffer[1] == az_magic[1]);
> + /*
> + Set version number to previous version (2).
> + */
> + s->version= (unsigned char) 2;
> return;
Hmm... didn't notice at the first glance... the above return is likely
not needed here.
> + } else {
> + /*
> + Unknown version.
> + Most probably due to a corrupt archive.
> + */
> + s->dirty= AZ_STATE_DIRTY;
> + s->z_err= Z_VERSION_ERROR;
> }
> }
>
>
> === modified file 'storage/archive/ha_archive.cc'
> --- a/storage/archive/ha_archive.cc 2009-09-23 13:21:29 +0000
> +++ b/storage/archive/ha_archive.cc 2009-11-10 12:29:37 +0000
> @@ -360,6 +360,12 @@ ARCHIVE_SHARE *ha_archive::get_share(con
> stats.auto_increment_value= archive_tmp.auto_increment + 1;
> share->rows_recorded= (ha_rows)archive_tmp.rows;
> share->crashed= archive_tmp.dirty;
> + /*
> + If archive version is less than 3, It should be upgraded before
> + use.
> + */
> + if (archive_tmp.version < ARCHIVE_VERSION)
> + *rc= HA_ERR_TABLE_NEEDS_UPGRADE;
> azclose(&archive_tmp);
>
> VOID(my_hash_insert(&archive_open_tables, (uchar*) share));
> @@ -491,7 +497,15 @@ int ha_archive::open(const char *name, i
> (open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no"));
> share= get_share(name, &rc);
>
> - if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options &
> HA_OPEN_FOR_REPAIR))
> + /*
> + Allow open on crashed table in repair mode only.
> + Block open on 5.0 ARCHIVE table. Though we have almost all$
> + routines to access these tables, they were not well tested.$
> + For now we have to refuse to open such table to avoid$
> + potential data loss.$
> + */
What does "$" at the end of the line mean?
> + if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options &
> HA_OPEN_FOR_REPAIR)
> + || rc == HA_ERR_TABLE_NEEDS_UPGRADE)
Though the above seem correct, it'll likely cause compiler warning. So
please use form suggested by me:
if ((rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR))
||
rc == HA_ERR_TABLE_NEEDS_UPGARDE)
Regards,
Sergey
--
Sergey Vojtovich <svoj@stripped>
MySQL AB, Software Engineer
Izhevsk, Russia, www.mysql.com