Below is the list of changes that have just been committed into a local
5.1 repository of pekka. When pekka 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.2397 06/05/16 13:13:50 pekka@stripped +5 -0
Merge mysql.com:/space/pekka/ndb/version/my50-bug14509
into mysql.com:/space/pekka/ndb/version/my51-bug14509
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
1.131 06/05/16 13:13:19 pekka@stripped +0 -5
use local, weird diff
sql/ha_ndbcluster.cc
1.304 06/05/16 13:09:19 pekka@stripped +1 -1
manual merge
storage/ndb/tools/restore/consumer_restore.cpp
1.30 06/05/16 13:05:20 pekka@stripped +0 -0
Auto merged
storage/ndb/src/ndbapi/Ndb.cpp
1.70 06/05/16 13:05:20 pekka@stripped +0 -0
Auto merged
storage/ndb/include/ndbapi/Ndb.hpp
1.51 06/05/16 13:05:20 pekka@stripped +0 -0
Auto merged
storage/ndb/tools/restore/consumer_restore.cpp
1.14.9.2 06/05/16 13:05:19 pekka@stripped +0 -0
Merge rename: ndb/tools/restore/consumer_restore.cpp ->
storage/ndb/tools/restore/consumer_restore.cpp
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
1.74.18.2 06/05/16 13:05:19 pekka@stripped +0 -0
Merge rename: ndb/src/ndbapi/NdbDictionaryImpl.cpp ->
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
storage/ndb/src/ndbapi/Ndb.cpp
1.49.9.2 06/05/16 13:05:19 pekka@stripped +0 -0
Merge rename: ndb/src/ndbapi/Ndb.cpp -> storage/ndb/src/ndbapi/Ndb.cpp
storage/ndb/include/ndbapi/Ndb.hpp
1.39.7.2 06/05/16 13:05:19 pekka@stripped +0 -0
Merge rename: ndb/include/ndbapi/Ndb.hpp -> storage/ndb/include/ndbapi/Ndb.hpp
# 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: pekka
# Host: orca.ndb.mysql.com
# Root: /space/pekka/ndb/version/my51-bug14509/RESYNC
--- 1.39.7.1/ndb/include/ndbapi/Ndb.hpp 2006-05-16 12:44:11 +02:00
+++ 1.51/storage/ndb/include/ndbapi/Ndb.hpp 2006-05-16 13:05:20 +02:00
@@ -984,6 +984,8 @@
class NdbEventOperation;
class NdbBlob;
class NdbReceiver;
+class TransporterFacade;
+class PollGuard;
class Ndb_local_table_info;
template <class T> struct Ndb_free_list_t;
@@ -1050,6 +1052,7 @@
friend class NdbReceiver;
friend class NdbOperation;
friend class NdbEventOperationImpl;
+ friend class NdbEventBuffer;
friend class NdbTransaction;
friend class Table;
friend class NdbApiSignal;
@@ -1059,6 +1062,7 @@
friend class NdbDictionaryImpl;
friend class NdbDictInterface;
friend class NdbBlob;
+ friend class NdbImpl;
#endif
public:
@@ -1144,6 +1148,15 @@
*/
void setDatabaseSchemaName(const char * aDatabaseSchemaName);
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ /** Set database and schema name to match previously retrieved table
+ *
+ * Returns non-zero if table internal name does not contain
+ * non-empty database and schema names
+ */
+ int setDatabaseAndSchemaName(const NdbDictionary::Table* t);
+#endif
+
/**
* Initializes the Ndb object
*
@@ -1205,13 +1218,10 @@
*
* @param eventName
* unique identifier of the event
- * @param bufferLength
- * circular buffer size for storing event data
*
* @return Object representing an event, NULL on failure
*/
- NdbEventOperation* createEventOperation(const char* eventName,
- const int bufferLength);
+ NdbEventOperation* createEventOperation(const char* eventName);
/**
* Drop a subscription to an event
*
@@ -1229,9 +1239,36 @@
* @param aMillisecondNumber
* maximum time to wait
*
- * @return the number of events that has occured, -1 on failure
+ * @return > 0 if events available, 0 if no events available, < 0 on failure
*/
- int pollEvents(int aMillisecondNumber);
+ int pollEvents(int aMillisecondNumber, Uint64 *latestGCI= 0);
+
+ /**
+ * Returns an event operation that has data after a pollEvents
+ *
+ * @return an event operations that has data, NULL if no events left with data.
+ */
+ NdbEventOperation *nextEvent();
+
+ /**
+ * Iterate over distinct event operations which are part of current
+ * GCI. Valid after nextEvent. Used to get summary information for
+ * the epoch (e.g. list of all tables) before processing event data.
+ *
+ * Set *iter=0 to start. Returns NULL when no more. If event_types
+ * is not NULL, it returns bitmask of received event types.
+ */
+ const NdbEventOperation*
+ getGCIEventOperations(Uint32* iter, Uint32* event_types);
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+ NdbEventOperation *getEventOperation(NdbEventOperation* eventOp= 0);
+ Uint64 getLatestGCI();
+ void forceGCP();
+ void setReportThreshEventGCISlip(unsigned thresh);
+ void setReportThreshEventFreeMem(unsigned thresh);
+#endif
/** @} *********************************************************************/
@@ -1434,6 +1471,8 @@
*
* @return tuple id or ~(Uint64)0 on error.
*/
+ int initAutoIncrement();
+
Uint64 getAutoIncrementValue(const char* aTableName,
Uint32 cacheSize = 1);
Uint64 getAutoIncrementValue(const NdbDictionary::Table * aTable,
@@ -1472,7 +1511,12 @@
/*****************************************************************************
* These are service routines used by the other classes in the NDBAPI.
****************************************************************************/
+ Uint32 get_cond_wait_index() { return cond_wait_index; }
+ void set_cond_wait_index(Uint32 index) { cond_wait_index = index; }
private:
+ Uint32 cond_wait_index;
+ Ndb *cond_signal_ndb;
+ void cond_signal();
void setup(Ndb_cluster_connection *ndb_cluster_connection,
const char* aCatalogName, const char* aSchemaName);
@@ -1499,7 +1543,6 @@
NdbIndexScanOperation* getScanOperation(); // Get a scan operation from idle
NdbIndexOperation* getIndexOperation();// Get an index operation from idle
- class NdbGlobalEventBufferHandle* getGlobalEventBufferHandle();
NdbBlob* getNdbBlob();// Get a blob handle etc
void releaseSignal(NdbApiSignal* anApiSignal);
@@ -1523,13 +1566,11 @@
// synchronous and asynchronous interface
void handleReceivedSignal(NdbApiSignal* anApiSignal, struct LinearSectionPtr ptr[3]);
- // Receive response signals
- int receiveResponse(int waitTime = WAITFOR_RESPONSE_TIMEOUT);
-
int sendRecSignal(Uint16 aNodeId,
Uint32 aWaitState,
NdbApiSignal* aSignal,
- Uint32 nodeSequence);
+ Uint32 nodeSequence,
+ Uint32 *ret_conn_seq= 0);
// Sets Restart GCI in Ndb object
void RestartGCI(int aRestartGCI);
@@ -1586,7 +1627,9 @@
Uint32 pollCompleted(NdbTransaction** aCopyArray);
void sendPrepTrans(int forceSend);
void reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfComplTrans);
- void waitCompletedTransactions(int milliSecs, int noOfEventsToWaitFor);
+ int poll_trans(int milliSecs, int noOfEventsToWaitFor, PollGuard *pg);
+ void waitCompletedTransactions(int milliSecs, int noOfEventsToWaitFor,
+ PollGuard *pg);
void completedTransaction(NdbTransaction* aTransaction);
void completedScanTransaction(NdbTransaction* aTransaction);
@@ -1638,7 +1681,7 @@
class NdbImpl * theImpl;
class NdbDictionaryImpl* theDictionary;
- class NdbGlobalEventBufferHandle* theGlobalEventBufferHandle;
+ class NdbEventBuffer* theEventBuffer;
NdbTransaction* theTransactionList;
NdbTransaction** theConnectionArray;
@@ -1648,6 +1691,8 @@
Uint64 the_last_check_time;
Uint64 theFirstTransId;
+ // The tupleId is retrieved from DB
+ const NdbDictionary::Table *m_sys_tab_0;
Uint32 theRestartGCI; // the Restart GCI used by DIHNDBTAMPER
--- 1.49.9.1/ndb/src/ndbapi/Ndb.cpp 2006-05-16 12:44:11 +02:00
+++ 1.70/storage/ndb/src/ndbapi/Ndb.cpp 2006-05-16 13:05:20 +02:00
@@ -29,6 +29,7 @@
#include <NdbOperation.hpp>
#include <NdbTransaction.hpp>
#include <NdbEventOperation.hpp>
+#include <NdbEventOperationImpl.hpp>
#include <NdbRecAttr.hpp>
#include <md5_hash.hpp>
#include <NdbSleep.h>
@@ -138,7 +139,7 @@
//***************************************************************************
int tReturnCode;
- TransporterFacade *tp = TransporterFacade::instance();
+ TransporterFacade *tp = theImpl->m_transporter_facade;
DBUG_ENTER("Ndb::NDB_connect");
@@ -173,23 +174,9 @@
tSignal->setData(theMyRef, 2); // Set my block reference
tNdbCon->Status(NdbTransaction::Connecting); // Set status to connecting
Uint32 nodeSequence;
- { // send and receive signal
- Guard guard(tp->theMutexPtr);
- nodeSequence = tp->getNodeSequence(tNode);
- bool node_is_alive = tp->get_node_alive(tNode);
- if (node_is_alive) {
- tReturnCode = tp->sendSignal(tSignal, tNode);
- releaseSignal(tSignal);
- if (tReturnCode != -1) {
- theImpl->theWaiter.m_node = tNode;
- theImpl->theWaiter.m_state = WAIT_TC_SEIZE;
- tReturnCode = receiveResponse();
- }//if
- } else {
- releaseSignal(tSignal);
- tReturnCode = -1;
- }//if
- }
+ tReturnCode= sendRecSignal(tNode, WAIT_TC_SEIZE, tSignal,
+ 0, &nodeSequence);
+ releaseSignal(tSignal);
if ((tReturnCode == 0) && (tNdbCon->Status() == NdbTransaction::Connected))
{
//************************************************
// Send and receive was successful
@@ -230,10 +217,9 @@
void
Ndb::doDisconnect()
{
+ DBUG_ENTER("Ndb::doDisconnect");
NdbTransaction* tNdbCon;
CHECK_STATUS_MACRO_VOID;
- /* DBUG_ENTER must be after CHECK_STATUS_MACRO_VOID because of 'return' */
- DBUG_ENTER("Ndb::doDisconnect");
Uint32 tNoOfDbNodes = theImpl->theNoOfDBnodes;
Uint8 *theDBnodes= theImpl->theDBnodes;
@@ -588,6 +574,7 @@
#ifdef CUSTOMER_RELEASE
return -1;
#else
+ DBUG_ENTER("Ndb::NdbTamper");
CHECK_STATUS_MACRO;
checkFailedNode();
@@ -609,20 +596,20 @@
break;
default:
theError.code = 4102;
- return -1;
+ DBUG_RETURN(-1);
}
tNdbConn = getNdbCon(); // Get free connection object
if (tNdbConn == NULL) {
theError.code = 4000;
- return -1;
+ DBUG_RETURN(-1);
}
tSignal.setSignal(GSN_DIHNDBTAMPER);
tSignal.setData (tAction, 1);
tSignal.setData(tNdbConn->ptr2int(),2);
tSignal.setData(theMyRef,3); // Set return block reference
tNdbConn->Status(NdbTransaction::Connecting); // Set status to connecting
- TransporterFacade *tp = TransporterFacade::instance();
+ TransporterFacade *tp = theImpl->m_transporter_facade;
if (tAction == 3) {
tp->lock_mutex();
tp->sendSignal(&tSignal, aNode);
@@ -634,12 +621,12 @@
if (tNode == 0) {
theError.code = 4002;
releaseNdbCon(tNdbConn);
- return -1;
+ DBUG_RETURN(-1);
}//if
ret_code = tp->sendSignal(&tSignal,aNode);
tp->unlock_mutex();
releaseNdbCon(tNdbConn);
- return ret_code;
+ DBUG_RETURN(ret_code);
} else {
do {
tp->lock_mutex();
@@ -650,7 +637,7 @@
if (tNode == 0) {
theError.code = 4009;
releaseNdbCon(tNdbConn);
- return -1;
+ DBUG_RETURN(-1);
}//if
ret_code = sendRecSignal(tNode, WAIT_NDB_TAMPER, &tSignal, 0);
if (ret_code == 0) {
@@ -658,15 +645,15 @@
theRestartGCI = 0;
}//if
releaseNdbCon(tNdbConn);
- return theRestartGCI;
+ DBUG_RETURN(theRestartGCI);
} else if ((ret_code == -5) || (ret_code == -2)) {
TRACE_DEBUG("Continue DIHNDBTAMPER when node failed/stopping");
} else {
- return -1;
+ DBUG_RETURN(-1);
}//if
} while (1);
}
- return 0;
+ DBUG_RETURN(0);
#endif
}
#if 0
@@ -767,7 +754,7 @@
BaseString internal_tabname(internalize_table_name(aTableName));
Ndb_local_table_info *info=
- theDictionary->get_local_table_info(internal_tabname, false);
+ theDictionary->get_local_table_info(internal_tabname);
if (info == 0) {
theError.code = theDictionary->getNdbError().code;
DBUG_RETURN(~(Uint64)0);
@@ -885,7 +872,7 @@
BaseString internal_tabname(internalize_table_name(aTableName));
Ndb_local_table_info *info=
- theDictionary->get_local_table_info(internal_tabname, false);
+ theDictionary->get_local_table_info(internal_tabname);
if (info == 0) {
theError.code = theDictionary->getNdbError().code;
DBUG_RETURN(~(Uint64)0);
@@ -943,6 +930,27 @@
DBUG_RETURN((opTupleIdOnNdb(info, val, 1) == val));
}
+int Ndb::initAutoIncrement()
+{
+ if (m_sys_tab_0)
+ return 0;
+
+ BaseString currentDb(getDatabaseName());
+ BaseString currentSchema(getDatabaseSchemaName());
+
+ setDatabaseName("sys");
+ setDatabaseSchemaName("def");
+
+ m_sys_tab_0 = getDictionary()->getTableGlobal("SYSTAB_0");
+
+ // Restore current name space
+ setDatabaseName(currentDb.c_str());
+ setDatabaseSchemaName(currentSchema.c_str());
+
+
+ return (m_sys_tab_0 == NULL);
+}
+
Uint64
Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 opValue, Uint32 op)
{
@@ -958,19 +966,14 @@
CHECK_STATUS_MACRO_ZERO;
- BaseString currentDb(getDatabaseName());
- BaseString currentSchema(getDatabaseSchemaName());
+ if (initAutoIncrement())
+ goto error_return;
- setDatabaseName("sys");
- setDatabaseSchemaName("def");
tConnection = this->startTransaction();
if (tConnection == NULL)
goto error_return;
- if (usingFullyQualifiedNames())
- tOperation = tConnection->getNdbOperation("SYSTAB_0");
- else
- tOperation = tConnection->getNdbOperation("sys/def/SYSTAB_0");
+ tOperation = tConnection->getNdbOperation(m_sys_tab_0);
if (tOperation == NULL)
goto error_handler;
@@ -1045,20 +1048,12 @@
this->closeTransaction(tConnection);
- // Restore current name space
- setDatabaseName(currentDb.c_str());
- setDatabaseSchemaName(currentSchema.c_str());
-
DBUG_RETURN(ret);
error_handler:
theError.code = tConnection->theError.code;
this->closeTransaction(tConnection);
error_return:
- // Restore current name space
- setDatabaseName(currentDb.c_str());
- setDatabaseSchemaName(currentSchema.c_str());
-
DBUG_PRINT("error", ("ndb=%d con=%d op=%d",
theError.code,
tConnection ? tConnection->theError.code : -1,
@@ -1083,39 +1078,37 @@
return Data;
#endif
}
+
+// <internal>
const char * Ndb::getCatalogName() const
{
return theImpl->m_dbname.c_str();
}
-
void Ndb::setCatalogName(const char * a_catalog_name)
{
- if (a_catalog_name)
- {
+ // TODO can table_name_separator be escaped?
+ if (a_catalog_name && ! strchr(a_catalog_name, table_name_separator)) {
theImpl->m_dbname.assign(a_catalog_name);
theImpl->update_prefix();
}
}
-
const char * Ndb::getSchemaName() const
{
return theImpl->m_schemaname.c_str();
}
-
void Ndb::setSchemaName(const char * a_schema_name)
{
- if (a_schema_name) {
+ // TODO can table_name_separator be escaped?
+ if (a_schema_name && ! strchr(a_schema_name, table_name_separator)) {
theImpl->m_schemaname.assign(a_schema_name);
theImpl->update_prefix();
}
}
+// </internal>
-/*
-Deprecated functions
-*/
const char * Ndb::getDatabaseName() const
{
return getCatalogName();
@@ -1135,6 +1128,26 @@
{
setSchemaName(a_schema_name);
}
+
+int Ndb::setDatabaseAndSchemaName(const NdbDictionary::Table* t)
+{
+ const char* s0 = t->m_impl.m_internalName.c_str();
+ const char* s1 = strchr(s0, table_name_separator);
+ if (s1 && s1 != s0) {
+ const char* s2 = strchr(s1 + 1, table_name_separator);
+ if (s2 && s2 != s1 + 1) {
+ char buf[NAME_LEN + 1];
+ if (s1 - s0 <= NAME_LEN && s2 - (s1 + 1) <= NAME_LEN) {
+ sprintf(buf, "%.*s", s1 - s0, s0);
+ setDatabaseName(buf);
+ sprintf(buf, "%.*s", s2 - (s1 + 1), s1 + 1);
+ setDatabaseSchemaName(buf);
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
bool Ndb::usingFullyQualifiedNames()
{
@@ -1197,9 +1210,16 @@
if (fullyQualifiedNames)
{
/* Internal table name format <db>/<schema>/<table>
- <db>/<schema> is already available in m_prefix
+ <db>/<schema>/ is already available in m_prefix
so just concat the two strings
*/
+#ifdef VM_TRACE
+ // verify that m_prefix looks like abc/def/
+ const char* s0 = theImpl->m_prefix.c_str();
+ const char* s1 = s0 ? strchr(s0, table_name_separator) : 0;
+ const char* s2 = s1 ? strchr(s1 + 1, table_name_separator) : 0;
+ assert(s1 && s1 != s0 && s2 && s2 != s1 + 1 && *(s2 +
1) == 0);
+#endif
ret.assfmt("%s%s",
theImpl->m_prefix.c_str(),
external_name);
@@ -1219,11 +1239,11 @@
BaseString ret;
DBUG_ENTER("internalize_index_name");
DBUG_PRINT("enter", ("external_name: %s, table_id: %d",
- external_name, table ? table->m_tableId : ~0));
+ external_name, table ? table->m_id : ~0));
if (!table)
{
DBUG_PRINT("error", ("!table"));
- return ret;
+ DBUG_RETURN(ret);
}
if (fullyQualifiedNames)
@@ -1231,7 +1251,7 @@
/* Internal index name format <db>/<schema>/<tabid>/<table>
*/
ret.assfmt("%s%d%c%s",
theImpl->m_prefix.c_str(),
- table->m_tableId,
+ table->m_id,
table_name_separator,
external_name);
}
@@ -1278,49 +1298,102 @@
return ret;
}
-NdbEventOperation* Ndb::createEventOperation(const char* eventName,
- const int bufferLength)
+// ToDo set event buffer size
+NdbEventOperation* Ndb::createEventOperation(const char* eventName)
{
- NdbEventOperation* tOp;
+ DBUG_ENTER("Ndb::createEventOperation");
+ NdbEventOperation* tOp= theEventBuffer->createEventOperation(eventName,
+ theError);
+ if (tOp)
+ {
+ // keep track of all event operations
+ NdbEventOperationImpl *op=
+ NdbEventBuffer::getEventOperationImpl(tOp);
+ op->m_next= theImpl->m_ev_op;
+ op->m_prev= 0;
+ theImpl->m_ev_op= op;
+ if (op->m_next)
+ op->m_next->m_prev= op;
+ }
+
+ DBUG_RETURN(tOp);
+}
+
+int Ndb::dropEventOperation(NdbEventOperation* tOp)
+{
+ DBUG_ENTER("Ndb::dropEventOperation");
+ // remove it from list
+ NdbEventOperationImpl *op=
+ NdbEventBuffer::getEventOperationImpl(tOp);
+ if (op->m_next)
+ op->m_next->m_prev= op->m_prev;
+ if (op->m_prev)
+ op->m_prev->m_next= op->m_next;
+ else
+ theImpl->m_ev_op= op->m_next;
- tOp = new NdbEventOperation(this, eventName, bufferLength);
+ assert(theImpl->m_ev_op == 0 || theImpl->m_ev_op->m_prev == 0);
- if (tOp == 0)
- {
- theError.code= 4000;
- return NULL;
- }
+ theEventBuffer->dropEventOperation(tOp);
+ DBUG_RETURN(0);
+}
- if (tOp->getState() != NdbEventOperation::EO_CREATED) {
- theError.code= tOp->getNdbError().code;
- delete tOp;
- tOp = NULL;
- }
+NdbEventOperation *Ndb::getEventOperation(NdbEventOperation* tOp)
+{
+ NdbEventOperationImpl *op;
+ if (tOp)
+ op= NdbEventBuffer::getEventOperationImpl(tOp)->m_next;
+ else
+ op= theImpl->m_ev_op;
+ if (op)
+ return op->m_facade;
+ return 0;
+}
- //now we have to look up this event in dict
+int
+Ndb::pollEvents(int aMillisecondNumber, Uint64 *latestGCI)
+{
+ return theEventBuffer->pollEvents(aMillisecondNumber, latestGCI);
+}
- return tOp;
+NdbEventOperation *Ndb::nextEvent()
+{
+ return theEventBuffer->nextEvent();
}
-int Ndb::dropEventOperation(NdbEventOperation* op) {
- delete op;
- return 0;
+const NdbEventOperation*
+Ndb::getGCIEventOperations(Uint32* iter, Uint32* event_types)
+{
+ NdbEventOperationImpl* op =
+ theEventBuffer->getGCIEventOperations(iter, event_types);
+ if (op != NULL)
+ return op->m_facade;
+ return NULL;
}
-NdbGlobalEventBufferHandle* Ndb::getGlobalEventBufferHandle()
+Uint64 Ndb::getLatestGCI()
{
- return theGlobalEventBufferHandle;
+ return theEventBuffer->getLatestGCI();
}
-//void Ndb::monitorEvent(NdbEventOperation *op, NdbEventCallback cb, void* rs)
-//{
-//}
+void Ndb::setReportThreshEventGCISlip(unsigned thresh)
+{
+ if (theEventBuffer->m_free_thresh != thresh)
+ {
+ theEventBuffer->m_free_thresh= thresh;
+ theEventBuffer->m_min_free_thresh= thresh;
+ theEventBuffer->m_max_free_thresh= 100;
+ }
+}
-int
-Ndb::pollEvents(int aMillisecondNumber)
+void Ndb::setReportThreshEventFreeMem(unsigned thresh)
{
- return NdbEventOperation::wait(theGlobalEventBufferHandle,
- aMillisecondNumber);
+ if (theEventBuffer->m_free_thresh != thresh)
+ {
+ theEventBuffer->m_free_thresh= thresh;
+ theEventBuffer->m_min_free_thresh= thresh;
+ theEventBuffer->m_max_free_thresh= 100;
+ }
}
#ifdef VM_TRACE
--- 1.74.18.1/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2006-05-16 12:44:11 +02:00
+++ 1.131/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2006-05-16 13:13:19 +02:00
@@ -29,6 +29,9 @@
#include <signaldata/AlterTable.hpp>
#include <signaldata/DropIndx.hpp>
#include <signaldata/ListTables.hpp>
+#include <signaldata/DropFilegroup.hpp>
+#include <signaldata/CreateFilegroup.hpp>
+#include <signaldata/WaitGCP.hpp>
#include <SimpleProperties.hpp>
#include <Bitmask.hpp>
#include <AttributeList.hpp>
@@ -38,10 +41,36 @@
#include "NdbBlobImpl.hpp"
#include <AttributeHeader.hpp>
#include <my_sys.h>
+#include <NdbEnv.h>
+#include <NdbMem.h>
+#include <ndb_version.h>
#define DEBUG_PRINT 0
#define INCOMPATIBLE_VERSION -2
+#define DICT_WAITFOR_TIMEOUT (7*24*60*60*1000)
+
+#define ERR_RETURN(a,b) \
+{\
+ DBUG_PRINT("exit", ("error %d", (a).code));\
+ DBUG_RETURN(b);\
+}
+
+extern Uint64 g_latest_trans_gci;
+int ndb_dictionary_is_mysqld = 0;
+
+bool
+is_ndb_blob_table(const char* name, Uint32* ptab_id, Uint32* pcol_no)
+{
+ return DictTabInfo::isBlobTableName(name, ptab_id, pcol_no);
+}
+
+bool
+is_ndb_blob_table(const NdbTableImpl* t)
+{
+ return is_ndb_blob_table(t->m_internalName.c_str());
+}
+
//#define EVENT_DEBUG
/**
@@ -77,8 +106,16 @@
m_defaultValue = col.m_defaultValue;
m_attrSize = col.m_attrSize;
m_arraySize = col.m_arraySize;
+ m_arrayType = col.m_arrayType;
+ m_storageType = col.m_storageType;
m_keyInfoPos = col.m_keyInfoPos;
- m_blobTable = col.m_blobTable;
+ if (col.m_blobTable == NULL)
+ m_blobTable = NULL;
+ else {
+ m_blobTable = new NdbTableImpl();
+ m_blobTable->assign(*col.m_blobTable);
+ }
+ m_column_no = col.m_column_no;
// Do not copy m_facade !!
return *this;
@@ -108,6 +145,7 @@
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Olddecimal:
case Olddecimalunsigned:
@@ -117,34 +155,57 @@
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Char:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1;
+ m_cs = default_cs;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
+ break;
case Varchar:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = default_cs;
+ m_arrayType = NDB_ARRAYTYPE_SHORT_VAR;
break;
case Binary:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1;
+ m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
+ break;
case Varbinary:
+ m_precision = 0;
+ m_scale = 0;
+ m_length = 1;
+ m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_SHORT_VAR;
+ break;
case Datetime:
case Date:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Blob:
m_precision = 256;
m_scale = 8000;
m_length = 4;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Text:
m_precision = 256;
m_scale = 8000;
m_length = 4;
m_cs = default_cs;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Time:
case Year:
@@ -153,24 +214,28 @@
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Bit:
m_precision = 0;
m_scale = 0;
m_length = 1;
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_FIXED;
break;
case Longvarchar:
m_precision = 0;
m_scale = 0;
m_length = 1; // legal
m_cs = default_cs;
+ m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
break;
case Longvarbinary:
m_precision = 0;
m_scale = 0;
m_length = 1; // legal
m_cs = NULL;
+ m_arrayType = NDB_ARRAYTYPE_MEDIUM_VAR;
break;
default:
case Undefined:
@@ -187,10 +252,18 @@
m_autoIncrement = false;
m_autoIncrementInitialValue = 1;
m_blobTable = NULL;
+ m_storageType = NDB_STORAGETYPE_MEMORY;
+#ifdef VM_TRACE
+ if(NdbEnv_GetEnv("NDB_DEFAULT_DISK", (char *)0, 0))
+ m_storageType = NDB_STORAGETYPE_DISK;
+#endif
}
NdbColumnImpl::~NdbColumnImpl()
{
+ if (m_blobTable != NULL)
+ delete m_blobTable;
+ m_blobTable = NULL;
}
bool
@@ -209,13 +282,11 @@
if(m_nullable != col.m_nullable){
DBUG_RETURN(false);
}
-#ifdef ndb_dictionary_dkey_fixed
- if(m_pk){
- if(m_distributionKey != col.m_distributionKey){
+ if (m_pk) {
+ if ((bool)m_distributionKey != (bool)col.m_distributionKey) {
DBUG_RETURN(false);
}
}
-#endif
if (m_precision != col.m_precision ||
m_scale != col.m_scale ||
m_length != col.m_length ||
@@ -229,11 +300,15 @@
DBUG_RETURN(false);
}
+ if (m_arrayType != col.m_arrayType || m_storageType != col.m_storageType){
+ DBUG_RETURN(false);
+ }
+
DBUG_RETURN(true);
}
NdbDictionary::Column *
-NdbColumnImpl::create_psuedo(const char * name){
+NdbColumnImpl::create_pseudo(const char * name){
NdbDictionary::Column * col = new NdbDictionary::Column();
col->setName(name);
if(!strcmp(name, "NDB$FRAGMENT")){
@@ -266,9 +341,31 @@
col->m_impl.m_attrId = AttributeHeader::RANGE_NO;
col->m_impl.m_attrSize = 4;
col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$DISK_REF")){
+ col->setType(NdbDictionary::Column::Bigunsigned);
+ col->m_impl.m_attrId = AttributeHeader::DISK_REF;
+ col->m_impl.m_attrSize = 8;
+ col->m_impl.m_arraySize = 1;
+ } else if(!strcmp(name, "NDB$RECORDS_IN_RANGE")){
+ col->setType(NdbDictionary::Column::Unsigned);
+ col->m_impl.m_attrId = AttributeHeader::RECORDS_IN_RANGE;
+ col->m_impl.m_attrSize = 4;
+ col->m_impl.m_arraySize = 4;
+ } else if(!strcmp(name, "NDB$ROWID")){
+ col->setType(NdbDictionary::Column::Bigunsigned);
+ col->m_impl.m_attrId = AttributeHeader::ROWID;
+ col->m_impl.m_attrSize = 4;
+ col->m_impl.m_arraySize = 2;
+ } else if(!strcmp(name, "NDB$ROW_GCI")){
+ col->setType(NdbDictionary::Column::Bigunsigned);
+ col->m_impl.m_attrId = AttributeHeader::ROW_GCI;
+ col->m_impl.m_attrSize = 8;
+ col->m_impl.m_arraySize = 1;
+ col->m_impl.m_nullable = true;
} else {
abort();
}
+ col->m_impl.m_storageType = NDB_STORAGETYPE_MEMORY;
return col;
}
@@ -277,13 +374,15 @@
*/
NdbTableImpl::NdbTableImpl()
- : NdbDictionary::Table(* this), m_facade(this)
+ : NdbDictionary::Table(* this),
+ NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(this)
{
init();
}
NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
- : NdbDictionary::Table(* this), m_facade(&f)
+ : NdbDictionary::Table(* this),
+ NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(&f)
{
init();
}
@@ -301,24 +400,49 @@
void
NdbTableImpl::init(){
m_changeMask= 0;
- m_tableId= RNIL;
+ m_id= RNIL;
+ m_version = ~0;
+ m_status = NdbDictionary::Object::Invalid;
+ m_type = NdbDictionary::Object::TypeUndefined;
+ m_primaryTableId= RNIL;
+ m_internalName.clear();
+ m_externalName.clear();
+ m_newExternalName.clear();
+ m_mysqlName.clear();
m_frm.clear();
+ m_newFrm.clear();
+ m_ts_name.clear();
+ m_new_ts_name.clear();
+ m_ts.clear();
+ m_new_ts.clear();
+ m_fd.clear();
+ m_new_fd.clear();
+ m_range.clear();
+ m_new_range.clear();
m_fragmentType= NdbDictionary::Object::FragAllSmall;
m_hashValueMask= 0;
m_hashpointerValue= 0;
+ m_linear_flag= true;
+ m_primaryTable.clear();
+ m_max_rows = 0;
+ m_default_no_part_flag = 1;
m_logging= true;
+ m_row_gci = true;
+ m_row_checksum = true;
m_kvalue= 6;
m_minLoadFactor= 78;
m_maxLoadFactor= 80;
m_keyLenInWords= 0;
m_fragmentCount= 0;
- m_dictionary= NULL;
m_index= NULL;
- m_indexType= NdbDictionary::Index::Undefined;
+ m_indexType= NdbDictionary::Object::TypeUndefined;
m_noOfKeys= 0;
m_noOfDistributionKeys= 0;
m_noOfBlobs= 0;
m_replicaCount= 0;
+ m_tablespace_name.clear();
+ m_tablespace_id = ~0;
+ m_tablespace_version = ~0;
}
bool
@@ -328,71 +452,216 @@
if ((m_internalName.c_str() == NULL) ||
(strcmp(m_internalName.c_str(), "") == 0) ||
(obj.m_internalName.c_str() == NULL) ||
- (strcmp(obj.m_internalName.c_str(), "") == 0)) {
+ (strcmp(obj.m_internalName.c_str(), "") == 0))
+ {
// Shallow equal
- if(strcmp(getName(), obj.getName()) != 0){
+ if(strcmp(getName(), obj.getName()) != 0)
+ {
DBUG_PRINT("info",("name %s != %s",getName(),obj.getName()));
DBUG_RETURN(false);
}
- } else
+ }
+ else
+ {
// Deep equal
- if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0){
+ if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0)
{
DBUG_PRINT("info",("m_internalName %s != %s",
m_internalName.c_str(),obj.m_internalName.c_str()));
DBUG_RETURN(false);
}
}
- if(m_fragmentType != obj.m_fragmentType){
- DBUG_PRINT("info",("m_fragmentType %d != %d",m_fragmentType,obj.m_fragmentType));
+ if (m_frm.length() != obj.m_frm.length() ||
+ (memcmp(m_frm.get_data(), obj.m_frm.get_data(), m_frm.length())))
+ {
+ DBUG_PRINT("info",("m_frm not equal"));
DBUG_RETURN(false);
}
- if(m_columns.size() != obj.m_columns.size()){
- DBUG_PRINT("info",("m_columns.size %d != %d",m_columns.size(),obj.m_columns.size()));
+ if (m_fd.length() != obj.m_fd.length() ||
+ (memcmp(m_fd.get_data(), obj.m_fd.get_data(), m_fd.length())))
+ {
+ DBUG_PRINT("info",("m_fd not equal"));
+ DBUG_RETURN(false);
+ }
+ if (m_ts.length() != obj.m_ts.length() ||
+ (memcmp(m_ts.get_data(), obj.m_ts.get_data(), m_ts.length())))
+ {
+ DBUG_PRINT("info",("m_ts not equal"));
+ DBUG_RETURN(false);
+ }
+ if (m_range.length() != obj.m_range.length() ||
+ (memcmp(m_range.get_data(), obj.m_range.get_data(), m_range.length())))
+ {
+ DBUG_PRINT("info",("m_range not equal"));
+ DBUG_RETURN(false);
+ }
+ if(m_fragmentType != obj.m_fragmentType)
+ {
+ DBUG_PRINT("info",("m_fragmentType %d != %d",m_fragmentType,
+ obj.m_fragmentType));
+ DBUG_RETURN(false);
+ }
+ if(m_columns.size() != obj.m_columns.size())
+ {
+ DBUG_PRINT("info",("m_columns.size %d != %d",m_columns.size(),
+ obj.m_columns.size()));
DBUG_RETURN(false);
}
- for(unsigned i = 0; i<obj.m_columns.size(); i++){
- if(!m_columns[i]->equal(* obj.m_columns[i])){
+ for(unsigned i = 0; i<obj.m_columns.size(); i++)
+ {
+ if(!m_columns[i]->equal(* obj.m_columns[i]))
+ {
DBUG_PRINT("info",("m_columns [%d] != [%d]",i,i));
DBUG_RETURN(false);
}
}
- if(m_logging != obj.m_logging){
+ if(m_linear_flag != obj.m_linear_flag)
+ {
+ DBUG_PRINT("info",("m_linear_flag %d != %d",m_linear_flag,
+ obj.m_linear_flag));
+ DBUG_RETURN(false);
+ }
+
+ if(m_max_rows != obj.m_max_rows)
+ {
+ DBUG_PRINT("info",("m_max_rows %d != %d",(int32)m_max_rows,
+ (int32)obj.m_max_rows));
+ DBUG_RETURN(false);
+ }
+
+ if(m_default_no_part_flag != obj.m_default_no_part_flag)
+ {
+ DBUG_PRINT("info",("m_default_no_part_flag %d != %d",m_default_no_part_flag,
+ obj.m_default_no_part_flag));
+ DBUG_RETURN(false);
+ }
+
+ if(m_logging != obj.m_logging)
+ {
DBUG_PRINT("info",("m_logging %d != %d",m_logging,obj.m_logging));
DBUG_RETURN(false);
}
- if(m_kvalue != obj.m_kvalue){
+ if(m_row_gci != obj.m_row_gci)
+ {
+ DBUG_PRINT("info",("m_row_gci %d != %d",m_row_gci,obj.m_row_gci));
+ DBUG_RETURN(false);
+ }
+
+ if(m_row_checksum != obj.m_row_checksum)
+ {
+ DBUG_PRINT("info",("m_row_checksum %d != %d",m_row_checksum,
+ obj.m_row_checksum));
+ DBUG_RETURN(false);
+ }
+
+ if(m_kvalue != obj.m_kvalue)
+ {
DBUG_PRINT("info",("m_kvalue %d != %d",m_kvalue,obj.m_kvalue));
DBUG_RETURN(false);
}
- if(m_minLoadFactor != obj.m_minLoadFactor){
- DBUG_PRINT("info",("m_minLoadFactor %d != %d",m_minLoadFactor,obj.m_minLoadFactor));
+ if(m_minLoadFactor != obj.m_minLoadFactor)
+ {
+ DBUG_PRINT("info",("m_minLoadFactor %d != %d",m_minLoadFactor,
+ obj.m_minLoadFactor));
DBUG_RETURN(false);
}
- if(m_maxLoadFactor != obj.m_maxLoadFactor){
- DBUG_PRINT("info",("m_maxLoadFactor %d != %d",m_maxLoadFactor,obj.m_maxLoadFactor));
+ if(m_maxLoadFactor != obj.m_maxLoadFactor)
+ {
+ DBUG_PRINT("info",("m_maxLoadFactor %d != %d",m_maxLoadFactor,
+ obj.m_maxLoadFactor));
DBUG_RETURN(false);
}
-
- DBUG_RETURN(true);
+
+ if(m_tablespace_id != obj.m_tablespace_id)
+ {
+ DBUG_PRINT("info",("m_tablespace_id %d != %d",m_tablespace_id,
+ obj.m_tablespace_id));
+ DBUG_RETURN(false);
+ }
+
+ if(m_tablespace_version != obj.m_tablespace_version)
+ {
+ DBUG_PRINT("info",("m_tablespace_version %d != %d",m_tablespace_version,
+ obj.m_tablespace_version));
+ DBUG_RETURN(false);
+ }
+
+ if(m_id != obj.m_id)
+ {
+ DBUG_PRINT("info",("m_id %d != %d",m_id,obj.m_id));
+ DBUG_RETURN(false);
+ }
+
+ if(m_version != obj.m_version)
+ {
+ DBUG_PRINT("info",("m_version %d != %d",m_version,obj.m_version));
+ DBUG_RETURN(false);
+ }
+
+ if(m_type != obj.m_type)
+ {
+ DBUG_PRINT("info",("m_type %d != %d",m_type,obj.m_type));
+ DBUG_RETURN(false);
+ }
+
+ if (m_type == NdbDictionary::Object::UniqueHashIndex ||
+ m_type == NdbDictionary::Object::OrderedIndex)
+ {
+ if(m_primaryTableId != obj.m_primaryTableId)
+ {
+ DBUG_PRINT("info",("m_primaryTableId %d != %d",m_primaryTableId,
+ obj.m_primaryTableId));
+ DBUG_RETURN(false);
+ }
+ if (m_indexType != obj.m_indexType)
+ {
+ DBUG_PRINT("info",("m_indexType %d != %d",m_indexType,obj.m_indexType));
+ DBUG_RETURN(false);
+ }
+ if(strcmp(m_primaryTable.c_str(), obj.m_primaryTable.c_str()) != 0)
+ {
+ DBUG_PRINT("info",("m_primaryTable %s != %s",
+ m_primaryTable.c_str(),obj.m_primaryTable.c_str()));
+ DBUG_RETURN(false);
+ }
+ }
+ DBUG_RETURN(true);
}
void
NdbTableImpl::assign(const NdbTableImpl& org)
{
- m_tableId = org.m_tableId;
+ /* m_changeMask intentionally not copied */
+ m_primaryTableId = org.m_primaryTableId;
m_internalName.assign(org.m_internalName);
- m_externalName.assign(org.m_externalName);
- m_newExternalName.assign(org.m_newExternalName);
+ updateMysqlName();
+ // If the name has been explicitly set, use that name
+ // otherwise use the fetched name
+ if (!org.m_newExternalName.empty())
+ m_externalName.assign(org.m_newExternalName);
+ else
+ m_externalName.assign(org.m_externalName);
m_frm.assign(org.m_frm.get_data(), org.m_frm.length());
- m_fragmentType = org.m_fragmentType;
- m_fragmentCount = org.m_fragmentCount;
+ m_ts_name.assign(org.m_ts_name.get_data(), org.m_ts_name.length());
+ m_new_ts_name.assign(org.m_new_ts_name.get_data(),
+ org.m_new_ts_name.length());
+ m_ts.assign(org.m_ts.get_data(), org.m_ts.length());
+ m_new_ts.assign(org.m_new_ts.get_data(), org.m_new_ts.length());
+ m_fd.assign(org.m_fd.get_data(), org.m_fd.length());
+ m_new_fd.assign(org.m_new_fd.get_data(), org.m_new_fd.length());
+ m_range.assign(org.m_range.get_data(), org.m_range.length());
+ m_new_range.assign(org.m_new_range.get_data(), org.m_new_range.length());
+ m_fragmentType = org.m_fragmentType;
+ /*
+ m_columnHashMask, m_columnHash, m_hashValueMask, m_hashpointerValue
+ is state calculated by computeAggregates and buildColumnHash
+ */
for(unsigned i = 0; i<org.m_columns.size(); i++){
NdbColumnImpl * col = new NdbColumnImpl();
const NdbColumnImpl * iorg = org.m_columns[i];
@@ -400,22 +669,39 @@
m_columns.push_back(col);
}
+ m_fragments = org.m_fragments;
+
+ m_linear_flag = org.m_linear_flag;
+ m_max_rows = org.m_max_rows;
+ m_default_no_part_flag = org.m_default_no_part_flag;
m_logging = org.m_logging;
+ m_row_gci = org.m_row_gci;
+ m_row_checksum = org.m_row_checksum;
m_kvalue = org.m_kvalue;
m_minLoadFactor = org.m_minLoadFactor;
m_maxLoadFactor = org.m_maxLoadFactor;
+ m_keyLenInWords = org.m_keyLenInWords;
+ m_fragmentCount = org.m_fragmentCount;
if (m_index != 0)
delete m_index;
m_index = org.m_index;
-
- m_noOfDistributionKeys = org.m_noOfDistributionKeys;
+
+ m_primaryTable = org.m_primaryTable;
+ m_indexType = org.m_indexType;
+
m_noOfKeys = org.m_noOfKeys;
- m_keyLenInWords = org.m_keyLenInWords;
+ m_noOfDistributionKeys = org.m_noOfDistributionKeys;
m_noOfBlobs = org.m_noOfBlobs;
+ m_replicaCount = org.m_replicaCount;
+ m_id = org.m_id;
m_version = org.m_version;
m_status = org.m_status;
+
+ m_tablespace_name = org.m_tablespace_name;
+ m_tablespace_id= org.m_tablespace_id;
+ m_tablespace_version = org.m_tablespace_version;
}
void NdbTableImpl::setName(const char * name)
@@ -432,11 +718,206 @@
return m_newExternalName.c_str();
}
+void
+NdbTableImpl::computeAggregates()
+{
+ m_noOfKeys = 0;
+ m_keyLenInWords = 0;
+ m_noOfDistributionKeys = 0;
+ m_noOfBlobs = 0;
+ Uint32 i, n;
+ for (i = 0; i < m_columns.size(); i++) {
+ NdbColumnImpl* col = m_columns[i];
+ if (col->m_pk) {
+ m_noOfKeys++;
+ m_keyLenInWords += (col->m_attrSize * col->m_arraySize + 3) / 4;
+ }
+ if (col->m_distributionKey == 2) // set by user
+ m_noOfDistributionKeys++;
+
+ if (col->getBlobType())
+ m_noOfBlobs++;
+ col->m_keyInfoPos = ~0;
+ }
+ if (m_noOfDistributionKeys == m_noOfKeys) {
+ // all is none!
+ m_noOfDistributionKeys = 0;
+ }
+
+ if (m_noOfDistributionKeys == 0)
+ {
+ // none is all!
+ for (i = 0, n = m_noOfKeys; n != 0; i++) {
+ NdbColumnImpl* col = m_columns[i];
+ if (col->m_pk) {
+ col->m_distributionKey = true; // set by us
+ n--;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0, n = m_noOfKeys; n != 0; i++) {
+ NdbColumnImpl* col = m_columns[i];
+ if (col->m_pk)
+ {
+ if(col->m_distributionKey == 1)
+ col->m_distributionKey = 0;
+ n--;
+ }
+ }
+ }
+
+ Uint32 keyInfoPos = 0;
+ for (i = 0, n = m_noOfKeys; n != 0; i++) {
+ NdbColumnImpl* col = m_columns[i];
+ if (col->m_pk) {
+ col->m_keyInfoPos = keyInfoPos++;
+ n--;
+ }
+ }
+}
+
+const void*
+NdbTableImpl::getTablespaceNames() const
+{
+ if (m_new_ts_name.empty())
+ return m_ts_name.get_data();
+ else
+ return m_new_ts_name.get_data();
+}
+
+Uint32
+NdbTableImpl::getTablespaceNamesLen() const
+{
+ if (m_new_ts_name.empty())
+ return m_ts_name.length();
+ else
+ return m_new_ts_name.length();
+}
+
+void NdbTableImpl::setTablespaceNames(const void *data, Uint32 len)
+{
+ m_new_ts_name.assign(data, len);
+}
+
+void NdbTableImpl::setFragmentCount(Uint32 count)
+{
+ m_fragmentCount= count;
+}
+
+Uint32 NdbTableImpl::getFragmentCount() const
+{
+ return m_fragmentCount;
+}
+
+void NdbTableImpl::setFrm(const void* data, Uint32 len)
+{
+ m_newFrm.assign(data, len);
+}
+
+const void *
+NdbTableImpl::getFrmData() const
+{
+ if (m_newFrm.empty())
+ return m_frm.get_data();
+ else
+ return m_newFrm.get_data();
+}
+
+Uint32
+NdbTableImpl::getFrmLength() const
+{
+ if (m_newFrm.empty())
+ return m_frm.length();
+ else
+ return m_newFrm.length();
+}
+
+void NdbTableImpl::setFragmentData(const void* data, Uint32 len)
+{
+ m_new_fd.assign(data, len);
+}
+
+const void *
+NdbTableImpl::getFragmentData() const
+{
+ if (m_new_fd.empty())
+ return m_fd.get_data();
+ else
+ return m_new_fd.get_data();
+}
+
+Uint32
+NdbTableImpl::getFragmentDataLen() const
+{
+ if (m_new_fd.empty())
+ return m_fd.length();
+ else
+ return m_new_fd.length();
+}
+
+void NdbTableImpl::setTablespaceData(const void* data, Uint32 len)
+{
+ m_new_ts.assign(data, len);
+}
+
+const void *
+NdbTableImpl::getTablespaceData() const
+{
+ if (m_new_ts.empty())
+ return m_ts.get_data();
+ else
+ return m_new_ts.get_data();
+}
+
+Uint32
+NdbTableImpl::getTablespaceDataLen() const
+{
+ if (m_new_ts.empty())
+ return m_ts.length();
+ else
+ return m_new_ts.length();
+}
+
+void NdbTableImpl::setRangeListData(const void* data, Uint32 len)
+{
+ m_new_range.assign(data, len);
+}
+
+const void *
+NdbTableImpl::getRangeListData() const
+{
+ if (m_new_range.empty())
+ return m_range.get_data();
+ else
+ return m_new_range.get_data();
+}
+
+Uint32
+NdbTableImpl::getRangeListDataLen() const
+{
+ if (m_new_range.empty())
+ return m_range.length();
+ else
+ return m_new_range.length();
+}
+
+void
+NdbTableImpl::updateMysqlName()
+{
+ Vector<BaseString> v;
+ if (m_internalName.split(v,"/") == 3)
+ {
+ m_mysqlName.assfmt("%s/%s",v[0].c_str(),v[2].c_str());
+ return;
+ }
+ m_mysqlName.assign("");
+}
void
NdbTableImpl::buildColumnHash(){
const Uint32 size = m_columns.size();
-
int i;
for(i = 31; i >= 0; i--){
if(((1 << i) & size) != 0){
@@ -503,19 +984,35 @@
Uint32
NdbTableImpl::get_nodes(Uint32 hashValue, const Uint16 ** nodes) const
{
- if(m_replicaCount > 0)
+ Uint32 fragmentId;
+ if(m_replicaCount == 0)
+ return 0;
+ switch (m_fragmentType)
{
- Uint32 fragmentId = hashValue & m_hashValueMask;
- if(fragmentId < m_hashpointerValue)
+ case NdbDictionary::Object::FragAllSmall:
+ case NdbDictionary::Object::FragAllMedium:
+ case NdbDictionary::Object::FragAllLarge:
+ case NdbDictionary::Object::FragSingle:
+ case NdbDictionary::Object::DistrKeyLin:
{
- fragmentId = hashValue & ((m_hashValueMask << 1) + 1);
+ fragmentId = hashValue & m_hashValueMask;
+ if(fragmentId < m_hashpointerValue)
+ fragmentId = hashValue & ((m_hashValueMask << 1) + 1);
+ break;
}
- Uint32 pos = fragmentId * m_replicaCount;
- if(pos + m_replicaCount <= m_fragments.size())
+ case NdbDictionary::Object::DistrKeyHash:
{
- * nodes = m_fragments.getBase()+pos;
- return m_replicaCount;
+ fragmentId = hashValue % m_fragmentCount;
+ break;
}
+ default:
+ return 0;
+ }
+ Uint32 pos = fragmentId * m_replicaCount;
+ if (pos + m_replicaCount <= m_fragments.size())
+ {
+ *nodes = m_fragments.getBase()+pos;
+ return m_replicaCount;
}
return 0;
}
@@ -525,23 +1022,23 @@
*/
NdbIndexImpl::NdbIndexImpl() :
- NdbDictionary::Index(* this),
- m_facade(this)
+ NdbDictionary::Index(* this),
+ NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(this)
{
init();
}
NdbIndexImpl::NdbIndexImpl(NdbDictionary::Index & f) :
NdbDictionary::Index(* this),
- m_facade(&f)
+ NdbDictObjectImpl(NdbDictionary::Object::OrderedIndex), m_facade(&f)
{
init();
}
void NdbIndexImpl::init()
{
- m_indexId= RNIL;
- m_type= NdbDictionary::Index::Undefined;
+ m_id= RNIL;
+ m_type= NdbDictionary::Object::TypeUndefined;
m_logging= true;
m_table= NULL;
}
@@ -586,14 +1083,14 @@
NdbEventImpl::NdbEventImpl() :
NdbDictionary::Event(* this),
- m_facade(this)
+ NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(this)
{
init();
}
NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
NdbDictionary::Event(* this),
- m_facade(&f)
+ NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(&f)
{
init();
}
@@ -602,38 +1099,58 @@
{
m_eventId= RNIL;
m_eventKey= RNIL;
- m_tableId= RNIL;
mi_type= 0;
m_dur= NdbDictionary::Event::ED_UNDEFINED;
+ m_mergeEvents = false;
m_tableImpl= NULL;
- m_bufferId= RNIL;
- eventOp= NULL;
+ m_rep= NdbDictionary::Event::ER_UPDATED;
}
NdbEventImpl::~NdbEventImpl()
{
for (unsigned i = 0; i < m_columns.size(); i++)
delete m_columns[i];
+ if (m_tableImpl)
+ delete m_tableImpl;
}
void NdbEventImpl::setName(const char * name)
{
- m_externalName.assign(name);
+ m_name.assign(name);
}
const char *NdbEventImpl::getName() const
{
- return m_externalName.c_str();
+ return m_name.c_str();
}
void
NdbEventImpl::setTable(const NdbDictionary::Table& table)
{
- m_tableImpl= &NdbTableImpl::getImpl(table);
+ setTable(&NdbTableImpl::getImpl(table));
m_tableName.assign(m_tableImpl->getName());
}
void
+NdbEventImpl::setTable(NdbTableImpl *tableImpl)
+{
+ DBUG_ASSERT(tableImpl->m_status != NdbDictionary::Object::Invalid);
+ if (!m_tableImpl)
+ m_tableImpl = new NdbTableImpl();
+ // Copy table, since event might be accessed from different threads
+ m_tableImpl->assign(*tableImpl);
+}
+
+const NdbDictionary::Table *
+NdbEventImpl::getTable() const
+{
+ if (m_tableImpl)
+ return m_tableImpl->m_facade;
+ else
+ return NULL;
+}
+
+void
NdbEventImpl::setTable(const char * table)
{
m_tableName.assign(table);
@@ -648,12 +1165,13 @@
void
NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t =
NdbDictionary::Event::TE_ALL)
{
- switch (t) {
- case NdbDictionary::Event::TE_INSERT : mi_type |= 1; break;
- case NdbDictionary::Event::TE_DELETE : mi_type |= 2; break;
- case NdbDictionary::Event::TE_UPDATE : mi_type |= 4; break;
- default: mi_type = 4 | 2 | 1; // all types
- }
+ mi_type |= (unsigned)t;
+}
+
+bool
+NdbEventImpl::getTableEvent(const NdbDictionary::Event::TableEvent t) const
+{
+ return (mi_type & (unsigned)t) == (unsigned)t;
}
void
@@ -668,11 +1186,46 @@
return m_dur;
}
+void
+NdbEventImpl::setReport(NdbDictionary::Event::EventReport r)
+{
+ m_rep = r;
+}
+
+NdbDictionary::Event::EventReport
+NdbEventImpl::getReport() const
+{
+ return m_rep;
+}
+
int NdbEventImpl::getNoOfEventColumns() const
{
return m_attrIds.size() + m_columns.size();
}
+const NdbDictionary::Column *
+NdbEventImpl::getEventColumn(unsigned no) const
+{
+ if (m_columns.size())
+ {
+ if (no < m_columns.size())
+ {
+ return m_columns[no];
+ }
+ }
+ else if (m_attrIds.size())
+ {
+ if (no < m_attrIds.size())
+ {
+ NdbTableImpl* tab= m_tableImpl;
+ if (tab == 0)
+ return 0;
+ return tab->getColumn(m_attrIds[no]);
+ }
+ }
+ return 0;
+}
+
/**
* NdbDictionaryImpl
*/
@@ -721,12 +1274,20 @@
delete NdbDictionary::Column::COMMIT_COUNT;
delete NdbDictionary::Column::ROW_SIZE;
delete NdbDictionary::Column::RANGE_NO;
+ delete NdbDictionary::Column::DISK_REF;
+ delete NdbDictionary::Column::RECORDS_IN_RANGE;
+ delete NdbDictionary::Column::ROWID;
+ delete NdbDictionary::Column::ROW_GCI;
NdbDictionary::Column::FRAGMENT= 0;
NdbDictionary::Column::FRAGMENT_MEMORY= 0;
NdbDictionary::Column::ROW_COUNT= 0;
NdbDictionary::Column::COMMIT_COUNT= 0;
NdbDictionary::Column::ROW_SIZE= 0;
NdbDictionary::Column::RANGE_NO= 0;
+ NdbDictionary::Column::DISK_REF= 0;
+ NdbDictionary::Column::RECORDS_IN_RANGE= 0;
+ NdbDictionary::Column::ROWID= 0;
+ NdbDictionary::Column::ROW_GCI= 0;
}
m_globalHash->unlock();
} else {
@@ -734,32 +1295,125 @@
}
}
-Ndb_local_table_info *
-NdbDictionaryImpl::fetchGlobalTableImpl(const BaseString& internalTableName)
+NdbTableImpl *
+NdbDictionaryImpl::fetchGlobalTableImplRef(const GlobalCacheInitObject &obj)
{
+ DBUG_ENTER("fetchGlobalTableImplRef");
NdbTableImpl *impl;
m_globalHash->lock();
- impl = m_globalHash->get(internalTableName.c_str());
+ impl = m_globalHash->get(obj.m_name.c_str());
m_globalHash->unlock();
if (impl == 0){
- impl = m_receiver.getTable(internalTableName,
+ impl = m_receiver.getTable(obj.m_name.c_str(),
m_ndb.usingFullyQualifiedNames());
+ if (impl != 0 && obj.init(*impl))
+ {
+ delete impl;
+ impl = 0;
+ }
m_globalHash->lock();
- m_globalHash->put(internalTableName.c_str(), impl);
+ m_globalHash->put(obj.m_name.c_str(), impl);
m_globalHash->unlock();
-
- if(impl == 0){
- return 0;
- }
}
+ DBUG_RETURN(impl);
+}
+
+void
+NdbDictionaryImpl::putTable(NdbTableImpl *impl)
+{
+ NdbTableImpl *old;
+
+ int ret = getBlobTables(*impl);
+ assert(ret == 0);
+
+ m_globalHash->lock();
+ if ((old= m_globalHash->get(impl->m_internalName.c_str())))
+ {
+ m_globalHash->alter_table_rep(old->m_internalName.c_str(),
+ impl->m_id,
+ impl->m_version,
+ FALSE);
+ }
+ m_globalHash->put(impl->m_internalName.c_str(), impl);
+ m_globalHash->unlock();
Ndb_local_table_info *info=
Ndb_local_table_info::create(impl, m_local_table_data_size);
+
+ m_localHash.put(impl->m_internalName.c_str(), info);
+
+ m_ndb.theFirstTupleId[impl->getTableId()] = ~0;
+ m_ndb.theLastTupleId[impl->getTableId()] = ~0;
+}
- m_localHash.put(internalTableName.c_str(), info);
- return info;
+int
+NdbDictionaryImpl::getBlobTables(NdbTableImpl &t)
+{
+ unsigned n= t.m_noOfBlobs;
+ DBUG_ENTER("NdbDictionaryImpl::addBlobTables");
+ // optimized for blob column being the last one
+ // and not looking for more than one if not neccessary
+ for (unsigned i = t.m_columns.size(); i > 0 && n > 0;) {
+ i--;
+ NdbColumnImpl & c = *t.m_columns[i];
+ if (! c.getBlobType() || c.getPartSize() == 0)
+ continue;
+ n--;
+ // retrieve blob table def from DICT - by-pass cache
+ char btname[NdbBlobImpl::BlobTableNameSize];
+ NdbBlob::getBlobTableName(btname, &t, &c);
+ BaseString btname_internal = m_ndb.internalize_table_name(btname);
+ NdbTableImpl* bt =
+ m_receiver.getTable(btname_internal, m_ndb.usingFullyQualifiedNames());
+ if (bt == NULL)
+ DBUG_RETURN(-1);
+
+ // TODO check primary id/version when returned by DICT
+
+ // the blob column owns the blob table
+ assert(c.m_blobTable == NULL);
+ c.m_blobTable = bt;
+ }
+ DBUG_RETURN(0);
+}
+
+NdbTableImpl*
+NdbDictionaryImpl::getBlobTable(const NdbTableImpl& tab, uint col_no)
+{
+ if (col_no < tab.m_columns.size()) {
+ NdbColumnImpl* col = tab.m_columns[col_no];
+ if (col != NULL) {
+ NdbTableImpl* bt = col->m_blobTable;
+ if (bt != NULL)
+ return bt;
+ else
+ m_error.code = 4273; // No blob table..
+ } else
+ m_error.code = 4249; // Invalid table..
+ } else
+ m_error.code = 4318; // Invalid attribute..
+ return NULL;
+}
+
+NdbTableImpl*
+NdbDictionaryImpl::getBlobTable(uint tab_id, uint col_no)
+{
+ DBUG_ENTER("NdbDictionaryImpl::getBlobTable");
+ DBUG_PRINT("enter", ("tab_id: %u col_no %u", tab_id, col_no));
+
+ NdbTableImpl* tab = m_receiver.getTable(tab_id,
+ m_ndb.usingFullyQualifiedNames());
+ if (tab == NULL)
+ DBUG_RETURN(NULL);
+ Ndb_local_table_info* info =
+ get_local_table_info(tab->m_internalName);
+ delete tab;
+ if (info == NULL)
+ DBUG_RETURN(NULL);
+ NdbTableImpl* bt = getBlobTable(*info->m_table_impl, col_no);
+ DBUG_RETURN(bt);
}
#if 0
@@ -784,17 +1438,25 @@
m_globalHash->lock();
if(f_dictionary_count++ == 0){
NdbDictionary::Column::FRAGMENT=
- NdbColumnImpl::create_psuedo("NDB$FRAGMENT");
+ NdbColumnImpl::create_pseudo("NDB$FRAGMENT");
NdbDictionary::Column::FRAGMENT_MEMORY=
- NdbColumnImpl::create_psuedo("NDB$FRAGMENT_MEMORY");
+ NdbColumnImpl::create_pseudo("NDB$FRAGMENT_MEMORY");
NdbDictionary::Column::ROW_COUNT=
- NdbColumnImpl::create_psuedo("NDB$ROW_COUNT");
+ NdbColumnImpl::create_pseudo("NDB$ROW_COUNT");
NdbDictionary::Column::COMMIT_COUNT=
- NdbColumnImpl::create_psuedo("NDB$COMMIT_COUNT");
+ NdbColumnImpl::create_pseudo("NDB$COMMIT_COUNT");
NdbDictionary::Column::ROW_SIZE=
- NdbColumnImpl::create_psuedo("NDB$ROW_SIZE");
+ NdbColumnImpl::create_pseudo("NDB$ROW_SIZE");
NdbDictionary::Column::RANGE_NO=
- NdbColumnImpl::create_psuedo("NDB$RANGE_NO");
+ NdbColumnImpl::create_pseudo("NDB$RANGE_NO");
+ NdbDictionary::Column::DISK_REF=
+ NdbColumnImpl::create_pseudo("NDB$DISK_REF");
+ NdbDictionary::Column::RECORDS_IN_RANGE=
+ NdbColumnImpl::create_pseudo("NDB$RECORDS_IN_RANGE");
+ NdbDictionary::Column::ROWID=
+ NdbColumnImpl::create_pseudo("NDB$ROWID");
+ NdbDictionary::Column::ROW_GCI=
+ NdbColumnImpl::create_pseudo("NDB$ROW_GCI");
}
m_globalHash->unlock();
return true;
@@ -908,12 +1570,6 @@
case GSN_SUB_START_REF:
tmp->execSUB_START_REF(signal, ptr);
break;
- case GSN_SUB_TABLE_DATA:
- tmp->execSUB_TABLE_DATA(signal, ptr);
- break;
- case GSN_SUB_GCP_COMPLETE_REP:
- tmp->execSUB_GCP_COMPLETE_REP(signal, ptr);
- break;
case GSN_SUB_STOP_CONF:
tmp->execSUB_STOP_CONF(signal, ptr);
break;
@@ -929,6 +1585,36 @@
case GSN_LIST_TABLES_CONF:
tmp->execLIST_TABLES_CONF(signal, ptr);
break;
+ case GSN_CREATE_FILEGROUP_REF:
+ tmp->execCREATE_FILEGROUP_REF(signal, ptr);
+ break;
+ case GSN_CREATE_FILEGROUP_CONF:
+ tmp->execCREATE_FILEGROUP_CONF(signal, ptr);
+ break;
+ case GSN_CREATE_FILE_REF:
+ tmp->execCREATE_FILE_REF(signal, ptr);
+ break;
+ case GSN_CREATE_FILE_CONF:
+ tmp->execCREATE_FILE_CONF(signal, ptr);
+ break;
+ case GSN_DROP_FILEGROUP_REF:
+ tmp->execDROP_FILEGROUP_REF(signal, ptr);
+ break;
+ case GSN_DROP_FILEGROUP_CONF:
+ tmp->execDROP_FILEGROUP_CONF(signal, ptr);
+ break;
+ case GSN_DROP_FILE_REF:
+ tmp->execDROP_FILE_REF(signal, ptr);
+ break;
+ case GSN_DROP_FILE_CONF:
+ tmp->execDROP_FILE_CONF(signal, ptr);
+ break;
+ case GSN_WAIT_GCP_CONF:
+ tmp->execWAIT_GCP_CONF(signal, ptr);
+ break;
+ case GSN_WAIT_GCP_REF:
+ tmp->execWAIT_GCP_REF(signal, ptr);
+ break;
default:
abort();
}
@@ -950,72 +1636,56 @@
}
int
-NdbDictInterface::dictSignal(NdbApiSignal* signal,
- LinearSectionPtr ptr[3],int noLSP,
- const int useMasterNodeId,
- const Uint32 RETRIES,
- const WaitSignalType wst,
- const int theWait,
- const int *errcodes,
- const int noerrcodes,
- const int temporaryMask)
+NdbDictInterface::dictSignal(NdbApiSignal* sig,
+ LinearSectionPtr ptr[3], int secs,
+ int node_specification,
+ WaitSignalType wst,
+ int timeout, Uint32 RETRIES,
+ const int *errcodes, int temporaryMask)
{
DBUG_ENTER("NdbDictInterface::dictSignal");
- DBUG_PRINT("enter", ("useMasterNodeId: %d", useMasterNodeId));
+ DBUG_PRINT("enter", ("useMasterNodeId: %d", node_specification));
for(Uint32 i = 0; i<RETRIES; i++){
- //if (useMasterNodeId == 0)
m_buffer.clear();
// Protected area
- m_transporter->lock_mutex();
- Uint32 aNodeId;
- if (useMasterNodeId) {
- if ((m_masterNodeId == 0) ||
- (!m_transporter->get_node_alive(m_masterNodeId))) {
- m_masterNodeId = m_transporter->get_an_alive_node();
- }//if
- aNodeId = m_masterNodeId;
- } else {
- aNodeId = m_transporter->get_an_alive_node();
+ /*
+ The PollGuard has an implicit call of unlock_and_signal through the
+ ~PollGuard method. This method is called implicitly by the compiler
+ in all places where the object is out of context due to a return,
+ break, continue or simply end of statement block
+ */
+ PollGuard poll_guard(m_transporter, &m_waiter, refToBlock(m_reference));
+ Uint32 node;
+ switch(node_specification){
+ case 0:
+ node = (m_transporter->get_node_alive(m_masterNodeId) ? m_masterNodeId :
+ (m_masterNodeId = m_transporter->get_an_alive_node()));
+ break;
+ case -1:
+ node = m_transporter->get_an_alive_node();
+ break;
+ default:
+ node = node_specification;
}
- if(aNodeId == 0){
+ DBUG_PRINT("info", ("node %d", node));
+ if(node == 0){
m_error.code= 4009;
- m_transporter->unlock_mutex();
DBUG_RETURN(-1);
}
- {
- int r;
- if (ptr) {
-#ifdef EVENT_DEBUG
- printf("Long signal %d ptr", noLSP);
- for (int q=0;q<noLSP;q++) {
- printf(" sz %d", ptr[q].sz);
- }
- printf("\n");
-#endif
- r = m_transporter->sendFragmentedSignal(signal, aNodeId, ptr, noLSP);
- } else {
-#ifdef EVENT_DEBUG
- printf("Short signal\n");
-#endif
- r = m_transporter->sendSignal(signal, aNodeId);
- }
- if(r != 0){
- m_transporter->unlock_mutex();
- continue;
- }
- }
+ int res = (ptr ?
+ m_transporter->sendFragmentedSignal(sig, node, ptr, secs):
+ m_transporter->sendSignal(sig, node));
+ if(res != 0){
+ DBUG_PRINT("info", ("dictSignal failed to send signal"));
+ continue;
+ }
m_error.code= 0;
-
- m_waiter.m_node = aNodeId;
- m_waiter.m_state = wst;
-
- m_waiter.wait(theWait);
- m_transporter->unlock_mutex();
+ int ret_val= poll_guard.wait_n_unlock(timeout, node, wst);
// End of Protected area
- if(m_waiter.m_state == NO_WAIT && m_error.code == 0){
+ if(ret_val == 0 && m_error.code == 0){
// Normal return
DBUG_RETURN(0);
}
@@ -1023,34 +1693,44 @@
/**
* Handle error codes
*/
- if(m_waiter.m_state == WAIT_NODE_FAILURE)
+ if(ret_val == -2) //WAIT_NODE_FAILURE
+ {
continue;
-
+ }
if(m_waiter.m_state == WST_WAIT_TIMEOUT)
{
+ DBUG_PRINT("info", ("dictSignal caught time-out"));
m_error.code = 4008;
DBUG_RETURN(-1);
}
- if ( (temporaryMask & m_error.code) != 0 ) {
+ if ( temporaryMask == -1)
+ {
+ const NdbError &error= getNdbError();
+ if (error.status == NdbError::TemporaryError)
+ continue;
+ }
+ else if ( (temporaryMask & m_error.code) != 0 ) {
continue;
}
- if (errcodes) {
- int doContinue = 0;
- for (int j=0; j < noerrcodes; j++)
- if(m_error.code == errcodes[j]) {
- doContinue = 1;
+ DBUG_PRINT("info", ("dictSignal caught error= %d", m_error.code));
+
+ if(m_error.code && errcodes)
+ {
+ int j;
+ for(j = 0; errcodes[j] ; j++){
+ if(m_error.code == errcodes[j]){
break;
}
- if (doContinue)
+ }
+ if(errcodes[j]) // Accepted error code
continue;
}
-
- DBUG_RETURN(-1);
+ break;
}
DBUG_RETURN(-1);
}
-#if 0
+
/*
Get dictionary information for a table using table id as reference
@@ -1061,8 +1741,8 @@
NdbDictInterface::getTable(int tableId, bool fullyQualifiedNames)
{
NdbApiSignal tSignal(m_reference);
- GetTabInfoReq* const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
-
+ GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
req->senderRef = m_reference;
req->senderData = 0;
req->requestType =
@@ -1074,8 +1754,6 @@
return getTable(&tSignal, 0, 0, fullyQualifiedNames);
}
-#endif
-
/*
Get dictionary information for a table using table name as the reference
@@ -1126,22 +1804,23 @@
LinearSectionPtr ptr[3],
Uint32 noOfSections, bool fullyQualifiedNames)
{
- int errCodes[] = {GetTabInfoRef::Busy };
-
- int r = dictSignal(signal,ptr,noOfSections,
- 0/*do not use masternode id*/,
- 100,
+ int errCodes[] = {GetTabInfoRef::Busy, 0 };
+ int r = dictSignal(signal, ptr, noOfSections,
+ -1, // any node
WAIT_GET_TAB_INFO_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes, 1);
- if (r) return 0;
+ DICT_WAITFOR_TIMEOUT, 100, errCodes);
+ if (r)
+ return 0;
+
NdbTableImpl * rt = 0;
- m_error.code= parseTableInfo(&rt,
- (Uint32*)m_buffer.get_data(),
- m_buffer.length() / 4, fullyQualifiedNames);
- if (rt != 0)
+ m_error.code = parseTableInfo(&rt,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4,
+ fullyQualifiedNames);
+ if(rt)
rt->buildColumnHash();
+
return rt;
}
@@ -1173,8 +1852,9 @@
NdbDictInterface::execGET_TABINFO_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef, signal->getDataPtr());
-
+ const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef,
+ signal->getDataPtr());
+
m_error.code= ref->errorCode;
m_waiter.signal(NO_WAIT);
}
@@ -1222,6 +1902,9 @@
{ DictTabInfo::AllNodesMediumTable, NdbDictionary::Object::FragAllMedium },
{ DictTabInfo::AllNodesLargeTable, NdbDictionary::Object::FragAllLarge },
{ DictTabInfo::SingleFragment, NdbDictionary::Object::FragSingle },
+ { DictTabInfo::DistrKeyHash, NdbDictionary::Object::DistrKeyHash },
+ { DictTabInfo::DistrKeyLin, NdbDictionary::Object::DistrKeyLin },
+ { DictTabInfo::UserDefined, NdbDictionary::Object::UserDefined },
{ -1, -1 }
};
@@ -1236,6 +1919,10 @@
{ DictTabInfo::IndexTrigger, NdbDictionary::Object::IndexTrigger },
{ DictTabInfo::SubscriptionTrigger,NdbDictionary::Object::SubscriptionTrigger },
{ DictTabInfo::ReadOnlyConstraint ,NdbDictionary::Object::ReadOnlyConstraint },
+ { DictTabInfo::Tablespace, NdbDictionary::Object::Tablespace },
+ { DictTabInfo::LogfileGroup, NdbDictionary::Object::LogfileGroup },
+ { DictTabInfo::Datafile, NdbDictionary::Object::Datafile },
+ { DictTabInfo::Undofile, NdbDictionary::Object::Undofile },
{ -1, -1 }
};
@@ -1270,62 +1957,86 @@
int
NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
const Uint32 * data, Uint32 len,
- bool fullyQualifiedNames)
+ bool fullyQualifiedNames,
+ Uint32 version)
{
- DBUG_ENTER("NdbDictInterface::parseTableInfo");
-
SimplePropertiesLinearReader it(data, len);
- DictTabInfo::Table tableDesc; tableDesc.init();
+ DictTabInfo::Table *tableDesc;
SimpleProperties::UnpackStatus s;
- s = SimpleProperties::unpack(it, &tableDesc,
+ DBUG_ENTER("NdbDictInterface::parseTableInfo");
+
+ tableDesc = (DictTabInfo::Table*)NdbMem_Allocate(sizeof(DictTabInfo::Table));
+ if (!tableDesc)
+ {
+ DBUG_RETURN(4000);
+ }
+ tableDesc->init();
+ s = SimpleProperties::unpack(it, tableDesc,
DictTabInfo::TableMapping,
DictTabInfo::TableMappingSize,
true, true);
if(s != SimpleProperties::Break){
+ NdbMem_Free((void*)tableDesc);
DBUG_RETURN(703);
}
- const char * internalName = tableDesc.TableName;
+ const char * internalName = tableDesc->TableName;
const char * externalName = Ndb::externalizeTableName(internalName,
fullyQualifiedNames);
NdbTableImpl * impl = new NdbTableImpl();
- impl->m_tableId = tableDesc.TableId;
- impl->m_version = tableDesc.TableVersion;
+ impl->m_id = tableDesc->TableId;
+ impl->m_version = tableDesc->TableVersion;
impl->m_status = NdbDictionary::Object::Retrieved;
impl->m_internalName.assign(internalName);
+ impl->updateMysqlName();
impl->m_externalName.assign(externalName);
- impl->m_frm.assign(tableDesc.FrmData, tableDesc.FrmLen);
+ impl->m_frm.assign(tableDesc->FrmData, tableDesc->FrmLen);
+ impl->m_fd.assign(tableDesc->FragmentData, tableDesc->FragmentDataLen);
+ impl->m_range.assign(tableDesc->RangeListData, tableDesc->RangeListDataLen);
+ impl->m_fragmentCount = tableDesc->FragmentCount;
+
+ /*
+ We specifically don't get tablespace data and range/list arrays here
+ since those are known by the MySQL Server through analysing the
+ frm file.
+ Fragment Data contains the real node group mapping and the fragment
+ identities used for each fragment. At the moment we have no need for
+ this.
+ Frm file is needed for autodiscovery.
+ */
impl->m_fragmentType = (NdbDictionary::Object::FragmentType)
- getApiConstant(tableDesc.FragmentType,
+ getApiConstant(tableDesc->FragmentType,
fragmentTypeMapping,
(Uint32)NdbDictionary::Object::FragUndefined);
- impl->m_logging = tableDesc.TableLoggedFlag;
- impl->m_kvalue = tableDesc.TableKValue;
- impl->m_minLoadFactor = tableDesc.MinLoadFactor;
- impl->m_maxLoadFactor = tableDesc.MaxLoadFactor;
+ Uint64 max_rows = ((Uint64)tableDesc->MaxRowsHigh) << 32;
+ max_rows += tableDesc->MaxRowsLow;
+ impl->m_max_rows = max_rows;
+ impl->m_default_no_part_flag = tableDesc->DefaultNoPartFlag;
+ impl->m_linear_flag = tableDesc->LinearHashFlag;
+ impl->m_logging = tableDesc->TableLoggedFlag;
+ impl->m_row_gci = tableDesc->RowGCIFlag;
+ impl->m_row_checksum = tableDesc->RowChecksumFlag;
+ impl->m_kvalue = tableDesc->TableKValue;
+ impl->m_minLoadFactor = tableDesc->MinLoadFactor;
+ impl->m_maxLoadFactor = tableDesc->MaxLoadFactor;
- impl->m_indexType = (NdbDictionary::Index::Type)
- getApiConstant(tableDesc.TableType,
+ impl->m_indexType = (NdbDictionary::Object::Type)
+ getApiConstant(tableDesc->TableType,
indexTypeMapping,
- NdbDictionary::Index::Undefined);
+ NdbDictionary::Object::TypeUndefined);
- if(impl->m_indexType == NdbDictionary::Index::Undefined){
+ if(impl->m_indexType == NdbDictionary::Object::TypeUndefined){
} else {
const char * externalPrimary =
- Ndb::externalizeTableName(tableDesc.PrimaryTable, fullyQualifiedNames);
+ Ndb::externalizeTableName(tableDesc->PrimaryTable, fullyQualifiedNames);
impl->m_primaryTable.assign(externalPrimary);
}
- Uint32 keyInfoPos = 0;
- Uint32 keyCount = 0;
- Uint32 blobCount = 0;
- Uint32 distKeys = 0;
-
Uint32 i;
- for(i = 0; i < tableDesc.NoOfAttributes; i++) {
+ for(i = 0; i < tableDesc->NoOfAttributes; i++) {
DictTabInfo::Attribute attrDesc; attrDesc.init();
s = SimpleProperties::unpack(it,
&attrDesc,
@@ -1334,6 +2045,7 @@
true, true);
if(s != SimpleProperties::Break){
delete impl;
+ NdbMem_Free((void*)tableDesc);
DBUG_RETURN(703);
}
@@ -1344,6 +2056,7 @@
// check type and compute attribute size and array size
if (! attrDesc.translateExtType()) {
delete impl;
+ NdbMem_Free((void*)tableDesc);
DBUG_RETURN(703);
}
col->m_type = (NdbDictionary::Column::Type)attrDesc.AttributeExtType;
@@ -1355,69 +2068,52 @@
// charset is defined exactly for char types
if (col->getCharType() != (cs_number != 0)) {
delete impl;
+ NdbMem_Free((void*)tableDesc);
DBUG_RETURN(703);
}
if (col->getCharType()) {
col->m_cs = get_charset(cs_number, MYF(0));
if (col->m_cs == NULL) {
delete impl;
+ NdbMem_Free((void*)tableDesc);
DBUG_RETURN(743);
}
}
col->m_attrSize = (1 << attrDesc.AttributeSize) / 8;
col->m_arraySize = attrDesc.AttributeArraySize;
+ col->m_arrayType = attrDesc.AttributeArrayType;
if(attrDesc.AttributeSize == 0)
{
col->m_attrSize = 4;
col->m_arraySize = (attrDesc.AttributeArraySize + 31) >> 5;
}
+ col->m_storageType = attrDesc.AttributeStorageType;
col->m_pk = attrDesc.AttributeKeyFlag;
- col->m_distributionKey = attrDesc.AttributeDKey;
+ col->m_distributionKey = attrDesc.AttributeDKey ? 2 : 0;
col->m_nullable = attrDesc.AttributeNullableFlag;
col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false);
col->m_autoIncrementInitialValue = ~0;
col->m_defaultValue.assign(attrDesc.AttributeDefaultValue);
- if(attrDesc.AttributeKeyFlag){
- col->m_keyInfoPos = keyInfoPos + 1;
- keyInfoPos += ((col->m_attrSize * col->m_arraySize + 3) / 4);
- keyCount++;
-
- if(attrDesc.AttributeDKey)
- distKeys++;
- } else {
- col->m_keyInfoPos = 0;
- }
- if (col->getBlobType())
- blobCount++;
- NdbColumnImpl * null = 0;
- impl->m_columns.fill(attrDesc.AttributeId, null);
- if(impl->m_columns[attrDesc.AttributeId] != 0){
- delete col;
- delete impl;
- DBUG_RETURN(703);
- }
- impl->m_columns[attrDesc.AttributeId] = col;
+ col->m_column_no = impl->m_columns.size();
+ impl->m_columns.push_back(col);
it.next();
}
- impl->m_noOfKeys = keyCount;
- impl->m_keyLenInWords = keyInfoPos;
- impl->m_noOfBlobs = blobCount;
- impl->m_noOfDistributionKeys = distKeys;
+ impl->computeAggregates();
- if(tableDesc.FragmentDataLen > 0)
+ if(tableDesc->ReplicaDataLen > 0)
{
- Uint32 replicaCount = tableDesc.FragmentData[0];
- Uint32 fragCount = tableDesc.FragmentData[1];
+ Uint16 replicaCount = ntohs(tableDesc->ReplicaData[0]);
+ Uint16 fragCount = ntohs(tableDesc->ReplicaData[1]);
impl->m_replicaCount = replicaCount;
impl->m_fragmentCount = fragCount;
-
- for(i = 0; i<(fragCount*replicaCount); i++)
+ DBUG_PRINT("info", ("replicaCount=%x , fragCount=%x",replicaCount,fragCount));
+ for(i = 0; i < (Uint32) (fragCount*replicaCount); i++)
{
- impl->m_fragments.push_back(tableDesc.FragmentData[i+2]);
+ impl->m_fragments.push_back(ntohs(tableDesc->ReplicaData[i+2]));
}
Uint32 topBit = (1 << 31);
@@ -1429,23 +2125,26 @@
}
else
{
- impl->m_fragmentCount = tableDesc.FragmentCount;
+ impl->m_fragmentCount = tableDesc->FragmentCount;
impl->m_replicaCount = 0;
impl->m_hashValueMask = 0;
impl->m_hashpointerValue = 0;
}
- if(distKeys == 0)
- {
- for(i = 0; i < tableDesc.NoOfAttributes; i++)
- {
- if(impl->m_columns[i]->getPrimaryKey())
- impl->m_columns[i]->m_distributionKey = true;
- }
- }
+ impl->m_tablespace_id = tableDesc->TablespaceId;
+ impl->m_tablespace_version = tableDesc->TablespaceVersion;
* ret = impl;
+ NdbMem_Free((void*)tableDesc);
+ if (version < MAKE_VERSION(5,1,3))
+ {
+ ;
+ }
+ else
+ {
+ DBUG_ASSERT(impl->m_fragmentCount > 0);
+ }
DBUG_RETURN(0);
}
@@ -1455,79 +2154,105 @@
int
NdbDictionaryImpl::createTable(NdbTableImpl &t)
{
+ DBUG_ENTER("NdbDictionaryImpl::createTable");
+
+ // if the new name has not been set, use the copied name
+ if (t.m_newExternalName.empty())
+ t.m_newExternalName.assign(t.m_externalName);
+
+ // create table
if (m_receiver.createTable(m_ndb, t) != 0)
- return -1;
- if (t.m_noOfBlobs == 0)
- return 0;
- // update table def from DICT
- Ndb_local_table_info *info=
- get_local_table_info(t.m_internalName,false);
- if (info == NULL) {
- m_error.code= 709;
- return -1;
+ DBUG_RETURN(-1);
+ Uint32* data = (Uint32*)m_receiver.m_buffer.get_data();
+ t.m_id = data[0];
+ t.m_version = data[1];
+
+ // update table def from DICT - by-pass cache
+ NdbTableImpl* t2 =
+ m_receiver.getTable(t.m_internalName, m_ndb.usingFullyQualifiedNames());
+
+ // check if we got back same table
+ if (t2 == NULL) {
+ DBUG_PRINT("info", ("table %s dropped by another thread",
+ t.m_internalName.c_str()));
+ m_error.code = 283;
+ DBUG_RETURN(-1);
+ }
+ if (t.m_id != t2->m_id || t.m_version != t2->m_version) {
+ DBUG_PRINT("info", ("table %s re-created by another thread",
+ t.m_internalName.c_str()));
+ m_error.code = 283;
+ delete t2;
+ DBUG_RETURN(-1);
+ }
+
+ // auto-increment - use "t" because initial value is not in DICT
+ {
+ bool autoIncrement = false;
+ Uint64 initialValue = 0;
+ for (Uint32 i = 0; i < t.m_columns.size(); i++) {
+ const NdbColumnImpl* c = t.m_columns[i];
+ assert(c != NULL);
+ if (c->m_autoIncrement) {
+ if (autoIncrement) {
+ m_error.code = 4335;
+ delete t2;
+ DBUG_RETURN(-1);
+ }
+ autoIncrement = true;
+ initialValue = c->m_autoIncrementInitialValue;
+ }
+ }
+ if (autoIncrement) {
+ // XXX unlikely race condition - t.m_id may no longer be same table
+ if (! m_ndb.setTupleIdInNdb(t.m_id, initialValue, false)) {
+ if (m_ndb.theError.code)
+ m_error.code = m_ndb.theError.code;
+ else
+ m_error.code = 4336;
+ delete t2;
+ DBUG_RETURN(-1);
+ }
+ }
}
- if (createBlobTables(*(info->m_table_impl)) != 0) {
+
+ // blob tables - use "t2" to get values set by kernel
+ if (t2->m_noOfBlobs != 0 && createBlobTables(*t2) != 0) {
int save_code = m_error.code;
- (void)dropTable(t);
- m_error.code= save_code;
- return -1;
+ (void)dropTable(*t2);
+ m_error.code = save_code;
+ delete t2;
+ DBUG_RETURN(-1);
}
- return 0;
+
+ // not entered in cache
+ delete t2;
+ DBUG_RETURN(0);
}
int
NdbDictionaryImpl::createBlobTables(NdbTableImpl &t)
{
+ DBUG_ENTER("NdbDictionaryImpl::createBlobTables");
for (unsigned i = 0; i < t.m_columns.size(); i++) {
NdbColumnImpl & c = *t.m_columns[i];
if (! c.getBlobType() || c.getPartSize() == 0)
continue;
NdbTableImpl bt;
NdbBlob::getBlobTable(bt, &t, &c);
- if (createTable(bt) != 0)
- return -1;
- // Save BLOB table handle
- Ndb_local_table_info *info=
- get_local_table_info(bt.m_internalName, false);
- if (info == 0) {
- return -1;
- }
- c.m_blobTable = info->m_table_impl;
- }
-
- return 0;
-}
-
-int
-NdbDictionaryImpl::addBlobTables(NdbTableImpl &t)
-{
- unsigned n= t.m_noOfBlobs;
- // optimized for blob column being the last one
- // and not looking for more than one if not neccessary
- for (unsigned i = t.m_columns.size(); i > 0 && n > 0;) {
- i--;
- NdbColumnImpl & c = *t.m_columns[i];
- if (! c.getBlobType() || c.getPartSize() == 0)
- continue;
- n--;
- char btname[NdbBlobImpl::BlobTableNameSize];
- NdbBlob::getBlobTableName(btname, &t, &c);
- // Save BLOB table handle
- NdbTableImpl * cachedBlobTable = getTable(btname);
- if (cachedBlobTable == 0) {
- return -1;
+ if (createTable(bt) != 0) {
+ DBUG_RETURN(-1);
}
- c.m_blobTable = cachedBlobTable;
}
-
- return 0;
+ DBUG_RETURN(0);
}
int
NdbDictInterface::createTable(Ndb & ndb,
NdbTableImpl & impl)
{
- return createOrAlterTable(ndb, impl, false);
+ DBUG_ENTER("NdbDictInterface::createTable");
+ DBUG_RETURN(createOrAlterTable(ndb, impl, false));
}
int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
@@ -1537,30 +2262,43 @@
DBUG_ENTER("NdbDictionaryImpl::alterTable");
Ndb_local_table_info * local = 0;
- if((local= get_local_table_info(originalInternalName, false)) == 0)
+ if((local= get_local_table_info(originalInternalName)) == 0)
{
m_error.code = 709;
DBUG_RETURN(-1);
}
// Alter the table
- int ret = m_receiver.alterTable(m_ndb, impl);
- if(ret == 0){
- // Remove cached information and let it be refreshed at next access
+ int ret = alterTableGlobal(*local->m_table_impl, impl);
+ if(ret == 0)
+ {
m_globalHash->lock();
- local->m_table_impl->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(local->m_table_impl);
+ m_globalHash->release(local->m_table_impl, 1);
m_globalHash->unlock();
m_localHash.drop(originalInternalName);
}
DBUG_RETURN(ret);
}
+int NdbDictionaryImpl::alterTableGlobal(NdbTableImpl &old_impl,
+ NdbTableImpl &impl)
+{
+ DBUG_ENTER("NdbDictionaryImpl::alterTableGlobal");
+ // Alter the table
+ int ret = m_receiver.alterTable(m_ndb, impl);
+ old_impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0){
+ DBUG_RETURN(ret);
+ }
+ ERR_RETURN(getNdbError(), ret);
+}
+
int
NdbDictInterface::alterTable(Ndb & ndb,
NdbTableImpl & impl)
{
- return createOrAlterTable(ndb, impl, true);
+ DBUG_ENTER("NdbDictInterface::alterTable");
+ DBUG_RETURN(createOrAlterTable(ndb, impl, true));
}
int
@@ -1568,8 +2306,12 @@
NdbTableImpl & impl,
bool alter)
{
- DBUG_ENTER("NdbDictInterface::createOrAlterTable");
unsigned i, err;
+ char *ts_names[MAX_NDB_PARTITIONS];
+ DBUG_ENTER("NdbDictInterface::createOrAlterTable");
+
+ impl.computeAggregates();
+
if((unsigned)impl.getNoOfPrimaryKeys() > NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY){
m_error.code= 4317;
DBUG_RETURN(-1);
@@ -1579,73 +2321,245 @@
m_error.code= 4318;
DBUG_RETURN(-1);
}
-
+
+ // Check if any changes for alter table
+
+ // Name change
if (!impl.m_newExternalName.empty()) {
+ if (alter)
+ {
+ AlterTableReq::setNameFlag(impl.m_changeMask, true);
+ }
impl.m_externalName.assign(impl.m_newExternalName);
- AlterTableReq::setNameFlag(impl.m_changeMask, true);
+ impl.m_newExternalName.clear();
+ }
+ // Definition change (frm)
+ if (!impl.m_newFrm.empty())
+ {
+ if (alter)
+ {
+ AlterTableReq::setFrmFlag(impl.m_changeMask, true);
+ }
+ impl.m_frm.assign(impl.m_newFrm.get_data(), impl.m_newFrm.length());
+ impl.m_newFrm.clear();
+ }
+ // Change FragmentData (fragment identity, state, tablespace id)
+ if (!impl.m_new_fd.empty())
+ {
+ if (alter)
+ {
+ AlterTableReq::setFragDataFlag(impl.m_changeMask, true);
+ }
+ impl.m_fd.assign(impl.m_new_fd.get_data(), impl.m_new_fd.length());
+ impl.m_new_fd.clear();
+ }
+ // Change Tablespace Name Data
+ if (!impl.m_new_ts_name.empty())
+ {
+ if (alter)
+ {
+ AlterTableReq::setTsNameFlag(impl.m_changeMask, true);
+ }
+ impl.m_ts_name.assign(impl.m_new_ts_name.get_data(),
+ impl.m_new_ts_name.length());
+ impl.m_new_ts_name.clear();
+ }
+ // Change Range/List Data
+ if (!impl.m_new_range.empty())
+ {
+ if (alter)
+ {
+ AlterTableReq::setRangeListFlag(impl.m_changeMask, true);
+ }
+ impl.m_range.assign(impl.m_new_range.get_data(),
+ impl.m_new_range.length());
+ impl.m_new_range.clear();
+ }
+ // Change Tablespace Data
+ if (!impl.m_new_ts.empty())
+ {
+ if (alter)
+ {
+ AlterTableReq::setTsFlag(impl.m_changeMask, true);
+ }
+ impl.m_ts.assign(impl.m_new_ts.get_data(),
+ impl.m_new_ts.length());
+ impl.m_new_ts.clear();
}
+
+ /*
+ TODO RONM: Here I need to insert checks for fragment array and
+ range or list array
+ */
+
//validate();
//aggregate();
const BaseString internalName(
ndb.internalize_table_name(impl.m_externalName.c_str()));
impl.m_internalName.assign(internalName);
- UtilBufferWriter w(m_buffer);
- DictTabInfo::Table tmpTab; tmpTab.init();
- BaseString::snprintf(tmpTab.TableName,
- sizeof(tmpTab.TableName),
+ impl.updateMysqlName();
+ DictTabInfo::Table *tmpTab;
+
+ tmpTab = (DictTabInfo::Table*)NdbMem_Allocate(sizeof(DictTabInfo::Table));
+ if (!tmpTab)
+ {
+ m_error.code = 4000;
+ DBUG_RETURN(-1);
+ }
+ tmpTab->init();
+ BaseString::snprintf(tmpTab->TableName,
+ sizeof(tmpTab->TableName),
internalName.c_str());
- bool haveAutoIncrement = false;
- Uint64 autoIncrementValue = 0;
Uint32 distKeys= 0;
- for(i = 0; i<sz; i++){
+ for(i = 0; i<sz; i++) {
const NdbColumnImpl * col = impl.m_columns[i];
- if(col == 0)
- continue;
- if (col->m_autoIncrement) {
- if (haveAutoIncrement) {
- m_error.code= 4335;
- DBUG_RETURN(-1);
- }
- haveAutoIncrement = true;
- autoIncrementValue = col->m_autoIncrementInitialValue;
+ if (col == NULL) {
+ m_error.code = 4272;
+ NdbMem_Free((void*)tmpTab);
+ DBUG_RETURN(-1);
}
if (col->m_distributionKey)
+ {
distKeys++;
+ }
}
+ if (distKeys == impl.m_noOfKeys)
+ distKeys= 0;
+ impl.m_noOfDistributionKeys= distKeys;
+
// Check max length of frm data
if (impl.m_frm.length() > MAX_FRM_DATA_SIZE){
m_error.code= 1229;
+ NdbMem_Free((void*)tmpTab);
DBUG_RETURN(-1);
}
- tmpTab.FrmLen = impl.m_frm.length();
- memcpy(tmpTab.FrmData, impl.m_frm.get_data(), impl.m_frm.length());
+ /*
+ TODO RONM: This needs to change to dynamic arrays instead
+ Frm Data, FragmentData, TablespaceData, RangeListData, TsNameData
+ */
+ tmpTab->FrmLen = impl.m_frm.length();
+ memcpy(tmpTab->FrmData, impl.m_frm.get_data(), impl.m_frm.length());
+
+ tmpTab->FragmentDataLen = impl.m_fd.length();
+ memcpy(tmpTab->FragmentData, impl.m_fd.get_data(), impl.m_fd.length());
+
+ tmpTab->TablespaceDataLen = impl.m_ts.length();
+ memcpy(tmpTab->TablespaceData, impl.m_ts.get_data(), impl.m_ts.length());
+
+ tmpTab->RangeListDataLen = impl.m_range.length();
+ memcpy(tmpTab->RangeListData, impl.m_range.get_data(),
+ impl.m_range.length());
+
+ memcpy(ts_names, impl.m_ts_name.get_data(),
+ impl.m_ts_name.length());
+
+ tmpTab->FragmentCount= impl.m_fragmentCount;
+ tmpTab->TableLoggedFlag = impl.m_logging;
+ tmpTab->RowGCIFlag = impl.m_row_gci;
+ tmpTab->RowChecksumFlag = impl.m_row_checksum;
+ tmpTab->TableKValue = impl.m_kvalue;
+ tmpTab->MinLoadFactor = impl.m_minLoadFactor;
+ tmpTab->MaxLoadFactor = impl.m_maxLoadFactor;
+ tmpTab->TableType = DictTabInfo::UserTable;
+ tmpTab->PrimaryTableId = impl.m_primaryTableId;
+ tmpTab->NoOfAttributes = sz;
+ tmpTab->MaxRowsHigh = (Uint32)(impl.m_max_rows >> 32);
+ tmpTab->MaxRowsLow = (Uint32)(impl.m_max_rows & 0xFFFFFFFF);
+ tmpTab->DefaultNoPartFlag = impl.m_default_no_part_flag;
+ tmpTab->LinearHashFlag = impl.m_linear_flag;
- tmpTab.TableLoggedFlag = impl.m_logging;
- tmpTab.TableKValue = impl.m_kvalue;
- tmpTab.MinLoadFactor = impl.m_minLoadFactor;
- tmpTab.MaxLoadFactor = impl.m_maxLoadFactor;
- tmpTab.TableType = DictTabInfo::UserTable;
- tmpTab.NoOfAttributes = sz;
-
- tmpTab.FragmentType = getKernelConstant(impl.m_fragmentType,
- fragmentTypeMapping,
- DictTabInfo::AllNodesSmallTable);
- tmpTab.TableVersion = rand();
+ if (impl.m_ts_name.length())
+ {
+ char **ts_name_ptr= (char**)ts_names;
+ i= 0;
+ do
+ {
+ NdbTablespaceImpl tmp;
+ if (*ts_name_ptr)
+ {
+ if(get_filegroup(tmp, NdbDictionary::Object::Tablespace,
+ (const char*)*ts_name_ptr) == 0)
+ {
+ tmpTab->TablespaceData[2*i] = tmp.m_id;
+ tmpTab->TablespaceData[2*i + 1] = tmp.m_version;
+ }
+ else
+ {
+ NdbMem_Free((void*)tmpTab);
+ DBUG_RETURN(-1);
+ }
+ }
+ else
+ {
+ /*
+ No tablespace used, set tablespace id to NULL
+ */
+ tmpTab->TablespaceData[2*i] = RNIL;
+ tmpTab->TablespaceData[2*i + 1] = 0;
+ }
+ ts_name_ptr++;
+ } while (++i < tmpTab->FragmentCount);
+ tmpTab->TablespaceDataLen= 4*i;
+ }
+ tmpTab->FragmentType = getKernelConstant(impl.m_fragmentType,
+ fragmentTypeMapping,
+ DictTabInfo::AllNodesSmallTable);
+ tmpTab->TableVersion = rand();
+
+ const char *tablespace_name= impl.m_tablespace_name.c_str();
+loop:
+ if(impl.m_tablespace_id != ~(Uint32)0)
+ {
+ tmpTab->TablespaceId = impl.m_tablespace_id;
+ tmpTab->TablespaceVersion = impl.m_tablespace_version;
+ }
+ else if(strlen(tablespace_name))
+ {
+ NdbTablespaceImpl tmp;
+ if(get_filegroup(tmp, NdbDictionary::Object::Tablespace,
+ tablespace_name) == 0)
+ {
+ tmpTab->TablespaceId = tmp.m_id;
+ tmpTab->TablespaceVersion = tmp.m_version;
+ }
+ else
+ {
+ // error set by get filegroup
+ NdbMem_Free((void*)tmpTab);
+ DBUG_RETURN(-1);
+ }
+ }
+ else
+ {
+ for(i = 0; i<sz; i++)
+ {
+ if(impl.m_columns[i]->m_storageType == NDB_STORAGETYPE_DISK)
+ {
+ tablespace_name = "DEFAULT-TS";
+ goto loop;
+ }
+ }
+ }
+
+ UtilBufferWriter w(m_buffer);
SimpleProperties::UnpackStatus s;
s = SimpleProperties::pack(w,
- &tmpTab,
+ tmpTab,
DictTabInfo::TableMapping,
DictTabInfo::TableMappingSize, true);
if(s != SimpleProperties::Eof){
abort();
}
+ NdbMem_Free((void*)tmpTab);
+ DBUG_PRINT("info",("impl.m_noOfDistributionKeys: %d impl.m_noOfKeys: %d distKeys: %d",
+ impl.m_noOfDistributionKeys, impl.m_noOfKeys, distKeys));
if (distKeys == impl.m_noOfKeys)
distKeys= 0;
impl.m_noOfDistributionKeys= distKeys;
@@ -1655,19 +2569,33 @@
if(col == 0)
continue;
+ DBUG_PRINT("info",("column: %s(%d) col->m_distributionKey: %d",
+ col->m_name.c_str(), i, col->m_distributionKey));
DictTabInfo::Attribute tmpAttr; tmpAttr.init();
BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
col->m_name.c_str());
- tmpAttr.AttributeId = i;
+ tmpAttr.AttributeId = col->m_attrId;
tmpAttr.AttributeKeyFlag = col->m_pk;
tmpAttr.AttributeNullableFlag = col->m_nullable;
- tmpAttr.AttributeDKey = distKeys ? col->m_distributionKey : 0;
+ tmpAttr.AttributeDKey = distKeys ? (bool)col->m_distributionKey : 0;
tmpAttr.AttributeExtType = (Uint32)col->m_type;
tmpAttr.AttributeExtPrecision = ((unsigned)col->m_precision & 0xFFFF);
tmpAttr.AttributeExtScale = col->m_scale;
tmpAttr.AttributeExtLength = col->m_length;
+ if(col->m_storageType == NDB_STORAGETYPE_DISK)
+ tmpAttr.AttributeArrayType = NDB_ARRAYTYPE_FIXED;
+ else
+ tmpAttr.AttributeArrayType = col->m_arrayType;
+
+ if(col->m_pk)
+ tmpAttr.AttributeStorageType = NDB_STORAGETYPE_MEMORY;
+ else
+ tmpAttr.AttributeStorageType = col->m_storageType;
+ if(col->getBlobType())
+ tmpAttr.AttributeStorageType = NDB_STORAGETYPE_MEMORY;
+
// check type and compute attribute size and array size
if (! tmpAttr.translateExtType()) {
m_error.code= 703;
@@ -1687,8 +2615,14 @@
}
// distribution key not supported for Char attribute
if (distKeys && col->m_distributionKey && col->m_cs != NULL) {
- m_error.code= 745;
- DBUG_RETURN(-1);
+ // we can allow this for non-var char where strxfrm does nothing
+ if (col->m_type == NdbDictionary::Column::Char &&
+ (col->m_cs->state & MY_CS_BINSORT))
+ ;
+ else {
+ m_error.code= 745;
+ DBUG_RETURN(-1);
+ }
}
// charset in upper half of precision
if (col->getCharType()) {
@@ -1706,137 +2640,89 @@
w.add(DictTabInfo::AttributeEnd, 1);
}
- NdbApiSignal tSignal(m_reference);
- tSignal.theReceiversBlockNumber = DBDICT;
+ int ret;
LinearSectionPtr ptr[1];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = m_buffer.length() / 4;
- int ret;
- if (alter)
- {
- AlterTableReq * const req =
- CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ if (alter) {
+ tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ;
+ tSignal.theLength = AlterTableReq::SignalLength;
+
+ AlterTableReq * req = CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
req->changeMask = impl.m_changeMask;
- req->tableId = impl.m_tableId;
+ req->tableId = impl.m_id;
req->tableVersion = impl.m_version;;
- tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ;
- tSignal.theLength = AlterTableReq::SignalLength;
- ret= alterTable(&tSignal, ptr);
- }
- else
- {
- CreateTableReq * const req =
- CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
+
+ int errCodes[] = { AlterTableRef::NotMaster, AlterTableRef::Busy, 0 };
+ ret = dictSignal(&tSignal, ptr, 1,
+ 0, // master
+ WAIT_ALTER_TAB_REQ,
+ DICT_WAITFOR_TIMEOUT, 100,
+ errCodes);
- req->senderRef = m_reference;
- req->senderData = 0;
+ if(m_error.code == AlterTableRef::InvalidTableVersion) {
+ // Clear caches and try again
+ DBUG_RETURN(INCOMPATIBLE_VERSION);
+ }
+ } else {
tSignal.theVerId_signalNumber = GSN_CREATE_TABLE_REQ;
tSignal.theLength = CreateTableReq::SignalLength;
- ret= createTable(&tSignal, ptr);
-
- if (ret)
- DBUG_RETURN(ret);
- if (haveAutoIncrement) {
- if (ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
- autoIncrementValue) == ~(Uint64)0) {
- DBUG_ASSERT(ndb.theError.code != 0);
- m_error= ndb.theError;
- ret = -1;
- }
- }
+ CreateTableReq * req = CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ int errCodes[] = { CreateTableRef::Busy, CreateTableRef::NotMaster, 0 };
+ ret = dictSignal(&tSignal, ptr, 1,
+ 0, // master node
+ WAIT_CREATE_INDX_REQ,
+ DICT_WAITFOR_TIMEOUT, 100,
+ errCodes);
}
+
DBUG_RETURN(ret);
}
-int
-NdbDictInterface::createTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
-{
-#if DEBUG_PRINT
- ndbout_c("BufferLen = %d", ptr[0].sz);
- SimplePropertiesLinearReader r(ptr[0].p, ptr[0].sz);
- r.printAll(ndbout);
-#endif
- const int noErrCodes = 2;
- int errCodes[noErrCodes] =
- {CreateTableRef::Busy,
- CreateTableRef::NotMaster};
- return dictSignal(signal,ptr,1,
- 1/*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes,noErrCodes);
-}
-
-
void
NdbDictInterface::execCREATE_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
-#if 0
const CreateTableConf* const conf=
CAST_CONSTPTR(CreateTableConf, signal->getDataPtr());
- Uint32 tableId= conf->tableId;
- Uint32 tableVersion= conf->tableVersion;
-#endif
+ m_buffer.grow(4 * 2); // 2 words
+ Uint32* data = (Uint32*)m_buffer.get_data();
+ data[0] = conf->tableId;
+ data[1] = conf->tableVersion;
m_waiter.signal(NO_WAIT);
}
void
-NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * signal,
+NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * sig,
LinearSectionPtr ptr[3])
{
- const CreateTableRef* const ref=
- CAST_CONSTPTR(CreateTableRef, signal->getDataPtr());
+ const CreateTableRef* ref = CAST_CONSTPTR(CreateTableRef, sig->getDataPtr());
m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
}
-int
-NdbDictInterface::alterTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
-{
-#if DEBUG_PRINT
- ndbout_c("BufferLen = %d", ptr[0].sz);
- SimplePropertiesLinearReader r(ptr[0].p, ptr[0].sz);
- r.printAll(ndbout);
-#endif
- const int noErrCodes = 2;
- int errCodes[noErrCodes] =
- {AlterTableRef::NotMaster,
- AlterTableRef::Busy};
- int r = dictSignal(signal,ptr,1,
- 1/*use masternode id*/,
- 100,WAIT_ALTER_TAB_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes, noErrCodes);
- if(m_error.code == AlterTableRef::InvalidTableVersion) {
- // Clear caches and try again
- return INCOMPATIBLE_VERSION;
- }
-
- return r;
-}
-
void
NdbDictInterface::execALTER_TABLE_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- //AlterTableConf* const conf = CAST_CONSTPTR(AlterTableConf, signal->getDataPtr());
m_waiter.signal(NO_WAIT);
}
void
-NdbDictInterface::execALTER_TABLE_REF(NdbApiSignal * signal,
+NdbDictInterface::execALTER_TABLE_REF(NdbApiSignal * sig,
LinearSectionPtr ptr[3])
{
- const AlterTableRef * const ref =
- CAST_CONSTPTR(AlterTableRef, signal->getDataPtr());
+ const AlterTableRef * ref = CAST_CONSTPTR(AlterTableRef, sig->getDataPtr());
m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
@@ -1850,6 +2736,7 @@
{
DBUG_ENTER("NdbDictionaryImpl::dropTable");
DBUG_PRINT("enter",("name: %s", name));
+ ASSERT_NOT_MYSQLD;
NdbTableImpl * tab = getTable(name);
if(tab == 0){
DBUG_RETURN(-1);
@@ -1859,16 +2746,14 @@
// we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) {
const BaseString internalTableName(m_ndb.internalize_table_name(name));
-
DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s",
internalTableName.c_str()));
m_localHash.drop(internalTableName.c_str());
m_globalHash->lock();
- tab->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(tab);
+ m_globalHash->release(tab, 1);
m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
}
-
+
DBUG_RETURN(ret);
}
@@ -1881,13 +2766,14 @@
return dropTable(name);
}
- if (impl.m_indexType != NdbDictionary::Index::Undefined) {
+ if (impl.m_indexType != NdbDictionary::Object::TypeUndefined)
+ {
m_receiver.m_error.code= 1228;
return -1;
}
List list;
- if ((res = listIndexes(list, impl.m_tableId)) == -1){
+ if ((res = listIndexes(list, impl.m_id)) == -1){
return -1;
}
for (unsigned i = 0; i < list.count; i++) {
@@ -1905,14 +2791,13 @@
}
int ret = m_receiver.dropTable(impl);
- if(ret == 0 || m_error.code == 709){
+ if(ret == 0 || m_error.code == 709 || m_error.code == 723){
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->release(&impl, 1);
m_globalHash->unlock();
return 0;
@@ -1922,6 +2807,50 @@
}
int
+NdbDictionaryImpl::dropTableGlobal(NdbTableImpl & impl)
+{
+ int res;
+ const char * name = impl.getName();
+ DBUG_ENTER("NdbDictionaryImpl::dropTableGlobal");
+ DBUG_ASSERT(impl.m_status != NdbDictionary::Object::New);
+ DBUG_ASSERT(impl.m_indexType == NdbDictionary::Object::TypeUndefined);
+
+ List list;
+ if ((res = listIndexes(list, impl.m_id)) == -1){
+ ERR_RETURN(getNdbError(), -1);
+ }
+ for (unsigned i = 0; i < list.count; i++) {
+ const List::Element& element = list.elements[i];
+ NdbIndexImpl *idx= getIndexGlobal(element.name, impl);
+ if (idx == NULL)
+ {
+ ERR_RETURN(getNdbError(), -1);
+ }
+ if ((res = dropIndexGlobal(*idx)) == -1)
+ {
+ releaseIndexGlobal(*idx, 1);
+ ERR_RETURN(getNdbError(), -1);
+ }
+ releaseIndexGlobal(*idx, 1);
+ }
+
+ if (impl.m_noOfBlobs != 0) {
+ if (dropBlobTables(impl) != 0){
+ ERR_RETURN(getNdbError(), -1);
+ }
+ }
+
+ int ret = m_receiver.dropTable(impl);
+ impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0 || m_error.code == 709 || m_error.code == 723)
+ {
+ DBUG_RETURN(0);
+ }
+
+ ERR_RETURN(getNdbError(), ret);
+}
+
+int
NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
{
DBUG_ENTER("NdbDictionaryImpl::dropBlobTables");
@@ -1929,15 +2858,21 @@
NdbColumnImpl & c = *t.m_columns[i];
if (! c.getBlobType() || c.getPartSize() == 0)
continue;
- char btname[NdbBlobImpl::BlobTableNameSize];
- NdbBlob::getBlobTableName(btname, &t, &c);
- if (dropTable(btname) != 0) {
- if (m_error.code != 709){
- DBUG_PRINT("exit",("error %u - exiting",m_error.code));
- DBUG_RETURN(-1);
- }
- DBUG_PRINT("info",("error %u - continuing",m_error.code));
+ NdbTableImpl* bt = c.m_blobTable;
+ if (bt == NULL) {
+ DBUG_PRINT("info", ("col %s: blob table pointer is NULL",
+ c.m_name.c_str()));
+ continue; // "force" mode on
+ }
+ // drop directly - by-pass cache
+ int ret = m_receiver.dropTable(*c.m_blobTable);
+ if (ret != 0) {
+ DBUG_PRINT("info", ("col %s: blob table %s: error %d",
+ c.m_name.c_str(), bt->m_internalName.c_str(), m_error.code));
+ if (! (ret == 709 || ret == 723)) // "force" mode on
+ ERR_RETURN(getNdbError(), -1);
}
+ // leave c.m_blobTable defined
}
DBUG_RETURN(0);
}
@@ -1950,28 +2885,21 @@
tSignal.theVerId_signalNumber = GSN_DROP_TABLE_REQ;
tSignal.theLength = DropTableReq::SignalLength;
- DropTableReq * const req = CAST_PTR(DropTableReq, tSignal.getDataPtrSend());
+ DropTableReq * req = CAST_PTR(DropTableReq, tSignal.getDataPtrSend());
req->senderRef = m_reference;
req->senderData = 0;
- req->tableId = impl.m_tableId;
+ req->tableId = impl.m_id;
req->tableVersion = impl.m_version;
- return dropTable(&tSignal, 0);
-}
-
-int
-NdbDictInterface::dropTable(NdbApiSignal* signal, LinearSectionPtr ptr[3])
-{
- const int noErrCodes = 3;
- int errCodes[noErrCodes] =
- {DropTableRef::NoDropTableRecordAvailable,
- DropTableRef::NotMaster,
- DropTableRef::Busy};
- int r = dictSignal(signal,NULL,0,
- 1/*use masternode id*/,
- 100,WAIT_DROP_TAB_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes, noErrCodes);
+ int errCodes[] =
+ { DropTableRef::NoDropTableRecordAvailable,
+ DropTableRef::NotMaster,
+ DropTableRef::Busy, 0 };
+ int r = dictSignal(&tSignal, 0, 0,
+ 0, // master
+ WAIT_DROP_TAB_REQ,
+ DICT_WAITFOR_TIMEOUT, 100,
+ errCodes);
if(m_error.code == DropTableRef::InvalidTableVersion) {
// Clear caches and try again
return INCOMPATIBLE_VERSION;
@@ -1995,7 +2923,7 @@
LinearSectionPtr ptr[3])
{
DBUG_ENTER("NdbDictInterface::execDROP_TABLE_REF");
- const DropTableRef* const ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
+ const DropTableRef* ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
m_error.code= ref->errorCode;
m_masterNodeId = ref->masterNodeId;
m_waiter.signal(NO_WAIT);
@@ -2008,10 +2936,10 @@
const char * internalTableName = impl.m_internalName.c_str();
DBUG_ENTER("NdbDictionaryImpl::invalidateObject");
DBUG_PRINT("enter", ("internal_name: %s", internalTableName));
+
m_localHash.drop(internalTableName);
m_globalHash->lock();
- impl.m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(&impl);
+ m_globalHash->release(&impl, 1);
m_globalHash->unlock();
DBUG_RETURN(0);
}
@@ -2020,12 +2948,14 @@
NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
{
const char * internalTableName = impl.m_internalName.c_str();
+ DBUG_ENTER("NdbDictionaryImpl::removeCachedObject");
+ DBUG_PRINT("enter", ("internal_name: %s", internalTableName));
m_localHash.drop(internalTableName);
m_globalHash->lock();
m_globalHash->release(&impl);
m_globalHash->unlock();
- return 0;
+ DBUG_RETURN(0);
}
/*****************************************************************
@@ -2035,15 +2965,16 @@
NdbDictionaryImpl::getIndexImpl(const char * externalName,
const BaseString& internalName)
{
- Ndb_local_table_info * info = get_local_table_info(internalName,
- false);
+ ASSERT_NOT_MYSQLD;
+ Ndb_local_table_info * info = get_local_table_info(internalName);
if(info == 0){
m_error.code = 4243;
return 0;
}
NdbTableImpl * tab = info->m_table_impl;
- if(tab->m_indexType == NdbDictionary::Index::Undefined){
+ if(tab->m_indexType == NdbDictionary::Object::TypeUndefined)
+ {
// Not an index
m_error.code = 4243;
return 0;
@@ -2055,33 +2986,48 @@
return 0;
}
+ return getIndexImpl(externalName, internalName, *tab, *prim);
+}
+
+NdbIndexImpl*
+NdbDictionaryImpl::getIndexImpl(const char * externalName,
+ const BaseString& internalName,
+ NdbTableImpl &tab,
+ NdbTableImpl &prim)
+{
+ DBUG_ENTER("NdbDictionaryImpl::getIndexImpl");
+ DBUG_ASSERT(tab.m_indexType != NdbDictionary::Object::TypeUndefined);
/**
* Create index impl
*/
NdbIndexImpl* idx;
- if(NdbDictInterface::create_index_obj_from_table(&idx, tab, prim) == 0){
- idx->m_table = tab;
+ if(NdbDictInterface::create_index_obj_from_table(&idx, &tab, &prim) == 0){
+ idx->m_table = &tab;
idx->m_externalName.assign(externalName);
idx->m_internalName.assign(internalName);
+ idx->m_table_id = prim.getObjectId();
+ idx->m_table_version = prim.getObjectVersion();
// 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;
+ DBUG_RETURN(idx);
}
- return 0;
+ DBUG_RETURN(0);
}
int
NdbDictInterface::create_index_obj_from_table(NdbIndexImpl** dst,
NdbTableImpl* tab,
- const NdbTableImpl* prim){
+ const NdbTableImpl* prim)
+{
+ DBUG_ENTER("NdbDictInterface::create_index_obj_from_table");
NdbIndexImpl *idx = new NdbIndexImpl();
idx->m_version = tab->m_version;
idx->m_status = tab->m_status;
- idx->m_indexId = tab->m_tableId;
+ idx->m_id = tab->m_id;
idx->m_externalName.assign(tab->getName());
idx->m_tableName.assign(prim->m_externalName);
- NdbDictionary::Index::Type type = idx->m_type = tab->m_indexType;
+ NdbDictionary::Object::Type type = idx->m_type = tab->m_indexType;
idx->m_logging = tab->m_logging;
// skip last attribute (NDB$PK or NDB$TNODE)
@@ -2107,7 +3053,7 @@
idx->m_key_ids[key_id] = i;
col->m_keyInfoPos = key_id;
- if(type == NdbDictionary::Index::OrderedIndex &&
+ if(type == NdbDictionary::Object::OrderedIndex &&
(primCol->m_distributionKey ||
(distKeys == 0 && primCol->getPrimaryKey())))
{
@@ -2127,7 +3073,8 @@
}
* dst = idx;
- return 0;
+ DBUG_PRINT("exit", ("m_id: %d m_version: %d", idx->m_id, idx->m_version));
+ DBUG_RETURN(0);
}
/*****************************************************************
@@ -2136,6 +3083,7 @@
int
NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
{
+ ASSERT_NOT_MYSQLD;
NdbTableImpl* tab = getTable(ix.getTable());
if(tab == 0){
m_error.code = 4249;
@@ -2145,9 +3093,15 @@
return m_receiver.createIndex(m_ndb, ix, * tab);
}
+int
+NdbDictionaryImpl::createIndex(NdbIndexImpl &ix, NdbTableImpl &tab)
+{
+ return m_receiver.createIndex(m_ndb, ix, tab);
+}
+
int
NdbDictInterface::createIndex(Ndb & ndb,
- NdbIndexImpl & impl,
+ const NdbIndexImpl & impl,
const NdbTableImpl & table)
{
//validate();
@@ -2161,8 +3115,6 @@
}
const BaseString internalName(
ndb.internalize_index_name(&table, impl.getName()));
- impl.m_internalName.assign(internalName);
-
w.add(DictTabInfo::TableName, internalName.c_str());
w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
@@ -2187,7 +3139,7 @@
}
req->setIndexType((DictTabInfo::TableType) it);
- req->setTableId(table.m_tableId);
+ req->setTableId(table.m_id);
req->setOnline(true);
AttributeList attributeList;
attributeList.sz = impl.m_columns.size();
@@ -2198,7 +3150,7 @@
m_error.code = 4247;
return -1;
}
- // Copy column definition
+ // Copy column definition XXX must be wrong, overwrites
*impl.m_columns[i] = *col;
// index key type check
@@ -2211,44 +3163,35 @@
m_error.code = err;
return -1;
}
- attributeList.id[i] = col->m_attrId;
+ // API uses external column number to talk to DICT
+ attributeList.id[i] = col->m_column_no;
}
LinearSectionPtr ptr[2];
ptr[0].p = (Uint32*)&attributeList;
ptr[0].sz = 1 + attributeList.sz;
ptr[1].p = (Uint32*)m_buffer.get_data();
ptr[1].sz = m_buffer.length() >> 2; //BUG?
- return createIndex(&tSignal, ptr);
-}
-int
-NdbDictInterface::createIndex(NdbApiSignal* signal,
- LinearSectionPtr ptr[3])
-{
- const int noErrCodes = 2;
- int errCodes[noErrCodes] = {CreateIndxRef::Busy, CreateIndxRef::NotMaster};
- return dictSignal(signal,ptr,2,
- 1 /*use masternode id*/,
- 100,
+ int errCodes[] = { CreateIndxRef::Busy, CreateIndxRef::NotMaster, 0 };
+ return dictSignal(&tSignal, ptr, 2,
+ 0, // master
WAIT_CREATE_INDX_REQ,
- -1,
- errCodes,noErrCodes);
+ DICT_WAITFOR_TIMEOUT, 100,
+ errCodes);
}
void
NdbDictInterface::execCREATE_INDX_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- //CreateTableConf* const conf = CAST_CONSTPTR(CreateTableConf,
signal->getDataPtr());
-
m_waiter.signal(NO_WAIT);
}
void
-NdbDictInterface::execCREATE_INDX_REF(NdbApiSignal * signal,
+NdbDictInterface::execCREATE_INDX_REF(NdbApiSignal * sig,
LinearSectionPtr ptr[3])
{
- const CreateIndxRef* const ref = CAST_CONSTPTR(CreateIndxRef, signal->getDataPtr());
+ const CreateIndxRef* ref = CAST_CONSTPTR(CreateIndxRef, sig->getDataPtr());
m_error.code = ref->getErrorCode();
if(m_error.code == ref->NotMaster)
m_masterNodeId= ref->masterNodeId;
@@ -2262,6 +3205,7 @@
NdbDictionaryImpl::dropIndex(const char * indexName,
const char * tableName)
{
+ ASSERT_NOT_MYSQLD;
NdbIndexImpl * idx = getIndex(indexName, tableName);
if (idx == 0) {
m_error.code = 4243;
@@ -2279,8 +3223,7 @@
m_localHash.drop(internalIndexName.c_str());
m_globalHash->lock();
- idx->m_table->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(idx->m_table);
+ m_globalHash->release(idx->m_table, 1);
m_globalHash->unlock();
return dropIndex(indexName, tableName);
}
@@ -2310,13 +3253,13 @@
return dropIndex(indexName, tableName);
}
- int ret = m_receiver.dropIndex(impl, *timpl);
- if(ret == 0){
- m_localHash.drop(internalIndexName.c_str());
+ int ret= dropIndexGlobal(impl);
+ if (ret == 0)
+ {
m_globalHash->lock();
- impl.m_table->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(impl.m_table);
+ m_globalHash->release(impl.m_table, 1);
m_globalHash->unlock();
+ m_localHash.drop(internalIndexName.c_str());
}
return ret;
}
@@ -2326,9 +3269,25 @@
}
int
+NdbDictionaryImpl::dropIndexGlobal(NdbIndexImpl & impl)
+{
+ DBUG_ENTER("NdbDictionaryImpl::dropIndexGlobal");
+ int ret = m_receiver.dropIndex(impl, *impl.m_table);
+ impl.m_status = NdbDictionary::Object::Invalid;
+ if(ret == 0)
+ {
+ DBUG_RETURN(0);
+ }
+ ERR_RETURN(getNdbError(), ret);
+}
+
+int
NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
const NdbTableImpl & timpl)
{
+ DBUG_ENTER("NdbDictInterface::dropIndex");
+ DBUG_PRINT("enter", ("indexId: %d indexVersion: %d",
+ timpl.m_id, timpl.m_version));
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_DROP_INDX_REQ;
@@ -2339,28 +3298,20 @@
req->setConnectionPtr(0);
req->setRequestType(DropIndxReq::RT_USER);
req->setTableId(~0); // DICT overwrites
- req->setIndexId(timpl.m_tableId);
+ req->setIndexId(timpl.m_id);
req->setIndexVersion(timpl.m_version);
- return dropIndex(&tSignal, 0);
-}
-
-int
-NdbDictInterface::dropIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3])
-{
- const int noErrCodes = 2;
- int errCodes[noErrCodes] = {DropIndxRef::Busy, DropIndxRef::NotMaster};
- int r = dictSignal(signal,NULL,0,
- 1/*Use masternode id*/,
- 100,
+ int errCodes[] = { DropIndxRef::Busy, DropIndxRef::NotMaster, 0 };
+ int r = dictSignal(&tSignal, 0, 0,
+ 0, // master
WAIT_DROP_INDX_REQ,
- WAITFOR_RESPONSE_TIMEOUT,
- errCodes,noErrCodes);
+ DICT_WAITFOR_TIMEOUT, 100,
+ errCodes);
if(m_error.code == DropIndxRef::InvalidIndexVersion) {
// Clear caches and try again
- return INCOMPATIBLE_VERSION;
+ ERR_RETURN(m_error, INCOMPATIBLE_VERSION);
}
- return r;
+ ERR_RETURN(m_error, r);
}
void
@@ -2374,7 +3325,7 @@
NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
{
- const DropIndxRef* const ref = CAST_CONSTPTR(DropIndxRef, signal->getDataPtr());
+ const DropIndxRef* ref = CAST_CONSTPTR(DropIndxRef, signal->getDataPtr());
m_error.code = ref->getErrorCode();
if(m_error.code == ref->NotMaster)
m_masterNodeId= ref->masterNodeId;
@@ -2388,26 +3339,24 @@
int
NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
{
+ DBUG_ENTER("NdbDictionaryImpl::createEvent");
int i;
- NdbTableImpl* tab = getTable(evnt.getTableName());
-
- if(tab == 0){
-#ifdef EVENT_DEBUG
- ndbout_c("NdbDictionaryImpl::createEvent: table not found: %s",
- evnt.getTableName());
-#endif
- return -1;
+ NdbTableImpl* tab= evnt.m_tableImpl;
+ if (tab == 0)
+ {
+ tab= getTable(evnt.getTableName());
+ if(tab == 0){
+ DBUG_PRINT("info",("NdbDictionaryImpl::createEvent: table not found: %s",
+ evnt.getTableName()));
+ ERR_RETURN(getNdbError(), -1);
+ }
+ evnt.setTable(tab);
}
- evnt.m_tableId = tab->m_tableId;
- evnt.m_tableImpl = tab;
-#ifdef EVENT_DEBUG
- ndbout_c("Event on tableId=%d", evnt.m_tableId);
-#endif
+ DBUG_PRINT("info",("Table: id: %d version: %d", tab->m_id, tab->m_version));
NdbTableImpl &table = *evnt.m_tableImpl;
-
int attributeList_sz = evnt.m_attrIds.size();
for (i = 0; i < attributeList_sz; i++) {
@@ -2418,17 +3367,19 @@
ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
evnt.getTableName());
m_error.code= 4713;
- return -1;
+ ERR_RETURN(getNdbError(), -1);
}
}
evnt.m_attrIds.clear();
attributeList_sz = evnt.m_columns.size();
-#ifdef EVENT_DEBUG
- ndbout_c("creating event %s", evnt.m_externalName.c_str());
- ndbout_c("no of columns %d", evnt.m_columns.size());
-#endif
+
+ DBUG_PRINT("info",("Event on tableId=%d, tableVersion=%d, event name %s, no of columns
%d",
+ table.m_id, table.m_version,
+ evnt.m_name.c_str(),
+ evnt.m_columns.size()));
+
int pk_count = 0;
evnt.m_attrListBitmask.clear();
@@ -2437,7 +3388,7 @@
table.getColumn(evnt.m_columns[i]->m_name.c_str());
if(col == 0){
m_error.code= 4247;
- return -1;
+ ERR_RETURN(getNdbError(), -1);
}
// Copy column definition
*evnt.m_columns[i] = *col;
@@ -2463,7 +3414,7 @@
for(i = 1; i<attributeList_sz; i++) {
if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) {
m_error.code= 4258;
- return -1;
+ ERR_RETURN(getNdbError(), -1);
}
}
@@ -2474,7 +3425,37 @@
#endif
// NdbDictInterface m_receiver;
- return m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */);
+ if (m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */) != 0)
+ ERR_RETURN(getNdbError(), -1);
+
+ // Create blob events
+ if (evnt.m_mergeEvents && createBlobEvents(evnt) != 0) {
+ int save_code = m_error.code;
+ (void)dropEvent(evnt.m_name.c_str());
+ m_error.code = save_code;
+ ERR_RETURN(getNdbError(), -1);
+ }
+ DBUG_RETURN(0);
+}
+
+int
+NdbDictionaryImpl::createBlobEvents(NdbEventImpl& evnt)
+{
+ DBUG_ENTER("NdbDictionaryImpl::createBlobEvents");
+ NdbTableImpl& t = *evnt.m_tableImpl;
+ Uint32 n = t.m_noOfBlobs;
+ Uint32 i;
+ for (i = 0; i < evnt.m_columns.size() && n > 0; i++) {
+ NdbColumnImpl & c = *evnt.m_columns[i];
+ if (! c.getBlobType() || c.getPartSize() == 0)
+ continue;
+ n--;
+ NdbEventImpl blob_evnt;
+ NdbBlob::getBlobEvent(blob_evnt, &evnt, &c);
+ if (createEvent(blob_evnt) != 0)
+ ERR_RETURN(getNdbError(), -1);
+ }
+ DBUG_RETURN(0);
}
int
@@ -2482,6 +3463,9 @@
NdbEventImpl & evnt,
int getFlag)
{
+ DBUG_ENTER("NdbDictInterface::createEvent");
+ DBUG_PRINT("enter",("getFlag=%d",getFlag));
+
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_CREATE_EVNT_REQ;
@@ -2499,22 +3483,31 @@
// getting event from Dictionary
req->setRequestType(CreateEvntReq::RT_USER_GET);
} else {
+ DBUG_PRINT("info",("tableId: %u tableVersion: %u",
+ evnt.m_tableImpl->m_id,
+ evnt.m_tableImpl->m_version));
// creating event in Dictionary
req->setRequestType(CreateEvntReq::RT_USER_CREATE);
- req->setTableId(evnt.m_tableId);
+ req->setTableId(evnt.m_tableImpl->m_id);
+ req->setTableVersion(evnt.m_tableImpl->m_version);
req->setAttrListBitmask(evnt.m_attrListBitmask);
req->setEventType(evnt.mi_type);
+ req->clearFlags();
+ if (evnt.m_rep & NdbDictionary::Event::ER_ALL)
+ req->setReportAll();
+ if (evnt.m_rep & NdbDictionary::Event::ER_SUBSCRIBE)
+ req->setReportSubscribe();
}
UtilBufferWriter w(m_buffer);
- const size_t len = strlen(evnt.m_externalName.c_str()) + 1;
+ const size_t len = strlen(evnt.m_name.c_str()) + 1;
if(len > MAX_TAB_NAME_SIZE) {
m_error.code= 4241;
- return -1;
+ ERR_RETURN(getNdbError(), -1);
}
- w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str());
+ w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
if (getFlag == 0)
{
@@ -2528,12 +3521,16 @@
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = (m_buffer.length()+3) >> 2;
- int ret = createEvent(&tSignal, ptr, 1);
+ int ret = dictSignal(&tSignal,ptr, 1,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ DICT_WAITFOR_TIMEOUT, 100,
+ 0, -1);
if (ret) {
- return ret;
+ ERR_RETURN(getNdbError(), ret);
}
-
+
char *dataPtr = (char *)m_buffer.get_data();
unsigned int lenCreateEvntConf = *((unsigned int *)dataPtr);
dataPtr += sizeof(lenCreateEvntConf);
@@ -2542,91 +3539,74 @@
// NdbEventImpl *evntImpl = (NdbEventImpl *)evntConf->getUserData();
+ evnt.m_eventId = evntConf->getEventId();
+ evnt.m_eventKey = evntConf->getEventKey();
+ evnt.m_table_id = evntConf->getTableId();
+ evnt.m_table_version = evntConf->getTableVersion();
+
if (getFlag) {
- evnt.m_tableId = evntConf->getTableId();
evnt.m_attrListBitmask = evntConf->getAttrListBitmask();
evnt.mi_type = evntConf->getEventType();
evnt.setTable(dataPtr);
} else {
- if (evnt.m_tableId != evntConf->getTableId() ||
+ if (evnt.m_tableImpl->m_id != evntConf->getTableId() ||
+ evnt.m_tableImpl->m_version != evntConf->getTableVersion() ||
//evnt.m_attrListBitmask != evntConf->getAttrListBitmask() ||
evnt.mi_type != evntConf->getEventType()) {
ndbout_c("ERROR*************");
- return 1;
+ ERR_RETURN(getNdbError(), 1);
}
}
- evnt.m_eventId = evntConf->getEventId();
- evnt.m_eventKey = evntConf->getEventKey();
-
- return ret;
-}
-
-int
-NdbDictInterface::createEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3], int noLSP)
-{
- const int noErrCodes = 1;
- int errCodes[noErrCodes] = {CreateEvntRef::Busy};
- return dictSignal(signal,ptr,noLSP,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- errCodes,noErrCodes, CreateEvntRef::Temporary);
+ DBUG_RETURN(0);
}
int
-NdbDictionaryImpl::executeSubscribeEvent(NdbEventImpl & ev)
+NdbDictionaryImpl::executeSubscribeEvent(NdbEventOperationImpl & ev_op)
{
// NdbDictInterface m_receiver;
- return m_receiver.executeSubscribeEvent(m_ndb, ev);
+ return m_receiver.executeSubscribeEvent(m_ndb, ev_op);
}
int
NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
- NdbEventImpl & evnt)
+ NdbEventOperationImpl & ev_op)
{
DBUG_ENTER("NdbDictInterface::executeSubscribeEvent");
NdbApiSignal tSignal(m_reference);
- // tSignal.theReceiversBlockNumber = SUMA;
tSignal.theReceiversBlockNumber = DBDICT;
tSignal.theVerId_signalNumber = GSN_SUB_START_REQ;
tSignal.theLength = SubStartReq::SignalLength2;
- SubStartReq * sumaStart = CAST_PTR(SubStartReq, tSignal.getDataPtrSend());
-
- sumaStart->subscriptionId = evnt.m_eventId;
- sumaStart->subscriptionKey = evnt.m_eventKey;
- sumaStart->part = SubscriptionData::TableData;
- sumaStart->subscriberData = evnt.m_bufferId & 0xFF;
- sumaStart->subscriberRef = m_reference;
+ SubStartReq * req = CAST_PTR(SubStartReq, tSignal.getDataPtrSend());
- DBUG_RETURN(executeSubscribeEvent(&tSignal, NULL));
-}
-
-int
-NdbDictInterface::executeSubscribeEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3])
-{
- return dictSignal(signal,NULL,0,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- NULL,0);
+ req->subscriptionId = ev_op.m_eventImpl->m_eventId;
+ req->subscriptionKey = ev_op.m_eventImpl->m_eventKey;
+ req->part = SubscriptionData::TableData;
+ req->subscriberData = ev_op.m_oid;
+ req->subscriberRef = m_reference;
+
+ DBUG_PRINT("info",("GSN_SUB_START_REQ subscriptionId=%d,subscriptionKey=%d,"
+ "subscriberData=%d",req->subscriptionId,
+ req->subscriptionKey,req->subscriberData));
+
+ DBUG_RETURN(dictSignal(&tSignal,NULL,0,
+ 0 /*use masternode id*/,
+ WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
+ -1, 100,
+ 0, -1));
}
int
-NdbDictionaryImpl::stopSubscribeEvent(NdbEventImpl & ev)
+NdbDictionaryImpl::stopSubscribeEvent(NdbEventOperationImpl & ev_op)
{
// NdbDictInterface m_receiver;
- return m_receiver.stopSubscribeEvent(m_ndb, ev);
+ return m_receiver.stopSubscribeEvent(m_ndb, ev_op);
}
int
NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
- NdbEventImpl & evnt)
+ NdbEventOperationImpl & ev_op)
{
DBUG_ENTER("NdbDictInterface::stopSubscribeEvent");
@@ -2636,36 +3616,34 @@
tSignal.theVerId_signalNumber = GSN_SUB_STOP_REQ;
tSignal.theLength = SubStopReq::SignalLength;
- SubStopReq * sumaStop = CAST_PTR(SubStopReq, tSignal.getDataPtrSend());
-
- sumaStop->subscriptionId = evnt.m_eventId;
- sumaStop->subscriptionKey = evnt.m_eventKey;
- sumaStop->subscriberData = evnt.m_bufferId & 0xFF;
- sumaStop->part = (Uint32) SubscriptionData::TableData;
- sumaStop->subscriberRef = m_reference;
+ SubStopReq * req = CAST_PTR(SubStopReq, tSignal.getDataPtrSend());
- DBUG_RETURN(stopSubscribeEvent(&tSignal, NULL));
-}
-
-int
-NdbDictInterface::stopSubscribeEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3])
-{
- return dictSignal(signal,NULL,0,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
- -1,
- NULL,0);
+ req->subscriptionId = ev_op.m_eventImpl->m_eventId;
+ req->subscriptionKey = ev_op.m_eventImpl->m_eventKey;
+ req->subscriberData = ev_op.m_oid;
+ req->part = (Uint32) SubscriptionData::TableData;
+ req->subscriberRef = m_reference;
+
+ DBUG_PRINT("info",("GSN_SUB_STOP_REQ subscriptionId=%d,subscriptionKey=%d,"
+ "subscriberData=%d",req->subscriptionId,
+ req->subscriptionKey,req->subscriberData));
+
+ DBUG_RETURN(dictSignal(&tSignal,NULL,0,
+ 0 /*use masternode id*/,
+ WAIT_CREATE_INDX_REQ /*WAIT_SUB_STOP__REQ*/,
+ -1, 100,
+ 0, -1));
}
NdbEventImpl *
-NdbDictionaryImpl::getEvent(const char * eventName)
+NdbDictionaryImpl::getEvent(const char * eventName, NdbTableImpl* tab)
{
- NdbEventImpl *ev = new NdbEventImpl();
+ DBUG_ENTER("NdbDictionaryImpl::getEvent");
+ DBUG_PRINT("enter",("eventName= %s", eventName));
+ NdbEventImpl *ev = new NdbEventImpl();
if (ev == NULL) {
- return NULL;
+ DBUG_RETURN(NULL);
}
ev->setName(eventName);
@@ -2674,48 +3652,112 @@
if (ret) {
delete ev;
- return NULL;
+ DBUG_RETURN(NULL);
}
// We only have the table name with internal name
- ev->setTable(m_ndb.externalizeTableName(ev->getTableName()));
- ev->m_tableImpl = getTable(ev->getTableName());
+ DBUG_PRINT("info",("table %s", ev->getTableName()));
+ if (tab == NULL)
+ {
+ tab= fetchGlobalTableImplRef(InitTable(this, ev->getTableName()));
+ if (tab == 0)
+ {
+ DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
+ delete ev;
+ DBUG_RETURN(NULL);
+ }
+ if ((tab->m_status != NdbDictionary::Object::Retrieved) ||
+ (tab->m_id != ev->m_table_id) ||
+ (table_version_major(tab->m_version) !=
+ table_version_major(ev->m_table_version)))
+ {
+ DBUG_PRINT("info", ("mismatch on verison in cache"));
+ releaseTableGlobal(*tab, 1);
+ tab= fetchGlobalTableImplRef(InitTable(this, ev->getTableName()));
+ if (tab == 0)
+ {
+ DBUG_PRINT("error",("unable to find table %s", ev->getTableName()));
+ delete ev;
+ DBUG_RETURN(NULL);
+ }
+ }
+ }
- // get the columns from the attrListBitmask
+ ev->setTable(tab);
+ ev->setTable(m_ndb.externalizeTableName(ev->getTableName()));
+ // get the columns from the attrListBitmask
NdbTableImpl &table = *ev->m_tableImpl;
AttributeMask & mask = ev->m_attrListBitmask;
- int attributeList_sz = mask.count();
- int id = -1;
+ unsigned attributeList_sz = mask.count();
-#ifdef EVENT_DEBUG
- ndbout_c("NdbDictionaryImpl::getEvent attributeList_sz = %d",
- attributeList_sz);
+ DBUG_PRINT("info",("Table: id: %d version: %d",
+ table.m_id, table.m_version));
+
+ if (table.m_id != ev->m_table_id ||
+ table_version_major(table.m_version) !=
+ table_version_major(ev->m_table_version))
+ {
+ m_error.code = 241;
+ delete ev;
+ DBUG_RETURN(NULL);
+ }
+#ifndef DBUG_OFF
char buf[128] = {0};
mask.getText(buf);
- ndbout_c("mask = %s", buf);
+ DBUG_PRINT("info",("attributeList_sz= %d, mask= %s",
+ attributeList_sz, buf));
#endif
- for(int i = 0; i < attributeList_sz; i++) {
- id++; while (!mask.get(id)) id++;
+
+ if ( attributeList_sz > table.getNoOfColumns() )
+ {
+ m_error.code = 241;
+ DBUG_PRINT("error",("Invalid version, too many columns"));
+ delete ev;
+ DBUG_RETURN(NULL);
+ }
- const NdbColumnImpl* col = table.getColumn(id);
- if(col == 0) {
-#ifdef EVENT_DEBUG
- ndbout_c("NdbDictionaryImpl::getEvent could not find column id %d", id);
-#endif
- m_error.code= 4247;
+ assert( (int)attributeList_sz <= table.getNoOfColumns() );
+ for(unsigned id= 0; ev->m_columns.size() < attributeList_sz; id++) {
+ if ( id >= table.getNoOfColumns())
+ {
+ m_error.code = 241;
+ DBUG_PRINT("error",("Invalid version, column %d out of range", id));
delete ev;
- return NULL;
+ DBUG_RETURN(NULL);
}
+ if (!mask.get(id))
+ continue;
+
+ const NdbColumnImpl* col = table.getColumn(id);
+ DBUG_PRINT("info",("column %d %s", id, col->getName()));
NdbColumnImpl* new_col = new NdbColumnImpl;
// Copy column definition
*new_col = *col;
-
ev->m_columns.push_back(new_col);
}
+ DBUG_RETURN(ev);
+}
- return ev;
+// ev is main event and has been retrieved previously
+NdbEventImpl *
+NdbDictionaryImpl::getBlobEvent(const NdbEventImpl& ev, uint col_no)
+{
+ DBUG_ENTER("NdbDictionaryImpl::getBlobEvent");
+ DBUG_PRINT("enter", ("ev=%s col=%u", ev.m_name.c_str(), col_no));
+
+ NdbTableImpl* tab = ev.m_tableImpl;
+ assert(tab != NULL && col_no < tab->m_columns.size());
+ NdbColumnImpl* col = tab->m_columns[col_no];
+ assert(col != NULL && col->getBlobType() && col->getPartSize() !=
0);
+ NdbTableImpl* blob_tab = col->m_blobTable;
+ assert(blob_tab != NULL);
+ char bename[MAX_TAB_NAME_SIZE];
+ NdbBlob::getBlobEventName(bename, &ev, col);
+
+ NdbEventImpl* blob_ev = getEvent(bename, blob_tab);
+ DBUG_RETURN(blob_ev);
}
void
@@ -2739,7 +3781,8 @@
Uint32 subscriptionId = createEvntConf->getEventId();
Uint32 subscriptionKey = createEvntConf->getEventKey();
- DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d",
+ DBUG_PRINT("info",("nodeid=%d,subscriptionId=%d,subscriptionKey=%d",
+ refToNode(signal->theSendersBlockRef),
subscriptionId,subscriptionKey));
m_waiter.signal(NO_WAIT);
DBUG_VOID_RETURN;
@@ -2756,6 +3799,8 @@
m_error.code= ref->getErrorCode();
DBUG_PRINT("error",("error=%d,line=%d,node=%d",ref->getErrorCode(),
ref->getErrorLine(),ref->getErrorNode()));
+ if (m_error.code == CreateEvntRef::NotMaster)
+ m_masterNodeId = ref->getMasterNode();
m_waiter.signal(NO_WAIT);
DBUG_VOID_RETURN;
}
@@ -2793,6 +3838,8 @@
DBUG_PRINT("error",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d,error=%d",
subscriptionId,subscriptionKey,subscriberData,m_error.code));
+ if (m_error.code == SubStopRef::NotMaster)
+ m_masterNodeId = subStopRef->m_masterNodeId;
m_waiter.signal(NO_WAIT);
DBUG_VOID_RETURN;
}
@@ -2841,77 +3888,11 @@
const SubStartRef * const subStartRef=
CAST_CONSTPTR(SubStartRef, signal->getDataPtr());
m_error.code= subStartRef->errorCode;
+ if (m_error.code == SubStartRef::NotMaster)
+ m_masterNodeId = subStartRef->m_masterNodeId;
m_waiter.signal(NO_WAIT);
DBUG_VOID_RETURN;
}
-void
-NdbDictInterface::execSUB_GCP_COMPLETE_REP(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
- const SubGcpCompleteRep * const rep=
- CAST_CONSTPTR(SubGcpCompleteRep, signal->getDataPtr());
-
- const Uint32 gci = rep->gci;
- // const Uint32 senderRef = rep->senderRef;
- const Uint32 subscriberData = rep->subscriberData;
-
- const Uint32 bufferId = subscriberData;
-
- const Uint32 ref = signal->theSendersBlockRef;
-
- NdbApiSignal tSignal(m_reference);
- SubGcpCompleteAcc * acc=
- CAST_PTR(SubGcpCompleteAcc, tSignal.getDataPtrSend());
-
- acc->rep = *rep;
-
- tSignal.theReceiversBlockNumber = refToBlock(ref);
- tSignal.theVerId_signalNumber = GSN_SUB_GCP_COMPLETE_ACC;
- tSignal.theLength = SubGcpCompleteAcc::SignalLength;
-
- Uint32 aNodeId = refToNode(ref);
-
- // m_transporter->lock_mutex();
- int r;
- r = m_transporter->sendSignal(&tSignal, aNodeId);
- // m_transporter->unlock_mutex();
-
- NdbGlobalEventBufferHandle::latestGCI(bufferId, gci);
-}
-
-void
-NdbDictInterface::execSUB_TABLE_DATA(NdbApiSignal * signal,
- LinearSectionPtr ptr[3])
-{
-#ifdef EVENT_DEBUG
- const char * FNAME = "NdbDictInterface::execSUB_TABLE_DATA";
-#endif
- //TODO
- const SubTableData * const sdata = CAST_CONSTPTR(SubTableData,
signal->getDataPtr());
-
- // const Uint32 gci = sdata->gci;
- // const Uint32 operation = sdata->operation;
- // const Uint32 tableId = sdata->tableId;
- // const Uint32 noOfAttrs = sdata->noOfAttributes;
- // const Uint32 dataLen = sdata->dataSize;
- const Uint32 subscriberData = sdata->subscriberData;
- // const Uint32 logType = sdata->logType;
-
- for (int i=signal->m_noOfSections;i < 3; i++) {
- ptr[i].p = NULL;
- ptr[i].sz = 0;
- }
-#ifdef EVENT_DEBUG
- ndbout_c("%s: senderData %d, gci %d, operation %d, tableId %d, noOfAttrs %d, dataLen
%d",
- FNAME, subscriberData, gci, operation, tableId, noOfAttrs, dataLen);
- ndbout_c("ptr[0] %u %u ptr[1] %u %u ptr[2] %u %u\n",
- ptr[0].p,ptr[0].sz,ptr[1].p,ptr[1].sz,ptr[2].p,ptr[2].sz);
-#endif
- const Uint32 bufferId = subscriberData;
-
- NdbGlobalEventBufferHandle::insertDataL(bufferId,
- sdata, ptr);
-}
/*****************************************************************
* Drop event
@@ -2919,13 +3900,68 @@
int
NdbDictionaryImpl::dropEvent(const char * eventName)
{
- NdbEventImpl *ev= new NdbEventImpl();
- ev->setName(eventName);
- int ret= m_receiver.dropEvent(*ev);
- delete ev;
+ DBUG_ENTER("NdbDictionaryImpl::dropEvent");
+ DBUG_PRINT("info", ("name=%s", eventName));
- // printf("__________________RET %u\n", ret);
- return ret;
+ NdbEventImpl *evnt = getEvent(eventName); // allocated
+ if (evnt == NULL) {
+ if (m_error.code != 723 && // no such table
+ m_error.code != 241) // invalid table
+ DBUG_RETURN(-1);
+ DBUG_PRINT("info", ("no table err=%d, drop by name alone", m_error.code));
+ evnt = new NdbEventImpl();
+ evnt->setName(eventName);
+ }
+ int ret = dropEvent(*evnt);
+ delete evnt;
+ DBUG_RETURN(ret);
+}
+
+int
+NdbDictionaryImpl::dropEvent(const NdbEventImpl& evnt)
+{
+ if (dropBlobEvents(evnt) != 0)
+ return -1;
+ if (m_receiver.dropEvent(evnt) != 0)
+ return -1;
+ return 0;
+}
+
+int
+NdbDictionaryImpl::dropBlobEvents(const NdbEventImpl& evnt)
+{
+ DBUG_ENTER("NdbDictionaryImpl::dropBlobEvents");
+ if (evnt.m_tableImpl != 0) {
+ const NdbTableImpl& t = *evnt.m_tableImpl;
+ Uint32 n = t.m_noOfBlobs;
+ Uint32 i;
+ for (i = 0; i < evnt.m_columns.size() && n > 0; i++) {
+ const NdbColumnImpl& c = *evnt.m_columns[i];
+ if (! c.getBlobType() || c.getPartSize() == 0)
+ continue;
+ n--;
+ NdbEventImpl* blob_evnt = getBlobEvent(evnt, i);
+ if (blob_evnt == NULL)
+ continue;
+ (void)dropEvent(*blob_evnt);
+ }
+ } else {
+ // loop over MAX_ATTRIBUTES_IN_TABLE ...
+ Uint32 i;
+ DBUG_PRINT("info", ("missing table definition, looping over "
+ "MAX_ATTRIBUTES_IN_TABLE(%d)",
+ MAX_ATTRIBUTES_IN_TABLE));
+ for (i = 0; i < MAX_ATTRIBUTES_IN_TABLE; i++) {
+ char bename[MAX_TAB_NAME_SIZE];
+ // XXX should get name from NdbBlob
+ sprintf(bename, "NDB$BLOBEVENT_%s_%u", evnt.getName(), i);
+ NdbEventImpl* bevnt = new NdbEventImpl();
+ bevnt->setName(bename);
+ (void)m_receiver.dropEvent(*bevnt);
+ delete bevnt;
+ }
+ }
+ DBUG_RETURN(0);
}
int
@@ -2943,29 +3979,19 @@
UtilBufferWriter w(m_buffer);
- w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str());
+ w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
LinearSectionPtr ptr[1];
ptr[0].p = (Uint32*)m_buffer.get_data();
ptr[0].sz = (m_buffer.length()+3) >> 2;
- return dropEvent(&tSignal, ptr, 1);
+ return dictSignal(&tSignal,ptr, 1,
+ 0 /*use masternode id*/,
+ WAIT_CREATE_INDX_REQ,
+ -1, 100,
+ 0, -1);
}
-int
-NdbDictInterface::dropEvent(NdbApiSignal* signal,
- LinearSectionPtr ptr[3], int noLSP)
-{
- //TODO
- const int noErrCodes = 1;
- int errCodes[noErrCodes] = {DropEvntRef::Busy};
- return dictSignal(signal,ptr,noLSP,
- 1 /*use masternode id*/,
- 100,
- WAIT_CREATE_INDX_REQ /*WAIT_CREATE_EVNT_REQ*/,
- -1,
- errCodes,noErrCodes, DropEvntRef::Temporary);
-}
void
NdbDictInterface::execDROP_EVNT_CONF(NdbApiSignal * signal,
LinearSectionPtr ptr[3])
@@ -2986,7 +4012,8 @@
DBUG_PRINT("info",("ErrorCode=%u Errorline=%u ErrorNode=%u",
ref->getErrorCode(), ref->getErrorLine(), ref->getErrorNode()));
-
+ if (m_error.code == DropEvntRef::NotMaster)
+ m_masterNodeId = ref->getMasterNode();
m_waiter.signal(NO_WAIT);
DBUG_VOID_RETURN;
}
@@ -3116,26 +4143,28 @@
for (Uint32 i = 0; i < RETRIES; i++) {
m_buffer.clear();
// begin protected
- m_transporter->lock_mutex();
+ /*
+ The PollGuard has an implicit call of unlock_and_signal through the
+ ~PollGuard method. This method is called implicitly by the compiler
+ in all places where the object is out of context due to a return,
+ break, continue or simply end of statement block
+ */
+ PollGuard poll_guard(m_transporter, &m_waiter, refToBlock(m_reference));
Uint16 aNodeId = m_transporter->get_an_alive_node();
if (aNodeId == 0) {
m_error.code= 4009;
- m_transporter->unlock_mutex();
return -1;
}
if (m_transporter->sendSignal(signal, aNodeId) != 0) {
- m_transporter->unlock_mutex();
continue;
}
m_error.code= 0;
- m_waiter.m_node = aNodeId;
- m_waiter.m_state = WAIT_LIST_TABLES_CONF;
- m_waiter.wait(WAITFOR_RESPONSE_TIMEOUT);
- m_transporter->unlock_mutex();
+ int ret_val= poll_guard.wait_n_unlock(DICT_WAITFOR_TIMEOUT,
+ aNodeId, WAIT_LIST_TABLES_CONF);
// end protected
- if (m_waiter.m_state == NO_WAIT && m_error.code == 0)
+ if (ret_val == 0 && m_error.code == 0)
return 0;
- if (m_waiter.m_state == WAIT_NODE_FAILURE)
+ if (ret_val == -2) //WAIT_NODE_FAILURE
continue;
return -1;
}
@@ -3155,6 +4184,794 @@
}
}
+int
+NdbDictionaryImpl::forceGCPWait()
+{
+ return m_receiver.forceGCPWait();
+}
+
+int
+NdbDictInterface::forceGCPWait()
+{
+ NdbApiSignal tSignal(m_reference);
+ WaitGCPReq* const req = CAST_PTR(WaitGCPReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->requestType = WaitGCPReq::CompleteForceStart;
+ tSignal.theReceiversBlockNumber = DBDIH;
+ tSignal.theVerId_signalNumber = GSN_WAIT_GCP_REQ;
+ tSignal.theLength = WaitGCPReq::SignalLength;
+
+ const Uint32 RETRIES = 100;
+ for (Uint32 i = 0; i < RETRIES; i++)
+ {
+ m_transporter->lock_mutex();
+ Uint16 aNodeId = m_transporter->get_an_alive_node();
+ if (aNodeId == 0) {
+ m_error.code= 4009;
+ m_transporter->unlock_mutex();
+ return -1;
+ }
+ if (m_transporter->sendSignal(&tSignal, aNodeId) != 0) {
+ m_transporter->unlock_mutex();
+ continue;
+ }
+ m_error.code= 0;
+ m_waiter.m_node = aNodeId;
+ m_waiter.m_state = WAIT_LIST_TABLES_CONF;
+ m_waiter.wait(DICT_WAITFOR_TIMEOUT);
+ m_transporter->unlock_mutex();
+ return 0;
+ }
+ return -1;
+}
+
+void
+NdbDictInterface::execWAIT_GCP_CONF(NdbApiSignal* signal,
+ LinearSectionPtr ptr[3])
+{
+ const WaitGCPConf * const conf=
+ CAST_CONSTPTR(WaitGCPConf, signal->getDataPtr());
+ g_latest_trans_gci= conf->gcp;
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execWAIT_GCP_REF(NdbApiSignal* signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+NdbFilegroupImpl::NdbFilegroupImpl(NdbDictionary::Object::Type t)
+ : NdbDictObjectImpl(t)
+{
+ m_extent_size = 0;
+ m_undo_buffer_size = 0;
+ m_logfile_group_id = ~0;
+ m_logfile_group_version = ~0;
+}
+
+NdbTablespaceImpl::NdbTablespaceImpl() :
+ NdbDictionary::Tablespace(* this),
+ NdbFilegroupImpl(NdbDictionary::Object::Tablespace), m_facade(this)
+{
+}
+
+NdbTablespaceImpl::NdbTablespaceImpl(NdbDictionary::Tablespace & f) :
+ NdbDictionary::Tablespace(* this),
+ NdbFilegroupImpl(NdbDictionary::Object::Tablespace), m_facade(&f)
+{
+}
+
+NdbTablespaceImpl::~NdbTablespaceImpl(){
+}
+
+void
+NdbTablespaceImpl::assign(const NdbTablespaceImpl& org)
+{
+ m_id = org.m_id;
+ m_version = org.m_version;
+ m_status = org.m_status;
+ m_type = org.m_type;
+
+ m_name.assign(org.m_name);
+ m_grow_spec = org.m_grow_spec;
+ m_extent_size = org.m_extent_size;
+ m_undo_free_words = org.m_undo_free_words;
+ m_logfile_group_id = org.m_logfile_group_id;
+ m_logfile_group_version = org.m_logfile_group_version;
+ m_logfile_group_name.assign(org.m_logfile_group_name);
+ m_undo_free_words = org.m_undo_free_words;
+}
+
+NdbLogfileGroupImpl::NdbLogfileGroupImpl() :
+ NdbDictionary::LogfileGroup(* this),
+ NdbFilegroupImpl(NdbDictionary::Object::LogfileGroup), m_facade(this)
+{
+}
+
+NdbLogfileGroupImpl::NdbLogfileGroupImpl(NdbDictionary::LogfileGroup & f) :
+ NdbDictionary::LogfileGroup(* this),
+ NdbFilegroupImpl(NdbDictionary::Object::LogfileGroup), m_facade(&f)
+{
+}
+
+NdbLogfileGroupImpl::~NdbLogfileGroupImpl(){
+}
+
+void
+NdbLogfileGroupImpl::assign(const NdbLogfileGroupImpl& org)
+{
+ m_id = org.m_id;
+ m_version = org.m_version;
+ m_status = org.m_status;
+ m_type = org.m_type;
+
+ m_name.assign(org.m_name);
+ m_grow_spec = org.m_grow_spec;
+ m_extent_size = org.m_extent_size;
+ m_undo_free_words = org.m_undo_free_words;
+ m_logfile_group_id = org.m_logfile_group_id;
+ m_logfile_group_version = org.m_logfile_group_version;
+ m_logfile_group_name.assign(org.m_logfile_group_name);
+ m_undo_free_words = org.m_undo_free_words;
+}
+
+NdbFileImpl::NdbFileImpl(NdbDictionary::Object::Type t)
+ : NdbDictObjectImpl(t)
+{
+ m_size = 0;
+ m_free = 0;
+ m_filegroup_id = ~0;
+ m_filegroup_version = ~0;
+}
+
+NdbDatafileImpl::NdbDatafileImpl() :
+ NdbDictionary::Datafile(* this),
+ NdbFileImpl(NdbDictionary::Object::Datafile), m_facade(this)
+{
+}
+
+NdbDatafileImpl::NdbDatafileImpl(NdbDictionary::Datafile & f) :
+ NdbDictionary::Datafile(* this),
+ NdbFileImpl(NdbDictionary::Object::Datafile), m_facade(&f)
+{
+}
+
+NdbDatafileImpl::~NdbDatafileImpl(){
+}
+
+void
+NdbDatafileImpl::assign(const NdbDatafileImpl& org)
+{
+ m_id = org.m_id;
+ m_version = org.m_version;
+ m_status = org.m_status;
+ m_type = org.m_type;
+
+ m_size = org.m_size;
+ m_free = org.m_free;
+ m_filegroup_id = org.m_filegroup_id;
+ m_filegroup_version = org.m_filegroup_version;
+ m_path.assign(org.m_path);
+ m_filegroup_name.assign(org.m_filegroup_name);
+}
+
+NdbUndofileImpl::NdbUndofileImpl() :
+ NdbDictionary::Undofile(* this),
+ NdbFileImpl(NdbDictionary::Object::Undofile), m_facade(this)
+{
+}
+
+NdbUndofileImpl::NdbUndofileImpl(NdbDictionary::Undofile & f) :
+ NdbDictionary::Undofile(* this),
+ NdbFileImpl(NdbDictionary::Object::Undofile), m_facade(&f)
+{
+}
+
+NdbUndofileImpl::~NdbUndofileImpl(){
+}
+
+void
+NdbUndofileImpl::assign(const NdbUndofileImpl& org)
+{
+ m_id = org.m_id;
+ m_version = org.m_version;
+ m_status = org.m_status;
+ m_type = org.m_type;
+
+ m_size = org.m_size;
+ m_free = org.m_free;
+ m_filegroup_id = org.m_filegroup_id;
+ m_filegroup_version = org.m_filegroup_version;
+ m_path.assign(org.m_path);
+ m_filegroup_name.assign(org.m_filegroup_name);
+}
+
+int
+NdbDictionaryImpl::createDatafile(const NdbDatafileImpl & file, bool force){
+ DBUG_ENTER("NdbDictionaryImpl::createDatafile");
+ NdbFilegroupImpl tmp(NdbDictionary::Object::Tablespace);
+ if(file.m_filegroup_version != ~(Uint32)0){
+ tmp.m_id = file.m_filegroup_id;
+ tmp.m_version = file.m_filegroup_version;
+ DBUG_RETURN(m_receiver.create_file(file, tmp));
+ }
+
+
+ if(m_receiver.get_filegroup(tmp, NdbDictionary::Object::Tablespace,
+ file.m_filegroup_name.c_str()) == 0){
+ DBUG_RETURN(m_receiver.create_file(file, tmp, force));
+ }
+ DBUG_RETURN(-1);
+}
+
+int
+NdbDictionaryImpl::dropDatafile(const NdbDatafileImpl & file){
+ return m_receiver.drop_file(file);
+}
+
+int
+NdbDictionaryImpl::createUndofile(const NdbUndofileImpl & file, bool force){
+ DBUG_ENTER("NdbDictionaryImpl::createUndofile");
+ NdbFilegroupImpl tmp(NdbDictionary::Object::LogfileGroup);
+ if(file.m_filegroup_version != ~(Uint32)0){
+ tmp.m_id = file.m_filegroup_id;
+ tmp.m_version = file.m_filegroup_version;
+ DBUG_RETURN(m_receiver.create_file(file, tmp));
+ }
+
+
+ if(m_receiver.get_filegroup(tmp, NdbDictionary::Object::LogfileGroup,
+ file.m_filegroup_name.c_str()) == 0){
+ DBUG_RETURN(m_receiver.create_file(file, tmp, force));
+ }
+ DBUG_PRINT("info", ("Failed to find filegroup"));
+ DBUG_RETURN(-1);
+}
+
+int
+NdbDictionaryImpl::dropUndofile(const NdbUndofileImpl & file){
+ return m_receiver.drop_file(file);
+}
+
+int
+NdbDictionaryImpl::createTablespace(const NdbTablespaceImpl & fg){
+ return m_receiver.create_filegroup(fg);
+}
+
+int
+NdbDictionaryImpl::dropTablespace(const NdbTablespaceImpl & fg){
+ return m_receiver.drop_filegroup(fg);
+}
+
+int
+NdbDictionaryImpl::createLogfileGroup(const NdbLogfileGroupImpl & fg){
+ return m_receiver.create_filegroup(fg);
+}
+
+int
+NdbDictionaryImpl::dropLogfileGroup(const NdbLogfileGroupImpl & fg){
+ return m_receiver.drop_filegroup(fg);
+}
+
+int
+NdbDictInterface::create_file(const NdbFileImpl & file,
+ const NdbFilegroupImpl & group,
+ bool overwrite){
+ DBUG_ENTER("NdbDictInterface::create_file");
+ UtilBufferWriter w(m_buffer);
+ DictFilegroupInfo::File f; f.init();
+ snprintf(f.FileName, sizeof(f.FileName), file.m_path.c_str());
+ f.FileType = file.m_type;
+ f.FilegroupId = group.m_id;
+ f.FilegroupVersion = group.m_version;
+ f.FileSizeHi = (file.m_size >> 32);
+ f.FileSizeLo = (file.m_size & 0xFFFFFFFF);
+
+ SimpleProperties::UnpackStatus s;
+ s = SimpleProperties::pack(w,
+ &f,
+ DictFilegroupInfo::FileMapping,
+ DictFilegroupInfo::FileMappingSize, true);
+
+ if(s != SimpleProperties::Eof){
+ abort();
+ }
+
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_CREATE_FILE_REQ;
+ tSignal.theLength = CreateFileReq::SignalLength;
+
+ CreateFileReq* req = CAST_PTR(CreateFileReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->objType = file.m_type;
+ req->requestInfo = 0;
+ if (overwrite)
+ req->requestInfo |= CreateFileReq::ForceCreateFile;
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ ptr[0].sz = m_buffer.length() / 4;
+
+ int err[] = { CreateFileRef::Busy, CreateFileRef::NotMaster, 0};
+ /*
+ Send signal without time-out since creating files can take a very long
+ time if the file is very big.
+ */
+ DBUG_RETURN(dictSignal(&tSignal, ptr, 1,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ -1, 100,
+ err));
+}
+
+void
+NdbDictInterface::execCREATE_FILE_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execCREATE_FILE_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const CreateFileRef* ref =
+ CAST_CONSTPTR(CreateFileRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+int
+NdbDictInterface::drop_file(const NdbFileImpl & file){
+ DBUG_ENTER("NdbDictInterface::drop_file");
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_DROP_FILE_REQ;
+ tSignal.theLength = DropFileReq::SignalLength;
+
+ DropFileReq* req = CAST_PTR(DropFileReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->file_id = file.m_id;
+ req->file_version = file.m_version;
+
+ int err[] = { DropFileRef::Busy, DropFileRef::NotMaster, 0};
+ DBUG_RETURN(dictSignal(&tSignal, 0, 0,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ DICT_WAITFOR_TIMEOUT, 100,
+ err));
+}
+
+void
+NdbDictInterface::execDROP_FILE_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execDROP_FILE_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const DropFileRef* ref =
+ CAST_CONSTPTR(DropFileRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+int
+NdbDictInterface::create_filegroup(const NdbFilegroupImpl & group){
+ DBUG_ENTER("NdbDictInterface::create_filegroup");
+ UtilBufferWriter w(m_buffer);
+ DictFilegroupInfo::Filegroup fg; fg.init();
+ snprintf(fg.FilegroupName, sizeof(fg.FilegroupName), group.m_name.c_str());
+ switch(group.m_type){
+ case NdbDictionary::Object::Tablespace:
+ {
+ fg.FilegroupType = DictTabInfo::Tablespace;
+ //fg.TS_DataGrow = group.m_grow_spec;
+ fg.TS_ExtentSize = group.m_extent_size;
+
+ if(group.m_logfile_group_version != ~(Uint32)0)
+ {
+ fg.TS_LogfileGroupId = group.m_logfile_group_id;
+ fg.TS_LogfileGroupVersion = group.m_logfile_group_version;
+ }
+ else
+ {
+ NdbLogfileGroupImpl tmp;
+ if(get_filegroup(tmp, NdbDictionary::Object::LogfileGroup,
+ group.m_logfile_group_name.c_str()) == 0)
+ {
+ fg.TS_LogfileGroupId = tmp.m_id;
+ fg.TS_LogfileGroupVersion = tmp.m_version;
+ }
+ else // error set by get filegroup
+ {
+ DBUG_RETURN(-1);
+ }
+ }
+ }
+ break;
+ case NdbDictionary::Object::LogfileGroup:
+ fg.LF_UndoBufferSize = group.m_undo_buffer_size;
+ fg.FilegroupType = DictTabInfo::LogfileGroup;
+ //fg.LF_UndoGrow = group.m_grow_spec;
+ break;
+ default:
+ abort();
+ DBUG_RETURN(-1);
+ };
+
+ SimpleProperties::UnpackStatus s;
+ s = SimpleProperties::pack(w,
+ &fg,
+ DictFilegroupInfo::Mapping,
+ DictFilegroupInfo::MappingSize, true);
+
+ if(s != SimpleProperties::Eof){
+ abort();
+ }
+
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_CREATE_FILEGROUP_REQ;
+ tSignal.theLength = CreateFilegroupReq::SignalLength;
+
+ CreateFilegroupReq* req =
+ CAST_PTR(CreateFilegroupReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->objType = fg.FilegroupType;
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ ptr[0].sz = m_buffer.length() / 4;
+
+ int err[] = { CreateFilegroupRef::Busy, CreateFilegroupRef::NotMaster, 0};
+ DBUG_RETURN(dictSignal(&tSignal, ptr, 1,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ DICT_WAITFOR_TIMEOUT, 100,
+ err));
+}
+
+void
+NdbDictInterface::execCREATE_FILEGROUP_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execCREATE_FILEGROUP_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const CreateFilegroupRef* ref =
+ CAST_CONSTPTR(CreateFilegroupRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+int
+NdbDictInterface::drop_filegroup(const NdbFilegroupImpl & group){
+ DBUG_ENTER("NdbDictInterface::drop_filegroup");
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_DROP_FILEGROUP_REQ;
+ tSignal.theLength = DropFilegroupReq::SignalLength;
+
+ DropFilegroupReq* req = CAST_PTR(DropFilegroupReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->filegroup_id = group.m_id;
+ req->filegroup_version = group.m_version;
+
+ int err[] = { DropFilegroupRef::Busy, DropFilegroupRef::NotMaster, 0};
+ DBUG_RETURN(dictSignal(&tSignal, 0, 0,
+ 0, // master
+ WAIT_CREATE_INDX_REQ,
+ DICT_WAITFOR_TIMEOUT, 100,
+ err));
+}
+
+void
+NdbDictInterface::execDROP_FILEGROUP_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execDROP_FILEGROUP_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const DropFilegroupRef* ref =
+ CAST_CONSTPTR(DropFilegroupRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+
+int
+NdbDictInterface::get_filegroup(NdbFilegroupImpl & dst,
+ NdbDictionary::Object::Type type,
+ const char * name){
+ DBUG_ENTER("NdbDictInterface::get_filegroup");
+ NdbApiSignal tSignal(m_reference);
+ GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
+ size_t strLen = strlen(name) + 1;
+
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->requestType =
+ GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
+ req->tableNameLen = strLen;
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
+ tSignal.theLength = GetTabInfoReq::SignalLength;
+
+ LinearSectionPtr ptr[1];
+ ptr[0].p = (Uint32*)name;
+ ptr[0].sz = (strLen + 3)/4;
+
+#ifndef IGNORE_VALGRIND_WARNINGS
+ if (strLen & 3)
+ {
+ Uint32 pad = 0;
+ m_buffer.clear();
+ m_buffer.append(name, strLen);
+ m_buffer.append(&pad, 4);
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ }
+#endif
+
+ int r = dictSignal(&tSignal, ptr, 1,
+ -1, // any node
+ WAIT_GET_TAB_INFO_REQ,
+ DICT_WAITFOR_TIMEOUT, 100);
+ if (r)
+ {
+ dst.m_id = -1;
+ dst.m_version = ~0;
+
+ DBUG_PRINT("info", ("get_filegroup failed dictSignal"));
+ DBUG_RETURN(-1);
+ }
+
+ m_error.code = parseFilegroupInfo(dst,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4);
+
+ if(m_error.code)
+ {
+ DBUG_PRINT("info", ("get_filegroup failed parseFilegroupInfo %d",
+ m_error.code));
+ DBUG_RETURN(m_error.code);
+ }
+
+ if(dst.m_type == NdbDictionary::Object::Tablespace)
+ {
+ NdbDictionary::LogfileGroup tmp;
+ get_filegroup(NdbLogfileGroupImpl::getImpl(tmp),
+ NdbDictionary::Object::LogfileGroup,
+ dst.m_logfile_group_id);
+ dst.m_logfile_group_name.assign(tmp.getName());
+ }
+
+ if(dst.m_type == type)
+ {
+ DBUG_RETURN(0);
+ }
+ DBUG_PRINT("info", ("get_filegroup failed no such filegroup"));
+ DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
+}
+
+int
+NdbDictInterface::parseFilegroupInfo(NdbFilegroupImpl &dst,
+ const Uint32 * data, Uint32 len)
+
+{
+ SimplePropertiesLinearReader it(data, len);
+
+ SimpleProperties::UnpackStatus status;
+ DictFilegroupInfo::Filegroup fg; fg.init();
+ status = SimpleProperties::unpack(it, &fg,
+ DictFilegroupInfo::Mapping,
+ DictFilegroupInfo::MappingSize,
+ true, true);
+
+ if(status != SimpleProperties::Eof){
+ return CreateFilegroupRef::InvalidFormat;
+ }
+
+ dst.m_id = fg.FilegroupId;
+ dst.m_version = fg.FilegroupVersion;
+ dst.m_type = (NdbDictionary::Object::Type)fg.FilegroupType;
+ dst.m_status = NdbDictionary::Object::Retrieved;
+
+ dst.m_name.assign(fg.FilegroupName);
+ dst.m_extent_size = fg.TS_ExtentSize;
+ dst.m_undo_buffer_size = fg.LF_UndoBufferSize;
+ dst.m_logfile_group_id = fg.TS_LogfileGroupId;
+ dst.m_logfile_group_version = fg.TS_LogfileGroupVersion;
+ dst.m_undo_free_words= ((Uint64)fg.LF_UndoFreeWordsHi << 32)
+ | (fg.LF_UndoFreeWordsLo);
+
+ return 0;
+}
+
+int
+NdbDictInterface::get_filegroup(NdbFilegroupImpl & dst,
+ NdbDictionary::Object::Type type,
+ Uint32 id){
+ DBUG_ENTER("NdbDictInterface::get_filegroup");
+ NdbApiSignal tSignal(m_reference);
+ GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->requestType =
+ GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
+ req->tableId = id;
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
+ tSignal.theLength = GetTabInfoReq::SignalLength;
+
+ int r = dictSignal(&tSignal, NULL, 1,
+ -1, // any node
+ WAIT_GET_TAB_INFO_REQ,
+ DICT_WAITFOR_TIMEOUT, 100);
+ if (r)
+ {
+ DBUG_PRINT("info", ("get_filegroup failed dictSignal"));
+ DBUG_RETURN(-1);
+ }
+
+ m_error.code = parseFilegroupInfo(dst,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4);
+
+ if(m_error.code)
+ {
+ DBUG_PRINT("info", ("get_filegroup failed parseFilegroupInfo %d",
+ m_error.code));
+ DBUG_RETURN(m_error.code);
+ }
+
+ if(dst.m_type == type)
+ {
+ DBUG_RETURN(0);
+ }
+ DBUG_PRINT("info", ("get_filegroup failed no such filegroup"));
+ DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
+}
+
+int
+NdbDictInterface::get_file(NdbFileImpl & dst,
+ NdbDictionary::Object::Type type,
+ int node,
+ const char * name){
+ DBUG_ENTER("NdbDictInterface::get_file");
+ NdbApiSignal tSignal(m_reference);
+ GetTabInfoReq * req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
+ size_t strLen = strlen(name) + 1;
+
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->requestType =
+ GetTabInfoReq::RequestByName | GetTabInfoReq::LongSignalConf;
+ req->tableNameLen = strLen;
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
+ tSignal.theLength = GetTabInfoReq::SignalLength;
+
+ LinearSectionPtr ptr[1];
+ ptr[0].p = (Uint32*)name;
+ ptr[0].sz = (strLen + 3)/4;
+
+#ifndef IGNORE_VALGRIND_WARNINGS
+ if (strLen & 3)
+ {
+ Uint32 pad = 0;
+ m_buffer.clear();
+ m_buffer.append(name, strLen);
+ m_buffer.append(&pad, 4);
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ }
+#endif
+
+ int r = dictSignal(&tSignal, ptr, 1,
+ node,
+ WAIT_GET_TAB_INFO_REQ,
+ DICT_WAITFOR_TIMEOUT, 100);
+ if (r)
+ {
+ DBUG_PRINT("info", ("get_file failed dictSignal"));
+ DBUG_RETURN(-1);
+ }
+
+ m_error.code = parseFileInfo(dst,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4);
+
+ if(m_error.code)
+ {
+ DBUG_PRINT("info", ("get_file failed parseFileInfo %d",
+ m_error.code));
+ DBUG_RETURN(m_error.code);
+ }
+
+ if(dst.m_type == NdbDictionary::Object::Undofile)
+ {
+ NdbDictionary::LogfileGroup tmp;
+ get_filegroup(NdbLogfileGroupImpl::getImpl(tmp),
+ NdbDictionary::Object::LogfileGroup,
+ dst.m_filegroup_id);
+ dst.m_filegroup_name.assign(tmp.getName());
+ }
+ else if(dst.m_type == NdbDictionary::Object::Datafile)
+ {
+ NdbDictionary::Tablespace tmp;
+ get_filegroup(NdbTablespaceImpl::getImpl(tmp),
+ NdbDictionary::Object::Tablespace,
+ dst.m_filegroup_id);
+ dst.m_filegroup_name.assign(tmp.getName());
+ dst.m_free *= tmp.getExtentSize();
+ }
+ else
+ dst.m_filegroup_name.assign("Not Yet Implemented");
+
+ if(dst.m_type == type)
+ {
+ DBUG_RETURN(0);
+ }
+ DBUG_PRINT("info", ("get_file failed no such file"));
+ DBUG_RETURN(m_error.code = GetTabInfoRef::TableNotDefined);
+}
+
+int
+NdbDictInterface::parseFileInfo(NdbFileImpl &dst,
+ const Uint32 * data, Uint32 len)
+{
+ SimplePropertiesLinearReader it(data, len);
+
+ SimpleProperties::UnpackStatus status;
+ DictFilegroupInfo::File f; f.init();
+ status = SimpleProperties::unpack(it, &f,
+ DictFilegroupInfo::FileMapping,
+ DictFilegroupInfo::FileMappingSize,
+ true, true);
+
+ if(status != SimpleProperties::Eof){
+ return CreateFilegroupRef::InvalidFormat;
+ }
+
+ dst.m_type= (NdbDictionary::Object::Type)f.FileType;
+ dst.m_id= f.FileId;
+ dst.m_version = f.FileVersion;
+
+ dst.m_size= ((Uint64)f.FileSizeHi << 32) | (f.FileSizeLo);
+ dst.m_path.assign(f.FileName);
+
+ dst.m_filegroup_id= f.FilegroupId;
+ dst.m_filegroup_version= f.FilegroupVersion;
+ dst.m_free= f.FileFreeExtents;
+ return 0;
+}
+
template class Vector<int>;
template class Vector<Uint16>;
template class Vector<Uint32>;
@@ -3162,3 +4979,13 @@
template class Vector<NdbTableImpl*>;
template class Vector<NdbColumnImpl*>;
+const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0;
+const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_MEMORY = 0;
+const NdbDictionary::Column * NdbDictionary::Column::ROW_COUNT = 0;
+const NdbDictionary::Column * NdbDictionary::Column::COMMIT_COUNT = 0;
+const NdbDictionary::Column * NdbDictionary::Column::ROW_SIZE = 0;
+const NdbDictionary::Column * NdbDictionary::Column::RANGE_NO = 0;
+const NdbDictionary::Column * NdbDictionary::Column::DISK_REF = 0;
+const NdbDictionary::Column * NdbDictionary::Column::RECORDS_IN_RANGE = 0;
+const NdbDictionary::Column * NdbDictionary::Column::ROWID = 0;
+const NdbDictionary::Column * NdbDictionary::Column::ROW_GCI = 0;
--- 1.303/sql/ha_ndbcluster.cc 2006-05-08 18:08:52 +02:00
+++ 1.304/sql/ha_ndbcluster.cc 2006-05-16 13:09:19 +02:00
@@ -2563,11 +2563,11 @@
Ndb *ndb= get_ndb();
Uint64 next_val= (Uint64) table->next_number_field->val_int() + 1;
DBUG_PRINT("info",
- ("Trying to set next auto increment value to %lu",
- (ulong) next_val));
- if (ndb->setAutoIncrementValue(m_table, next_val, TRUE))
- DBUG_PRINT("info",
- ("Setting next auto increment value to %u", next_val));
+ ("Trying to set next auto increment value to %llu",
+ (ulonglong) next_val));
+ if (ndb->setAutoIncrementValue(m_table, next_val, TRUE)
+ == ~(Uint64)0)
+ ERR_RETURN(ndb->getNdbError());
}
m_skip_auto_increment= TRUE;
--- 1.14.9.1/ndb/tools/restore/consumer_restore.cpp 2006-05-16 12:44:11 +02:00
+++ 1.30/storage/ndb/tools/restore/consumer_restore.cpp 2006-05-16 13:05:20 +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);
@@ -155,13 +158,483 @@
return ret;
}
+
+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::Tablespace * ts = m_tablespaces[old.getTablespaceId()];
+ debug << "Connecting datafile " << old.getPath()
+ << " to tablespace: oldid: " << old.getTablespaceId()
+ << " 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::LogfileGroup * lg =
+ m_logfilegroups[old.getLogfileGroupId()];
+ debug << "Connecting undofile " << old.getPath()
+ << " to logfile group: oldid: " << old.getLogfileGroupId()
+ << " 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
*/
@@ -185,15 +658,71 @@
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);
+ }
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 ;
@@ -204,7 +733,50 @@
err << "Unable to find table: " << split[2].c_str() << endl;
return false;
}
- if(m_restore_meta){
+ 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 ;
+ }
+
m_ndb->setAutoIncrementValue(tab, ~(Uint64)0, false);
}
const NdbDictionary::Table* null = 0;
@@ -272,7 +844,7 @@
return true;
}
-void BackupRestore::tuple(const TupleS & tup)
+void BackupRestore::tuple(const TupleS & tup, Uint32 fragmentId)
{
if (!m_restore)
return;
@@ -292,6 +864,7 @@
m_free_callback = cb->next;
cb->retries = 0;
+ cb->fragId = fragmentId;
cb->tup = tup; // must do copy!
tuple_a(cb);
@@ -299,6 +872,7 @@
void BackupRestore::tuple_a(restore_callback_t *cb)
{
+ Uint32 partition_id = cb->fragId;
while (cb->retries < 10)
{
/**
@@ -312,6 +886,7 @@
m_ndb->sendPollNdb(3000, 1);
continue;
}
+ err << "Cannot start transaction" << endl;
exitHandler();
} // if
@@ -324,6 +899,7 @@
{
if (errorHandler(cb))
continue;
+ err << "Cannot get operation: " << cb->connection->getNdbError()
<< endl;
exitHandler();
} // if
@@ -331,9 +907,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++)
{
@@ -344,11 +948,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;
@@ -376,6 +980,7 @@
{
if (errorHandler(cb))
continue;
+ err << "Error defining op: " << cb->connection->getNdbError()
<< endl;
exitHandler();
}
@@ -448,30 +1053,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;
}
@@ -505,6 +1108,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)
{
@@ -550,7 +1182,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++)
{
@@ -716,3 +1360,5 @@
template class Vector<NdbDictionary::Table*>;
template class Vector<const NdbDictionary::Table*>;
+template class Vector<NdbDictionary::Tablespace*>;
+template class Vector<NdbDictionary::LogfileGroup*>;
| Thread |
|---|
| • bk commit into 5.1 tree (pekka:1.2397) | pekka | 16 May |