diff options
author | unknown <ramil/ram@mysql.com/ramil.myoffice.izhnet.ru> | 2007-07-14 00:13:37 +0500 |
---|---|---|
committer | unknown <ramil/ram@mysql.com/ramil.myoffice.izhnet.ru> | 2007-07-14 00:13:37 +0500 |
commit | e4b46e7af637b6b7b2fe0573f4885904aa6b495d (patch) | |
tree | 80872a77ca2c021ab85ffc98dd27b96c1b145db2 /storage/csv | |
parent | 43d2564820b7c3c23e7aedbc59831ff37e9069ed (diff) | |
download | mariadb-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.cc | 52 | ||||
-rw-r--r-- | storage/csv/ha_tina.h | 3 |
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); |