summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <ingo@mysql.com>2005-04-29 14:56:04 +0200
committerunknown <ingo@mysql.com>2005-04-29 14:56:04 +0200
commitc6dedf4ed45707df5bd54e1c2126707e542cd8a1 (patch)
tree7607a315fe88da0871e8491ffc151bf981475bb8
parent45236ee55d9f3f86efc67482c52bf6070b8e195c (diff)
parent17e6c8f292d0273ef26d0c3deeaa259e5d0d8db9 (diff)
downloadmariadb-git-c6dedf4ed45707df5bd54e1c2126707e542cd8a1.tar.gz
Merge mysql.com:/home/mydev/mysql-5.0
into mysql.com:/home/mydev/mysql-5.0-5000
-rw-r--r--mysql-test/r/ndb_multi.result22
-rw-r--r--mysql-test/t/ndb_multi.test24
-rw-r--r--ndb/include/ndbapi/NdbDictionary.hpp5
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp11
-rw-r--r--sql/ha_ndbcluster.cc80
-rw-r--r--sql/ha_ndbcluster.h4
6 files changed, 122 insertions, 24 deletions
diff --git a/mysql-test/r/ndb_multi.result b/mysql-test/r/ndb_multi.result
index 5696fda1c07..2080be241e8 100644
--- a/mysql-test/r/ndb_multi.result
+++ b/mysql-test/r/ndb_multi.result
@@ -13,6 +13,26 @@ a
show status like 'handler_discover%';
Variable_name Value
Handler_discover 0
+select * from t1;
+a
+2
+drop table t1;
+create table t1 (a int) engine=ndbcluster;
+insert into t1 value (2);
+select * from t1;
+a
+2
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+drop table t1;
+create table t1 (a int) engine=ndbcluster;
+insert into t1 value (2);
+select * from t1;
+ERROR HY000: Got error 241 'Invalid schema object version' from ndbcluster
+select * from t1;
+a
+2
flush status;
select * from t1;
a
@@ -20,7 +40,7 @@ a
update t1 set a=3 where a=2;
show status like 'handler_discover%';
Variable_name Value
-Handler_discover 1
+Handler_discover 0
create table t3 (a int not null primary key, b varchar(22),
c int, last_col text) engine=ndb;
insert into t3 values(1, 'Hi!', 89, 'Longtext column');
diff --git a/mysql-test/t/ndb_multi.test b/mysql-test/t/ndb_multi.test
index 24651913a79..85950c72cf9 100644
--- a/mysql-test/t/ndb_multi.test
+++ b/mysql-test/t/ndb_multi.test
@@ -18,6 +18,30 @@ select * from t1;
select * from t2;
show status like 'handler_discover%';
+# Check dropping and recreating table on same server
+connect (con1,localhost,,,test);
+connect (con2,localhost,,,test);
+connection con1;
+select * from t1;
+connection con2;
+drop table t1;
+create table t1 (a int) engine=ndbcluster;
+insert into t1 value (2);
+connection con1;
+select * from t1;
+
+# Check dropping and recreating table on different server
+connection server2;
+show status like 'handler_discover%';
+drop table t1;
+create table t1 (a int) engine=ndbcluster;
+insert into t1 value (2);
+connection server1;
+# Currently a retry is required remotely
+--error 1296
+select * from t1;
+select * from t1;
+
# Connect to server2 and use the tables from there
connection server2;
flush status;
diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp
index 7a945c1c22e..86130be4c4b 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -76,8 +76,11 @@ public:
Changed, ///< The object has been modified in memory
///< and has to be commited in NDB Kernel for
///< changes to take effect
- Retrieved ///< The object exist and has been read
+ Retrieved, ///< The object exist and has been read
///< into main memory from NDB Kernel
+ Invalid ///< The object has been invalidated
+ ///< and should not be used
+
};
/**
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index ff87a72f636..96c8f6020e5 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -1526,6 +1526,7 @@ int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
// If in local cache it must be in global
if (!cachedImpl)
abort();
+ cachedImpl->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(cachedImpl);
m_globalHash->unlock();
}
@@ -1830,8 +1831,8 @@ NdbDictionaryImpl::dropTable(const char * name)
DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName));
m_localHash.drop(internalTableName);
-
m_globalHash->lock();
+ tab->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(tab);
m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
@@ -1875,10 +1876,11 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
int ret = m_receiver.dropTable(impl);
if(ret == 0 || m_error.code == 709){
const char * internalTableName = impl.m_internalName.c_str();
+
m_localHash.drop(internalTableName);
-
m_globalHash->lock();
+ impl.m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(&impl);
m_globalHash->unlock();
@@ -1976,6 +1978,7 @@ NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
m_localHash.drop(internalTableName);
m_globalHash->lock();
+ impl.m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(&impl);
m_globalHash->unlock();
return 0;
@@ -2242,8 +2245,8 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
m_ndb.internalizeTableName(indexName); // Index is also a table
m_localHash.drop(internalIndexName);
-
m_globalHash->lock();
+ idx->m_table->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(idx->m_table);
m_globalHash->unlock();
return dropIndex(indexName, tableName);
@@ -2277,8 +2280,8 @@ NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
int ret = m_receiver.dropIndex(impl, *timpl);
if(ret == 0){
m_localHash.drop(internalIndexName);
-
m_globalHash->lock();
+ impl.m_table->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(impl.m_table);
m_globalHash->unlock();
}
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index dbcb8c8fdfd..b61dbd1792c 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -418,11 +418,28 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd)
# The mapped error code
*/
-void ha_ndbcluster::invalidateDictionaryCache()
+void ha_ndbcluster::invalidate_dictionary_cache(bool global)
{
NDBDICT *dict= get_ndb()->getDictionary();
+ DBUG_ENTER("invalidate_dictionary_cache");
DBUG_PRINT("info", ("invalidating %s", m_tabname));
- dict->invalidateTable(m_tabname);
+
+ if (global)
+ {
+ const NDBTAB *tab= dict->getTable(m_tabname);
+ if (!tab)
+ DBUG_VOID_RETURN;
+ if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ {
+ // Global cache has already been invalidated
+ dict->removeCachedTable(m_tabname);
+ global= FALSE;
+ }
+ else
+ dict->invalidateTable(m_tabname);
+ }
+ else
+ dict->removeCachedTable(m_tabname);
table->s->version=0L; /* Free when thread is ready */
/* Invalidate indexes */
for (uint i= 0; i < table->s->keys; i++)
@@ -434,18 +451,28 @@ void ha_ndbcluster::invalidateDictionaryCache()
switch(idx_type) {
case(PRIMARY_KEY_ORDERED_INDEX):
case(ORDERED_INDEX):
- dict->invalidateIndex(index->getName(), m_tabname);
+ if (global)
+ dict->invalidateIndex(index->getName(), m_tabname);
+ else
+ dict->removeCachedIndex(index->getName(), m_tabname);
break;
case(UNIQUE_ORDERED_INDEX):
- dict->invalidateIndex(index->getName(), m_tabname);
+ if (global)
+ dict->invalidateIndex(index->getName(), m_tabname);
+ else
+ dict->removeCachedIndex(index->getName(), m_tabname);
case(UNIQUE_INDEX):
- dict->invalidateIndex(unique_index->getName(), m_tabname);
+ if (global)
+ dict->invalidateIndex(unique_index->getName(), m_tabname);
+ else
+ dict->removeCachedIndex(unique_index->getName(), m_tabname);
break;
case(PRIMARY_KEY_INDEX):
case(UNDEFINED_INDEX):
break;
}
}
+ DBUG_VOID_RETURN;
}
int ha_ndbcluster::ndb_err(NdbTransaction *trans)
@@ -457,7 +484,7 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans)
ERR_PRINT(err);
switch (err.classification) {
case NdbError::SchemaError:
- invalidateDictionaryCache();
+ invalidate_dictionary_cache(TRUE);
if (err.code==284)
{
@@ -882,7 +909,14 @@ int ha_ndbcluster::get_metadata(const char *path)
if (!(tab= dict->getTable(m_tabname)))
ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
+ // Check if thread has stale local cache
+ if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ {
+ invalidate_dictionary_cache(FALSE);
+ if (!(tab= dict->getTable(m_tabname)))
+ ERR_RETURN(dict->getNdbError());
+ DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
+ }
/*
Compare FrmData in NDB with frm file from disk.
*/
@@ -901,7 +935,7 @@ int ha_ndbcluster::get_metadata(const char *path)
if (!invalidating_ndb_table)
{
DBUG_PRINT("info", ("Invalidating table"));
- invalidateDictionaryCache();
+ invalidate_dictionary_cache(TRUE);
invalidating_ndb_table= TRUE;
}
else
@@ -927,7 +961,7 @@ int ha_ndbcluster::get_metadata(const char *path)
if (error)
DBUG_RETURN(error);
- m_tableVersion= tab->getObjectVersion();
+ m_table_version= tab->getObjectVersion();
m_table= (void *)tab;
m_table_info= NULL; // Set in external lock
@@ -3269,15 +3303,25 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
void *tab_info;
if (!(tab= dict->getTable(m_tabname, &tab_info)))
ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
- if (m_table != (void *)tab || m_tableVersion != tab->getObjectVersion())
+ DBUG_PRINT("info", ("Table schema version: %d",
+ tab->getObjectVersion()));
+ // Check if thread has stale local cache
+ if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ {
+ invalidate_dictionary_cache(FALSE);
+ if (!(tab= dict->getTable(m_tabname, &tab_info)))
+ ERR_RETURN(dict->getNdbError());
+ DBUG_PRINT("info", ("Table schema version: %d",
+ tab->getObjectVersion()));
+ }
+ if (m_table != (void *)tab || m_table_version < tab->getObjectVersion())
{
/*
The table has been altered, refresh the index list
*/
build_index_list(ndb, table, ILBP_OPEN);
m_table= (void *)tab;
- m_tableVersion = tab->getObjectVersion();
+ m_table_version = tab->getObjectVersion();
}
m_table_info= tab_info;
}
@@ -3321,7 +3365,6 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
thd_ndb->stmt= NULL;
}
}
- m_table= NULL;
m_table_info= NULL;
/*
@@ -4036,7 +4079,13 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
dict= ndb->getDictionary();
if (!(orig_tab= dict->getTable(m_tabname)))
ERR_RETURN(dict->getNdbError());
-
+ // Check if thread has stale local cache
+ if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ {
+ dict->removeCachedTable(m_tabname);
+ if (!(orig_tab= dict->getTable(m_tabname)))
+ ERR_RETURN(dict->getNdbError());
+ }
m_table= (void *)orig_tab;
// Change current database to that of target table
set_dbname(to);
@@ -4159,7 +4208,7 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_active_trans(NULL),
m_active_cursor(NULL),
m_table(NULL),
- m_tableVersion(-1),
+ m_table_version(-1),
m_table_info(NULL),
m_table_flags(HA_REC_NOT_IN_SEQ |
HA_NULL_IN_KEY |
@@ -4409,7 +4458,6 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
DBUG_RETURN(1);
ERR_RETURN(err);
}
-
DBUG_PRINT("info", ("Found table %s", tab->getName()));
len= tab->getFrmLength();
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 4dbab18b828..81b2873d9dd 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -558,7 +558,7 @@ private:
void print_results();
ulonglong get_auto_increment();
- void invalidateDictionaryCache();
+ void invalidate_dictionary_cache(bool global);
int ndb_err(NdbTransaction*);
bool uses_blob_value(bool all_fields);
@@ -596,7 +596,7 @@ private:
NdbTransaction *m_active_trans;
NdbScanOperation *m_active_cursor;
void *m_table;
- int m_tableVersion;
+ int m_table_version;
void *m_table_info;
char m_dbname[FN_HEADLEN];
//char m_schemaname[FN_HEADLEN];