summaryrefslogtreecommitdiff
path: root/storage/archive/ha_archive.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/archive/ha_archive.cc')
-rw-r--r--storage/archive/ha_archive.cc218
1 files changed, 98 insertions, 120 deletions
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index 342f8be956e..d18e46c08b1 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -1,5 +1,6 @@
/*
Copyright (c) 2004, 2012, Oracle and/or its affiliates
+ Copyright (c) 2010, 2013 Monty Program Ab.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -25,6 +26,7 @@
#include <myisam.h> // T_EXTEND
#include "ha_archive.h"
+#include "discover.h"
#include <my_dir.h>
#include <mysql/plugin.h>
@@ -104,7 +106,6 @@ static HASH archive_open_tables;
/* The file extension */
#define ARZ ".ARZ" // The data file
#define ARN ".ARN" // Files used during an optimize call
-#define ARM ".ARM" // Meta file (deprecated)
/*
uchar + uchar
@@ -120,10 +121,7 @@ extern "C" PSI_file_key arch_key_file_data;
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,
- uchar **frmblob,
- size_t *frmlen);
+int archive_discover(handlerton *hton, THD* thd, TABLE_SHARE *share);
/*
Number of rows that will force a bulk insert.
@@ -161,12 +159,11 @@ static PSI_mutex_info all_archive_mutexes[]=
{ &az_key_mutex_ARCHIVE_SHARE_mutex, "ARCHIVE_SHARE::mutex", 0}
};
-PSI_file_key arch_key_file_metadata, arch_key_file_data, arch_key_file_frm;
+PSI_file_key arch_key_file_metadata, arch_key_file_data;
static PSI_file_info all_archive_files[]=
{
{ &arch_key_file_metadata, "metadata", 0},
- { &arch_key_file_data, "data", 0},
- { &arch_key_file_frm, "FRM", 0}
+ { &arch_key_file_data, "data", 0}
};
static void init_archive_psi_keys(void)
@@ -198,6 +195,14 @@ static void init_archive_psi_keys(void)
TRUE Error
*/
+/*
+ We just implement one additional file extension.
+*/
+static const char *ha_archive_exts[] = {
+ ARZ,
+ NullS
+};
+
int archive_db_init(void *p)
{
DBUG_ENTER("archive_db_init");
@@ -212,7 +217,8 @@ int archive_db_init(void *p)
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;
+ archive_hton->discover_table= archive_discover;
+ archive_hton->tablefile_extensions= ha_archive_exts;
if (mysql_mutex_init(az_key_mutex_archive_mutex,
&archive_mutex, MY_MUTEX_INIT_FAST))
@@ -261,22 +267,20 @@ ha_archive::ha_archive(handlerton *hton, TABLE_SHARE *table_arg)
archive_reader_open= FALSE;
}
-int archive_discover(handlerton *hton, THD* thd, const char *db,
- const char *name,
- uchar **frmblob,
- size_t *frmlen)
+int archive_discover(handlerton *hton, THD* thd, TABLE_SHARE *share)
{
DBUG_ENTER("archive_discover");
- DBUG_PRINT("archive_discover", ("db: %s, name: %s", db, name));
+ DBUG_PRINT("archive_discover", ("db: '%s' name: '%s'", share->db.str,
+ share->table_name.str));
azio_stream frm_stream;
char az_file[FN_REFLEN];
- char *frm_ptr;
+ uchar *frm_ptr;
MY_STAT file_stat;
- build_table_filename(az_file, sizeof(az_file) - 1, db, name, ARZ, 0);
+ strxmov(az_file, share->normalized_path.str, ARZ, NullS);
if (!(mysql_file_stat(/* arch_key_file_data */ 0, az_file, &file_stat, MYF(0))))
- goto err;
+ DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
if (!(azopen(&frm_stream, az_file, O_RDONLY|O_BINARY)))
{
@@ -286,19 +290,23 @@ int archive_discover(handlerton *hton, THD* thd, const char *db,
}
if (frm_stream.frm_length == 0)
- goto err;
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
- frm_ptr= (char *)my_malloc(sizeof(char) * frm_stream.frm_length, MYF(0));
- azread_frm(&frm_stream, frm_ptr);
- azclose(&frm_stream);
+ frm_ptr= (uchar *)my_malloc(sizeof(char) * frm_stream.frm_length,
+ MYF(MY_THREAD_SPECIFIC | MY_WME));
+ if (!frm_ptr)
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- *frmlen= frm_stream.frm_length;
- *frmblob= (uchar*) frm_ptr;
+ if (azread_frm(&frm_stream, frm_ptr))
+ goto ret;
- DBUG_RETURN(0);
-err:
- my_errno= 0;
- DBUG_RETURN(1);
+ azclose(&frm_stream);
+
+ my_errno= share->init_from_binary_frm_image(thd, 1,
+ frm_ptr, frm_stream.frm_length);
+ret:
+ my_free(frm_ptr);
+ DBUG_RETURN(my_errno);
}
/*
@@ -427,6 +435,9 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc)
*/
if (archive_tmp.version < ARCHIVE_VERSION)
*rc= HA_ERR_TABLE_NEEDS_UPGRADE;
+ else if (frm_compare(&archive_tmp))
+ *rc= HA_ERR_TABLE_DEF_CHANGED;
+
azclose(&archive_tmp);
(void) my_hash_insert(&archive_open_tables, (uchar*) share);
@@ -529,20 +540,6 @@ int ha_archive::init_archive_reader()
}
-/*
- We just implement one additional file extension.
-*/
-static const char *ha_archive_exts[] = {
- ARZ,
- NullS
-};
-
-const char **ha_archive::bas_ext() const
-{
- return ha_archive_exts;
-}
-
-
/*
When opening a file we:
Create/get our shared structure.
@@ -569,14 +566,8 @@ int ha_archive::open(const char *name, int mode, uint open_options)
{
case 0:
break;
+ case HA_ERR_TABLE_DEF_CHANGED:
case HA_ERR_CRASHED_ON_USAGE:
- DBUG_PRINT("ha_archive", ("archive table was crashed"));
- if (open_options & HA_OPEN_FOR_REPAIR)
- {
- rc= 0;
- break;
- }
- /* fall through */
case HA_ERR_TABLE_NEEDS_UPGRADE:
if (open_options & HA_OPEN_FOR_REPAIR)
{
@@ -655,9 +646,10 @@ int ha_archive::close(void)
int ha_archive::frm_copy(azio_stream *src, azio_stream *dst)
{
int rc= 0;
- char *frm_ptr;
+ uchar *frm_ptr;
- if (!(frm_ptr= (char *) my_malloc(src->frm_length, MYF(0))))
+ if (!(frm_ptr= (uchar *) my_malloc(src->frm_length,
+ MYF(MY_THREAD_SPECIFIC | MY_WME))))
return HA_ERR_OUT_OF_MEM;
/* Write file offset is set to the end of the file. */
@@ -671,6 +663,25 @@ int ha_archive::frm_copy(azio_stream *src, azio_stream *dst)
}
+/**
+ Compare frm blob with the on-disk frm file
+
+ @param s The azio stream.
+
+ @return Zero if equal, non-zero otherwise.
+*/
+
+int ha_archive::frm_compare(azio_stream *s)
+{
+ if (!s->frmver_length)
+ return 0; // Old pre-10.0 archive table. Never rediscover.
+
+ LEX_CUSTRING *ver= &table->s->tabledef_version;
+ return ver->length != s->frmver_length ||
+ memcmp(ver->str, s->frmver, ver->length);
+}
+
+
/*
We create our data file here. The format is pretty simple.
You can read about the format of the data file above.
@@ -687,9 +698,8 @@ 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
- uchar *frm_ptr;
+ const uchar *frm_ptr;
+ size_t frm_len;
DBUG_ENTER("ha_archive::create");
@@ -738,56 +748,40 @@ int ha_archive::create(const char *name, TABLE *table_arg,
There is a chance that the file was "discovered". In this case
just use whatever file is there.
*/
- if (!(mysql_file_stat(/* arch_key_file_data */ 0, name_buff, &file_stat, MYF(0))))
+ my_errno= 0;
+ if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR|O_BINARY)))
{
- my_errno= 0;
- if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR|O_BINARY)))
- {
- error= errno;
- goto error2;
- }
+ 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
- */
- if ((frm_file= mysql_file_open(arch_key_file_frm, name_buff, O_RDONLY, MYF(0))) >= 0)
- {
- if (!mysql_file_fstat(frm_file, &file_stat, MYF(MY_WME)))
- {
- frm_ptr= (uchar *)my_malloc(sizeof(uchar) * (size_t)file_stat.st_size, MYF(0));
- if (frm_ptr)
- {
- mysql_file_read(frm_file, frm_ptr, (size_t)file_stat.st_size, MYF(0));
- azwrite_frm(&create_stream, (char *)frm_ptr, (size_t)file_stat.st_size);
- my_free(frm_ptr);
- }
- }
- mysql_file_close(frm_file, MYF(0));
- }
+ /*
+ Here is where we open up the frm and pass it to archive to store
+ */
+ if (!table_arg->s->read_frm_image(&frm_ptr, &frm_len))
+ {
+ azwrite_frm(&create_stream, frm_ptr, frm_len);
+ table_arg->s->free_frm_image(frm_ptr);
+ }
- if (create_info->comment.str)
- azwrite_comment(&create_stream, create_info->comment.str,
- create_info->comment.length);
+ 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 ?
- stats.auto_increment_value - 1 : 0;
- if (azclose(&create_stream))
- {
- error= errno;
- goto error2;
- }
+ /*
+ 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 ?
+ stats.auto_increment_value - 1 : 0;
+ 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));
@@ -906,10 +900,11 @@ int ha_archive::write_row(uchar *buf)
mysql_mutex_lock(&share->mutex);
- if (!share->archive_write_open)
- if (init_archive_writer())
- DBUG_RETURN(errno);
-
+ if (!share->archive_write_open && init_archive_writer())
+ {
+ rc= errno;
+ goto error;
+ }
if (table->next_number_field && record == table->record[0])
{
@@ -939,7 +934,8 @@ int ha_archive::write_row(uchar *buf)
First we create a buffer that we can use for reading rows, and can pass
to get_row().
*/
- if (!(read_buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
+ if (!(read_buf= (uchar*) my_malloc(table->s->reclength,
+ MYF(MY_THREAD_SPECIFIC | MY_WME))))
{
rc= HA_ERR_OUT_OF_MEM;
goto error;
@@ -989,7 +985,6 @@ int ha_archive::write_row(uchar *buf)
error:
mysql_mutex_unlock(&share->mutex);
my_free(read_buf);
-
DBUG_RETURN(rc);
}
@@ -1809,23 +1804,6 @@ void ha_archive::destroy_record_buffer(archive_record_buffer *r)
struct st_mysql_storage_engine archive_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
-mysql_declare_plugin(archive)
-{
- MYSQL_STORAGE_ENGINE_PLUGIN,
- &archive_storage_engine,
- "ARCHIVE",
- "Brian Aker, MySQL AB",
- "Archive storage engine",
- PLUGIN_LICENSE_GPL,
- archive_db_init, /* Plugin Init */
- archive_db_done, /* Plugin Deinit */
- 0x0300 /* 3.0 */,
- NULL, /* status variables */
- NULL, /* system variables */
- NULL, /* config options */
- 0, /* flags */
-}
-mysql_declare_plugin_end;
maria_declare_plugin(archive)
{
MYSQL_STORAGE_ENGINE_PLUGIN,