mirror of
https://github.com/MariaDB/server.git
synced 2025-09-02 09:41:40 +03:00
Ndb backup/restore also handle indexes
ndb/src/kernel/blocks/backup/Backup.cpp: Save meta data for indexes (but not actual data) ndb/src/kernel/blocks/backup/Backup.hpp: Save meta data for indexes (but not actual data) ndb/src/kernel/blocks/backup/restore/consumer.hpp: Introduced endOfTables into Consumer interface ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp: Store indexes and create then when endOfTables is called ndb/src/kernel/blocks/backup/restore/consumer_restore.hpp: Store indexes and create then when endOfTables is called ndb/src/kernel/blocks/backup/restore/main.cpp: Run endOfTables ndb/src/ndbapi/NdbDictionaryImpl.cpp: Split getIndexImpl into 2 methods (one being used by restore) ndb/src/ndbapi/NdbDictionaryImpl.hpp: Split getIndexImpl into 2 methods (one being used by restore)
This commit is contained in:
@@ -885,7 +885,7 @@ Backup::execBACKUP_REQ(Signal* signal)
|
||||
}//if
|
||||
|
||||
ndbrequire(ptr.p->pages.empty());
|
||||
ndbrequire(ptr.p->tables.empty());
|
||||
ndbrequire(ptr.p->tables.isEmpty());
|
||||
|
||||
ptr.p->masterData.state.forceState(INITIAL);
|
||||
ptr.p->masterData.state.setState(DEFINING);
|
||||
@@ -2484,8 +2484,7 @@ Backup::execLIST_TABLES_CONF(Signal* signal)
|
||||
jam();
|
||||
Uint32 tableId = ListTablesConf::getTableId(conf->tableData[i]);
|
||||
Uint32 tableType = ListTablesConf::getTableType(conf->tableData[i]);
|
||||
if (tableType != DictTabInfo::SystemTable &&
|
||||
tableType != DictTabInfo::UserTable) {
|
||||
if (!DictTabInfo::isTable(tableType) && !DictTabInfo::isIndex(tableType)){
|
||||
jam();
|
||||
continue;
|
||||
}//if
|
||||
@@ -2864,7 +2863,12 @@ Backup::execGET_TABINFO_CONF(Signal* signal)
|
||||
return;
|
||||
}//if
|
||||
|
||||
TablePtr tmp = tabPtr;
|
||||
ptr.p->tables.next(tabPtr);
|
||||
if(DictTabInfo::isIndex(tmp.p->tableType)){
|
||||
ptr.p->tables.release(tmp);
|
||||
}
|
||||
|
||||
if(tabPtr.i == RNIL) {
|
||||
jam();
|
||||
|
||||
@@ -2906,7 +2910,11 @@ Backup::parseTableDescription(Signal* signal, BackupRecordPtr ptr, Uint32 len)
|
||||
|
||||
TablePtr tabPtr;
|
||||
ndbrequire(findTable(ptr, tabPtr, tmpTab.TableId));
|
||||
|
||||
if(DictTabInfo::isIndex(tabPtr.p->tableType)){
|
||||
jam();
|
||||
return tabPtr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize table object
|
||||
*/
|
||||
|
@@ -441,7 +441,7 @@ public:
|
||||
Uint32 startGCP;
|
||||
Uint32 currGCP;
|
||||
Uint32 stopGCP;
|
||||
SLList<Table> tables;
|
||||
DLList<Table> tables;
|
||||
SLList<TriggerRecord> triggers;
|
||||
|
||||
SLList<BackupFile> files;
|
||||
|
@@ -24,6 +24,7 @@ public:
|
||||
virtual ~BackupConsumer() { }
|
||||
virtual bool init() { return true;}
|
||||
virtual bool table(const TableS &){return true;}
|
||||
virtual bool endOfTables() { return true; }
|
||||
virtual void tuple(const TupleS &){}
|
||||
virtual void tuple_free(){}
|
||||
virtual void endOfTuples(){}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "consumer_restore.hpp"
|
||||
#include <NdbSleep.h>
|
||||
#include <NdbDictionaryImpl.hpp>
|
||||
|
||||
extern FilteredNdbOut err;
|
||||
extern FilteredNdbOut info;
|
||||
@@ -141,7 +142,13 @@ BackupRestore::table(const TableS & table){
|
||||
*/
|
||||
if(match_blob(name) >= 0)
|
||||
return true;
|
||||
|
||||
|
||||
const NdbTableImpl & tmptab = NdbTableImpl::getImpl(* table.m_dictTable);
|
||||
if(tmptab.m_indexType != NdbDictionary::Index::Undefined){
|
||||
m_indexes.push_back(table.m_dictTable);
|
||||
return true;
|
||||
}
|
||||
|
||||
BaseString tmp(name);
|
||||
Vector<BaseString> split;
|
||||
if(tmp.split(split, "/") != 3){
|
||||
@@ -178,6 +185,65 @@ BackupRestore::table(const TableS & table){
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BackupRestore::endOfTables(){
|
||||
if(!m_restore_meta)
|
||||
return true;
|
||||
|
||||
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
|
||||
for(size_t i = 0; i<m_indexes.size(); i++){
|
||||
const NdbTableImpl & indtab = NdbTableImpl::getImpl(* m_indexes[i]);
|
||||
|
||||
BaseString tmp(indtab.m_primaryTable.c_str());
|
||||
Vector<BaseString> split;
|
||||
if(tmp.split(split, "/") != 3){
|
||||
err << "Invalid table name format " << indtab.m_primaryTable.c_str()
|
||||
<< endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_ndb->setDatabaseName(split[0].c_str());
|
||||
m_ndb->setSchemaName(split[1].c_str());
|
||||
|
||||
const NdbDictionary::Table * prim = dict->getTable(split[2].c_str());
|
||||
if(prim == 0){
|
||||
err << "Unable to find base table \"" << split[2].c_str()
|
||||
<< "\" for index "
|
||||
<< indtab.getName() << endl;
|
||||
return false;
|
||||
}
|
||||
NdbTableImpl& base = NdbTableImpl::getImpl(*prim);
|
||||
NdbIndexImpl* idx;
|
||||
int id;
|
||||
char idxName[255], buf[255];
|
||||
if(sscanf(indtab.getName(), "%[^/]/%[^/]/%d/%s",
|
||||
buf, buf, &id, idxName) != 4){
|
||||
err << "Invalid index name format " << indtab.getName() << endl;
|
||||
return false;
|
||||
}
|
||||
if(NdbDictInterface::create_index_obj_from_table(&idx, &indtab, &base))
|
||||
{
|
||||
err << "Failed to create index " << idxName
|
||||
<< " on " << split[2].c_str() << endl;
|
||||
return false;
|
||||
}
|
||||
idx->setName(idxName);
|
||||
if(dict->createIndex(* idx) != 0)
|
||||
{
|
||||
delete idx;
|
||||
err << "Failed to create index " << idxName
|
||||
<< " on " << split[2].c_str() << endl
|
||||
<< dict->getNdbError() << endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
delete idx;
|
||||
info << "Successfully created index " << idxName
|
||||
<< " on " << split[2].c_str() << endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BackupRestore::tuple(const TupleS & tup)
|
||||
{
|
||||
if (!m_restore)
|
||||
|
@@ -49,6 +49,7 @@ public:
|
||||
virtual bool init();
|
||||
virtual void release();
|
||||
virtual bool table(const TableS &);
|
||||
virtual bool endOfTables();
|
||||
virtual void tuple(const TupleS &);
|
||||
virtual void tuple_free();
|
||||
virtual void tuple_a(restore_callback_t *cb);
|
||||
@@ -83,6 +84,8 @@ public:
|
||||
const NdbDictionary::Table* m_new_table;
|
||||
} m_cache;
|
||||
const NdbDictionary::Table* get_table(const NdbDictionary::Table* );
|
||||
|
||||
Vector<const NdbDictionary::Table*> m_indexes;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -276,78 +276,85 @@ main(int argc, const char** argv)
|
||||
}
|
||||
}
|
||||
|
||||
for(i= 0; i < g_consumers.size(); i++)
|
||||
if (!g_consumers[i]->endOfTables())
|
||||
{
|
||||
ndbout_c("Restore: Failed while closing tables");
|
||||
return -11;
|
||||
}
|
||||
|
||||
if (ga_restore || ga_print)
|
||||
{
|
||||
if (ga_restore)
|
||||
if (ga_restore)
|
||||
{
|
||||
RestoreDataIterator dataIter(metaData, &free_data_callback);
|
||||
|
||||
// Read data file header
|
||||
if (!dataIter.readHeader())
|
||||
{
|
||||
RestoreDataIterator dataIter(metaData, &free_data_callback);
|
||||
|
||||
// Read data file header
|
||||
if (!dataIter.readHeader())
|
||||
{
|
||||
ndbout << "Failed to read header of data file. Exiting..." ;
|
||||
return -11;
|
||||
}
|
||||
|
||||
|
||||
while (dataIter.readFragmentHeader(res= 0))
|
||||
{
|
||||
const TupleS* tuple;
|
||||
while ((tuple = dataIter.getNextTuple(res= 1)) != 0)
|
||||
{
|
||||
if (checkSysTable(tuple->getTable()->getTableName()))
|
||||
for(Uint32 i= 0; i < g_consumers.size(); i++)
|
||||
g_consumers[i]->tuple(* tuple);
|
||||
} // while (tuple != NULL);
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
ndbout_c("Restore: An error occured while restoring data. "
|
||||
"Exiting...");
|
||||
return -1;
|
||||
}
|
||||
if (!dataIter.validateFragmentFooter()) {
|
||||
ndbout_c("Restore: Error validating fragment footer. "
|
||||
"Exiting...");
|
||||
return -1;
|
||||
}
|
||||
} // while (dataIter.readFragmentHeader(res))
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
err << "Restore: An error occured while restoring data. Exiting... res=" << res << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
dataIter.validateFooter(); //not implemented
|
||||
|
||||
for (i= 0; i < g_consumers.size(); i++)
|
||||
g_consumers[i]->endOfTuples();
|
||||
|
||||
RestoreLogIterator logIter(metaData);
|
||||
if (!logIter.readHeader())
|
||||
{
|
||||
err << "Failed to read header of data file. Exiting..." << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const LogEntry * logEntry = 0;
|
||||
while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
|
||||
{
|
||||
if (checkSysTable(logEntry->m_table->getTableName()))
|
||||
for(Uint32 i= 0; i < g_consumers.size(); i++)
|
||||
g_consumers[i]->logEntry(* logEntry);
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
err << "Restore: An restoring the data log. Exiting... res=" << res << endl;
|
||||
return -1;
|
||||
}
|
||||
logIter.validateFooter(); //not implemented
|
||||
for (i= 0; i < g_consumers.size(); i++)
|
||||
g_consumers[i]->endOfLogEntrys();
|
||||
ndbout << "Failed to read header of data file. Exiting..." ;
|
||||
return -11;
|
||||
}
|
||||
|
||||
|
||||
while (dataIter.readFragmentHeader(res= 0))
|
||||
{
|
||||
const TupleS* tuple;
|
||||
while ((tuple = dataIter.getNextTuple(res= 1)) != 0)
|
||||
{
|
||||
if (checkSysTable(tuple->getTable()->getTableName()))
|
||||
for(Uint32 i= 0; i < g_consumers.size(); i++)
|
||||
g_consumers[i]->tuple(* tuple);
|
||||
} // while (tuple != NULL);
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
ndbout_c("Restore: An error occured while restoring data. "
|
||||
"Exiting...");
|
||||
return -1;
|
||||
}
|
||||
if (!dataIter.validateFragmentFooter()) {
|
||||
ndbout_c("Restore: Error validating fragment footer. "
|
||||
"Exiting...");
|
||||
return -1;
|
||||
}
|
||||
} // while (dataIter.readFragmentHeader(res))
|
||||
|
||||
if (res < 0)
|
||||
{
|
||||
err << "Restore: An error occured while restoring data. Exiting... res=" << res << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
dataIter.validateFooter(); //not implemented
|
||||
|
||||
for (i= 0; i < g_consumers.size(); i++)
|
||||
g_consumers[i]->endOfTuples();
|
||||
|
||||
RestoreLogIterator logIter(metaData);
|
||||
if (!logIter.readHeader())
|
||||
{
|
||||
err << "Failed to read header of data file. Exiting..." << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const LogEntry * logEntry = 0;
|
||||
while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
|
||||
{
|
||||
if (checkSysTable(logEntry->m_table->getTableName()))
|
||||
for(Uint32 i= 0; i < g_consumers.size(); i++)
|
||||
g_consumers[i]->logEntry(* logEntry);
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
err << "Restore: An restoring the data log. Exiting... res=" << res << endl;
|
||||
return -1;
|
||||
}
|
||||
logIter.validateFooter(); //not implemented
|
||||
for (i= 0; i < g_consumers.size(); i++)
|
||||
g_consumers[i]->endOfLogEntrys();
|
||||
}
|
||||
}
|
||||
clearConsumers();
|
||||
return 1;
|
||||
|
@@ -1773,7 +1773,7 @@ NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
|
||||
*/
|
||||
NdbIndexImpl*
|
||||
NdbDictionaryImpl::getIndexImpl(const char * externalName,
|
||||
const char * internalName)
|
||||
const char * internalName)
|
||||
{
|
||||
NdbTableImpl* tab = getTableImpl(internalName);
|
||||
if(tab == 0){
|
||||
@@ -1796,14 +1796,30 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
|
||||
/**
|
||||
* Create index impl
|
||||
*/
|
||||
NdbIndexImpl* idx = new NdbIndexImpl();
|
||||
NdbIndexImpl* idx;
|
||||
if(NdbDictInterface::create_index_obj_from_table(&idx, tab, prim) == 0){
|
||||
idx->m_table = tab;
|
||||
idx->m_internalName.assign(internalName);
|
||||
// TODO Assign idx to tab->m_index
|
||||
// Don't do it right now since assign can't asign a table with index
|
||||
// tab->m_index = idx;
|
||||
return idx;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
|
||||
const NdbTableImpl* tab,
|
||||
const NdbTableImpl* prim){
|
||||
NdbIndexImpl *idx = new NdbIndexImpl();
|
||||
idx->m_version = tab->m_version;
|
||||
idx->m_status = tab->m_status;
|
||||
idx->m_indexId = tab->m_tableId;
|
||||
idx->m_internalName.assign(internalName);
|
||||
idx->m_externalName.assign(externalName);
|
||||
idx->m_externalName.assign(tab->getName());
|
||||
idx->m_tableName.assign(prim->m_externalName);
|
||||
idx->m_type = tab->m_indexType;
|
||||
idx->m_logging = tab->m_logging;
|
||||
// skip last attribute (NDB$PK or NDB$TNODE)
|
||||
for(unsigned i = 0; i+1<tab->m_columns.size(); i++){
|
||||
NdbColumnImpl* col = new NdbColumnImpl;
|
||||
@@ -1819,12 +1835,9 @@ NdbDictionaryImpl::getIndexImpl(const char * externalName,
|
||||
idx->m_key_ids[key_id] = i;
|
||||
col->m_keyInfoPos = key_id;
|
||||
}
|
||||
|
||||
idx->m_table = tab;
|
||||
// TODO Assign idx to tab->m_index
|
||||
// Don't do it right now since assign can't asign a table with index
|
||||
// tab->m_index = idx;
|
||||
return idx;
|
||||
|
||||
* dst = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
|
@@ -304,6 +304,10 @@ public:
|
||||
const Uint32 * data, Uint32 len,
|
||||
bool fullyQualifiedNames);
|
||||
|
||||
static int create_index_obj_from_table(NdbIndexImpl ** dst,
|
||||
const NdbTableImpl*,
|
||||
const NdbTableImpl*);
|
||||
|
||||
NdbError & m_error;
|
||||
private:
|
||||
Uint32 m_reference;
|
||||
|
Reference in New Issue
Block a user