Commit 9fd43125 authored by unknown's avatar unknown

This patch passes comment to be embedded in ARZ.

Fixes autodiscovery of tables. 
Allows the FRM to be extracted from the ARZ file via archive_reader. 


storage/archive/archive_reader.c:
  Extract FRM command added.
  We now print the embedded comment
storage/archive/archive_test.c:
  Additional tests for FRM annd comment
storage/archive/azio.c:
  Filled in functionality for comment and frm.
storage/archive/azlib.h:
  Refactored position.
storage/archive/ha_archive.cc:
  Discovery mechanism filled in.
parent 58b898f6
......@@ -18,7 +18,7 @@ static const char *opt_tmpdir;
static const char *new_auto_increment_value;
static const char *load_default_groups[]= { "archive_reader", 0 };
static char **default_argv;
int opt_check, opt_force, opt_quiet, opt_backup= 0;
int opt_check, opt_force, opt_quiet, opt_backup= 0, opt_extract_frm;
int main(int argc, char *argv[])
{
......@@ -53,6 +53,20 @@ int main(int argc, char *argv[])
printf("\tLongest Row %u\n", reader_handle.longest_row);
printf("\tShortest Row %u\n", reader_handle.shortest_row);
printf("\tState %s\n", ( reader_handle.dirty ? "dirty" : "clean"));
printf("\tFRM stored at %u\n", reader_handle.frm_start_pos);
printf("\tComment stored at %u\n", reader_handle.comment_start_pos);
printf("\tData starts at %u\n", (unsigned int)reader_handle.start);
if (reader_handle.frm_start_pos)
printf("\tFRM length %u\n", reader_handle.frm_length);
if (reader_handle.comment_start_pos)
{
char *comment =
(char *) malloc(sizeof(char) * reader_handle.comment_length);
azread_comment(&reader_handle, comment);
printf("\tComment length %u\n\t\t%.*s\n", reader_handle.comment_length,
reader_handle.comment_length, comment);
free(comment);
}
}
else
{
......@@ -148,6 +162,23 @@ int main(int argc, char *argv[])
}
writer_handle.auto_increment= reader_handle.auto_increment;
if (reader_handle.frm_length)
{
char *ptr;
ptr= (char *)my_malloc(sizeof(char) * reader_handle.frm_length, MYF(0));
azread_frm(&reader_handle, ptr);
azwrite_frm(&writer_handle, ptr, reader_handle.frm_length);
my_free(ptr, MYF(0));
}
if (reader_handle.comment_length)
{
char *ptr;
ptr= (char *)my_malloc(sizeof(char) * reader_handle.comment_length, MYF(0));
azread_comment(&reader_handle, ptr);
azwrite_comment(&writer_handle, ptr, reader_handle.comment_length);
my_free(ptr, MYF(0));
}
while ((read= azread(&reader_handle, (byte *)size_buffer,
ARCHIVE_ROW_HEADER_SIZE, &error)))
......@@ -192,6 +223,18 @@ int main(int argc, char *argv[])
azclose(&writer_handle);
}
if (opt_extract_frm)
{
File frm_file;
char *ptr;
frm_file= my_open(argv[1], O_CREAT|O_RDWR|O_BINARY, MYF(0));
ptr= (char *)my_malloc(sizeof(char) * reader_handle.frm_length, MYF(0));
azread_frm(&reader_handle, ptr);
my_write(frm_file, ptr, reader_handle.frm_length, MYF(0));
my_close(frm_file, MYF(0));
my_free(ptr, MYF(0));
}
end:
printf("\n");
azclose(&reader_handle);
......@@ -211,6 +254,9 @@ get_one_option(int optid,
case 'c':
opt_check= 1;
break;
case 'e':
opt_extract_frm= 1;
break;
case 'f':
opt_force= 1;
printf("Not implemented yet\n");
......@@ -257,6 +303,9 @@ static struct my_option my_long_options[] =
"Output debug log. Often this is 'd:t:o,filename'.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"extract-frm", 'e',
"Extract the frm file.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"force", 'f',
"Restart with -r if there are any errors in the table.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
......
......@@ -17,11 +17,14 @@
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <my_getopt.h>
#include <mysql_version.h>
#define ARCHIVE_ROW_HEADER_SIZE 4
#define COMMENT_STRING "Your bases"
#define FRM_STRING "My bases"
#define TEST_FILENAME "test.az"
#define TEST_STRING_INIT "YOU don't know about me without you have read a book by the name of The Adventures of Tom Sawyer; but that ain't no matter. That book was made by Mr. Mark Twain, and he told the truth, mainly. There was things which he stretched, but mainly he told the truth. That is nothing. I never seen anybody but lied one time or another, without it was Aunt Polly, or the widow, or maybe Mary. Aunt Polly--Tom's Aunt Polly, she is--and Mary, and the Widow Douglas is all told about in that book, which is mostly a true book, with some stretchers, as I said before. Now the way that the book winds up is this: Tom and me found the money that the robbers hid in the cave, and it made us rich. We got six thousand dollars apiece--all gold. It was an awful sight of money when it was piled up. Well, Judge Thatcher he took it and put it out at interest, and it fetched us a dollar a day apiece all the year round --more than a body could tell what to do with. The Widow Douglas she took me for her son, and allowed she would..."
#define TEST_LOOP_NUM 100
......@@ -44,6 +47,7 @@ int size_test(unsigned long long length, unsigned long long rows_to_test_for);
int main(int argc, char *argv[])
{
unsigned int ret;
char comment_str[10];
int error;
unsigned int x;
......@@ -67,6 +71,19 @@ int main(int argc, char *argv[])
return 0;
}
azwrite_comment(&writer_handle, (char *)COMMENT_STRING,
(unsigned int)strlen(COMMENT_STRING));
azread_comment(&writer_handle, comment_str);
assert(!memcmp(COMMENT_STRING, comment_str,
strlen(COMMENT_STRING)));
azwrite_frm(&writer_handle, (char *)FRM_STRING,
(unsigned int)strlen(FRM_STRING));
azread_frm(&writer_handle, comment_str);
assert(!memcmp(FRM_STRING, comment_str,
strlen(FRM_STRING)));
if (!(ret= azopen(&reader_handle, TEST_FILENAME, O_RDONLY|O_BINARY)))
{
printf("Could not open test file\n");
......@@ -87,6 +104,10 @@ int main(int argc, char *argv[])
}
azflush(&writer_handle, Z_SYNC_FLUSH);
azread_comment(&writer_handle, comment_str);
assert(!memcmp(COMMENT_STRING, comment_str,
strlen(COMMENT_STRING)));
/* Lets test that our internal stats are good */
assert(writer_handle.rows == TEST_LOOP_NUM);
......@@ -94,15 +115,16 @@ int main(int argc, char *argv[])
azflush(&reader_handle, Z_SYNC_FLUSH);
assert(reader_handle.rows == TEST_LOOP_NUM);
assert(reader_handle.auto_increment == 0);
assert(reader_handle.check_point == 62);
assert(reader_handle.check_point == 96);
assert(reader_handle.forced_flushes == 1);
assert(reader_handle.comment_length == 10);
assert(reader_handle.dirty == AZ_STATE_SAVED);
writer_handle.auto_increment= 4;
azflush(&writer_handle, Z_SYNC_FLUSH);
assert(writer_handle.rows == TEST_LOOP_NUM);
assert(writer_handle.auto_increment == 4);
assert(writer_handle.check_point == 62);
assert(writer_handle.check_point == 96);
assert(writer_handle.forced_flushes == 2);
assert(writer_handle.dirty == AZ_STATE_SAVED);
......@@ -181,7 +203,7 @@ int main(int argc, char *argv[])
azflush(&reader_handle, Z_SYNC_FLUSH);
assert(reader_handle.rows == 102);
assert(reader_handle.auto_increment == 4);
assert(reader_handle.check_point == 1256);
assert(reader_handle.check_point == 1290);
assert(reader_handle.forced_flushes == 4);
assert(reader_handle.dirty == AZ_STATE_SAVED);
......
......@@ -128,7 +128,12 @@ int az_open (azio_stream *s, const char *path, int Flags, File fd)
s->longest_row= 0;
s->auto_increment= 0;
s->check_point= 0;
s->comment_start_pos= 0;
s->comment_length= 0;
s->frm_start_pos= 0;
s->frm_length= 0;
s->dirty= 1; /* We create the file dirty */
s->start = AZHEADER_SIZE + AZMETA_BUFFER_SIZE;
write_header(s);
my_seek(s->file, 0, MY_SEEK_END, MYF(0));
}
......@@ -153,7 +158,6 @@ void write_header(azio_stream *s)
char buffer[AZHEADER_SIZE + AZMETA_BUFFER_SIZE];
char *ptr= buffer;
s->start = AZHEADER_SIZE + AZMETA_BUFFER_SIZE;
s->block_size= AZ_BUFSIZE;
s->version = (unsigned char)az_magic[1];
s->minor_version = (unsigned char)az_magic[2];
......@@ -167,8 +171,12 @@ void write_header(azio_stream *s)
*(ptr + AZ_BLOCK_POS)= (unsigned char)(s->block_size/1024); /* Reserved for block size */
*(ptr + AZ_STRATEGY_POS)= (unsigned char)Z_DEFAULT_STRATEGY; /* Compression Type */
int4store(ptr + AZ_FRM_POS, 0); /* FRM Block */
int4store(ptr + AZ_FRM_POS, s->frm_start_pos); /* FRM Block */
int4store(ptr + AZ_FRM_LENGTH_POS, s->frm_length); /* FRM Block */
int4store(ptr + AZ_COMMENT_POS, s->comment_start_pos); /* COMMENT Block */
int4store(ptr + AZ_COMMENT_LENGTH_POS, s->comment_length); /* COMMENT Block */
int4store(ptr + AZ_META_POS, 0); /* Meta Block */
int4store(ptr + AZ_META_LENGTH_POS, 0); /* Meta Block */
int8store(ptr + AZ_START_POS, (unsigned long long)s->start); /* Start of Data Block Index Block */
int8store(ptr + AZ_ROW_POS, (unsigned long long)s->rows); /* Start of Data Block Index Block */
int8store(ptr + AZ_FLUSH_POS, (unsigned long long)s->forced_flushes); /* Start of Data Block Index Block */
......@@ -176,10 +184,12 @@ void write_header(azio_stream *s)
int8store(ptr + AZ_AUTOINCREMENT_POS, (unsigned long long)s->auto_increment); /* Start of Data Block Index Block */
int4store(ptr+ AZ_LONGEST_POS , s->longest_row); /* Longest row */
int4store(ptr+ AZ_SHORTEST_POS, s->shortest_row); /* Shorest row */
int4store(ptr+ AZ_FRM_POS,
AZHEADER_SIZE + AZMETA_BUFFER_SIZE); /* FRM position */
*(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, buffer, (uint)s->start, 0, MYF(0));
my_pwrite(s->file, buffer, AZHEADER_SIZE + AZMETA_BUFFER_SIZE, 0, MYF(0));
}
/* ===========================================================================
......@@ -303,6 +313,8 @@ void check_header(azio_stream *s)
buffer[len]= get_byte(s);
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
read_header(s, buffer);
for (; len < s->start; len++)
get_byte(s);
}
else
{
......@@ -326,6 +338,10 @@ void read_header(azio_stream *s, unsigned char *buffer)
s->auto_increment= (unsigned long long)uint8korr(buffer + AZ_AUTOINCREMENT_POS);
s->longest_row= (unsigned int)uint4korr(buffer + AZ_LONGEST_POS);
s->shortest_row= (unsigned int)uint4korr(buffer + AZ_SHORTEST_POS);
s->frm_start_pos= (unsigned int)uint4korr(buffer + AZ_FRM_POS);
s->frm_length= (unsigned int)uint4korr(buffer + AZ_FRM_LENGTH_POS);
s->comment_start_pos= (unsigned int)uint4korr(buffer + AZ_COMMENT_POS);
s->comment_length= (unsigned int)uint4korr(buffer + AZ_COMMENT_LENGTH_POS);
s->dirty= (unsigned int)buffer[AZ_DIRTY_POS];
}
else
......@@ -497,7 +513,6 @@ unsigned int azwrite (azio_stream *s, voidpc buf, unsigned int len)
s->stream.next_in = (Bytef*)buf;
s->stream.avail_in = len;
s->rows++;
while (s->stream.avail_in != 0)
......@@ -782,3 +797,65 @@ int azclose (azio_stream *s)
return destroy(s);
}
/*
Though this was added to support MySQL's FRM file, anything can be
stored in this location.
*/
int azwrite_frm(azio_stream *s, char *blob, unsigned int length)
{
if (s->mode == 'r')
return 1;
if (s->rows > 0)
return 1;
s->frm_start_pos= s->start;
s->frm_length= length;
s->start+= length;
my_pwrite(s->file, blob, s->frm_length, s->frm_start_pos, MYF(0));
write_header(s);
my_seek(s->file, 0, MY_SEEK_END, MYF(0));
return 0;
}
int azread_frm(azio_stream *s, char *blob)
{
my_pread(s->file, blob, s->frm_length, s->frm_start_pos, MYF(0));
return 0;
}
/*
Simple comment field
*/
int azwrite_comment(azio_stream *s, char *blob, unsigned int length)
{
if (s->mode == 'r')
return 1;
if (s->rows > 0)
return 1;
s->comment_start_pos= s->start;
s->comment_length= length;
s->start+= length;
my_pwrite(s->file, blob, s->comment_length, s->comment_start_pos, MYF(0));
write_header(s);
my_seek(s->file, 0, MY_SEEK_END, MYF(0));
return 0;
}
int azread_comment(azio_stream *s, char *blob)
{
my_pread(s->file, blob, s->comment_length, s->comment_start_pos, MYF(0));
return 0;
}
......@@ -49,9 +49,10 @@ extern "C" {
#define AZMETA_BUFFER_SIZE sizeof(unsigned long long) \
+ sizeof(unsigned long long) + sizeof(unsigned long long) + sizeof(unsigned long long) \
+ sizeof(unsigned int) + sizeof(unsigned int) \
+ sizeof(unsigned int) + sizeof(unsigned int) \
+ sizeof(unsigned char)
#define AZHEADER_SIZE 21
#define AZHEADER_SIZE 29
#define AZ_MAGIC_POS 0
#define AZ_VERSION_POS 1
......@@ -59,15 +60,19 @@ extern "C" {
#define AZ_BLOCK_POS 3
#define AZ_STRATEGY_POS 4
#define AZ_FRM_POS 5
#define AZ_META_POS 9
#define AZ_START_POS 13
#define AZ_ROW_POS 21
#define AZ_FLUSH_POS 29
#define AZ_CHECK_POS 37
#define AZ_AUTOINCREMENT_POS 45
#define AZ_LONGEST_POS 53
#define AZ_SHORTEST_POS 57
#define AZ_DIRTY_POS 61
#define AZ_FRM_LENGTH_POS 9
#define AZ_META_POS 13
#define AZ_META_LENGTH_POS 17
#define AZ_START_POS 21
#define AZ_ROW_POS 29
#define AZ_FLUSH_POS 37
#define AZ_CHECK_POS 45
#define AZ_AUTOINCREMENT_POS 53
#define AZ_LONGEST_POS 61
#define AZ_SHORTEST_POS 65
#define AZ_COMMENT_POS 69
#define AZ_COMMENT_LENGTH_POS 73
#define AZ_DIRTY_POS 77
/*
......@@ -220,6 +225,10 @@ typedef struct azio_stream {
unsigned int longest_row; /* Longest row */
unsigned int shortest_row; /* Shortest row */
unsigned char dirty; /* State of file */
unsigned int frm_start_pos; /* Position for start of FRM */
unsigned int frm_length; /* Position for start of FRM */
unsigned int comment_start_pos; /* Position for start of comment */
unsigned int comment_length; /* Position for start of comment */
} azio_stream;
/* basic functions */
......@@ -322,6 +331,11 @@ extern int azclose(azio_stream *file);
error number (see function gzerror below).
*/
extern int azwrite_frm (azio_stream *s, char *blob, unsigned int length);
extern int azread_frm (azio_stream *s, char *blob);
extern int azwrite_comment (azio_stream *s, char *blob, unsigned int length);
extern int azread_comment (azio_stream *s, char *blob);
#ifdef __cplusplus
}
#endif
......@@ -139,6 +139,10 @@ static HASH archive_open_tables;
static handler *archive_create_handler(handlerton *hton,
TABLE_SHARE *table,
MEM_ROOT *mem_root);
int archive_discover(handlerton *hton, THD* thd, const char *db,
const char *name,
const void** frmblob,
uint* frmlen);
/*
Number of rows that will force a bulk insert.
......@@ -186,10 +190,11 @@ int archive_db_init(void *p)
handlerton *archive_hton;
archive_hton= (handlerton *)p;
archive_hton->state=SHOW_OPTION_YES;
archive_hton->db_type=DB_TYPE_ARCHIVE_DB;
archive_hton->create=archive_create_handler;
archive_hton->flags=HTON_NO_FLAGS;
archive_hton->state= SHOW_OPTION_YES;
archive_hton->db_type= DB_TYPE_ARCHIVE_DB;
archive_hton->create= archive_create_handler;
archive_hton->flags= HTON_NO_FLAGS;
archive_hton->discover= archive_discover;
if (pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST))
goto error;
......@@ -236,6 +241,46 @@ ha_archive::ha_archive(handlerton *hton, TABLE_SHARE *table_arg)
ref_length = sizeof(my_off_t);
}
int archive_discover(handlerton *hton, THD* thd, const char *db,
const char *name,
const void** frmblob,
uint* frmlen)
{
DBUG_ENTER("archive_discover");
DBUG_PRINT("archive_discover", ("db: %s, name: %s", db, name));
azio_stream frm_stream;
char az_file[FN_REFLEN];
char *frm_ptr;
MY_STAT file_stat;
fn_format(az_file, name, db, ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
if (!(my_stat(az_file, &file_stat, MYF(0))))
goto err;
if (!(azopen(&frm_stream, az_file, O_RDONLY|O_BINARY)))
{
if (errno == EROFS || errno == EACCES)
DBUG_RETURN(my_errno= errno);
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
}
if (frm_stream.frm_length == 0)
goto err;
frm_ptr= (char *)my_malloc(sizeof(char) * frm_stream.frm_length, MYF(0));
azread_frm(&frm_stream, frm_ptr);
azclose(&frm_stream);
*frmlen= frm_stream.frm_length;
*frmblob= frm_ptr;
DBUG_RETURN(0);
err:
my_errno= 0;
DBUG_RETURN(1);
}
/*
This method reads the header of a datafile and returns whether or not it was successful.
*/
......@@ -321,7 +366,7 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name,
share->crashed= FALSE;
share->archive_write_open= FALSE;
fn_format(share->data_file_name, table_name, "",
ARZ,MY_REPLACE_EXT|MY_UNPACK_FILENAME);
ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
strmov(share->table_name, table_name);
DBUG_PRINT("ha_archive", ("Data File %s",
share->data_file_name));
......@@ -540,6 +585,9 @@ int ha_archive::create(const char *name, TABLE *table_arg,
char linkname[FN_REFLEN];
int error;
azio_stream create_stream; /* Archive file we are working with */
File frm_file; /* File handler for readers */
MY_STAT file_stat; // Stat information for the data file
char *frm_ptr;
DBUG_ENTER("ha_archive::create");
......@@ -578,7 +626,6 @@ int ha_archive::create(const char *name, TABLE *table_arg,
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
fn_format(linkname, name, "", ARZ,
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
//MY_UNPACK_FILENAME | MY_APPEND_EXT);
}
else
{
......@@ -587,28 +634,56 @@ int ha_archive::create(const char *name, TABLE *table_arg,
linkname[0]= 0;
}
if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR|O_BINARY)))
/*
There is a chance that the file was "discovered". In this case
just use whatever file is there.
*/
if (!(my_stat(name_buff, &file_stat, MYF(0))))
{
error= errno;
goto error2;
}
my_errno= 0;
if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR|O_BINARY)))
{
error= errno;
goto error2;
}
if (linkname[0])
my_symlink(name_buff, linkname, MYF(0));
fn_format(name_buff, name, "", ".frm",
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
if (linkname[0])
my_symlink(name_buff, linkname, MYF(0));
/*
Here is where we open up the frm and pass it to archive to store
*/
frm_file= my_open(name_buff, O_RDONLY, MYF(0));
VOID(my_fstat(frm_file, &file_stat, MYF(MY_WME)));
frm_ptr= (char *)my_malloc(sizeof(char) * file_stat.st_size , MYF(0));
my_read(frm_file, frm_ptr, file_stat.st_size, MYF(0));
azwrite_frm(&create_stream, frm_ptr, file_stat.st_size);
my_close(frm_file, MYF(0));
my_free(frm_ptr, MYF(0));
if (create_info->comment.str)
azwrite_comment(&create_stream, create_info->comment.str,
create_info->comment.length);
/*
Yes you need to do this, because the starting value
for the autoincrement may not be zero.
*/
create_stream.auto_increment= stats.auto_increment_value;
if (azclose(&create_stream))
{
error= errno;
goto error2;
}
}
else
my_errno= 0;
DBUG_PRINT("ha_archive", ("Creating File %s", name_buff));
DBUG_PRINT("ha_archive", ("Creating Link %s", linkname));
/*
Yes you need to do this, because the starting value
for the autoincrement may not be zero.
*/
create_stream.auto_increment= stats.auto_increment_value;
if (azclose(&create_stream))
{
error= errno;
goto error2;
}
DBUG_RETURN(0);
......@@ -1232,7 +1307,7 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
/* Lets create a file to contain the new data */
fn_format(writer_filename, share->table_name, "", ARN,
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR|O_BINARY)))
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
......
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