summaryrefslogtreecommitdiff
path: root/sql/discover.cc
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-04-09 15:31:29 +0200
committerSergei Golubchik <sergii@pisem.net>2013-04-09 15:31:29 +0200
commit03dfb2c1210f75e234b5571a40a9aa92cb1afa45 (patch)
treeb6e97baed151432f30c12b30c28563aa1875327b /sql/discover.cc
parent2a9662b401405ee8f8f0849f7f90faac1081e26e (diff)
downloadmariadb-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.cc124
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;
+}