summaryrefslogtreecommitdiff
path: root/ndb/src/ndbapi/NdbDictionaryImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ndb/src/ndbapi/NdbDictionaryImpl.cpp')
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp2733
1 files changed, 2733 insertions, 0 deletions
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
new file mode 100644
index 00000000000..bd94ba9b080
--- /dev/null
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -0,0 +1,2733 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "NdbDictionaryImpl.hpp"
+#include "API.hpp"
+#include <NdbOut.hpp>
+#include <AttrType.hpp>
+#include "NdbApiSignal.hpp"
+#include "TransporterFacade.hpp"
+#include <signaldata/GetTabInfo.hpp>
+#include <signaldata/DictTabInfo.hpp>
+#include <signaldata/CreateTable.hpp>
+#include <signaldata/CreateIndx.hpp>
+#include <signaldata/CreateEvnt.hpp>
+#include <signaldata/SumaImpl.hpp>
+#include <signaldata/DropTable.hpp>
+#include <signaldata/AlterTable.hpp>
+#include <signaldata/DropIndx.hpp>
+#include <signaldata/ListTables.hpp>
+#include <SimpleProperties.hpp>
+#include <Bitmask.hpp>
+#include <AttributeList.hpp>
+#include <NdbEventOperation.hpp>
+#include "NdbEventOperationImpl.hpp"
+#include <assert.h>
+
+#define DEBUG_PRINT 0
+#define INCOMPATIBLE_VERSION -2
+
+//#define EVENT_DEBUG
+
+/**
+ * Column
+ */
+NdbColumnImpl::NdbColumnImpl()
+ : NdbDictionary::Column(* this), m_facade(this)
+{
+ init();
+}
+
+NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
+ : NdbDictionary::Column(* this), m_facade(&f)
+{
+ init();
+}
+
+NdbColumnImpl::NdbColumnImpl&
+NdbColumnImpl::operator=(const NdbColumnImpl::NdbColumnImpl& col)
+{
+ m_attrId = col.m_attrId;
+ m_name = col.m_name;
+ m_type = col.m_type;
+ m_precision = col.m_precision;
+ m_scale = col.m_scale;
+ m_length = col.m_length;
+ m_pk = col.m_pk;
+ m_tupleKey = col.m_tupleKey;
+ m_distributionKey = col.m_distributionKey;
+ m_distributionGroup = col.m_distributionGroup;
+ m_distributionGroupBits = col.m_distributionGroupBits;
+ m_nullable = col.m_nullable;
+ m_indexOnly = col.m_indexOnly;
+ m_autoIncrement = col.m_autoIncrement;
+ m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
+ m_defaultValue = col.m_defaultValue;
+ m_attrType = col.m_attrType;
+ m_attrSize = col.m_attrSize;
+ m_arraySize = col.m_arraySize;
+ m_keyInfoPos = col.m_keyInfoPos;
+ // Do not copy m_facade !!
+
+ return *this;
+}
+
+void
+NdbColumnImpl::init()
+{
+ m_attrId = -1;
+ m_type = NdbDictionary::Column::Unsigned;
+ m_pk = false;
+ m_nullable = false;
+ m_tupleKey = false;
+ m_indexOnly = false;
+ m_distributionKey = false;
+ m_distributionGroup = false;
+ m_distributionGroupBits = 8;
+ m_length = 1;
+ m_scale = 5;
+ m_precision = 5;
+ m_keyInfoPos = 0;
+ m_attrSize = 4,
+ m_arraySize = 1,
+ m_autoIncrement = false;
+ m_autoIncrementInitialValue = 1;
+}
+
+NdbColumnImpl::~NdbColumnImpl()
+{
+}
+
+bool
+NdbColumnImpl::equal(const NdbColumnImpl& col) const
+{
+ if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
+ return false;
+ }
+ if(m_type != col.m_type){
+ return false;
+ }
+ if(m_pk != col.m_pk){
+ return false;
+ }
+ if(m_nullable != col.m_nullable){
+ return false;
+ }
+ if(m_pk){
+ if(m_tupleKey != col.m_tupleKey){
+ return false;
+ }
+ if(m_indexOnly != col.m_indexOnly){
+ return false;
+ }
+ if(m_distributionKey != col.m_distributionKey){
+ return false;
+ }
+ if(m_distributionGroup != col.m_distributionGroup){
+ return false;
+ }
+ if(m_distributionGroup &&
+ (m_distributionGroupBits != col.m_distributionGroupBits)){
+ return false;
+ }
+ }
+ if(m_length != col.m_length){
+ return false;
+ }
+
+ switch(m_type){
+ case NdbDictionary::Column::Undefined:
+ break;
+ case NdbDictionary::Column::Tinyint:
+ case NdbDictionary::Column::Tinyunsigned:
+ case NdbDictionary::Column::Smallint:
+ case NdbDictionary::Column::Smallunsigned:
+ case NdbDictionary::Column::Mediumint:
+ case NdbDictionary::Column::Mediumunsigned:
+ case NdbDictionary::Column::Int:
+ case NdbDictionary::Column::Unsigned:
+ case NdbDictionary::Column::Float:
+ break;
+ case NdbDictionary::Column::Decimal:
+ if(m_scale != col.m_scale ||
+ m_precision != col.m_precision){
+ return false;
+ }
+ break;
+ case NdbDictionary::Column::Char:
+ case NdbDictionary::Column::Varchar:
+ case NdbDictionary::Column::Binary:
+ case NdbDictionary::Column::Varbinary:
+ if(m_length != col.m_length){
+ return false;
+ }
+ break;
+ case NdbDictionary::Column::Bigint:
+ case NdbDictionary::Column::Bigunsigned:
+ case NdbDictionary::Column::Double:
+ case NdbDictionary::Column::Datetime:
+ case NdbDictionary::Column::Timespec:
+ case NdbDictionary::Column::Blob:
+ break;
+ }
+ if (m_autoIncrement != col.m_autoIncrement){
+ return false;
+ }
+ if(strcmp(m_defaultValue.c_str(), col.m_defaultValue.c_str()) != 0){
+ return false;
+ }
+
+ return true;
+}
+
+void
+NdbColumnImpl::assign(const NdbColumnImpl& org)
+{
+ m_attrId = org.m_attrId;
+ m_name.assign(org.m_name);
+ m_type = org.m_type;
+ m_precision = org.m_precision;
+ m_scale = org.m_scale;
+ m_length = org.m_length;
+ m_pk = org.m_pk;
+ m_tupleKey = org.m_tupleKey;
+ m_distributionKey = org.m_distributionKey;
+ m_distributionGroup = org.m_distributionGroup;
+ m_distributionGroupBits = org.m_distributionGroupBits;
+ m_nullable = org.m_nullable;
+ m_indexOnly = org.m_indexOnly;
+ m_autoIncrement = org.m_autoIncrement;
+ m_autoIncrementInitialValue = org.m_autoIncrementInitialValue;
+ m_defaultValue.assign(org.m_defaultValue);
+ m_keyInfoPos = org.m_keyInfoPos;
+ m_attrSize = org.m_attrSize;
+ m_arraySize = org.m_arraySize;
+}
+
+/**
+ * NdbTableImpl
+ */
+
+NdbTableImpl::NdbTableImpl()
+ : NdbDictionary::Table(* this), m_facade(this)
+{
+ m_noOfKeys = 0;
+ m_index = 0;
+ init();
+}
+
+NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
+ : NdbDictionary::Table(* this), m_facade(&f)
+{
+ init();
+}
+
+NdbTableImpl::~NdbTableImpl()
+{
+ if (m_index != 0) {
+ delete m_index;
+ m_index = 0;
+ }
+ for (unsigned i = 0; i < m_columns.size(); i++)
+ delete m_columns[i];
+}
+
+void
+NdbTableImpl::init(){
+ clearNewProperties();
+ m_frm.clear();
+ m_fragmentType = NdbDictionary::Object::FragAllMedium;
+ m_logging = true;
+ m_kvalue = 6;
+ m_minLoadFactor = 78;
+ m_maxLoadFactor = 80;
+
+ m_index = 0;
+ m_indexType = NdbDictionary::Index::Undefined;
+
+ m_noOfKeys = 0;
+}
+
+bool
+NdbTableImpl::equal(const NdbTableImpl& obj) const
+{
+ 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)) {
+ // Shallow equal
+ if(strcmp(getName(), obj.getName()) != 0){
+ return false;
+ }
+ } else
+ // Deep equal
+ if(strcmp(m_internalName.c_str(), obj.m_internalName.c_str()) != 0){
+ return false;
+ }
+
+ if(m_fragmentType != obj.m_fragmentType){
+ return false;
+ }
+
+ if(m_columns.size() != obj.m_columns.size()){
+ return false;
+ }
+
+ for(unsigned i = 0; i<obj.m_columns.size(); i++){
+ if(!m_columns[i]->equal(* obj.m_columns[i])){
+ return false;
+ }
+ }
+
+ if(m_logging != obj.m_logging){
+ return false;
+ }
+
+ if(m_kvalue != obj.m_kvalue){
+ return false;
+ }
+
+ if(m_minLoadFactor != obj.m_minLoadFactor){
+ return false;
+ }
+
+ if(m_maxLoadFactor != obj.m_maxLoadFactor){
+ return false;
+ }
+
+ return true;
+}
+
+void
+NdbTableImpl::assign(const NdbTableImpl& org)
+{
+ m_tableId = org.m_tableId;
+ m_internalName.assign(org.m_internalName);
+ m_externalName.assign(org.m_externalName);
+ m_newExternalName.assign(org.m_newExternalName);
+ m_frm.assign(org.m_frm.get_data(), org.m_frm.length());
+ m_fragmentType = org.m_fragmentType;
+
+ for(unsigned i = 0; i<org.m_columns.size(); i++){
+ NdbColumnImpl * col = new NdbColumnImpl();
+ const NdbColumnImpl * iorg = org.m_columns[i];
+ col->assign(* iorg);
+ m_columns.push_back(col);
+ }
+
+ m_logging = org.m_logging;
+ m_kvalue = org.m_kvalue;
+ m_minLoadFactor = org.m_minLoadFactor;
+ m_maxLoadFactor = org.m_maxLoadFactor;
+
+ if (m_index != 0)
+ delete m_index;
+ m_index = org.m_index;
+
+ m_noOfKeys = org.m_noOfKeys;
+
+ m_version = org.m_version;
+ m_status = org.m_status;
+}
+
+void NdbTableImpl::setName(const char * name)
+{
+ m_newExternalName.assign(name);
+}
+
+const char *
+NdbTableImpl::getName() const
+{
+ if (m_newExternalName.empty())
+ return m_externalName.c_str();
+ else
+ return m_newExternalName.c_str();
+}
+
+void NdbTableImpl::clearNewProperties()
+{
+ m_newExternalName.assign("");
+ m_changeMask = 0;
+}
+
+void NdbTableImpl::copyNewProperties()
+{
+ if (!m_newExternalName.empty()) {
+ m_externalName.assign(m_newExternalName);
+ AlterTableReq::setNameFlag(m_changeMask, true);
+ }
+}
+
+void
+NdbTableImpl::buildColumnHash(){
+ const Uint32 size = m_columns.size();
+
+ for(size_t i = 31; i >= 0; i--){
+ if(((1 << i) & size) != 0){
+ m_columnHashMask = (1 << (i + 1)) - 1;
+ break;
+ }
+ }
+
+ Vector<Uint32> hashValues;
+ Vector<Vector<Uint32> > chains; chains.fill(size, hashValues);
+ for(size_t i = 0; i<size; i++){
+ Uint32 hv = Hash(m_columns[i]->getName()) & 0xFFFE;
+ Uint32 bucket = hv & m_columnHashMask;
+ bucket = (bucket < size ? bucket : bucket - size);
+ assert(bucket < size);
+ hashValues.push_back(hv);
+ chains[bucket].push_back(i);
+ }
+
+ m_columnHash.clear();
+ Uint32 tmp = 1;
+ m_columnHash.fill((unsigned)size-1, tmp); // Default no chaining
+
+ Uint32 pos = 0; // In overflow vector
+ for(size_t i = 0; i<size; i++){
+ Uint32 sz = chains[i].size();
+ if(sz == 1){
+ Uint32 col = chains[i][0];
+ Uint32 hv = hashValues[col];
+ Uint32 bucket = hv & m_columnHashMask;
+ bucket = (bucket < size ? bucket : bucket - size);
+ m_columnHash[bucket] = (col << 16) | hv | 1;
+ } else if(sz > 1){
+ Uint32 col = chains[i][0];
+ Uint32 hv = hashValues[col];
+ Uint32 bucket = hv & m_columnHashMask;
+ bucket = (bucket < size ? bucket : bucket - size);
+ m_columnHash[bucket] = (sz << 16) | (((size - bucket) + pos) << 1);
+ for(size_t j = 0; j<sz; j++, pos++){
+ Uint32 col = chains[i][j];
+ Uint32 hv = hashValues[col];
+ m_columnHash.push_back((col << 16) | hv);
+ }
+ }
+ }
+
+ m_columnHash.push_back(0); // Overflow when looping in end of array
+
+#if 0
+ for(size_t i = 0; i<m_columnHash.size(); i++){
+ Uint32 tmp = m_columnHash[i];
+ int col = -1;
+ if(i < size && (tmp & 1) == 1){
+ col = (tmp >> 16);
+ } else if(i >= size){
+ col = (tmp >> 16);
+ }
+ ndbout_c("m_columnHash[%d] %s = %x",
+ i, col > 0 ? m_columns[col]->getName() : "" , m_columnHash[i]);
+ }
+#endif
+}
+
+/**
+ * NdbIndexImpl
+ */
+
+NdbIndexImpl::NdbIndexImpl() :
+ NdbDictionary::Index(* this),
+ m_facade(this)
+{
+ m_logging = true;
+}
+
+NdbIndexImpl::NdbIndexImpl(NdbDictionary::Index & f) :
+ NdbDictionary::Index(* this),
+ m_facade(&f)
+{
+ m_logging = true;
+}
+
+NdbIndexImpl::~NdbIndexImpl(){
+ for (unsigned i = 0; i < m_columns.size(); i++)
+ delete m_columns[i];
+}
+
+void NdbIndexImpl::setName(const char * name)
+{
+ m_externalName.assign(name);
+}
+
+const char *
+NdbIndexImpl::getName() const
+{
+ return m_externalName.c_str();
+}
+
+void
+NdbIndexImpl::setTable(const char * table)
+{
+ m_tableName.assign(table);
+}
+
+const char *
+NdbIndexImpl::getTable() const
+{
+ return m_tableName.c_str();
+}
+
+/**
+ * NdbEventImpl
+ */
+
+NdbEventImpl::NdbEventImpl() :
+ NdbDictionary::Event(* this),
+ m_facade(this)
+{
+ mi_type = 0;
+ m_dur = NdbDictionary::Event::ED_UNDEFINED;
+ eventOp = NULL;
+ m_tableImpl = NULL;
+}
+
+NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) :
+ NdbDictionary::Event(* this),
+ m_facade(&f)
+{
+ mi_type = 0;
+ m_dur = NdbDictionary::Event::ED_UNDEFINED;
+ eventOp = NULL;
+ m_tableImpl = NULL;
+}
+
+NdbEventImpl::~NdbEventImpl()
+{
+ for (unsigned i = 0; i < m_columns.size(); i++)
+ delete m_columns[i];
+}
+
+void NdbEventImpl::setName(const char * name)
+{
+ m_externalName.assign(name);
+}
+
+void
+NdbEventImpl::setTable(const char * table)
+{
+ m_tableName.assign(table);
+}
+
+const char *
+NdbEventImpl::getTable() const
+{
+ return m_tableName.c_str();
+}
+
+const char *
+NdbEventImpl::getName() const
+{
+ return m_externalName.c_str();
+}
+
+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
+ }
+}
+
+void
+NdbEventImpl::setDurability(const NdbDictionary::Event::EventDurability d)
+{
+ m_dur = d;
+}
+
+/**
+ * NdbDictionaryImpl
+ */
+
+NdbDictionaryImpl::NdbDictionaryImpl(Ndb &ndb)
+ : NdbDictionary::Dictionary(* this),
+ m_facade(this),
+ m_receiver(m_error),
+ m_ndb(ndb)
+{
+ m_globalHash = 0;
+}
+
+NdbDictionaryImpl::NdbDictionaryImpl(Ndb &ndb,
+ NdbDictionary::Dictionary & f)
+ : NdbDictionary::Dictionary(* this),
+ m_facade(&f),
+ m_receiver(m_error),
+ m_ndb(ndb)
+{
+ m_globalHash = 0;
+}
+
+NdbDictionaryImpl::~NdbDictionaryImpl()
+{
+ NdbElement_t<NdbTableImpl> * curr = m_localHash.m_tableHash.getNext(0);
+ while(curr != 0){
+ m_globalHash->lock();
+ m_globalHash->release(curr->theData);
+ m_globalHash->unlock();
+
+ curr = m_localHash.m_tableHash.getNext(curr);
+ }
+}
+
+void
+initDict(NdbDictionary::Dictionary & d)
+{
+ TransporterFacade * tf = TransporterFacade::instance();
+ NdbDictionaryImpl & impl = NdbDictionaryImpl::getImpl(d);
+
+ impl.m_receiver.setTransporter(tf);
+}
+
+bool
+NdbDictionaryImpl::setTransporter(class TransporterFacade * tf)
+{
+ if(tf != 0){
+ m_globalHash = &tf->m_globalDictCache;
+ return m_receiver.setTransporter(tf);
+ }
+
+ return false;
+}
+
+bool
+NdbDictionaryImpl::setTransporter(class Ndb* ndb,
+ class TransporterFacade * tf)
+{
+ m_globalHash = &tf->m_globalDictCache;
+ return m_receiver.setTransporter(ndb, tf);
+}
+
+NdbTableImpl *
+NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
+ NdbTableImpl * table)
+{
+ const char * internalName =
+ m_ndb.internalizeIndexName(table, index->getName());
+
+ return getTable(Ndb::externalizeTableName(internalName));
+}
+
+bool
+NdbDictInterface::setTransporter(class TransporterFacade * tf)
+{
+ if(tf == 0)
+ return false;
+
+ Guard g(tf->theMutexPtr);
+
+ m_blockNumber = tf->open(this,
+ execSignal,
+ execNodeStatus);
+
+ if ( m_blockNumber == -1 ) {
+ m_error.code = 4105;
+ return false; // no more free blocknumbers
+ }//if
+ Uint32 theNode = tf->ownId();
+ m_reference = numberToRef(m_blockNumber, theNode);
+ m_transporter = tf;
+ m_waiter.m_mutex = tf->theMutexPtr;
+
+ return true;
+}
+
+bool
+NdbDictInterface::setTransporter(class Ndb* ndb, class TransporterFacade * tf)
+{
+ m_blockNumber = -1;
+ m_reference = ndb->getReference();
+ m_transporter = tf;
+ m_waiter.m_mutex = tf->theMutexPtr;
+
+ return true;
+}
+
+NdbDictInterface::~NdbDictInterface()
+{
+ if (m_transporter != NULL){
+ if (m_blockNumber != -1)
+ m_transporter->close(m_blockNumber);
+ }
+}
+
+void
+NdbDictInterface::execSignal(void* dictImpl,
+ class NdbApiSignal* signal,
+ class LinearSectionPtr ptr[3])
+{
+ NdbDictInterface * tmp = (NdbDictInterface*)dictImpl;
+
+ const Uint32 gsn = signal->readSignalNumber();
+ switch(gsn){
+ case GSN_GET_TABINFOREF:
+ tmp->execGET_TABINFO_REF(signal, ptr);
+ break;
+ case GSN_GET_TABINFO_CONF:
+ tmp->execGET_TABINFO_CONF(signal, ptr);
+ break;
+ case GSN_CREATE_TABLE_REF:
+ tmp->execCREATE_TABLE_REF(signal, ptr);
+ break;
+ case GSN_CREATE_TABLE_CONF:
+ tmp->execCREATE_TABLE_CONF(signal, ptr);
+ break;
+ case GSN_DROP_TABLE_REF:
+ tmp->execDROP_TABLE_REF(signal, ptr);
+ break;
+ case GSN_DROP_TABLE_CONF:
+ tmp->execDROP_TABLE_CONF(signal, ptr);
+ break;
+ case GSN_ALTER_TABLE_REF:
+ tmp->execALTER_TABLE_REF(signal, ptr);
+ break;
+ case GSN_ALTER_TABLE_CONF:
+ tmp->execALTER_TABLE_CONF(signal, ptr);
+ break;
+ case GSN_CREATE_INDX_REF:
+ tmp->execCREATE_INDX_REF(signal, ptr);
+ break;
+ case GSN_CREATE_INDX_CONF:
+ tmp->execCREATE_INDX_CONF(signal, ptr);
+ break;
+ case GSN_DROP_INDX_REF:
+ tmp->execDROP_INDX_REF(signal, ptr);
+ break;
+ case GSN_DROP_INDX_CONF:
+ tmp->execDROP_INDX_CONF(signal, ptr);
+ break;
+ case GSN_CREATE_EVNT_REF:
+ tmp->execCREATE_EVNT_REF(signal, ptr);
+ break;
+ case GSN_CREATE_EVNT_CONF:
+ tmp->execCREATE_EVNT_CONF(signal, ptr);
+ break;
+ case GSN_SUB_START_CONF:
+ tmp->execSUB_START_CONF(signal, ptr);
+ break;
+ 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;
+ case GSN_SUB_STOP_REF:
+ tmp->execSUB_STOP_REF(signal, ptr);
+ break;
+ case GSN_DROP_EVNT_REF:
+ tmp->execDROP_EVNT_REF(signal, ptr);
+ break;
+ case GSN_DROP_EVNT_CONF:
+ tmp->execDROP_EVNT_CONF(signal, ptr);
+ break;
+ case GSN_LIST_TABLES_CONF:
+ tmp->execLIST_TABLES_CONF(signal, ptr);
+ break;
+ default:
+ abort();
+ }
+}
+
+void
+NdbDictInterface::execNodeStatus(void* dictImpl, NodeId aNode,
+ bool alive, bool nfCompleted)
+{
+ NdbDictInterface * tmp = (NdbDictInterface*)dictImpl;
+
+ if(!alive && !nfCompleted){
+ return;
+ }
+
+ if (!alive && nfCompleted){
+ tmp->m_waiter.nodeFail(aNode);
+ }
+}
+
+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)
+{
+ 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();
+ }
+ if(aNodeId == 0){
+ m_error.code = 4009;
+ m_transporter->unlock_mutex();
+ 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;
+ }
+ }
+
+ m_error.code = 0;
+
+ m_waiter.m_node = aNodeId;
+ m_waiter.m_state = wst;
+
+ m_waiter.wait(theWait);
+ // End of Protected area
+
+ if(m_waiter.m_state == NO_WAIT && m_error.code == 0){
+ // Normal return
+ return 0;
+ }
+
+ /**
+ * Handle error codes
+ */
+ if(m_waiter.m_state == WAIT_NODE_FAILURE)
+ continue;
+
+ 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;
+ continue;
+ }
+ if (doContinue)
+ continue;
+ }
+
+ return -1;
+ }
+ return -1;
+}
+
+/*****************************************************************
+ * get tab info
+ */
+NdbTableImpl *
+NdbDictInterface::getTable(int tableId)
+{
+ NdbApiSignal tSignal(m_reference);
+ GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->requestType =
+ GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
+ req->tableId = tableId;
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_GET_TABINFOREQ;
+ tSignal.theLength = GetTabInfoReq::SignalLength;
+
+ return getTable(&tSignal, 0, 0);
+}
+
+NdbTableImpl *
+NdbDictInterface::getTable(const char * name)
+{
+ NdbApiSignal tSignal(m_reference);
+ GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, tSignal.getDataPtrSend());
+
+ const Uint32 strLen = strlen(name) + 1; // NULL Terminated
+ if(strLen > MAX_TAB_NAME_SIZE) {//sizeof(req->tableName)){
+ m_error.code = 4307;
+ return 0;
+ }
+
+ 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::HeaderLength + ((strLen + 3) / 4);
+ tSignal.theLength = GetTabInfoReq::SignalLength;
+ LinearSectionPtr ptr[1];
+ ptr[0].p = (Uint32*)name;
+ ptr[0].sz = strLen;
+
+ return getTable(&tSignal, ptr, 1);
+}
+
+NdbTableImpl *
+NdbDictInterface::getTable(class NdbApiSignal * signal,
+ LinearSectionPtr ptr[3],
+ Uint32 noOfSections)
+{
+ //GetTabInfoReq * const req = CAST_PTR(GetTabInfoReq, signal->getDataPtrSend());
+ int r = dictSignal(signal,ptr,noOfSections,
+ 0/*do not use masternode id*/,
+ 100,
+ WAIT_GET_TAB_INFO_REQ,
+ WAITFOR_RESPONSE_TIMEOUT,
+ NULL,0);
+ if (r) return 0;
+
+ NdbTableImpl * rt = 0;
+ m_error.code = parseTableInfo(&rt,
+ (Uint32*)m_buffer.get_data(),
+ m_buffer.length() / 4);
+ rt->buildColumnHash();
+ return rt;
+}
+
+void
+NdbDictInterface::execGET_TABINFO_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const GetTabInfoConf* conf = CAST_CONSTPTR(GetTabInfoConf, signal->getDataPtr());
+ if(signal->isFirstFragment()){
+ m_fragmentId = signal->getFragmentId();
+ m_buffer.grow(4 * conf->totalLen);
+ } else {
+ if(m_fragmentId != signal->getFragmentId()){
+ abort();
+ }
+ }
+
+ const Uint32 i = GetTabInfoConf::DICT_TAB_INFO;
+ m_buffer.append(ptr[i].p, 4 * ptr[i].sz);
+
+ if(!signal->isLastFragment()){
+ return;
+ }
+
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execGET_TABINFO_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const GetTabInfoRef* ref = CAST_CONSTPTR(GetTabInfoRef, signal->getDataPtr());
+
+ m_error.code = ref->errorCode;
+ m_waiter.signal(NO_WAIT);
+}
+
+/*****************************************************************
+ * Pack/Unpack tables
+ */
+struct ApiKernelMapping {
+ Int32 kernelConstant;
+ Int32 apiConstant;
+};
+
+Uint32
+getApiConstant(Int32 kernelConstant, const ApiKernelMapping map[], Uint32 def)
+{
+ int i = 0;
+ while(map[i].kernelConstant != kernelConstant){
+ if(map[i].kernelConstant == -1 &&
+ map[i].apiConstant == -1){
+ return def;
+ }
+ i++;
+ }
+ return map[i].apiConstant;
+}
+
+Uint32
+getKernelConstant(Int32 apiConstant, const ApiKernelMapping map[], Uint32 def)
+{
+ int i = 0;
+ while(map[i].apiConstant != apiConstant){
+ if(map[i].kernelConstant == -1 &&
+ map[i].apiConstant == -1){
+ return def;
+ }
+ i++;
+ }
+ return map[i].kernelConstant;
+}
+
+static const
+ApiKernelMapping
+fragmentTypeMapping[] = {
+ { DictTabInfo::AllNodesSmallTable, NdbDictionary::Object::FragAllSmall },
+ { DictTabInfo::AllNodesMediumTable, NdbDictionary::Object::FragAllMedium },
+ { DictTabInfo::AllNodesLargeTable, NdbDictionary::Object::FragAllLarge },
+ { DictTabInfo::SingleFragment, NdbDictionary::Object::FragSingle },
+ { -1, -1 }
+};
+
+static const
+ApiKernelMapping
+objectTypeMapping[] = {
+ { DictTabInfo::SystemTable, NdbDictionary::Object::SystemTable },
+ { DictTabInfo::UserTable, NdbDictionary::Object::UserTable },
+ { DictTabInfo::UniqueHashIndex, NdbDictionary::Object::UniqueHashIndex },
+ { DictTabInfo::HashIndex, NdbDictionary::Object::HashIndex },
+ { DictTabInfo::UniqueOrderedIndex, NdbDictionary::Object::UniqueOrderedIndex },
+ { DictTabInfo::OrderedIndex, NdbDictionary::Object::OrderedIndex },
+ { DictTabInfo::HashIndexTrigger, NdbDictionary::Object::HashIndexTrigger },
+ { DictTabInfo::IndexTrigger, NdbDictionary::Object::IndexTrigger },
+ { DictTabInfo::SubscriptionTrigger,NdbDictionary::Object::SubscriptionTrigger },
+ { DictTabInfo::ReadOnlyConstraint ,NdbDictionary::Object::ReadOnlyConstraint },
+ { -1, -1 }
+};
+
+static const
+ApiKernelMapping
+objectStateMapping[] = {
+ { DictTabInfo::StateOffline, NdbDictionary::Object::StateOffline },
+ { DictTabInfo::StateBuilding, NdbDictionary::Object::StateBuilding },
+ { DictTabInfo::StateDropping, NdbDictionary::Object::StateDropping },
+ { DictTabInfo::StateOnline, NdbDictionary::Object::StateOnline },
+ { DictTabInfo::StateBroken, NdbDictionary::Object::StateBroken },
+ { -1, -1 }
+};
+
+static const
+ApiKernelMapping
+objectStoreMapping[] = {
+ { DictTabInfo::StoreTemporary, NdbDictionary::Object::StoreTemporary },
+ { DictTabInfo::StorePermanent, NdbDictionary::Object::StorePermanent },
+ { -1, -1 }
+};
+
+static const
+ApiKernelMapping
+indexTypeMapping[] = {
+ { DictTabInfo::UniqueHashIndex, NdbDictionary::Index::UniqueHashIndex },
+ { DictTabInfo::HashIndex, NdbDictionary::Index::HashIndex },
+ { DictTabInfo::UniqueOrderedIndex, NdbDictionary::Index::UniqueOrderedIndex},
+ { DictTabInfo::OrderedIndex, NdbDictionary::Index::OrderedIndex },
+ { -1, -1 }
+};
+
+static const
+ApiKernelMapping
+columnTypeMapping[] = {
+ { DictTabInfo::ExtTinyint, NdbDictionary::Column::Tinyint },
+ { DictTabInfo::ExtTinyunsigned, NdbDictionary::Column::Tinyunsigned },
+ { DictTabInfo::ExtSmallint, NdbDictionary::Column::Smallint },
+ { DictTabInfo::ExtSmallunsigned, NdbDictionary::Column::Smallunsigned },
+ { DictTabInfo::ExtMediumint, NdbDictionary::Column::Mediumint },
+ { DictTabInfo::ExtMediumunsigned, NdbDictionary::Column::Mediumunsigned },
+ { DictTabInfo::ExtInt, NdbDictionary::Column::Int },
+ { DictTabInfo::ExtUnsigned, NdbDictionary::Column::Unsigned },
+ { DictTabInfo::ExtBigint, NdbDictionary::Column::Bigint },
+ { DictTabInfo::ExtBigunsigned, NdbDictionary::Column::Bigunsigned },
+ { DictTabInfo::ExtFloat, NdbDictionary::Column::Float },
+ { DictTabInfo::ExtDouble, NdbDictionary::Column::Double },
+ { DictTabInfo::ExtDecimal, NdbDictionary::Column::Decimal },
+ { DictTabInfo::ExtChar, NdbDictionary::Column::Char },
+ { DictTabInfo::ExtVarchar, NdbDictionary::Column::Varchar },
+ { DictTabInfo::ExtBinary, NdbDictionary::Column::Binary },
+ { DictTabInfo::ExtVarbinary, NdbDictionary::Column::Varbinary },
+ { DictTabInfo::ExtDatetime, NdbDictionary::Column::Datetime },
+ { DictTabInfo::ExtTimespec, NdbDictionary::Column::Timespec },
+ { -1, -1 }
+};
+
+int
+NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
+ const Uint32 * data, Uint32 len)
+{
+ SimplePropertiesLinearReader it(data, len);
+ DictTabInfo::Table tableDesc; tableDesc.init();
+ SimpleProperties::UnpackStatus s;
+ s = SimpleProperties::unpack(it, &tableDesc,
+ DictTabInfo::TableMapping,
+ DictTabInfo::TableMappingSize,
+ true, true);
+
+ if(s != SimpleProperties::Break){
+ return 703;
+ }
+ const char * internalName = tableDesc.TableName;
+ const char * externalName = Ndb::externalizeTableName(internalName);
+
+ NdbTableImpl * impl = new NdbTableImpl();
+ impl->m_tableId = tableDesc.TableId;
+ impl->m_version = tableDesc.TableVersion;
+ impl->m_status = NdbDictionary::Object::Retrieved;
+ impl->m_internalName.assign(internalName);
+ impl->m_externalName.assign(externalName);
+
+ impl->m_frm.assign(tableDesc.FrmData, tableDesc.FrmLen);
+
+ impl->m_fragmentType = (NdbDictionary::Object::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;
+
+ impl->m_indexType = (NdbDictionary::Index::Type)
+ getApiConstant(tableDesc.TableType,
+ indexTypeMapping,
+ NdbDictionary::Index::Undefined);
+
+ if(impl->m_indexType == NdbDictionary::Index::Undefined){
+ } else {
+ const char * externalPrimary =
+ Ndb::externalizeTableName(tableDesc.PrimaryTable);
+ impl->m_primaryTable.assign(externalPrimary);
+ }
+
+ Uint32 keyInfoPos = 0;
+ Uint32 keyCount = 0;
+
+ for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) {
+ DictTabInfo::Attribute attrDesc; attrDesc.init();
+ s = SimpleProperties::unpack(it,
+ &attrDesc,
+ DictTabInfo::AttributeMapping,
+ DictTabInfo::AttributeMappingSize,
+ true, true);
+ if(s != SimpleProperties::Break){
+ delete impl;
+ return 703;
+ }
+
+ NdbColumnImpl * col = new NdbColumnImpl();
+ col->m_attrId = attrDesc.AttributeId;
+ col->setName(attrDesc.AttributeName);
+ col->m_type = (NdbDictionary::Column::Type)
+ getApiConstant(attrDesc.AttributeExtType,
+ columnTypeMapping,
+ NdbDictionary::Column::Undefined);
+ if (col->m_type == NdbDictionary::Column::Undefined) {
+ delete impl;
+ return 703;
+ }
+ col->m_extType = attrDesc.AttributeExtType;
+ col->m_precision = attrDesc.AttributeExtPrecision;
+ col->m_scale = attrDesc.AttributeExtScale;
+ col->m_length = attrDesc.AttributeExtLength;
+
+ // translate to old kernel types and sizes
+ if (! attrDesc.translateExtType()) {
+ delete impl;
+ return 703;
+ }
+ col->m_attrType =attrDesc.AttributeType;
+ col->m_attrSize = (1 << attrDesc.AttributeSize) / 8;
+ col->m_arraySize = attrDesc.AttributeArraySize;
+
+ col->m_pk = attrDesc.AttributeKeyFlag;
+ col->m_tupleKey = 0;
+ col->m_distributionKey = attrDesc.AttributeDKey;
+ col->m_distributionGroup = attrDesc.AttributeDGroup;
+ col->m_distributionGroupBits = 16;
+ col->m_nullable = attrDesc.AttributeNullableFlag;
+ col->m_indexOnly = (attrDesc.AttributeStoredInd ? false : true);
+ 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++;
+ } else {
+ col->m_keyInfoPos = 0;
+ }
+
+ NdbColumnImpl * null = 0;
+ impl->m_columns.fill(attrDesc.AttributeId, null);
+ if(impl->m_columns[attrDesc.AttributeId] != 0){
+ delete col;
+ delete impl;
+ return 703;
+ }
+ impl->m_columns[attrDesc.AttributeId] = col;
+ it.next();
+ }
+ impl->m_noOfKeys = keyCount;
+ * ret = impl;
+ return 0;
+}
+
+/*****************************************************************
+ * Create table and alter table
+ */
+int
+NdbDictInterface::createTable(Ndb & ndb,
+ NdbTableImpl & impl)
+{
+ return createOrAlterTable(ndb, impl, false);
+}
+
+int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
+{
+ BaseString internalName = impl.m_internalName;
+ const char * originalInternalName = internalName.c_str();
+ BaseString externalName = impl.m_externalName;
+ const char * originalExternalName = externalName.c_str();
+ NdbTableImpl * oldTab = getTable(originalExternalName);
+
+ if(!oldTab){
+ m_error.code = 709;
+ 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
+ if (m_localHash.get(originalInternalName) != NULL) {
+ m_localHash.drop(originalInternalName);
+ NdbTableImpl * cachedImpl = m_globalHash->get(originalInternalName);
+ // If in local cache it must be in global
+ if (!cachedImpl)
+ abort();
+ m_globalHash->lock();
+ m_globalHash->drop(cachedImpl);
+ m_globalHash->unlock();
+ }
+ }
+
+ return ret;
+}
+
+int
+NdbDictInterface::alterTable(Ndb & ndb,
+ NdbTableImpl & impl)
+{
+ return createOrAlterTable(ndb, impl, true);
+}
+
+int
+NdbDictInterface::createOrAlterTable(Ndb & ndb,
+ NdbTableImpl & impl,
+ bool alter)
+{
+ if((unsigned)impl.getNoOfPrimaryKeys() > MAXNROFTUPLEKEY){
+ m_error.code = 4317;
+ return -1;
+ }
+ unsigned sz = impl.m_columns.size();
+ if (sz > NDB_MAX_ATTRIBUTES_IN_TABLE){
+ m_error.code = 4318;
+ return -1;
+ }
+
+ impl.copyNewProperties();
+ //validate();
+ //aggregate();
+
+ const char * internalName =
+ ndb.internalizeTableName(impl.m_externalName.c_str());
+ impl.m_internalName.assign(internalName);
+ UtilBufferWriter w(m_buffer);
+ DictTabInfo::Table tmpTab; tmpTab.init();
+ snprintf(tmpTab.TableName,
+ sizeof(tmpTab.TableName),
+ internalName);
+
+ bool haveAutoIncrement = false;
+ Uint64 autoIncrementValue;
+ for(unsigned 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;
+ return -1;
+ }
+ haveAutoIncrement = true;
+ autoIncrementValue = col->m_autoIncrementInitialValue;
+ }
+ }
+
+ // Check max length of frm data
+ if (impl.m_frm.length() > MAX_FRM_DATA_SIZE){
+ m_error.code = 1229;
+ return -1;
+ }
+ tmpTab.FrmLen = impl.m_frm.length();
+ memcpy(tmpTab.FrmData, impl.m_frm.get_data(), impl.m_frm.length());
+
+ 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();
+
+ SimpleProperties::UnpackStatus s;
+ s = SimpleProperties::pack(w,
+ &tmpTab,
+ DictTabInfo::TableMapping,
+ DictTabInfo::TableMappingSize, true);
+
+ if(s != SimpleProperties::Eof){
+ abort();
+ }
+
+ for(unsigned i = 0; i<sz; i++){
+ const NdbColumnImpl * col = impl.m_columns[i];
+ if(col == 0)
+ continue;
+
+ DictTabInfo::Attribute tmpAttr; tmpAttr.init();
+ snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
+ col->m_name.c_str());
+ tmpAttr.AttributeId = i;
+ tmpAttr.AttributeKeyFlag = col->m_pk || col->m_tupleKey;
+ tmpAttr.AttributeNullableFlag = col->m_nullable;
+ tmpAttr.AttributeStoredInd = (col->m_indexOnly ? 0 : 1);
+ tmpAttr.AttributeDKey = col->m_distributionKey;
+ tmpAttr.AttributeDGroup = col->m_distributionGroup;
+
+ tmpAttr.AttributeExtType =
+ getKernelConstant(col->m_type,
+ columnTypeMapping,
+ DictTabInfo::ExtUndefined);
+ tmpAttr.AttributeExtPrecision = col->m_precision;
+ tmpAttr.AttributeExtScale = col->m_scale;
+ tmpAttr.AttributeExtLength = col->m_length;
+
+ // DICT will ignore and recompute this
+ (void)tmpAttr.translateExtType();
+
+ tmpAttr.AttributeAutoIncrement = col->m_autoIncrement;
+ snprintf(tmpAttr.AttributeDefaultValue,
+ sizeof(tmpAttr.AttributeDefaultValue),
+ col->m_defaultValue.c_str());
+ s = SimpleProperties::pack(w,
+ &tmpAttr,
+ DictTabInfo::AttributeMapping,
+ DictTabInfo::TableMappingSize, true);
+ w.add(DictTabInfo::AttributeEnd, 1);
+ }
+
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ if (alter) {
+ AlterTableReq * const req =
+ CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
+
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->changeMask = impl.m_changeMask;
+ req->tableId = impl.m_tableId;
+ req->tableVersion = impl.m_version;;
+ tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ;
+ tSignal.theLength = AlterTableReq::SignalLength;
+ }
+ else {
+ CreateTableReq * const req =
+ CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
+
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ tSignal.theVerId_signalNumber = GSN_CREATE_TABLE_REQ;
+ tSignal.theLength = CreateTableReq::SignalLength;
+ }
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ ptr[0].sz = m_buffer.length() / 4;
+
+ int ret = (alter) ?
+ alterTable(&tSignal, ptr)
+ : createTable(&tSignal, ptr);
+
+ if (haveAutoIncrement) {
+ // if (!ndb.setAutoIncrementValue(impl.m_internalName.c_str(), autoIncrementValue)) {
+ if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(), autoIncrementValue)) {
+ m_error.code = 4336;
+ ndb.theError = m_error;
+ ret = -1; // errorcode set in initialize_autoincrement
+ }
+ }
+ 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])
+{
+ //CreateTableConf* const conf = CAST_PTR(CreateTableConf, signal->getDataPtr());
+
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execCREATE_TABLE_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const CreateTableRef* const ref = CAST_CONSTPTR(CreateTableRef, signal->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,
+ LinearSectionPtr ptr[3])
+{
+ const AlterTableRef * const ref =
+ CAST_CONSTPTR(AlterTableRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+/*****************************************************************
+ * Drop table
+ */
+int
+NdbDictionaryImpl::dropTable(const char * name)
+{
+ NdbTableImpl * tab = getTable(name);
+ if(tab == 0){
+ return -1;
+ }
+ int ret = dropTable(* tab);
+ // If table stored in cache is incompatible with the one in the kernel
+ // we must clear the cache and try again
+ if (ret == INCOMPATIBLE_VERSION) {
+ const char * internalTableName = m_ndb.internalizeTableName(name);
+
+ m_localHash.drop(internalTableName);
+
+ m_globalHash->lock();
+ m_globalHash->drop(tab);
+ m_globalHash->unlock();
+ return dropTable(name);
+ }
+
+ return ret;
+}
+
+int
+NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
+{
+ const char * name = impl.getName();
+ if(impl.m_status == NdbDictionary::Object::New){
+ return dropTable(name);
+ }
+
+ if (impl.m_indexType != NdbDictionary::Index::Undefined) {
+ m_receiver.m_error.code = 1228;
+ return -1;
+ }
+
+ List list;
+ if (listIndexes(list, name) == -1)
+ return -1;
+ for (unsigned i = 0; i < list.count; i++) {
+ const List::Element& element = list.elements[i];
+ if (dropIndex(element.name, name) == -1)
+ return -1;
+ }
+ int ret = m_receiver.dropTable(impl);
+ if(ret == 0){
+ const char * internalTableName = impl.m_internalName.c_str();
+
+ m_localHash.drop(internalTableName);
+
+ m_globalHash->lock();
+ m_globalHash->drop(&impl);
+ m_globalHash->unlock();
+ }
+
+ return ret;
+}
+
+int
+NdbDictInterface::dropTable(const NdbTableImpl & impl)
+{
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_DROP_TABLE_REQ;
+ tSignal.theLength = DropTableReq::SignalLength;
+
+ DropTableReq * const req = CAST_PTR(DropTableReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->tableId = impl.m_tableId;
+ 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);
+ if(m_error.code == DropTableRef::InvalidTableVersion) {
+ // Clear caches and try again
+ return INCOMPATIBLE_VERSION;
+ }
+ return r;
+}
+
+void
+NdbDictInterface::execDROP_TABLE_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ //DropTableConf* const conf = CAST_CONSTPTR(DropTableConf, signal->getDataPtr());
+
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execDROP_TABLE_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const DropTableRef* const ref = CAST_CONSTPTR(DropTableRef, signal->getDataPtr());
+ m_error.code = ref->errorCode;
+ m_masterNodeId = ref->masterNodeId;
+ m_waiter.signal(NO_WAIT);
+}
+
+int
+NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
+{
+ const char * internalTableName = impl.m_internalName.c_str();
+
+ m_localHash.drop(internalTableName);
+ m_globalHash->lock();
+ m_globalHash->drop(&impl);
+ m_globalHash->unlock();
+ return 0;
+}
+
+int
+NdbDictionaryImpl::removeCachedObject(NdbTableImpl & impl)
+{
+ const char * internalTableName = impl.m_internalName.c_str();
+
+ m_localHash.drop(internalTableName);
+ m_globalHash->lock();
+ m_globalHash->release(&impl);
+ m_globalHash->unlock();
+ return 0;
+}
+
+/*****************************************************************
+ * Get index info
+ */
+NdbIndexImpl*
+NdbDictionaryImpl::getIndexImpl(const char * externalName,
+ const char * internalName)
+{
+ NdbTableImpl* tab = getTableImpl(internalName);
+ if(tab == 0){
+ m_error.code = 4243;
+ return 0;
+ }
+
+ if(tab->m_indexType == NdbDictionary::Index::Undefined){
+ // Not an index
+ m_error.code = 4243;
+ return 0;
+ }
+
+ NdbTableImpl* primTab = getTable(tab->m_primaryTable.c_str());
+ if(primTab == 0){
+ m_error.code = 4243;
+ return 0;
+ }
+
+ /**
+ * Create index impl
+ */
+ NdbIndexImpl* idx = new NdbIndexImpl();
+ idx->m_version = tab->m_version;
+ idx->m_status = tab->m_status;
+ idx->m_indexId = tab->m_tableId;
+ idx->m_internalName.assign(internalName);
+ idx->m_externalName.assign(externalName);
+ idx->m_tableName.assign(primTab->m_externalName);
+ idx->m_type = tab->m_indexType;
+ // skip last attribute (NDB$PK or NDB$TNODE)
+ for(unsigned i = 0; i+1<tab->m_columns.size(); i++){
+ NdbColumnImpl* col = new NdbColumnImpl;
+ // Copy column definition
+ *col = *tab->m_columns[i];
+ idx->m_columns.push_back(col);
+ }
+
+ idx->m_table = tab;
+ // TODO Assign idx to tab->m_index
+ // Don't do it right now since assign can't asign a table with index
+ // tab->m_index = idx;
+ return idx;
+}
+
+/*****************************************************************
+ * Create index
+ */
+int
+NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
+{
+ NdbTableImpl* tab = getTable(ix.getTable());
+ if(tab == 0){
+ m_error.code = 4249;
+ return -1;
+ }
+
+ return m_receiver.createIndex(m_ndb, ix, * tab);
+}
+
+int
+NdbDictInterface::createIndex(Ndb & ndb,
+ NdbIndexImpl & impl,
+ const NdbTableImpl & table)
+{
+ //validate();
+ //aggregate();
+
+ UtilBufferWriter w(m_buffer);
+ const size_t len = strlen(impl.m_externalName.c_str()) + 1;
+ if(len > MAX_TAB_NAME_SIZE) {
+ m_error.code = 4241;
+ return -1;
+ }
+ const char * internalName =
+ ndb.internalizeIndexName(&table, impl.getName());
+
+ impl.m_internalName.assign(internalName);
+
+ w.add(DictTabInfo::TableName, internalName);
+ w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
+
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_CREATE_INDX_REQ;
+ tSignal.theLength = CreateIndxReq::SignalLength;
+
+ CreateIndxReq * const req = CAST_PTR(CreateIndxReq, tSignal.getDataPtrSend());
+
+ req->setUserRef(m_reference);
+ req->setConnectionPtr(0);
+ req->setRequestType(CreateIndxReq::RT_USER);
+
+ Uint32 it = getKernelConstant(impl.m_type,
+ indexTypeMapping,
+ DictTabInfo::UndefTableType);
+
+ if(it == DictTabInfo::UndefTableType){
+ m_error.code = 4250;
+ return -1;
+ }
+ req->setIndexType((DictTabInfo::TableType) it);
+
+ req->setTableId(table.m_tableId);
+ req->setOnline(true);
+ AttributeList attributeList;
+ attributeList.sz = impl.m_columns.size();
+ for(unsigned i = 0; i<attributeList.sz; i++){
+ const NdbColumnImpl* col =
+ table.getColumn(impl.m_columns[i]->m_name.c_str());
+ if(col == 0){
+ m_error.code = 4247;
+ return -1;
+ }
+ // Copy column definition
+ *impl.m_columns[i] = *col;
+
+ if(col->m_pk && col->m_indexOnly){
+ m_error.code = 4245;
+ return -1;
+ }
+
+ if (it == DictTabInfo::UniqueHashIndex &&
+ (col->m_nullable) && (attributeList.sz > 1)) {
+ // We only support one NULL attribute
+ m_error.code = 4246;
+ return -1;
+ }
+ attributeList.id[i] = col->m_attrId;
+ }
+ if (it == DictTabInfo::UniqueHashIndex) {
+ // Sort index attributes according to primary table (using insertion sort)
+ for(unsigned i = 1; i < attributeList.sz; i++) {
+ unsigned int temp = attributeList.id[i];
+ unsigned int j = i;
+ while((j > 0) && (attributeList.id[j - 1] > temp)) {
+ attributeList.id[j] = attributeList.id[j - 1];
+ j--;
+ }
+ attributeList.id[j] = temp;
+ }
+ // Check for illegal duplicate attributes
+ for(unsigned i = 0; i<attributeList.sz; i++) {
+ if ((i != (attributeList.sz - 1)) &&
+ (attributeList.id[i] == attributeList.id[i+1])) {
+ m_error.code = 4258;
+ return -1;
+ }
+ }
+ }
+ LinearSectionPtr ptr[3];
+ 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 = 1;
+ int errCodes[noErrCodes] = {CreateIndxRef::Busy};
+ return dictSignal(signal,ptr,2,
+ 1 /*use masternode id*/,
+ 100,
+ WAIT_CREATE_INDX_REQ,
+ -1,
+ errCodes,noErrCodes);
+}
+
+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,
+ LinearSectionPtr ptr[3])
+{
+ const CreateIndxRef* const ref = CAST_CONSTPTR(CreateIndxRef, signal->getDataPtr());
+ m_error.code = ref->getErrorCode();
+ m_waiter.signal(NO_WAIT);
+}
+
+/*****************************************************************
+ * Drop index
+ */
+int
+NdbDictionaryImpl::dropIndex(const char * indexName,
+ const char * tableName)
+{
+ NdbIndexImpl * idx = getIndex(indexName, tableName);
+ if (idx == 0) {
+ m_error.code = 4243;
+ return -1;
+ }
+ int ret = dropIndex(*idx, tableName);
+ // If index stored in cache is incompatible with the one in the kernel
+ // we must clear the cache and try again
+ if (ret == INCOMPATIBLE_VERSION) {
+ const char * internalIndexName = (tableName)
+ ?
+ m_ndb.internalizeIndexName(getTable(tableName), indexName)
+ :
+ m_ndb.internalizeTableName(indexName); // Index is also a table
+
+ m_localHash.drop(internalIndexName);
+
+ m_globalHash->lock();
+ m_globalHash->drop(idx->m_table);
+ m_globalHash->unlock();
+ return dropIndex(indexName, tableName);
+ }
+
+ return ret;
+}
+
+int
+NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
+{
+ const char * indexName = impl.getName();
+ if (tableName || Ndb::usingFullyQualifiedNames()) {
+ NdbTableImpl * timpl = impl.m_table;
+
+ if (timpl == 0) {
+ m_error.code = 709;
+ return -1;
+ }
+
+ const char * internalIndexName = (tableName)
+ ?
+ m_ndb.internalizeIndexName(getTable(tableName), indexName)
+ :
+ m_ndb.internalizeTableName(indexName); // Index is also a table
+
+ if(impl.m_status == NdbDictionary::Object::New){
+ return dropIndex(indexName, tableName);
+ }
+
+ int ret = m_receiver.dropIndex(impl, *timpl);
+ if(ret == 0){
+ m_localHash.drop(internalIndexName);
+
+ m_globalHash->lock();
+ m_globalHash->drop(impl.m_table);
+ m_globalHash->unlock();
+ }
+
+ return ret;
+ }
+
+ m_error.code = 4243;
+ return -1;
+}
+
+int
+NdbDictInterface::dropIndex(const NdbIndexImpl & impl,
+ const NdbTableImpl & timpl)
+{
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_DROP_INDX_REQ;
+ tSignal.theLength = DropIndxReq::SignalLength;
+
+ DropIndxReq * const req = CAST_PTR(DropIndxReq, tSignal.getDataPtrSend());
+ req->setUserRef(m_reference);
+ req->setConnectionPtr(0);
+ req->setRequestType(DropIndxReq::RT_USER);
+ req->setTableId(~0); // DICT overwrites
+ req->setIndexId(timpl.m_tableId);
+ req->setIndexVersion(timpl.m_version);
+
+ return dropIndex(&tSignal, 0);
+}
+
+int
+NdbDictInterface::dropIndex(NdbApiSignal* signal, LinearSectionPtr ptr[3])
+{
+ const int noErrCodes = 1;
+ int errCodes[noErrCodes] = {DropIndxRef::Busy};
+ int r = dictSignal(signal,NULL,0,
+ 1/*Use masternode id*/,
+ 100,
+ WAIT_DROP_INDX_REQ,
+ WAITFOR_RESPONSE_TIMEOUT,
+ errCodes,noErrCodes);
+ if(m_error.code == DropIndxRef::InvalidIndexVersion) {
+ // Clear caches and try again
+ return INCOMPATIBLE_VERSION;
+ }
+ return r;
+}
+
+void
+NdbDictInterface::execDROP_INDX_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execDROP_INDX_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+ const DropIndxRef* const ref = CAST_CONSTPTR(DropIndxRef, signal->getDataPtr());
+ m_error.code = ref->getErrorCode();
+ m_waiter.signal(NO_WAIT);
+}
+
+/*****************************************************************
+ * Create event
+ */
+
+int
+NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
+{
+ NdbTableImpl* tab = getTable(evnt.getTable());
+
+ if(tab == 0){
+ // m_error.code = 3249;
+ ndbout_c(":createEvent: table %s not found", evnt.getTable());
+#ifdef EVENT_DEBUG
+ ndbout_c("NdbDictionaryImpl::createEvent: table not found: %s", evnt.getTable());
+#endif
+ return -1;
+ }
+
+ evnt.m_tableId = tab->m_tableId;
+ evnt.m_tableImpl = tab;
+#ifdef EVENT_DEBUG
+ ndbout_c("Event on tableId=%d", evnt.m_tableId);
+#endif
+
+ NdbTableImpl &table = *evnt.m_tableImpl;
+
+
+ int attributeList_sz = evnt.m_attrIds.size();
+
+ for (int i = 0; i < attributeList_sz; i++) {
+ NdbColumnImpl *col_impl = table.getColumn(evnt.m_attrIds[i]);
+ if (col_impl) {
+ evnt.m_facade->addColumn(*(col_impl->m_facade));
+ } else {
+ ndbout_c("Attr id %u in table %s not found", evnt.m_attrIds[i],
+ evnt.getTable());
+ return -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
+ int pk_count = 0;
+ evnt.m_attrListBitmask.clear();
+
+ for(int i = 0; i<attributeList_sz; i++){
+ const NdbColumnImpl* col =
+ table.getColumn(evnt.m_columns[i]->m_name.c_str());
+ if(col == 0){
+ m_error.code = 4247;
+ return -1;
+ }
+ // Copy column definition
+ *evnt.m_columns[i] = *col;
+
+ if(col->m_pk){
+ pk_count++;
+ }
+
+ evnt.m_attrListBitmask.set(col->m_attrId);
+ }
+
+ // Sort index attributes according to primary table (using insertion sort)
+ for(int i = 1; i < attributeList_sz; i++) {
+ NdbColumnImpl* temp = evnt.m_columns[i];
+ unsigned int j = i;
+ while((j > 0) && (evnt.m_columns[j - 1]->m_attrId > temp->m_attrId)) {
+ evnt.m_columns[j] = evnt.m_columns[j - 1];
+ j--;
+ }
+ evnt.m_columns[j] = temp;
+ }
+ // Check for illegal duplicate attributes
+ for(int 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;
+ }
+ }
+
+#ifdef EVENT_DEBUG
+ char buf[128] = {0};
+ evnt.m_attrListBitmask.getText(buf);
+ ndbout_c("createEvent: mask = %s", buf);
+#endif
+
+ // NdbDictInterface m_receiver;
+ return m_receiver.createEvent(m_ndb, evnt, 0 /* getFlag unset */);
+}
+
+int
+NdbDictInterface::createEvent(class Ndb & ndb,
+ NdbEventImpl & evnt,
+ int getFlag)
+{
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_CREATE_EVNT_REQ;
+ if (getFlag)
+ tSignal.theLength = CreateEvntReq::SignalLengthGet;
+ else
+ tSignal.theLength = CreateEvntReq::SignalLengthCreate;
+
+ CreateEvntReq * const req = CAST_PTR(CreateEvntReq, tSignal.getDataPtrSend());
+
+ req->setUserRef(m_reference);
+ req->setUserData(0);
+
+ if (getFlag) {
+ // getting event from Dictionary
+ req->setRequestType(CreateEvntReq::RT_USER_GET);
+ } else {
+ // creating event in Dictionary
+ req->setRequestType(CreateEvntReq::RT_USER_CREATE);
+ req->setTableId(evnt.m_tableId);
+ req->setAttrListBitmask(evnt.m_attrListBitmask);
+ req->setEventType(evnt.mi_type);
+ }
+
+ UtilBufferWriter w(m_buffer);
+
+ const size_t len = strlen(evnt.m_externalName.c_str()) + 1;
+ if(len > MAX_TAB_NAME_SIZE) {
+ m_error.code = 4241;
+ return -1;
+ }
+
+ w.add(SimpleProperties::StringValue, evnt.m_externalName.c_str());
+
+ if (getFlag == 0)
+ w.add(SimpleProperties::StringValue,
+ ndb.internalizeTableName(evnt.m_tableName.c_str()));
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ ptr[0].sz = (m_buffer.length()+3) >> 2;
+
+ int ret = createEvent(&tSignal, ptr, 1);
+
+ if (ret) {
+ return ret;
+ }
+
+ char *dataPtr = (char *)m_buffer.get_data();
+ unsigned int lenCreateEvntConf = *((unsigned int *)dataPtr);
+ dataPtr += sizeof(lenCreateEvntConf);
+ CreateEvntConf const * evntConf = (CreateEvntConf *)dataPtr;
+ dataPtr += lenCreateEvntConf;
+
+ // NdbEventImpl *evntImpl = (NdbEventImpl *)evntConf->getUserData();
+
+ 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() ||
+ //evnt.m_attrListBitmask != evntConf->getAttrListBitmask() ||
+ evnt.mi_type != evntConf->getEventType()) {
+ ndbout_c("ERROR*************");
+ return 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);
+}
+
+int
+NdbDictionaryImpl::executeSubscribeEvent(NdbEventImpl & ev)
+{
+ // NdbDictInterface m_receiver;
+ return m_receiver.executeSubscribeEvent(m_ndb, ev);
+}
+
+int
+NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
+ NdbEventImpl & evnt)
+{
+ 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;
+
+ 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);
+}
+
+int
+NdbDictionaryImpl::stopSubscribeEvent(NdbEventImpl & ev)
+{
+ // NdbDictInterface m_receiver;
+ return m_receiver.stopSubscribeEvent(m_ndb, ev);
+}
+
+int
+NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
+ NdbEventImpl & evnt)
+{
+#ifdef EVENT_DEBUG
+ ndbout_c("SUB_STOP_REQ");
+#endif
+
+ NdbApiSignal tSignal(m_reference);
+ // tSignal.theReceiversBlockNumber = SUMA;
+ tSignal.theReceiversBlockNumber = DBDICT;
+ 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;
+
+ 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);
+}
+
+NdbEventImpl *
+NdbDictionaryImpl::getEvent(const char * eventName)
+{
+ NdbEventImpl *ev = new NdbEventImpl();
+
+ if (ev == NULL) {
+ return NULL;
+ }
+
+ ev->setName(eventName);
+
+ int ret = m_receiver.createEvent(m_ndb, *ev, 1 /* getFlag set */);
+
+ if (ret) {
+ delete ev;
+ return NULL;
+ }
+
+ // We only have the table name with internal name
+ ev->setTable(m_ndb.externalizeTableName(ev->getTable()));
+ ev->m_tableImpl = getTable(ev->getTable());
+
+ // get the columns from the attrListBitmask
+
+ NdbTableImpl &table = *ev->m_tableImpl;
+ AttributeMask & mask = ev->m_attrListBitmask;
+ int attributeList_sz = mask.count();
+ int id = -1;
+
+#ifdef EVENT_DEBUG
+ ndbout_c("NdbDictionaryImpl::getEvent attributeList_sz = %d",
+ attributeList_sz);
+ char buf[128] = {0};
+ mask.getText(buf);
+ ndbout_c("mask = %s", buf);
+#endif
+
+ for(int i = 0; i < attributeList_sz; i++) {
+ id++; while (!mask.get(id)) id++;
+
+ 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;
+ delete ev;
+ return NULL;
+ }
+ NdbColumnImpl* new_col = new NdbColumnImpl;
+ // Copy column definition
+ *new_col = *col;
+
+ ev->m_columns.push_back(new_col);
+ }
+
+ return ev;
+}
+
+void
+NdbDictInterface::execCREATE_EVNT_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+#ifdef EVENT_DEBUG
+ ndbout << "NdbDictionaryImpl.cpp: execCREATE_EVNT_CONF" << endl;
+#endif
+ m_buffer.clear();
+ unsigned int len = signal->getLength() << 2;
+ m_buffer.append((char *)&len, sizeof(len));
+ m_buffer.append(signal->getDataPtr(), len);
+
+ if (signal->m_noOfSections > 0) {
+ m_buffer.append((char *)ptr[0].p, strlen((char *)ptr[0].p)+1);
+ }
+
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execCREATE_EVNT_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+#ifdef EVENT_DEBUG
+ ndbout << "NdbDictionaryImpl.cpp: execCREATE_EVNT_REF" << endl;
+ ndbout << "Exiting" << endl;
+ exit(-1);
+#endif
+
+ const CreateEvntRef* const ref = CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr());
+ m_error.code = ref->getErrorCode();
+#ifdef EVENT_DEBUG
+ ndbout_c("execCREATE_EVNT_REF");
+ ndbout_c("ErrorCode %u", ref->getErrorCode());
+ ndbout_c("Errorline %u", ref->getErrorLine());
+ ndbout_c("ErrorNode %u", ref->getErrorNode());
+#endif
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execSUB_STOP_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+#ifdef EVENT_DEBUG
+ ndbout << "Got GSN_SUB_STOP_CONF" << endl;
+#endif
+ // SubRemoveConf * const sumaRemoveConf = CAST_CONSTPTR(SubRemoveConf, signal->getDataPtr());
+
+ // Uint32 subscriptionId = sumaRemoveConf->subscriptionId;
+ // Uint32 subscriptionKey = sumaRemoveConf->subscriptionKey;
+ // Uint32 senderData = sumaRemoveConf->senderData;
+
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execSUB_STOP_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+#ifdef EVENT_DEBUG
+ ndbout << "Got GSN_SUB_STOP_REF" << endl;
+#endif
+ // SubRemoveConf * const sumaRemoveRef = CAST_CONSTPTR(SubRemoveRef, signal->getDataPtr());
+
+ // Uint32 subscriptionId = sumaRemoveRef->subscriptionId;
+ // Uint32 subscriptionKey = sumaRemoveRef->subscriptionKey;
+ // Uint32 senderData = sumaRemoveRef->senderData;
+
+ m_error.code = 1;
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execSUB_START_CONF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+#ifdef EVENT_DEBUG
+ ndbout << "Got GSN_SUB_START_CONF" << endl;
+#endif
+ const SubStartConf * const sumaStartConf = CAST_CONSTPTR(SubStartConf, signal->getDataPtr());
+
+ // Uint32 subscriptionId = sumaStartConf->subscriptionId;
+ // Uint32 subscriptionKey = sumaStartConf->subscriptionKey;
+ SubscriptionData::Part part =
+ (SubscriptionData::Part)sumaStartConf->part;
+ // Uint32 subscriberData = sumaStartConf->subscriberData;
+
+ switch(part) {
+ case SubscriptionData::MetaData: {
+#ifdef EVENT_DEBUG
+ ndbout << "SubscriptionData::MetaData" << endl;
+#endif
+ m_error.code = 1;
+ break;
+ }
+ case SubscriptionData::TableData: {
+#ifdef EVENT_DEBUG
+ ndbout << "SubscriptionData::TableData" << endl;
+#endif
+ break;
+ }
+ default: {
+#ifdef EVENT_DEBUG
+ ndbout_c("NdbDictInterface::execSUB_START_CONF wrong data");
+#endif
+ m_error.code = 1;
+ break;
+ }
+ }
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execSUB_START_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+#ifdef EVENT_DEBUG
+ ndbout << "Got GSN_SUB_START_REF" << endl;
+#endif
+ m_error.code = 1;
+ m_waiter.signal(NO_WAIT);
+}
+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
+ */
+int
+NdbDictionaryImpl::dropEvent(const char * eventName)
+{
+ NdbEventImpl *ev = new NdbEventImpl();
+ ev->setName(eventName);
+ int ret = m_receiver.dropEvent(*ev);
+ delete ev;
+
+ // printf("__________________RET %u\n", ret);
+ return ret;
+}
+
+int
+NdbDictInterface::dropEvent(const NdbEventImpl &evnt)
+{
+ NdbApiSignal tSignal(m_reference);
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_DROP_EVNT_REQ;
+ tSignal.theLength = DropEvntReq::SignalLength;
+
+ DropEvntReq * const req = CAST_PTR(DropEvntReq, tSignal.getDataPtrSend());
+
+ req->setUserRef(m_reference);
+ req->setUserData(0);
+
+ UtilBufferWriter w(m_buffer);
+
+ w.add(SimpleProperties::StringValue, evnt.m_externalName.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);
+}
+
+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])
+{
+#ifdef EVENT_DEBUG
+ ndbout << "NdbDictionaryImpl.cpp: execDROP_EVNT_CONF" << endl;
+#endif
+
+ m_waiter.signal(NO_WAIT);
+}
+
+void
+NdbDictInterface::execDROP_EVNT_REF(NdbApiSignal * signal,
+ LinearSectionPtr ptr[3])
+{
+#ifdef EVENT_DEBUG
+ ndbout << "NdbDictionaryImpl.cpp: execDROP_EVNT_REF" << endl;
+#endif
+ const DropEvntRef* const ref = CAST_CONSTPTR(DropEvntRef, signal->getDataPtr());
+ m_error.code = ref->getErrorCode();
+
+#if 0
+ ndbout_c("execDROP_EVNT_REF");
+ ndbout_c("ErrorCode %u", ref->getErrorCode());
+ ndbout_c("Errorline %u", ref->getErrorLine());
+ ndbout_c("ErrorNode %u", ref->getErrorNode());
+#endif
+
+ m_waiter.signal(NO_WAIT);
+}
+
+/*****************************************************************
+ * List objects or indexes
+ */
+int
+NdbDictionaryImpl::listObjects(List& list, NdbDictionary::Object::Type type)
+{
+ ListTablesReq req;
+ req.requestData = 0;
+ req.setTableType(getKernelConstant(type, objectTypeMapping, 0));
+ req.setListNames(true);
+ return m_receiver.listObjects(list, req.requestData);
+}
+
+int
+NdbDictionaryImpl::listIndexes(List& list, const char * tableName)
+{
+ ListTablesReq
+ req;
+ NdbTableImpl* impl = getTable(tableName);
+ if (impl == 0)
+ return -1;
+ req.requestData = 0;
+ req.setTableId(impl->m_tableId);
+ req.setListNames(true);
+ req.setListIndexes(true);
+ return m_receiver.listObjects(list, req.requestData);
+}
+
+int
+NdbDictInterface::listObjects(NdbDictionary::Dictionary::List& list,
+ Uint32 requestData)
+{
+ NdbApiSignal tSignal(m_reference);
+ ListTablesReq* const req = CAST_PTR(ListTablesReq, tSignal.getDataPtrSend());
+ req->senderRef = m_reference;
+ req->senderData = 0;
+ req->requestData = requestData;
+ tSignal.theReceiversBlockNumber = DBDICT;
+ tSignal.theVerId_signalNumber = GSN_LIST_TABLES_REQ;
+ tSignal.theLength = ListTablesReq::SignalLength;
+ if (listObjects(&tSignal) != 0)
+ return -1;
+ // count
+ const Uint32* data = (const Uint32*)m_buffer.get_data();
+ const unsigned length = m_buffer.length() / 4;
+ list.count = 0;
+ bool ok = true;
+ unsigned pos, count;
+ pos = count = 0;
+ while (pos < length) {
+ // table id - name length - name
+ pos++;
+ if (pos >= length) {
+ ok = false;
+ break;
+ }
+ Uint32 n = (data[pos++] + 3) >> 2;
+ pos += n;
+ if (pos > length) {
+ ok = false;
+ break;
+ }
+ count++;
+ }
+ if (! ok) {
+ // bad signal data
+ m_error.code = 4213;
+ return -1;
+ }
+ list.count = count;
+ list.elements = new NdbDictionary::Dictionary::List::Element[count];
+ pos = count = 0;
+ while (pos < length) {
+ NdbDictionary::Dictionary::List::Element& element = list.elements[count];
+ Uint32 d = data[pos++];
+ element.id = ListTablesConf::getTableId(d);
+ element.type = (NdbDictionary::Object::Type)
+ getApiConstant(ListTablesConf::getTableType(d), objectTypeMapping, 0);
+ element.state = (NdbDictionary::Object::State)
+ getApiConstant(ListTablesConf::getTableState(d), objectStateMapping, 0);
+ element.store = (NdbDictionary::Object::Store)
+ getApiConstant(ListTablesConf::getTableStore(d), objectStoreMapping, 0);
+ // table or index name
+ Uint32 n = (data[pos++] + 3) >> 2;
+ BaseString databaseName;
+ BaseString schemaName;
+ BaseString objectName;
+ if ((element.type == NdbDictionary::Object::UniqueHashIndex) ||
+ (element.type == NdbDictionary::Object::HashIndex) ||
+ (element.type == NdbDictionary::Object::UniqueOrderedIndex) ||
+ (element.type == NdbDictionary::Object::OrderedIndex)) {
+ char * indexName = new char[n << 2];
+ memcpy(indexName, &data[pos], n << 2);
+ databaseName = Ndb::getDatabaseFromInternalName(indexName);
+ schemaName = Ndb::getSchemaFromInternalName(indexName);
+ objectName = BaseString(Ndb::externalizeIndexName(indexName));
+ delete [] indexName;
+ } else if ((element.type == NdbDictionary::Object::SystemTable) ||
+ (element.type == NdbDictionary::Object::UserTable)) {
+ char * tableName = new char[n << 2];
+ memcpy(tableName, &data[pos], n << 2);
+ databaseName = Ndb::getDatabaseFromInternalName(tableName);
+ schemaName = Ndb::getSchemaFromInternalName(tableName);
+ objectName = BaseString(Ndb::externalizeTableName(tableName));
+ delete [] tableName;
+ }
+ else {
+ char * otherName = new char[n << 2];
+ memcpy(otherName, &data[pos], n << 2);
+ objectName = BaseString(otherName);
+ delete [] otherName;
+ }
+ element.database = new char[databaseName.length() + 1];
+ strcpy(element.database, databaseName.c_str());
+ element.schema = new char[schemaName.length() + 1];
+ strcpy(element.schema, schemaName.c_str());
+ element.name = new char[objectName.length() + 1];
+ strcpy(element.name, objectName.c_str());
+ pos += n;
+ count++;
+ }
+ return 0;
+}
+
+int
+NdbDictInterface::listObjects(NdbApiSignal* signal)
+{
+ const Uint32 RETRIES = 100;
+ for (Uint32 i = 0; i < RETRIES; i++) {
+ m_buffer.clear();
+ // begin protected
+ 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(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);
+ // end protected
+ if (m_waiter.m_state == NO_WAIT && m_error.code == 0)
+ return 0;
+ if (m_waiter.m_state == WAIT_NODE_FAILURE)
+ continue;
+ return -1;
+ }
+ return -1;
+}
+
+void
+NdbDictInterface::execLIST_TABLES_CONF(NdbApiSignal* signal,
+ LinearSectionPtr ptr[3])
+{
+ const unsigned off = ListTablesConf::HeaderLength;
+ const unsigned len = (signal->getLength() - off);
+ m_buffer.append(signal->getDataPtr() + off, len << 2);
+ if (signal->getLength() < ListTablesConf::SignalLength) {
+ // last signal has less than full length
+ m_waiter.signal(NO_WAIT);
+ }
+}