Commit dd07a90d authored by unknown's avatar unknown

Changed WL#1424 to use the function ha_find_files. This is a simpler...

Changed WL#1424 to use the function ha_find_files. This is a simpler implementation and all handler specific code is hidden in the appropriate handler.


mysql-test/r/ndb_autodiscover.result:
  Update test result, number of rows is 1
mysql-test/t/ndb_autodiscover.test:
  Dont run the test where table is dropped in NDb with ndb_drop_table
sql/ha_ndbcluster.cc:
  Implement function ndbcluster_find_files which will discover new tables and delete old tables
sql/ha_ndbcluster.h:
  Implement function ndbcluster_find_files 
  Remove function ndbcluster_list_tables and ndbcluster_can_discover
sql/handler.cc:
  Add ha_find_files called from mysql_find_files
  Remove ha_can_discover and ha_list_tables
sql/handler.h:
  Add ha_find_files called from mysql_find_files
  Remove ha_can_discover and ha_list_tables
sql/sql_show.cc:
  Revert to original version of sql_show.cc
  Only changes to this version is that ha_find_files is called from mysql_find_files in order to give the handlers a possibility to find new files in engine
parent 4d18add0
......@@ -145,7 +145,7 @@ flush tables;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t6 MyISAM 9 Fixed 1 260 # # # 0 NULL # # NULL # NULL
t7 ndbcluster 9 Fixed 100 0 # # # 0 NULL # # NULL # NULL
t7 ndbcluster 9 Fixed 1 0 # # # 0 NULL # # NULL # NULL
show status like 'handler_discover%';
Variable_name Value
Handler_discover 2
......
......@@ -189,30 +189,33 @@ drop table t6, t7;
# saying "No such table existed"
#
flush status;
create table t4(
id int not null primary key,
name char(27)
) engine=ndb;
insert into t4 values (1, "Automatic");
select * from t4;
# Commented out, to be fixed
#
#flush status;
#
#create table t4(
# id int not null primary key,
# name char(27)
#) engine=ndb;
#insert into t4 values (1, "Automatic");
#select * from t4;
#
# Remove the table from NDB
system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t4;
system exec ../ndb/tools/ndb_show_tables > show_tables.log;
#system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t4 > /dev/null ;
#system exec ../ndb/tools/ndb_show_tables > var/log/ndb_show_tables.log;
#
# Test that correct error is returned
--error 1146
select * from t4;
--error 1146
select * from t4;
show status like 'handler_discover%';
drop table t4;
show tables;
#--error 1146
#select * from t4;
#--error 1146
#select * from t4;
#
#show status like 'handler_discover%';
#drop table t4;
#
#show tables;
......
......@@ -123,8 +123,6 @@ static const err_code_mapping err_map[]=
{ 827, HA_ERR_RECORD_FILE_FULL },
{ 832, HA_ERR_RECORD_FILE_FULL },
{ 0, 1 },
{ -1, -1 }
};
......@@ -3657,14 +3655,6 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
DBUG_RETURN(0);
}
int ndbcluster_can_discover(THD *thd, const char *name)
{
DBUG_ENTER("ndbcluster_can_discover");
DBUG_RETURN(!my_strcasecmp(system_charset_info, fn_ext(name), ha_ndb_ext))
}
/*
Check if a table exists in NDB
......@@ -3699,21 +3689,39 @@ int ndbcluster_table_exists(THD* thd, const char *db, const char *name)
}
/*
List tables in NDB Cluster
*/
int ndbcluster_list_tables(THD* thd, HASH *tables, const char* db)
extern "C" byte* ndb_tables_get_key(const char *entry, uint *length,
my_bool not_used __attribute__((unused)))
{
*length= strlen(entry);
return (byte*) entry;
}
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir)
{
uint i;
NdbDictionary::Dictionary::List list;
Ndb* ndb;
char name[FN_REFLEN];
HASH ndb_tables;
DBUG_ENTER("ndbcluster_list_tables");
DBUG_PRINT("enter", ("db: %s", db));
if (!(ndb= check_ndb_in_thd(thd)))
DBUG_RETURN(HA_ERR_NO_CONNECTION);
if (dir)
DBUG_RETURN(0); // Discover of databases not yet discovered
if (hash_init(&ndb_tables, system_charset_info,32,0,0,
(hash_get_key)ndb_tables_get_key,0,0))
{
DBUG_PRINT("info", ("Failed to init HASH ndb_tables"));
DBUG_RETURN(-1);
}
/* List tables in NDB Cluster kernel */
NDBDICT *dict= ndb->getDictionary();
if (dict->listObjects(list,
......@@ -3723,14 +3731,82 @@ int ndbcluster_list_tables(THD* thd, HASH *tables, const char* db)
for (i= 0 ; i < list.count ; i++)
{
NdbDictionary::Dictionary::List::Element& t= list.elements[i];
DBUG_PRINT("discover", ("%d: %s/%s", t.id, t.database, t.name));
if (strcmp(t.database, db) == 0)
DBUG_PRINT("discover", ("%d, %s/%s", t.id, t.database, t.name));
if (my_hash_insert(&ndb_tables, (byte*)thd->strdup(t.name)))
continue;
// Only discover files that fullfill wildcard
if (wild)
{
DBUG_PRINT("info", ("my_hash_insert %s", t.name));
(void)my_hash_insert(tables, (byte*)thd->strdup(t.name));;
if (lower_case_table_names)
{
if (wild_case_compare(files_charset_info, t.name, wild))
continue;
}
else if (wild_compare(t.name,wild,0))
continue;
}
// Discover the file if it does not already exists on disk
(void)strxnmov(name, FN_REFLEN,
mysql_data_home,"/",t.database,"/",t.name,reg_ext,NullS);
DBUG_PRINT("discover", ("Check access for %s", name));
if (access(name, F_OK))
{
DBUG_PRINT("discover", ("Table %s need disocver", name));
pthread_mutex_lock(&LOCK_open);
ha_create_table_from_engine(thd, t.database, t.name, true);
pthread_mutex_unlock(&LOCK_open);
}
}
DBUG_RETURN(0);
/*
Find all .ndb files in current dir and check
if they still exists in NDB
*/
char *ext;
MY_DIR *dirp;
FILEINFO *file;
if (!(dirp= my_dir(path,MYF(MY_WME | (dir ? MY_WANT_STAT : 0)))))
DBUG_RETURN(-1);
for (i= 0; i < (uint)dirp->number_off_files; i++)
{
file= dirp->dir_entry+i;
{
ext= fn_ext(file->name);
if(!my_strcasecmp(system_charset_info, ext, ha_ndb_ext))
{
DBUG_PRINT("discover", ("Found file: %s", file->name));
*ext= 0;
if (hash_search(&ndb_tables, file->name, strlen(file->name)))
continue;
DBUG_PRINT("discover", ("File didn't exist in ndb_tables list"));
// Verify that handler agrees table is gone.
if (ndbcluster_table_exists(thd, db, file->name) == 0)
{
DBUG_PRINT("discover", ("Remove table %s/%s",db, file->name ));
// Delete the table and all related files
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
table_list.db= (char*) db;
table_list.real_name=(char*)file->name;
(void)mysql_rm_table_part2_with_lock(thd, &table_list,
/* if_exists */ true,
/* drop_temporary */ false,
/* dont_log_query*/ true);
}
}
}
}
hash_free(&ndb_tables);
my_dirend(dirp);
DBUG_RETURN(0);
}
......
......@@ -279,8 +279,8 @@ void ndbcluster_close_connection(THD *thd);
int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
const void** frmblob, uint* frmlen);
int ndbcluster_can_discover(THD *thd, const char *name);
int ndbcluster_list_tables(THD* thd, HASH* tables, const char* db);
int ndbcluster_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir);
int ndbcluster_table_exists(THD* thd, const char *db, const char *name);
int ndbcluster_drop_database(const char* path);
......
......@@ -1464,39 +1464,26 @@ int ha_discover(THD* thd, const char* db, const char* name,
/*
Ask handler if it would support discover of a file
with this name
RETURN
0 Does not recognise file
1 File can be discovered
Call this function in order to give the handler the possiblity
to ask engine if there are any new tables that should be written to disk
or any dropped tables that need to be removed from disk
*/
int ha_can_discover(THD* thd, const char* name)
int
ha_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir)
{
int error= 0; // Can't discover this file name
DBUG_ENTER("ha_can_discover");
DBUG_PRINT("enter", ("name: %s", name));
#ifdef HAVE_NDBCLUSTER_DB
if (have_ndbcluster == SHOW_OPTION_YES)
error= ndbcluster_can_discover(thd, name);
#endif
DBUG_RETURN(error);
}
/*
Get a list of tables that exists in handler(s)
*/
int ha_list_tables(THD* thd, HASH *tables, const char* db)
{
int error= 0;
DBUG_ENTER("ha_list_tables");
DBUG_PRINT("enter", ("db: %s", db));
DBUG_ENTER("ha_find_files");
DBUG_PRINT("enter", ("db: %s, path: %s, wild: %s, dir: %d",
db, path, wild, dir));
#ifdef HAVE_NDBCLUSTER_DB
if (have_ndbcluster == SHOW_OPTION_YES)
error= ndbcluster_list_tables(thd, tables, db);
error= ndbcluster_find_files(thd, db, path, wild, dir);
#endif
DBUG_RETURN(error);
}
/*
......
......@@ -565,7 +565,8 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache,
KEY_CACHE *new_key_cache);
int ha_discover(THD* thd, const char* dbname, const char* name,
const void** frmblob, uint* frmlen);
int ha_list_tables(THD* thd, HASH *tables, const char* db);
int ha_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir);
int ha_table_exists(THD* thd, const char* db, const char* name);
int ha_can_discover(THD* thd, const char* name);
......@@ -358,59 +358,34 @@ int mysqld_show_column_types(THD *thd)
}
/*
Ask all engines if they can provide a list of available tables.
Returns a list of available tables.
*/
int
mysql_discover_tables(THD *thd, HASH *ha_tables, const char *db, bool dir)
{
DBUG_ENTER("mysql_discover_files");
if (dir)
DBUG_RETURN(0); // Discover of directories(databases) not supported yet
// Get list of files in storage engine
if (ha_list_tables(thd, ha_tables, db))
DBUG_RETURN(-1);
DBUG_PRINT("info",("discovered: %d files", ha_tables->records));
DBUG_RETURN(0);
}
/*
List all files or directories in a given location
Returns
files - list of files where wild card has been applied
all_files - list of all files
dsc_files - list of files which are discoverable
*/
int
mysql_list_files(THD *thd, const char *db, const char *path, const char *wild,
bool dir, List<char> *files, HASH *all_files, HASH* dsc_files)
mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
const char *wild, bool dir)
{
uint i;
char *ext, **dsc_ext;
char *ext;
MY_DIR *dirp;
FILEINFO *file;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint col_access=thd->col_access;
#endif
TABLE_LIST table_list;
DBUG_ENTER("mysql_list_files");
DBUG_ENTER("mysql_find_files");
if (wild && !wild[0])
wild=0;
if (ha_find_files(thd,db,path,wild,dir))
DBUG_RETURN(-1);
bzero((char*) &table_list,sizeof(table_list));
if (!(dirp = my_dir(path,MYF(MY_WME | (dir ? MY_WANT_STAT : 0)))))
DBUG_RETURN(-1);
for (i= 0; i < (uint)dirp->number_off_files; i++)
for (i=0 ; i < (uint) dirp->number_off_files ; i++)
{
file= dirp->dir_entry+i;
file=dirp->dir_entry+i;
if (dir)
{ /* Return databases */
#ifdef USE_SYMDIR
......@@ -420,7 +395,7 @@ mysql_list_files(THD *thd, const char *db, const char *path, const char *wild,
/* Only show the sym file if it points to a directory */
char buff[FN_REFLEN], *end;
MY_STAT status;
*ext= 0; /* Remove extension */
*ext=0; /* Remove extension */
unpack_dirname(buff, file->name);
end= strend(buff);
if (end != buff && end[-1] == FN_LIBCHAR)
......@@ -439,36 +414,11 @@ mysql_list_files(THD *thd, const char *db, const char *path, const char *wild,
}
else
{
// Don't process temp files
if (is_prefix(file->name, tmp_file_prefix))
continue;
ext= fn_ext(file->name);
// Check for files that indicates the table can be discovered
if (ha_can_discover(thd, file->name))
{
DBUG_PRINT("info", ("Discoverable file found: %s", file->name));
*ext= 0;
if (my_hash_insert(dsc_files, (byte*)thd->strdup(file->name)))
{
my_dirend(dirp);
DBUG_RETURN(-1);
}
continue;
}
// Return only .frm files
if (my_strcasecmp(system_charset_info, ext,reg_ext))
continue;
*ext=0;
// Insert into list of all .frm files
if (my_hash_insert(all_files, (byte*)thd->strdup(file->name)))
{
my_dirend(dirp);
DBUG_RETURN(-1);
}
// Return only .frm files which aren't temp files.
if (my_strcasecmp(system_charset_info, ext=fn_ext(file->name),reg_ext) ||
is_prefix(file->name,tmp_file_prefix))
continue;
*ext=0;
if (wild)
{
if (lower_case_table_names)
......@@ -497,114 +447,11 @@ mysql_list_files(THD *thd, const char *db, const char *path, const char *wild,
DBUG_RETURN(-1);
}
}
DBUG_PRINT("info",("found: %d files", files->elements));
my_dirend(dirp);
DBUG_RETURN(0);
}
extern "C" byte* ha_tables_get_key(const char *entry, uint *length,
my_bool not_used __attribute__((unused)))
{
*length= strlen(entry);
return (byte*) entry;
}
int
mysql_find_files(THD *thd,List<char> *files, const char *db,
const char *path, const char *wild, bool dir)
{
int error= -1;
uint i;
bool discovery_performed= false;
DBUG_ENTER("mysql_find_files");
DBUG_PRINT("enter", ("db: %s, path: %s, wild: %s, dir: %d",
db, path, wild, dir));
if (wild && !wild[0])
wild=0;
HASH ha_tables, all_files, dsc_files;
if (hash_init(&ha_tables,system_charset_info,32,0,0,
(hash_get_key) ha_tables_get_key,0,0) ||
hash_init(&all_files,system_charset_info,32,0,0,
(hash_get_key) ha_tables_get_key,0,0) ||
hash_init(&dsc_files,system_charset_info,32,0,0,
(hash_get_key) ha_tables_get_key,0,0))
goto err_end;
if (mysql_discover_tables(thd, &ha_tables, db, dir))
goto err_end;
if (mysql_list_files(thd, db, path, wild, dir,
files, &all_files, &dsc_files))
goto err_end;
/*
Discovery part 1
Loop through handler files and see if any of them should be discovered
*/
for (i= 0; i < ha_tables.records; i++)
{
const char *name = hash_element(&ha_tables, i);
if (hash_search(&all_files, name, strlen(name)))
continue;
// Table was in handler, but not in list of all tables
DBUG_PRINT("info", ("Table to discover[%d]: %s", i, name));
pthread_mutex_lock(&LOCK_open);
ha_create_table_from_engine(thd, db, name, true);
pthread_mutex_unlock(&LOCK_open);
discovery_performed= true;
}
/*
Discovery part2
Loop through dsc files and see if any of them need to be deleted
*/
for (i= 0; i < dsc_files.records; i++)
{
const char *name = hash_element(&dsc_files, i);
if (hash_search(&ha_tables, name, strlen(name)))
continue;
// Table was only on disk and not in handler
DBUG_PRINT("info", ("Table[%d]: %s only exists on disk", i, name));
// Verify that handler agrees table is gone.
if (ha_table_exists(thd, db, name) == 0)
{
// Delete the table and all related files
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
table_list.db= (char*) db;
table_list.real_name=(char*)name;
(void)mysql_rm_table_part2_with_lock(thd, &table_list,
/* if_exists */ true,
/* drop_temporary */ false,
/* dont_log_query*/ true);
discovery_performed= true;
}
}
if (discovery_performed)
{
// Call mysql_list_files one more time to get an updated list
DBUG_PRINT("info", ("Calling mysql_list_files one more time"));
files->empty();
if (mysql_list_files(thd, db, path, wild, dir,
files, &all_files, &dsc_files))
goto err_end;
}
DBUG_PRINT("info",("found: %d files", files->elements));
error = 0;
err_end:
hash_free(&ha_tables);
hash_free(&all_files);
hash_free(&dsc_files);
DBUG_RETURN(error);
}
/***************************************************************************
Extended version of mysqld_show_tables
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment