Below is the list of changes that have just been committed into a local
5.1 repository of tomas. When tomas does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2233 06/07/06 19:02:38 tomas@stripped +3 -0
Merge poseidon.ndb.mysql.com:/home/tomas/mysql-5.0
into poseidon.ndb.mysql.com:/home/tomas/mysql-5.1-ndb
storage/ndb/tools/restore/consumer_restore.cpp
1.34 06/07/06 19:02:33 tomas@stripped +44 -0
manual merge
mysql-test/t/ndb_restore.test
1.21 06/07/06 19:02:33 tomas@stripped +8 -9
manual merge
mysql-test/r/ndb_restore.result
1.17 06/07/06 19:02:33 tomas@stripped +11 -16
manual merge
storage/ndb/tools/restore/consumer_restore.cpp
1.14.12.2 06/07/06 18:53:25 tomas@stripped +0 -0
Merge rename: ndb/tools/restore/consumer_restore.cpp -> storage/ndb/tools/restore/consumer_restore.cpp
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: tomas
# Host: poseidon.ndb.mysql.com
# Root: /home/tomas/mysql-5.1-ndb/RESYNC
--- 1.14.12.1/ndb/tools/restore/consumer_restore.cpp 2006-07-06 18:50:32 +02:00
+++ 1.34/storage/ndb/tools/restore/consumer_restore.cpp 2006-07-06 19:02:33 +02:00
@@ -16,6 +16,7 @@
#include <NDBT_ReturnCodes.h>
#include "consumer_restore.hpp"
+#include <my_sys.h>
#include <NdbSleep.h>
extern my_bool opt_core;
@@ -25,6 +26,8 @@
extern FilteredNdbOut debug;
static void callback(int, NdbTransaction*, void*);
+static Uint32 get_part_id(const NdbDictionary::Table *table,
+ Uint32 hash_value);
extern const char * g_connect_string;
extern BaseString g_options;
@@ -34,7 +37,7 @@
{
release();
- if (!m_restore && !m_restore_meta)
+ if (!m_restore && !m_restore_meta && !m_restore_epoch)
return true;
m_cluster_connection = new Ndb_cluster_connection(g_connect_string);
@@ -179,13 +182,486 @@
} while (1);
}
+
+static bool default_nodegroups(NdbDictionary::Table *table)
+{
+ Uint16 *node_groups = (Uint16*)table->getFragmentData();
+ Uint32 no_parts = table->getFragmentDataLen() >> 1;
+ Uint32 i;
+
+ if (node_groups[0] != 0)
+ return false;
+ for (i = 1; i < no_parts; i++)
+ {
+ if (node_groups[i] != UNDEF_NODEGROUP)
+ return false;
+ }
+ return true;
+}
+
+
+static Uint32 get_no_fragments(Uint64 max_rows, Uint32 no_nodes)
+{
+ Uint32 i = 0;
+ Uint32 acc_row_size = 27;
+ Uint32 acc_fragment_size = 512*1024*1024;
+ Uint32 no_parts= (max_rows*acc_row_size)/acc_fragment_size + 1;
+ Uint32 reported_parts = no_nodes;
+ while (reported_parts < no_parts && ++i < 4 &&
+ (reported_parts + no_parts) < MAX_NDB_PARTITIONS)
+ reported_parts+= no_nodes;
+ if (reported_parts < no_parts)
+ {
+ err << "Table will be restored but will not be able to handle the maximum";
+ err << " amount of rows as requested" << endl;
+ }
+ return reported_parts;
+}
+
+
+static void set_default_nodegroups(NdbDictionary::Table *table)
+{
+ Uint32 no_parts = table->getFragmentCount();
+ Uint16 node_group[MAX_NDB_PARTITIONS];
+ Uint32 i;
+
+ node_group[0] = 0;
+ for (i = 1; i < no_parts; i++)
+ {
+ node_group[i] = UNDEF_NODEGROUP;
+ }
+ table->setFragmentData((const void*)node_group, 2 * no_parts);
+}
+
+Uint32 BackupRestore::map_ng(Uint32 ng)
+{
+ NODE_GROUP_MAP *ng_map = m_nodegroup_map;
+
+ if (ng == UNDEF_NODEGROUP ||
+ ng_map[ng].map_array[0] == UNDEF_NODEGROUP)
+ {
+ return ng;
+ }
+ else
+ {
+ Uint32 new_ng;
+ Uint32 curr_inx = ng_map[ng].curr_index;
+ Uint32 new_curr_inx = curr_inx + 1;
+
+ assert(ng < MAX_NDB_PARTITIONS);
+ assert(curr_inx < MAX_MAPS_PER_NODE_GROUP);
+ assert(new_curr_inx < MAX_MAPS_PER_NODE_GROUP);
+
+ if (new_curr_inx >= MAX_MAPS_PER_NODE_GROUP)
+ new_curr_inx = 0;
+ else if (ng_map[ng].map_array[new_curr_inx] == UNDEF_NODEGROUP)
+ new_curr_inx = 0;
+ new_ng = ng_map[ng].map_array[curr_inx];
+ ng_map[ng].curr_index = new_curr_inx;
+ return new_ng;
+ }
+}
+
+
+bool BackupRestore::map_nodegroups(Uint16 *ng_array, Uint32 no_parts)
+{
+ Uint32 i;
+ bool mapped = FALSE;
+ DBUG_ENTER("map_nodegroups");
+
+ assert(no_parts < MAX_NDB_PARTITIONS);
+ for (i = 0; i < no_parts; i++)
+ {
+ Uint32 ng;
+ ng = map_ng((Uint32)ng_array[i]);
+ if (ng != ng_array[i])
+ mapped = TRUE;
+ ng_array[i] = ng;
+ }
+ DBUG_RETURN(mapped);
+}
+
+
+static void copy_byte(const char **data, char **new_data, uint *len)
+{
+ **new_data = **data;
+ (*data)++;
+ (*new_data)++;
+ (*len)++;
+}
+
+
+bool BackupRestore::search_replace(char *search_str, char **new_data,
+ const char **data, const char *end_data,
+ uint *new_data_len)
+{
+ uint search_str_len = strlen(search_str);
+ uint inx = 0;
+ bool in_delimiters = FALSE;
+ bool escape_char = FALSE;
+ char start_delimiter = 0;
+ DBUG_ENTER("search_replace");
+
+ do
+ {
+ char c = **data;
+ copy_byte(data, new_data, new_data_len);
+ if (escape_char)
+ {
+ escape_char = FALSE;
+ }
+ else if (in_delimiters)
+ {
+ if (c == start_delimiter)
+ in_delimiters = FALSE;
+ }
+ else if (c == '\'' || c == '\"')
+ {
+ in_delimiters = TRUE;
+ start_delimiter = c;
+ }
+ else if (c == '\\')
+ {
+ escape_char = TRUE;
+ }
+ else if (c == search_str[inx])
+ {
+ inx++;
+ if (inx == search_str_len)
+ {
+ bool found = FALSE;
+ uint number = 0;
+ while (*data != end_data)
+ {
+ if (isdigit(**data))
+ {
+ found = TRUE;
+ number = (10 * number) + (**data);
+ if (number > MAX_NDB_NODES)
+ break;
+ }
+ else if (found)
+ {
+ /*
+ After long and tedious preparations we have actually found
+ a node group identifier to convert. We'll use the mapping
+ table created for node groups and then insert the new number
+ instead of the old number.
+ */
+ uint temp = map_ng(number);
+ int no_digits = 0;
+ char digits[10];
+ while (temp != 0)
+ {
+ digits[no_digits] = temp % 10;
+ no_digits++;
+ temp/=10;
+ }
+ for (no_digits--; no_digits >= 0; no_digits--)
+ {
+ **new_data = digits[no_digits];
+ *new_data_len+=1;
+ }
+ DBUG_RETURN(FALSE);
+ }
+ else
+ break;
+ (*data)++;
+ }
+ DBUG_RETURN(TRUE);
+ }
+ }
+ else
+ inx = 0;
+ } while (*data < end_data);
+ DBUG_RETURN(FALSE);
+}
+
+bool BackupRestore::map_in_frm(char *new_data, const char *data,
+ uint data_len, uint *new_data_len)
+{
+ const char *end_data= data + data_len;
+ const char *end_part_data;
+ const char *part_data;
+ char *extra_ptr;
+ uint start_key_definition_len = uint2korr(data + 6);
+ uint key_definition_len = uint4korr(data + 47);
+ uint part_info_len;
+ DBUG_ENTER("map_in_frm");
+
+ if (data_len < 4096) goto error;
+ extra_ptr = (char*)data + start_key_definition_len + key_definition_len;
+ if ((int)data_len < ((extra_ptr - data) + 2)) goto error;
+ extra_ptr = extra_ptr + 2 + uint2korr(extra_ptr);
+ if ((int)data_len < ((extra_ptr - data) + 2)) goto error;
+ extra_ptr = extra_ptr + 2 + uint2korr(extra_ptr);
+ if ((int)data_len < ((extra_ptr - data) + 4)) goto error;
+ part_info_len = uint4korr(extra_ptr);
+ part_data = extra_ptr + 4;
+ if ((int)data_len < ((part_data + part_info_len) - data)) goto error;
+
+ do
+ {
+ copy_byte(&data, &new_data, new_data_len);
+ } while (data < part_data);
+ end_part_data = part_data + part_info_len;
+ do
+ {
+ if (search_replace((char*)" NODEGROUP = ", &new_data, &data,
+ end_part_data, new_data_len))
+ goto error;
+ } while (data != end_part_data);
+ do
+ {
+ copy_byte(&data, &new_data, new_data_len);
+ } while (data < end_data);
+ DBUG_RETURN(FALSE);
+error:
+ DBUG_RETURN(TRUE);
+}
+
+
+bool BackupRestore::translate_frm(NdbDictionary::Table *table)
+{
+ const void *pack_data, *data, *new_pack_data;
+ char *new_data;
+ uint data_len, pack_len, new_data_len, new_pack_len;
+ uint no_parts, extra_growth;
+ DBUG_ENTER("translate_frm");
+
+ pack_data = table->getFrmData();
+ no_parts = table->getFragmentCount();
+ /*
+ Add max 4 characters per partition to handle worst case
+ of mapping from single digit to 5-digit number.
+ Fairly future-proof, ok up to 99999 node groups.
+ */
+ extra_growth = no_parts * 4;
+ if (unpackfrm(&data, &data_len, pack_data))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ if ((new_data = my_malloc(data_len + extra_growth, MYF(0))))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ if (map_in_frm(new_data, (const char*)data, data_len, &new_data_len))
+ {
+ my_free(new_data, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (packfrm((const void*)new_data, new_data_len,
+ &new_pack_data, &new_pack_len))
+ {
+ my_free(new_data, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ table->setFrm(new_pack_data, new_pack_len);
+ DBUG_RETURN(FALSE);
+}
+
+#include <signaldata/DictTabInfo.hpp>
+
+bool
+BackupRestore::object(Uint32 type, const void * ptr)
+{
+ if (!m_restore_meta)
+ return true;
+
+ NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
+ switch(type){
+ case DictTabInfo::Tablespace:
+ {
+ NdbDictionary::Tablespace old(*(NdbDictionary::Tablespace*)ptr);
+
+ Uint32 id = old.getObjectId();
+
+ if (!m_no_restore_disk)
+ {
+ NdbDictionary::LogfileGroup * lg = m_logfilegroups[old.getDefaultLogfileGroupId()];
+ old.setDefaultLogfileGroup(* lg);
+ info << "Creating tablespace: " << old.getName() << "..." << flush;
+ int ret = dict->createTablespace(old);
+ if (ret)
+ {
+ NdbError errobj= dict->getNdbError();
+ info << "FAILED " << errobj << endl;
+ return false;
+ }
+ info << "done" << endl;
+ }
+
+ NdbDictionary::Tablespace curr = dict->getTablespace(old.getName());
+ NdbError errobj = dict->getNdbError();
+ if(errobj.classification == ndberror_cl_none)
+ {
+ NdbDictionary::Tablespace* currptr = new NdbDictionary::Tablespace(curr);
+ NdbDictionary::Tablespace * null = 0;
+ m_tablespaces.set(currptr, id, null);
+ debug << "Retreived tablespace: " << currptr->getName()
+ << " oldid: " << id << " newid: " << currptr->getObjectId()
+ << " " << (void*)currptr << endl;
+ return true;
+ }
+
+ err << "Failed to retrieve tablespace \"" << old.getName() << "\": "
+ << errobj << endl;
+
+ return false;
+ break;
+ }
+ case DictTabInfo::LogfileGroup:
+ {
+ NdbDictionary::LogfileGroup old(*(NdbDictionary::LogfileGroup*)ptr);
+
+ Uint32 id = old.getObjectId();
+
+ if (!m_no_restore_disk)
+ {
+ info << "Creating logfile group: " << old.getName() << "..." << flush;
+ int ret = dict->createLogfileGroup(old);
+ if (ret)
+ {
+ NdbError errobj= dict->getNdbError();
+ info << "FAILED" << errobj << endl;
+ return false;
+ }
+ info << "done" << endl;
+ }
+
+ NdbDictionary::LogfileGroup curr = dict->getLogfileGroup(old.getName());
+ NdbError errobj = dict->getNdbError();
+ if(errobj.classification == ndberror_cl_none)
+ {
+ NdbDictionary::LogfileGroup* currptr =
+ new NdbDictionary::LogfileGroup(curr);
+ NdbDictionary::LogfileGroup * null = 0;
+ m_logfilegroups.set(currptr, id, null);
+ debug << "Retreived logfile group: " << currptr->getName()
+ << " oldid: " << id << " newid: " << currptr->getObjectId()
+ << " " << (void*)currptr << endl;
+ return true;
+ }
+
+ err << "Failed to retrieve logfile group \"" << old.getName() << "\": "
+ << errobj << endl;
+
+ return false;
+ break;
+ }
+ case DictTabInfo::Datafile:
+ {
+ if (!m_no_restore_disk)
+ {
+ NdbDictionary::Datafile old(*(NdbDictionary::Datafile*)ptr);
+ NdbDictionary::ObjectId objid;
+ old.getTablespaceId(&objid);
+ NdbDictionary::Tablespace * ts = m_tablespaces[objid.getObjectId()];
+ debug << "Connecting datafile " << old.getPath()
+ << " to tablespace: oldid: " << objid.getObjectId()
+ << " newid: " << ts->getObjectId() << endl;
+ old.setTablespace(* ts);
+ info << "Creating datafile \"" << old.getPath() << "\"..." << flush;
+ if (dict->createDatafile(old))
+ {
+ info << "FAILED " << dict->getNdbError() << endl;
+ return false;
+ }
+ info << "done" << endl;
+ }
+ return true;
+ break;
+ }
+ case DictTabInfo::Undofile:
+ {
+ if (!m_no_restore_disk)
+ {
+ NdbDictionary::Undofile old(*(NdbDictionary::Undofile*)ptr);
+ NdbDictionary::ObjectId objid;
+ old.getLogfileGroupId(&objid);
+ NdbDictionary::LogfileGroup * lg = m_logfilegroups[objid.getObjectId()];
+ debug << "Connecting undofile " << old.getPath()
+ << " to logfile group: oldid: " << objid.getObjectId()
+ << " newid: " << lg->getObjectId()
+ << " " << (void*)lg << endl;
+ old.setLogfileGroup(* lg);
+ info << "Creating undofile \"" << old.getPath() << "\"..." << flush;
+ if (dict->createUndofile(old))
+ {
+ info << "FAILED " << dict->getNdbError() << endl;
+ return false;
+ }
+ info << "done" << endl;
+ }
+ return true;
+ break;
+ }
+ }
+ return true;
+}
+
+bool
+BackupRestore::update_apply_status(const RestoreMetaData &metaData)
+{
+ if (!m_restore_epoch)
+ return true;
+
+ bool result= false;
+
+ m_ndb->setDatabaseName(NDB_REP_DB);
+ m_ndb->setSchemaName("def");
+
+ NdbDictionary::Dictionary *dict= m_ndb->getDictionary();
+ const NdbDictionary::Table *ndbtab= dict->getTable(Ndb_apply_table);
+ if (!ndbtab)
+ {
+ err << Ndb_apply_table << ": "
+ << dict->getNdbError() << endl;
+ return false;
+ }
+ Uint32 server_id= 0;
+ Uint64 epoch= metaData.getStopGCP();
+ NdbTransaction * trans= m_ndb->startTransaction();
+ if (!trans)
+ {
+ err << Ndb_apply_table << ": "
+ << m_ndb->getNdbError() << endl;
+ return false;
+ }
+ NdbOperation * op= trans->getNdbOperation(ndbtab);
+ if (!op)
+ {
+ err << Ndb_apply_table << ": "
+ << trans->getNdbError() << endl;
+ goto err;
+ }
+ if (op->writeTuple() ||
+ op->equal(0u, (const char *)&server_id, sizeof(server_id)) ||
+ op->setValue(1u, (const char *)&epoch, sizeof(epoch)))
+ {
+ err << Ndb_apply_table << ": "
+ << op->getNdbError() << endl;
+ goto err;
+ }
+ if (trans->execute(NdbTransaction::Commit))
+ {
+ err << Ndb_apply_table << ": "
+ << trans->getNdbError() << endl;
+ goto err;
+ }
+ result= true;
+err:
+ m_ndb->closeTransaction(trans);
+ return result;
+}
+
bool
BackupRestore::table(const TableS & table){
if (!m_restore && !m_restore_meta)
return true;
const char * name = table.getTableName();
-
+
/**
* Ignore blob tables
*/
@@ -209,10 +685,53 @@
m_ndb->setSchemaName(split[1].c_str());
NdbDictionary::Dictionary* dict = m_ndb->getDictionary();
- if(m_restore_meta){
+ if(m_restore_meta)
+ {
NdbDictionary::Table copy(*table.m_dictTable);
copy.setName(split[2].c_str());
+ Uint32 id;
+ if (copy.getTablespace(&id))
+ {
+ debug << "Connecting " << name << " to tablespace oldid: " << id << flush;
+ NdbDictionary::Tablespace* ts = m_tablespaces[id];
+ debug << " newid: " << ts->getObjectId() << endl;
+ copy.setTablespace(* ts);
+ }
+
+ if (copy.getDefaultNoPartitionsFlag())
+ {
+ /*
+ Table was defined with default number of partitions. We can restore
+ it with whatever is the default in this cluster.
+ We use the max_rows parameter in calculating the default number.
+ */
+ Uint32 no_nodes = m_cluster_connection->no_db_nodes();
+ copy.setFragmentCount(get_no_fragments(copy.getMaxRows(),
+ no_nodes));
+ set_default_nodegroups(©);
+ }
+ else
+ {
+ /*
+ Table was defined with specific number of partitions. It should be
+ restored with the same number of partitions. It will either be
+ restored in the same node groups as when backup was taken or by
+ using a node group map supplied to the ndb_restore program.
+ */
+ Uint16 *ng_array = (Uint16*)copy.getFragmentData();
+ Uint16 no_parts = copy.getFragmentCount();
+ if (map_nodegroups(ng_array, no_parts))
+ {
+ if (translate_frm(©))
+ {
+ err << "Create table " << table.getTableName() << " failed: ";
+ err << "Translate frm error" << endl;
+ return false;
+ }
+ }
+ copy.setFragmentData((const void *)ng_array, no_parts << 1);
+ }
/*
update min and max rows to reflect the table, this to
@@ -227,7 +746,20 @@
if (dict->createTable(copy) == -1)
{
err << "Create table " << table.getTableName() << " failed: "
- << dict->getNdbError() << endl;
+ << dict->getNdbError() << endl;
+ if (dict->getNdbError().code == 771)
+ {
+ /*
+ The user on the cluster where the backup was created had specified
+ specific node groups for partitions. Some of these node groups
+ didn't exist on this cluster. We will warn the user of this and
+ inform him of his option.
+ */
+ err << "The node groups defined in the table didn't exist in this";
+ err << " cluster." << endl << "There is an option to use the";
+ err << " the parameter ndb-nodegroup-map to define a mapping from";
+ err << endl << "the old nodegroups to new nodegroups" << endl;
+ }
return false;
}
info << "Successfully restored table " << table.getTableName()<< endl ;
@@ -238,6 +770,50 @@
err << "Unable to find table: " << split[2].c_str() << endl;
return false;
}
+ if(m_restore_meta)
+ {
+ if (tab->getFrmData())
+ {
+ // a MySQL Server table is restored, thus an event should be created
+ BaseString event_name("REPL$");
+ event_name.append(split[0].c_str());
+ event_name.append("/");
+ event_name.append(split[2].c_str());
+
+ NdbDictionary::Event my_event(event_name.c_str());
+ my_event.setTable(*tab);
+ my_event.addTableEvent(NdbDictionary::Event::TE_ALL);
+
+ // add all columns to the event
+ bool has_blobs = false;
+ for(int a= 0; a < tab->getNoOfColumns(); a++)
+ {
+ my_event.addEventColumn(a);
+ NdbDictionary::Column::Type t = tab->getColumn(a)->getType();
+ if (t == NdbDictionary::Column::Blob ||
+ t == NdbDictionary::Column::Text)
+ has_blobs = true;
+ }
+ if (has_blobs)
+ my_event.mergeEvents(true);
+
+ while ( dict->createEvent(my_event) ) // Add event to database
+ {
+ if (dict->getNdbError().classification == NdbError::SchemaObjectExists)
+ {
+ info << "Event for table " << table.getTableName()
+ << " already exists, removing.\n";
+ if (!dict->dropEvent(my_event.getName()))
+ continue;
+ }
+ err << "Create table event for " << table.getTableName() << " failed: "
+ << dict->getNdbError() << endl;
+ dict->dropTable(split[2].c_str());
+ return false;
+ }
+ info << "Successfully restored table event " << event_name << endl ;
+ }
+ }
const NdbDictionary::Table* null = 0;
m_new_tables.fill(table.m_dictTable->getTableId(), null);
m_new_tables[table.m_dictTable->getTableId()] = tab;
@@ -303,7 +879,7 @@
return true;
}
-void BackupRestore::tuple(const TupleS & tup)
+void BackupRestore::tuple(const TupleS & tup, Uint32 fragmentId)
{
if (!m_restore)
return;
@@ -323,6 +899,7 @@
m_free_callback = cb->next;
cb->retries = 0;
+ cb->fragId = fragmentId;
cb->tup = tup; // must do copy!
tuple_a(cb);
@@ -330,6 +907,7 @@
void BackupRestore::tuple_a(restore_callback_t *cb)
{
+ Uint32 partition_id = cb->fragId;
while (cb->retries < 10)
{
/**
@@ -343,6 +921,7 @@
m_ndb->sendPollNdb(3000, 1);
continue;
}
+ err << "Cannot start transaction" << endl;
exitHandler();
} // if
@@ -355,6 +934,7 @@
{
if (errorHandler(cb))
continue;
+ err << "Cannot get operation: " << cb->connection->getNdbError() << endl;
exitHandler();
} // if
@@ -362,9 +942,37 @@
{
if (errorHandler(cb))
continue;
+ err << "Error defining op: " << cb->connection->getNdbError() << endl;
exitHandler();
} // if
-
+
+ if (table->getFragmentType() == NdbDictionary::Object::UserDefined)
+ {
+ if (table->getDefaultNoPartitionsFlag())
+ {
+ /*
+ This can only happen for HASH partitioning with
+ user defined hash function where user hasn't
+ specified the number of partitions and we
+ have to calculate it. We use the hash value
+ stored in the record to calculate the partition
+ to use.
+ */
+ int i = tup.getNoOfAttributes() - 1;
+ const AttributeData *attr_data = tup.getData(i);
+ Uint32 hash_value = *attr_data->u_int32_value;
+ op->setPartitionId(get_part_id(table, hash_value));
+ }
+ else
+ {
+ /*
+ Either RANGE or LIST (with or without subparts)
+ OR HASH partitioning with user defined hash
+ function but with fixed set of partitions.
+ */
+ op->setPartitionId(partition_id);
+ }
+ }
int ret = 0;
for (int j = 0; j < 2; j++)
{
@@ -375,11 +983,11 @@
int size = attr_desc->size;
int arraySize = attr_desc->arraySize;
char * dataPtr = attr_data->string_value;
- Uint32 length = (size * arraySize) / 8;
-
+ Uint32 length = attr_data->size;
+
if (j == 0 && tup.getTable()->have_auto_inc(i))
tup.getTable()->update_max_auto_val(dataPtr,size);
-
+
if (attr_desc->m_column->getPrimaryKey())
{
if (j == 1) continue;
@@ -407,6 +1015,7 @@
{
if (errorHandler(cb))
continue;
+ err << "Error defining op: " << cb->connection->getNdbError() << endl;
exitHandler();
}
@@ -479,30 +1088,28 @@
switch(error.status)
{
case NdbError::Success:
+ err << "Success error: " << error << endl;
return false;
// ERROR!
- break;
case NdbError::TemporaryError:
err << "Temporary error: " << error << endl;
NdbSleep_MilliSleep(sleepTime);
return true;
// RETRY
- break;
case NdbError::UnknownResult:
- err << error << endl;
+ err << "Unknown: " << error << endl;
return false;
// ERROR!
- break;
default:
case NdbError::PermanentError:
//ERROR
- err << error << endl;
+ err << "Permanent: " << error << endl;
return false;
- break;
}
+ err << "No error status" << endl;
return false;
}
@@ -536,6 +1143,35 @@
tuple_free();
}
+static bool use_part_id(const NdbDictionary::Table *table)
+{
+ if (table->getDefaultNoPartitionsFlag() &&
+ (table->getFragmentType() == NdbDictionary::Object::UserDefined))
+ return false;
+ else
+ return true;
+}
+
+static Uint32 get_part_id(const NdbDictionary::Table *table,
+ Uint32 hash_value)
+{
+ Uint32 no_frags = table->getFragmentCount();
+
+ if (table->getLinearFlag())
+ {
+ Uint32 part_id;
+ Uint32 mask = 1;
+ while (no_frags > mask) mask <<= 1;
+ mask--;
+ part_id = hash_value & mask;
+ if (part_id >= no_frags)
+ part_id = hash_value & (mask >> 1);
+ return part_id;
+ }
+ else
+ return (hash_value % no_frags);
+}
+
void
BackupRestore::logEntry(const LogEntry & tup)
{
@@ -581,7 +1217,19 @@
err << "Error defining op: " << trans->getNdbError() << endl;
exitHandler();
} // if
-
+
+ if (table->getFragmentType() == NdbDictionary::Object::UserDefined)
+ {
+ if (table->getDefaultNoPartitionsFlag())
+ {
+ const AttributeS * attr = tup[tup.size()-1];
+ Uint32 hash_value = *(Uint32*)attr->Data.string_value;
+ op->setPartitionId(get_part_id(table, hash_value));
+ }
+ else
+ op->setPartitionId(tup.m_frag_id);
+ }
+
Bitmask<4096> keys;
for (Uint32 i= 0; i < tup.size(); i++)
{
@@ -747,3 +1395,5 @@
template class Vector<NdbDictionary::Table*>;
template class Vector<const NdbDictionary::Table*>;
+template class Vector<NdbDictionary::Tablespace*>;
+template class Vector<NdbDictionary::LogfileGroup*>;
--- 1.16/mysql-test/r/ndb_restore.result 2006-04-26 01:11:31 +02:00
+++ 1.17/mysql-test/r/ndb_restore.result 2006-07-06 19:02:33 +02:00
@@ -1,6 +1,6 @@
use test;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c;
CREATE TABLE `t1_c` (
`capgoaledatta` smallint(5) unsigned NOT NULL auto_increment,
`goaledatta` char(2) NOT NULL default '',
@@ -116,6 +116,8 @@
PRIMARY KEY (`kattjame`,`hunderaaarbagefa`,`hassetistart`,`hassetino`)
) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO `t9_c` VALUES ('3g4jh8gar2t','joe','q3.net','elredun.com','q3.net','436643316120','436643316939','91341234568968','695595699','1.1.1.1','2.2.6.2','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',3123123,9569,6565,1),('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643316120','436643316939','8956234534568968','5254595969','1.1.1.1','8.6.2.2','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565,2),('4545435545','john','q3.net','q3.net','acne.li','436643316120','436643316939','45345234568968','995696699','1.1.1.1','2.9.9.2','2','86998','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8823123,169,3565,3);
+CREATE TABLE `t10_c` (a INT AUTO_INCREMENT KEY) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+INSERT INTO t10_c VALUES (1),(2),(3);
create table t1 engine=myisam as select * from t1_c;
create table t2 engine=myisam as select * from t2_c;
create table t3 engine=myisam as select * from t3_c;
@@ -125,6 +127,7 @@
create table t7 engine=myisam as select * from t7_c;
create table t8 engine=myisam as select * from t8_c;
create table t9 engine=myisam as select * from t9_c;
+create table t10 engine=ndbcluster as select * from t10_c;
CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
DELETE FROM test.backup_info;
LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
@@ -132,7 +135,7 @@
@the_backup_id:=backup_id
<the_backup_id>
DROP TABLE test.backup_info;
-drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
+drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c;
select count(*) from t1;
count(*)
5
@@ -455,7 +458,12 @@
select * from t9_c) a;
count(*)
3
-drop table t1_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
+select * from t10_c order by a;
+a
+1
+2
+3
+drop table t1_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c;
CREATE TEMPORARY TABLE IF NOT EXISTS test.backup_info (id INT, backup_id INT) ENGINE = HEAP;
DELETE FROM test.backup_info;
LOAD DATA INFILE '../tmp.dat' INTO TABLE test.backup_info FIELDS TERMINATED BY ',';
@@ -464,6 +472,6 @@
<the_backup_id>
DROP TABLE test.backup_info;
Create table test/def/t2_c failed: Translate frm error
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
drop table if exists t2_c;
520093696,<the_backup_id>
--- 1.20/mysql-test/t/ndb_restore.test 2006-04-26 01:11:31 +02:00
+++ 1.21/mysql-test/t/ndb_restore.test 2006-07-06 19:02:33 +02:00
@@ -4,8 +4,8 @@
--disable_warnings
use test;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c;
--enable_warnings
CREATE TABLE `t1_c` (
@@ -132,6 +132,13 @@
) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
INSERT INTO `t9_c` VALUES ('3g4jh8gar2t','joe','q3.net','elredun.com','q3.net','436643316120','436643316939','91341234568968','695595699','1.1.1.1','2.2.6.2','3','86989','34','x','x','2012-03-12 18:35:04','2012-12-05 12:35:04',3123123,9569,6565,1),('4tt45345235','pap','q3plus.qt','q3plus.qt','q3.net','436643316120','436643316939','8956234534568968','5254595969','1.1.1.1','8.6.2.2','4','86989','34','x','x','2012-03-12 12:55:34','2012-12-05 11:20:04',3223433,3369,9565,2),('4545435545','john','q3.net','q3.net','acne.li','436643316120','436643316939','45345234568968','995696699','1.1.1.1','2.9.9.2','2','86998','34','x','x','2012-03-12 11:35:03','2012-12-05 08:50:04',8823123,169,3565,3);
+# Bug #20820
+# auto inc table not handled correctly when restored from cluster backup
+# - before fix ndb_restore would not set auto inc value correct,
+# seen by select below
+CREATE TABLE t10_c (a INT AUTO_INCREMENT KEY) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+INSERT INTO t10_c VALUES (1),(2),(3);
+
create table t1 engine=myisam as select * from t1_c;
create table t2 engine=myisam as select * from t2_c;
create table t3 engine=myisam as select * from t3_c;
@@ -141,10 +148,11 @@
create table t7 engine=myisam as select * from t7_c;
create table t8 engine=myisam as select * from t8_c;
create table t9 engine=myisam as select * from t9_c;
+create table t10 engine=myisam as select * from t10_c;
--source include/ndb_backup.inc
-drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
+drop table t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c, t10_c;
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 1 -m -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults -b $the_backup_id -n 2 -r --print --print_meta $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id >> $NDB_TOOLS_OUTPUT
@@ -205,6 +213,9 @@
from (select * from t9 union
select * from t9_c) a;
+# Bug #20820 cont'd
+select * from t10_c order by a;
+
#
# Try Partitioned tables as well
#
@@ -353,7 +364,7 @@
# guaranteed to be from t2_c, this since order of tables in backup
# is none deterministic
#
-drop table t1_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
+drop table t1_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c,t10_c;
--source include/ndb_backup.inc
--exec $NDB_TOOLS_DIR/ndb_restore --no-defaults --core=0 -b $the_backup_id -n 1 -m -r --ndb-nodegroup_map '(0,1)' $NDB_BACKUP_DIR/BACKUP/BACKUP-$the_backup_id 2>&1 | grep Translate || true
@@ -362,7 +373,7 @@
#
--disable_warnings
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
drop table if exists t2_c;
--enable_warnings
@@ -372,4 +383,4 @@
--exec $NDB_TOOLS_DIR/ndb_select_all --no-defaults -d sys -D , SYSTAB_0 | grep 520093696, | sed "s/,$the_backup_id/,<the_backup_id>/"
-# End of 4.1 tests
+# End of 5.0 tests (4.1 test intermixed to save test time)
| Thread |
|---|
| • bk commit into 5.1 tree (tomas:1.2233) | tomas | 6 Jul |