diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-04-09 15:31:29 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-04-09 15:31:29 +0200 |
commit | 03dfb2c1210f75e234b5571a40a9aa92cb1afa45 (patch) | |
tree | b6e97baed151432f30c12b30c28563aa1875327b /sql/discover.cc | |
parent | 2a9662b401405ee8f8f0849f7f90faac1081e26e (diff) | |
download | mariadb-git-03dfb2c1210f75e234b5571a40a9aa92cb1afa45.tar.gz |
file-based table discovery for discovering storage engines
also:
* move few tests from archive/archive.test to archive/discover.test
* fix (unintentionally) bug#34104, updated result files
Diffstat (limited to 'sql/discover.cc')
-rw-r--r-- | sql/discover.cc | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/sql/discover.cc b/sql/discover.cc index b9dba92a780..72b88c8780b 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -128,7 +128,131 @@ int writefrm(const char *name, const uchar *frmdata, size_t len) DBUG_RETURN(error); } /* writefrm */ +static inline void advance(FILEINFO* &from, FILEINFO* &to, + FILEINFO* cur, bool &skip) +{ + if (skip) // if not copying + from= cur; // just advance the start pointer + else // if copying + if (to == from) // but to the same place (not shifting the data) + from= to= cur; // advance both pointers + else // otherwise + while (from < cur) // have to copy [from...cur) to [to...) + *to++ = *from++; + skip= false; +} + +/** + Go through the directory listing looking for files with a specified + extension and add them to the result list + + @details + This function may be called many times on the same directory listing + but with different extensions. To avoid discovering the same table twice, + whenever a table file is discovered, all files with the same name + (independently from the extensions) are removed from the list. + + Example: the list contained + { "db.opt", "t1.MYD", "t1.MYI", "t1.frm", "t2.ARZ", "t3.ARZ", "t3.frm" } + on discovering all ".frm" files, tables "t1" and "t3" will be found, + and list will become + { "db.opt", "t2.ARZ" } + and now ".ARZ" discovery can discover the table "t2" + + @note + This function assumes that the directory listing is sorted alphabetically. + + @note Partitioning makes this more complicated. A partitioned table t1 might + have files, like t1.frm, t1#P#part1.ibd, t1#P#foo.ibd, etc. + That means we need to compare file names only up to the first '#' or '.' + whichever comes first. +*/ +int extension_based_table_discovery(MY_DIR *dirp, const char *ext_meta, + handlerton::discovered_list *result) +{ + CHARSET_INFO *cs= character_set_filesystem; + size_t ext_meta_len= strlen(ext_meta); + FILEINFO *from, *to, *cur, *end; + bool skip= false; + + from= to= cur= dirp->dir_entry; + end= cur + dirp->number_of_files; + while (cur < end) + { + char *octothorp= strrchr(cur->name, '#'); + char *ext= strchr(octothorp ? octothorp : cur->name, FN_EXTCHAR); + if (ext && octothorp != cur->name) + { + size_t len= (octothorp ? octothorp : ext) - cur->name; + if (from != cur && + (my_strnncoll(cs, (uchar*)from->name, len, (uchar*)cur->name, len) || + (from->name[len] != FN_EXTCHAR && from->name[len] != '#'))) + advance(from, to, cur, skip); + if (my_strnncoll(cs, (uchar*)ext, strlen(ext), + (uchar*)ext_meta, ext_meta_len) == 0) + { + *ext = 0; + if (result->add_file(cur->name)) + return 1; + *ext = FN_EXTCHAR; + skip= true; // table discovered, skip all files with the same name + } + } + else + { + advance(from, to, cur, skip); + from++; + } + cur++; + } + advance(from, to, cur, skip); + dirp->number_of_files= to - dirp->dir_entry; + return 0; +} + +/** + Simple, not reusable file-based table discovery + + @details + simplified version of extension_based_table_discovery(), that does not + modify the list of files. It cannot be called many times for the same + directory listing, otherwise it'll produce duplicate results. + + @note + For backward compatibility reasons, this will find tables with names, + starting from '#', as long as they don't start from '#sql-'. + These names are invalid since 5.0, and the compex discovery function + will ignore them. Anyone still having these files, should disable + discovering engines, and rename these invalid table files. +*/ +int ext_table_discovery_simple(MY_DIR *dirp, const char *ext_meta, + handlerton::discovered_list *result) +{ + CHARSET_INFO *cs= character_set_filesystem; + size_t ext_meta_len= strlen(ext_meta); + FILEINFO *cur, *end; + + cur= dirp->dir_entry; + end= cur + dirp->number_of_files; + while (cur < end) + { + char *ext= strrchr(cur->name, FN_EXTCHAR); + + if (ext && !is_prefix(cur->name, tmp_file_prefix)) + { + if (my_strnncoll(cs, (uchar*)ext, strlen(ext), + (uchar*)ext_meta, ext_meta_len) == 0) + { + *ext = 0; + if (result->add_file(cur->name)) + return 1; + } + } + cur++; + } + return 0; +} |