summaryrefslogtreecommitdiff
path: root/storage/csv
diff options
context:
space:
mode:
authorunknown <ramil/ram@mysql.com/ramil.myoffice.izhnet.ru>2007-07-14 00:13:37 +0500
committerunknown <ramil/ram@mysql.com/ramil.myoffice.izhnet.ru>2007-07-14 00:13:37 +0500
commite4b46e7af637b6b7b2fe0573f4885904aa6b495d (patch)
tree80872a77ca2c021ab85ffc98dd27b96c1b145db2 /storage/csv
parent43d2564820b7c3c23e7aedbc59831ff37e9069ed (diff)
downloadmariadb-git-e4b46e7af637b6b7b2fe0573f4885904aa6b495d.tar.gz
Fix for bug #29253: csv table reportedly marked as crashed
Problem: the data file changes made during delete/update are not visible to other threads as the file is reopened, so reading data with old descriptors might miss the changes. Fix: reopen the data file before reading if it was reopened during delete/update to ensure there's no data behind. Note: there's no simple test case. storage/csv/ha_tina.cc: Fix for bug #29253: csv table reportedly marked as crashed - use the data file version technic to ensure we always see changes made by other threads: a) increase share->data_file_version each time we reopen the data file, i.e. at the end of update/delete. b) compare the local data file version with the shared one each time we want to read data, reopen it if they differ. storage/csv/ha_tina.h: Fix for bug #29253: csv table reportedly marked as crashed - use the data file version technic to ensure we always see changes made by other threads: a) increase share->data_file_version each time we reopen the data file, i.e. at the end og update/delete. b) compare the local data file version with shared one each time we want to read data, reopen it if they differ.
Diffstat (limited to 'storage/csv')
-rw-r--r--storage/csv/ha_tina.cc52
-rw-r--r--storage/csv/ha_tina.h3
2 files changed, 49 insertions, 6 deletions
diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index 07bd28f8e65..34c1fcde58d 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -163,6 +163,7 @@ static TINA_SHARE *get_share(const char *table_name, TABLE *table)
share->rows_recorded= 0;
share->update_file_opened= FALSE;
share->tina_write_opened= FALSE;
+ share->data_file_version= 0;
strmov(share->table_name, table_name);
fn_format(share->data_file_name, table_name, "", CSV_EXT,
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
@@ -440,7 +441,7 @@ ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
*/
current_position(0), next_position(0), local_saved_data_file_length(0),
file_buff(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH),
- records_is_known(0)
+ local_data_file_version(0), records_is_known(0)
{
/* Set our original buffers from pre-allocated memory */
buffer.set((char*)byte_buffer, IO_SIZE, &my_charset_bin);
@@ -815,6 +816,7 @@ int ha_tina::open(const char *name, int mode, uint open_options)
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
}
+ local_data_file_version= share->data_file_version;
if ((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
DBUG_RETURN(0);
@@ -985,6 +987,33 @@ int ha_tina::delete_row(const uchar * buf)
}
+/**
+ @brief Initialize the data file.
+
+ @details Compare the local version of the data file with the shared one.
+ If they differ, there are some changes behind and we have to reopen
+ the data file to make the changes visible.
+ Call @c file_buff->init_buff() at the end to read the beginning of the
+ data file into buffer.
+
+ @retval 0 OK.
+ @retval 1 There was an error.
+*/
+
+int ha_tina::init_data_file()
+{
+ if (local_data_file_version != share->data_file_version)
+ {
+ local_data_file_version= share->data_file_version;
+ if (my_close(data_file, MYF(0)) ||
+ (data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
+ return 1;
+ }
+ file_buff->init_buff(data_file);
+ return 0;
+}
+
+
/*
All table scans call this first.
The order of a table scan is:
@@ -1021,9 +1050,8 @@ int ha_tina::rnd_init(bool scan)
DBUG_ENTER("ha_tina::rnd_init");
/* set buffer to the beginning of the file */
- file_buff->init_buff(data_file);
- if (share->crashed)
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ if (share->crashed || init_data_file())
+ DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
current_position= next_position= 0;
stats.records= 0;
@@ -1247,6 +1275,16 @@ int ha_tina::rnd_end()
if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
DBUG_RETURN(-1);
/*
+ As we reopened the data file, increase share->data_file_version
+ in order to force other threads waiting on a table lock and
+ have already opened the table to reopen the data file.
+ That makes the latest changes become visible to them.
+ Update local_data_file_version as no need to reopen it in the
+ current thread.
+ */
+ share->data_file_version++;
+ local_data_file_version= share->data_file_version;
+ /*
The datafile is consistent at this point and the write filedes is
closed, so nothing worrying will happen to it in case of a crash.
Here we record this fact to the meta-file.
@@ -1308,7 +1346,8 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt)
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
/* position buffer to the start of the file */
- file_buff->init_buff(data_file);
+ if (init_data_file())
+ DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
/*
Local_saved_data_file_length is initialized during the lock phase.
@@ -1480,7 +1519,8 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt)
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
/* position buffer to the start of the file */
- file_buff->init_buff(data_file);
+ if (init_data_file())
+ DBUG_RETURN(HA_ERR_CRASHED);
/*
Local_saved_data_file_length is initialized during the lock phase.
diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
index 2e43f1a2307..5bb3e9a79a0 100644
--- a/storage/csv/ha_tina.h
+++ b/storage/csv/ha_tina.h
@@ -49,6 +49,7 @@ typedef struct st_tina_share {
File tina_write_filedes; /* File handler for readers */
bool crashed; /* Meta file is crashed */
ha_rows rows_recorded; /* Number of rows in tables */
+ uint data_file_version; /* Version of the data file used */
} TINA_SHARE;
struct tina_set {
@@ -79,12 +80,14 @@ class ha_tina: public handler
tina_set *chain_ptr;
uchar chain_alloced;
uint32 chain_size;
+ uint local_data_file_version; /* Saved version of the data file used */
bool records_is_known;
private:
bool get_write_pos(off_t *end_pos, tina_set *closest_hole);
int open_update_temp_file_if_needed();
int init_tina_writer();
+ int init_data_file();
public:
ha_tina(handlerton *hton, TABLE_SHARE *table_arg);