List:Commits« Previous MessageNext Message »
From:tomas Date:April 11 2007 1:51pm
Subject:bk commit into 5.1 tree (tomas:1.2573)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of tomas. When tomas does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-04-11 15:51:09+02:00, tomas@stripped +28 -0
  Merge whalegate.ndb.mysql.com:/home/tomas/mysql-5.0-ndb
  into  whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-single-user
  MERGE: 1.1810.2374.119

  sql/ha_ndbcluster.cc@stripped, 2007-04-11 15:51:05+02:00, tomas@stripped +4 -47
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.175.1.133

  storage/ndb/include/ndbapi/Ndb.hpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +1 -1
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.39.11.2

  storage/ndb/include/ndbapi/Ndb.hpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/include/ndbapi/Ndb.hpp -> storage/ndb/include/ndbapi/Ndb.hpp

  storage/ndb/include/ndbapi/NdbDictionary.hpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +0 -0
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.48.11.2

  storage/ndb/include/ndbapi/NdbDictionary.hpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/include/ndbapi/NdbDictionary.hpp -> storage/ndb/include/ndbapi/NdbDictionary.hpp

  storage/ndb/include/ndbapi/NdbReceiver.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.15.4.2

  storage/ndb/include/ndbapi/NdbReceiver.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/include/ndbapi/NdbReceiver.hpp -> storage/ndb/include/ndbapi/NdbReceiver.hpp

  storage/ndb/include/ndbapi/NdbTransaction.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.41.8.2

  storage/ndb/include/ndbapi/NdbTransaction.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/include/ndbapi/NdbTransaction.hpp -> storage/ndb/include/ndbapi/NdbTransaction.hpp

  storage/ndb/include/util/BaseString.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.7.2.2

  storage/ndb/include/util/BaseString.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/include/util/BaseString.hpp -> storage/ndb/include/util/BaseString.hpp

  storage/ndb/include/util/Vector.hpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +0 -2
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.4.4.2

  storage/ndb/include/util/Vector.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/include/util/Vector.hpp -> storage/ndb/include/util/Vector.hpp

  storage/ndb/src/common/util/BaseString.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.7.2.2

  storage/ndb/src/common/util/BaseString.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/common/util/BaseString.cpp -> storage/ndb/src/common/util/BaseString.cpp

  storage/ndb/src/ndbapi/DictCache.cpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +1 -1
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.12.11.2

  storage/ndb/src/ndbapi/DictCache.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/DictCache.cpp -> storage/ndb/src/ndbapi/DictCache.cpp

  storage/ndb/src/ndbapi/DictCache.hpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +0 -0
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.6.10.2

  storage/ndb/src/ndbapi/DictCache.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/DictCache.hpp -> storage/ndb/src/ndbapi/DictCache.hpp

  storage/ndb/src/ndbapi/Makefile.am@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +0 -0
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.12.5.2

  storage/ndb/src/ndbapi/Makefile.am@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/Makefile.am -> storage/ndb/src/ndbapi/Makefile.am

  storage/ndb/src/ndbapi/Ndb.cpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +0 -1
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.49.25.2

  storage/ndb/src/ndbapi/Ndb.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/Ndb.cpp -> storage/ndb/src/ndbapi/Ndb.cpp

  storage/ndb/src/ndbapi/NdbDictionary.cpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +3 -4
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.34.8.2

  storage/ndb/src/ndbapi/NdbDictionary.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbDictionary.cpp -> storage/ndb/src/ndbapi/NdbDictionary.cpp

  storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +27 -40
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.74.34.2

  storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbDictionaryImpl.cpp -> storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp

  storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +0 -0
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.30.13.2

  storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbDictionaryImpl.hpp -> storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp

  storage/ndb/src/ndbapi/NdbImpl.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.8.10.2

  storage/ndb/src/ndbapi/NdbImpl.hpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbImpl.hpp -> storage/ndb/src/ndbapi/NdbImpl.hpp

  storage/ndb/src/ndbapi/NdbOperation.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.15.4.2

  storage/ndb/src/ndbapi/NdbOperation.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbOperation.cpp -> storage/ndb/src/ndbapi/NdbOperation.cpp

  storage/ndb/src/ndbapi/NdbRecAttr.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.20.15.2

  storage/ndb/src/ndbapi/NdbRecAttr.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbRecAttr.cpp -> storage/ndb/src/ndbapi/NdbRecAttr.cpp

  storage/ndb/src/ndbapi/NdbReceiver.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.15.3.2

  storage/ndb/src/ndbapi/NdbReceiver.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbReceiver.cpp -> storage/ndb/src/ndbapi/NdbReceiver.cpp

  storage/ndb/src/ndbapi/NdbScanFilter.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.8.7.2

  storage/ndb/src/ndbapi/NdbScanFilter.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbScanFilter.cpp -> storage/ndb/src/ndbapi/NdbScanFilter.cpp

  storage/ndb/src/ndbapi/NdbScanOperation.cpp@stripped, 2007-04-11 15:22:09+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.66.30.2

  storage/ndb/src/ndbapi/NdbScanOperation.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbScanOperation.cpp -> storage/ndb/src/ndbapi/NdbScanOperation.cpp

  storage/ndb/src/ndbapi/NdbTransaction.cpp@stripped, 2007-04-11 15:22:09+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.43.26.2

  storage/ndb/src/ndbapi/NdbTransaction.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/NdbTransaction.cpp -> storage/ndb/src/ndbapi/NdbTransaction.cpp

  storage/ndb/src/ndbapi/Ndbif.cpp@stripped, 2007-04-11 15:22:09+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.27.11.2

  storage/ndb/src/ndbapi/Ndbif.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/Ndbif.cpp -> storage/ndb/src/ndbapi/Ndbif.cpp

  storage/ndb/src/ndbapi/Ndblist.cpp@stripped, 2007-04-11 15:22:09+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.13.6.2

  storage/ndb/src/ndbapi/Ndblist.cpp@stripped, 2007-04-11 15:22:07+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/Ndblist.cpp -> storage/ndb/src/ndbapi/Ndblist.cpp

  storage/ndb/src/ndbapi/ObjectMap.hpp@stripped, 2007-04-11 15:51:06+02:00, tomas@stripped +1 -3
    Bug#26176 NdbObjectIdMap::expand unable to expand!! mysqld got signal 11
    - manual merge to 5.1
    MERGE: 1.7.4.2

  storage/ndb/src/ndbapi/ObjectMap.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/ObjectMap.hpp -> storage/ndb/src/ndbapi/ObjectMap.hpp

  storage/ndb/src/ndbapi/SignalSender.cpp@stripped, 2007-04-11 15:22:09+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.3.12.2

  storage/ndb/src/ndbapi/SignalSender.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/SignalSender.cpp -> storage/ndb/src/ndbapi/SignalSender.cpp

  storage/ndb/src/ndbapi/ndb_cluster_connection.cpp@stripped, 2007-04-11 15:22:09+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.29.13.2

  storage/ndb/src/ndbapi/ndb_cluster_connection.cpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/ndb_cluster_connection.cpp -> storage/ndb/src/ndbapi/ndb_cluster_connection.cpp

  storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp@stripped, 2007-04-11 15:22:09+02:00, tomas@stripped +0 -0
    Auto merged
    MERGE: 1.2.4.2

  storage/ndb/src/ndbapi/ndb_cluster_connection_impl.hpp@stripped, 2007-04-11 15:22:08+02:00, tomas@stripped +0 -0
    Merge rename: ndb/src/ndbapi/ndb_cluster_connection_impl.hpp -> storage/ndb/src/ndbapi/ndb_cluster_connection_impl.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:	tomas
# Host:	whalegate.ndb.mysql.com
# Root:	/home/tomas/mysql-5.1-single-user/RESYNC

--- 1.39.11.1/ndb/include/ndbapi/Ndb.hpp	2007-04-11 15:21:08 +02:00
+++ 1.62/storage/ndb/include/ndbapi/Ndb.hpp	2007-04-11 15:51:06 +02:00
@@ -37,6 +37,9 @@
    In addition, the NDB API defines a structure NdbError, which contains the 
    specification for an error.
 
+   It is also possible to receive "events" triggered when data in the database in changed.
+   This is done through the NdbEventOperation class.
+
    There are also some auxiliary classes, which are listed in the class hierarchy.
      
    The main structure of an application program is as follows:
@@ -497,12 +500,11 @@
   
    There are four conditions leading to the transfer of database 
    operations from Ndb object buffers to the NDB kernel:
-   -# The NDB Transporter (TCP/IP, OSE, SCI or shared memory)
+   -# The NDB Transporter (TCP/IP, SCI or shared memory)
       decides that a buffer is full and sends it off. 
       The buffer size is implementation-dependent and
       may change between MySQL Cluster releases.
       On TCP/IP the buffer size is usually around 64 KB;
-      on OSE/Delta it is usually less than 2000 bytes. 
       Since each Ndb object provides a single buffer per storage node, 
       the notion of a "full" buffer is local to this storage node.
    -# The accumulation of statistical data on transferred information
@@ -964,6 +966,7 @@
 
 class NdbObjectIdMap;
 class NdbOperation;
+class NdbEventOperationImpl;
 class NdbScanOperation;
 class NdbIndexScanOperation;
 class NdbIndexOperation;
@@ -976,22 +979,20 @@
 class NdbCall;
 class Table;
 class BaseString;
+class NdbEventOperation;
 class NdbBlob;
 class NdbReceiver;
+class TransporterFacade;
+class PollGuard;
 class Ndb_local_table_info;
 template <class T> struct Ndb_free_list_t;
 
+typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
 
-#if defined NDB_OSE
-/**
- * Default time to wait for response after request has been sent to 
- * NDB Cluster (Set to 10 seconds usually, but to 100 s in 
- * the OSE operating system)
- */
-#define WAITFOR_RESPONSE_TIMEOUT 100000 // Milliseconds
-#else
 #define WAITFOR_RESPONSE_TIMEOUT 120000 // Milliseconds
-#endif
+
+#define NDB_SYSTEM_DATABASE "sys"
+#define NDB_SYSTEM_SCHEMA "def"
 
 /**
  * @class Ndb 
@@ -1042,6 +1043,8 @@
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
   friend class NdbReceiver;
   friend class NdbOperation;
+  friend class NdbEventOperationImpl;
+  friend class NdbEventBuffer;
   friend class NdbTransaction;
   friend class Table;
   friend class NdbApiSignal;
@@ -1051,6 +1054,7 @@
   friend class NdbDictionaryImpl;
   friend class NdbDictInterface;
   friend class NdbBlob;
+  friend class NdbImpl;
   friend class Ndb_free_list_t<NdbRecAttr>;  
   friend class Ndb_free_list_t<NdbApiSignal>;
   friend class Ndb_free_list_t<NdbLabel>;
@@ -1092,6 +1096,15 @@
 
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
   /**
+   * The current ndb_cluster_connection get_ndb_cluster_connection.
+   *
+   * @return the current connection
+   */
+  Ndb_cluster_connection& get_ndb_cluster_connection();
+#endif
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+  /**
    * The current catalog name can be fetched by getCatalogName.
    *
    * @return the current catalog name
@@ -1148,6 +1161,15 @@
    */
   int 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
    *
@@ -1200,6 +1222,71 @@
   /** @} *********************************************************************/
 
   /** 
+   * @name Event subscriptions
+   * @{
+   */
+
+  /**
+   * Create a subcription to an event defined in the database
+   *
+   * @param eventName
+   *        unique identifier of the event
+   *
+   * @return Object representing an event, NULL on failure
+   */
+  NdbEventOperation* createEventOperation(const char* eventName);
+  /**
+   * Drop a subscription to an event
+   *
+   * @param eventOp
+   *        Event operation
+   *
+   * @return 0 on success
+   */
+  int dropEventOperation(NdbEventOperation* eventOp);
+
+  /**
+   * Wait for an event to occur. Will return as soon as an event
+   * is detected on any of the created events.
+   *
+   * @param aMillisecondNumber
+   *        maximum time to wait
+   *
+   * @return > 0 if events available, 0 if no events available, < 0 on failure
+   */
+  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
+  int flushIncompleteEvents(Uint64 gci);
+  NdbEventOperation *getEventOperation(NdbEventOperation* eventOp= 0);
+  Uint64 getLatestGCI();
+  void forceGCP();
+  void setReportThreshEventGCISlip(unsigned thresh);
+  void setReportThreshEventFreeMem(unsigned thresh);
+#endif
+
+  /** @} *********************************************************************/
+
+  /** 
    * @name Starting and Closing Transactions
    * @{
    */
@@ -1390,7 +1477,9 @@
 
   /**
    * Return a unique tuple id for a table.  The id sequence is
-   * ascending but may contain gaps.
+   * ascending but may contain gaps.  Methods which have no
+   * TupleIdRange argument use NDB API dict cache.  They may
+   * not be called from mysqld.
    *
    * @param aTableName table name
    *
@@ -1398,26 +1487,48 @@
    *
    * @return 0 or -1 on error, and tupleId in out parameter
    */
+  struct TupleIdRange {
+    TupleIdRange() {}
+    Uint64 m_first_tuple_id;
+    Uint64 m_last_tuple_id;
+    void reset() {
+      m_first_tuple_id = ~(Uint64)0;
+      m_last_tuple_id = ~(Uint64)0;
+    };
+  };
+
+  int initAutoIncrement();
+
   int getAutoIncrementValue(const char* aTableName, 
                             Uint64 & tupleId, Uint32 cacheSize);
   int getAutoIncrementValue(const NdbDictionary::Table * aTable, 
                             Uint64 & tupleId, Uint32 cacheSize);
+  int getAutoIncrementValue(const NdbDictionary::Table * aTable, 
+                            TupleIdRange & range, Uint64 & tupleId,
+                            Uint32 cacheSize);
   int readAutoIncrementValue(const char* aTableName,
                              Uint64 & tupleId);
   int readAutoIncrementValue(const NdbDictionary::Table * aTable,
                              Uint64 & tupleId);
+  int readAutoIncrementValue(const NdbDictionary::Table * aTable,
+                             TupleIdRange & range, Uint64 & tupleId);
   int setAutoIncrementValue(const char* aTableName,
                             Uint64 tupleId, bool increase);
   int setAutoIncrementValue(const NdbDictionary::Table * aTable,
                             Uint64 tupleId, bool increase);
+  int setAutoIncrementValue(const NdbDictionary::Table * aTable,
+                            TupleIdRange & range, Uint64 tupleId,
+                            bool increase);
 private:
-  int getTupleIdFromNdb(Ndb_local_table_info* info,
-                        Uint64 & tupleId, Uint32 cacheSize);
-  int readTupleIdFromNdb(Ndb_local_table_info* info,
-                         Uint64 & tupleId);
-  int setTupleIdInNdb(Ndb_local_table_info* info,
-                      Uint64 tupleId, bool increase);
-  int opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op);
+  int getTupleIdFromNdb(const NdbTableImpl* table,
+                        TupleIdRange & range, Uint64 & tupleId,
+                        Uint32 cacheSize);
+  int readTupleIdFromNdb(const NdbTableImpl* table,
+                         TupleIdRange & range, Uint64 & tupleId);
+  int setTupleIdInNdb(const NdbTableImpl* table,
+                      TupleIdRange & range, Uint64 tupleId, bool increase);
+  int opTupleIdOnNdb(const NdbTableImpl* table,
+                     TupleIdRange & range, Uint64 & opValue, Uint32 op);
 public:
 
   /**
@@ -1441,12 +1552,18 @@
 /*****************************************************************************
  *	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);
 
   void connected(Uint32 block_reference);
+  void report_node_connected(Uint32 nodeId);
  
 
   NdbTransaction*  startTransactionLocal(Uint32 aPrio, Uint32 aFragmentId); 
@@ -1468,7 +1585,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);
@@ -1492,13 +1608,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);
@@ -1555,7 +1669,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);
 
@@ -1571,6 +1687,8 @@
   const char * externalizeIndexName(const char * internalIndexName,
                                     bool fullyQualifiedNames);
   const char * externalizeIndexName(const char * internalIndexName);
+  const BaseString old_internalize_index_name(const NdbTableImpl * table,
+					      const char * external_name) const;
   const BaseString internalize_index_name(const NdbTableImpl * table,
                                           const char * external_name) const;
 
@@ -1607,7 +1725,7 @@
 
   class NdbImpl * theImpl;
   class NdbDictionaryImpl* theDictionary;
-  class NdbGlobalEventBufferHandle* theGlobalEventBufferHandle;
+  class NdbEventBuffer* theEventBuffer;
 
   NdbTransaction*	theTransactionList;
   NdbTransaction**      theConnectionArray;
@@ -1617,6 +1735,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.41.8.1/ndb/include/ndbapi/NdbTransaction.hpp	2007-04-11 15:21:08 +02:00
+++ 1.55/storage/ndb/include/ndbapi/NdbTransaction.hpp	2007-04-11 15:22:08 +02:00
@@ -20,6 +20,7 @@
 #include "NdbError.hpp"
 #include "NdbDictionary.hpp"
 #include "Ndb.hpp"
+#include "NdbOperation.hpp"
 
 class NdbTransaction;
 class NdbOperation;
@@ -44,11 +45,12 @@
 
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
 enum AbortOption {
-  CommitIfFailFree= 0,         
-  TryCommit= 0,
-  AbortOnError= 0,
-  CommitAsMuchAsPossible= 2,
-  AO_IgnoreError= 2
+  DefaultAbortOption = NdbOperation::DefaultAbortOption,
+  CommitIfFailFree = NdbOperation::AbortOnError,         
+  TryCommit = NdbOperation::AbortOnError,
+  AbortOnError= NdbOperation::AbortOnError,
+  CommitAsMuchAsPossible = NdbOperation::AO_IgnoreError,
+  AO_IgnoreError= NdbOperation::AO_IgnoreError
 };
 enum ExecType { 
   NoExecTypeDef = -1,
@@ -145,20 +147,6 @@
 public:
 
   /**
-   * Commit type of transaction
-   */
-  enum AbortOption {
-    AbortOnError=               ///< Abort transaction on failed operation
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
-    ::AbortOnError
-#endif
-    ,AO_IgnoreError=            ///< Transaction continues on failed operation
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
-    ::AO_IgnoreError
-#endif
-  };
-
-  /**
    * Execution type of transaction
    */
   enum ExecType {
@@ -316,13 +304,15 @@
    * @return 0 if successful otherwise -1.
    */
   int execute(ExecType execType,
-	      AbortOption abortOption = AbortOnError,
+	      NdbOperation::AbortOption = NdbOperation::DefaultAbortOption,
 	      int force = 0 );
 #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
   int execute(::ExecType execType,
-	      ::AbortOption abortOption = ::AbortOnError,
-	      int force = 0 )
-  { return execute ((ExecType)execType,(AbortOption)abortOption,force); }
+	      ::AbortOption abortOption = ::DefaultAbortOption,
+	      int force = 0 ) {
+    return execute ((ExecType)execType,
+		    (NdbOperation::AbortOption)abortOption,
+		    force); }
 #endif
 
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
@@ -353,14 +343,14 @@
   void executeAsynchPrepare(ExecType          execType,
 			    NdbAsynchCallback callback,
 			    void*             anyObject,
-			    AbortOption abortOption = AbortOnError);
+			    NdbOperation::AbortOption = NdbOperation::DefaultAbortOption);
 #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
   void executeAsynchPrepare(::ExecType       execType,
 			    NdbAsynchCallback callback,
 			    void*             anyObject,
-			    ::AbortOption abortOption = ::AbortOnError)
-  { executeAsynchPrepare((ExecType)execType, callback, anyObject,
-			 (AbortOption)abortOption); }
+			    ::AbortOption ao = ::DefaultAbortOption) {
+    executeAsynchPrepare((ExecType)execType, callback, anyObject,
+			 (NdbOperation::AbortOption)ao); }
 #endif
 
   /**
@@ -379,14 +369,14 @@
   void executeAsynch(ExecType            aTypeOfExec,
 		     NdbAsynchCallback   aCallback,
 		     void*               anyObject,
-		     AbortOption abortOption = AbortOnError);
+		     NdbOperation::AbortOption = NdbOperation::DefaultAbortOption);
 #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
   void executeAsynch(::ExecType         aTypeOfExec,
 		     NdbAsynchCallback   aCallback,
 		     void*               anyObject,
-		     ::AbortOption abortOption= ::AbortOnError)
+		     ::AbortOption abortOption= ::DefaultAbortOption)
   { executeAsynch((ExecType)aTypeOfExec, aCallback, anyObject,
-		  (AbortOption)abortOption); }
+		  (NdbOperation::AbortOption)abortOption); }
 #endif
 #endif
   /**
@@ -588,7 +578,7 @@
   int init();           // Initialize connection object for new transaction
 
   int executeNoBlobs(ExecType execType, 
-	             AbortOption abortOption = AbortOnError,
+	             NdbOperation::AbortOption = NdbOperation::DefaultAbortOption,
 	             int force = 0 );
   
   /**
@@ -642,7 +632,7 @@
   int 	sendCOMMIT();                   // Send a TC_COMMITREQ signal;
   void	setGCI(int GCI);		// Set the global checkpoint identity
  
-  int	OpCompleteFailure(Uint8 abortoption, bool setFailure = true);
+  int	OpCompleteFailure(NdbOperation*);
   int	OpCompleteSuccess();
   void	CompletedOperations();	        // Move active ops to list of completed
  
@@ -732,11 +722,11 @@
 
   Uint32	theNoOfOpSent;				// How many operations have been sent	    
   Uint32	theNoOfOpCompleted;			// How many operations have completed
-  Uint32        theNoOfOpFetched;           	        // How many operations was actually fetched
   Uint32	theMyRef;				// Our block reference		
   Uint32	theTCConPtr;				// Transaction Co-ordinator connection pointer.
   Uint64	theTransactionId;			// theTransactionId of the transaction
   Uint32	theGlobalCheckpointId;			// The gloabl checkpoint identity of the transaction
+  Uint64 *p_latest_trans_gci;                           // Reference to latest gci for connection
   ConStatusType	theStatus;				// The status of the connection		
   enum CompletionStatus { 
     NotCompleted,
@@ -755,7 +745,6 @@
   bool theTransactionIsStarted; 
   bool theInUseState;
   bool theSimpleState;
-  Uint8 m_abortOption;           // Type of commit
 
   enum ListState {  
     NotInList, 
@@ -796,7 +785,7 @@
   Uint8 thePendingBlobOps;
   inline bool hasBlobOperation() { return theBlobFlag; }
 
-  static void sendTC_COMMIT_ACK(NdbApiSignal *,
+  static void sendTC_COMMIT_ACK(class TransporterFacade *, NdbApiSignal *,
 				Uint32 transId1, Uint32 transId2, 
 				Uint32 aBlockRef);
 

--- 1.48.11.1/ndb/include/ndbapi/NdbDictionary.hpp	2007-04-11 15:21:08 +02:00
+++ 1.90/storage/ndb/include/ndbapi/NdbDictionary.hpp	2007-04-11 15:51:06 +02:00
@@ -95,7 +95,9 @@
      * Get version of object
      */
     virtual int getObjectVersion() const = 0;
-
+    
+    virtual int getObjectId() const = 0;
+    
     /**
      * Object type
      */
@@ -108,7 +110,11 @@
       HashIndexTrigger = 7,   ///< Index maintenance, internal
       IndexTrigger = 8,       ///< Index maintenance, internal
       SubscriptionTrigger = 9,///< Backup or replication, internal
-      ReadOnlyConstraint = 10 ///< Trigger, internal
+      ReadOnlyConstraint = 10,///< Trigger, internal
+      Tablespace = 20,        ///< Tablespace
+      LogfileGroup = 21,      ///< Logfile group
+      Datafile = 22,          ///< Datafile
+      Undofile = 23           ///< Undofile
     };
 
     /**
@@ -129,7 +135,7 @@
      */
     enum Store {
       StoreUndefined = 0,     ///< Undefined
-      StoreTemporary = 1,     ///< Object or data deleted on system restart
+      StoreNotLogged = 1,     ///< Object or data deleted on system restart
       StorePermanent = 2      ///< Permanent. logged to disk
     };
 
@@ -149,12 +155,42 @@
       FragSingle = 1,         ///< Only one fragment
       FragAllSmall = 2,       ///< One fragment per node, default
       FragAllMedium = 3,      ///< two fragments per node
-      FragAllLarge = 4        ///< Four fragments per node.
+      FragAllLarge = 4,       ///< Four fragments per node.
+      DistrKeyHash = 5,
+      DistrKeyLin = 6,
+      UserDefined = 7
     };
   };
 
-  class Table; // forward declaration
+  class Dictionary; // Forward declaration
   
+  class ObjectId : public Object 
+  {
+  public:
+    ObjectId();
+    virtual ~ObjectId();
+    
+    /**
+     * Get status of object
+     */
+    virtual Status getObjectStatus() const;
+    
+    /**
+     * Get version of object
+     */
+    virtual int getObjectVersion() const;
+    
+    virtual int getObjectId() const;
+    
+  private:
+    friend class NdbDictObjectImpl;
+    class NdbDictObjectImpl & m_impl;
+  };
+  
+  class Table; // forward declaration
+  class Tablespace; // forward declaration
+//  class NdbEventOperation; // forward declaration
+
   /**
    * @class Column
    * @brief Represents a column in an NDB Cluster table
@@ -211,6 +247,34 @@
       Timestamp = NDB_TYPE_TIMESTAMP  ///< Unix time
     };
 
+    /*
+     * Array type specifies internal attribute format.
+     *
+     * - ArrayTypeFixed is stored as fixed number of bytes.  This type
+     *   is fastest to access but can waste space.
+     *
+     * - ArrayTypeVar is stored as variable number of bytes with a fixed
+     *   overhead of 2 bytes.
+     *
+     * Default is ArrayTypeVar for Var* types and ArrayTypeFixed for
+     * others.  The default is normally ok.
+     */
+    enum ArrayType {
+      ArrayTypeFixed = NDB_ARRAYTYPE_FIXED,          // 0 length bytes
+      ArrayTypeShortVar = NDB_ARRAYTYPE_SHORT_VAR,   // 1 length bytes
+      ArrayTypeMediumVar = NDB_ARRAYTYPE_MEDIUM_VAR // 2 length bytes
+    };
+
+    /*
+     * Storage type specifies whether attribute is stored in memory or
+     * on disk.  Default is memory.  Disk attributes are potentially
+     * much slower to access and cannot be indexed in version 5.1.
+     */
+    enum StorageType {
+      StorageTypeMemory = NDB_STORAGETYPE_MEMORY,
+      StorageTypeDisk = NDB_STORAGETYPE_DISK
+    };
+
     /** 
      * @name General 
      * @{
@@ -237,6 +301,10 @@
      */
     int getColumnNo() const;
 
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    int getAttrId() const;
+#endif
+
     /**
      * Check if column is equal to some other column
      * @param  column  Column to compare with
@@ -330,6 +398,9 @@
     inline bool getDistributionKey() const { return getPartitionKey(); };
 #endif
 
+    ArrayType getArrayType() const;
+    StorageType getStorageType() const;
+
     /** @} *******************************************************************/
 
 
@@ -438,6 +509,9 @@
     { setPartitionKey(enable); };
 #endif
 
+    void setArrayType(ArrayType type);
+    void setStorageType(StorageType type);
+
     /** @} *******************************************************************/
 
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
@@ -450,11 +524,17 @@
     const char* getDefaultValue() const;
 
     static const Column * FRAGMENT;
-    static const Column * FRAGMENT_MEMORY;
+    static const Column * FRAGMENT_FIXED_MEMORY;
+    static const Column * FRAGMENT_VARSIZED_MEMORY;
     static const Column * ROW_COUNT;
     static const Column * COMMIT_COUNT;
     static const Column * ROW_SIZE;
     static const Column * RANGE_NO;
+    static const Column * DISK_REF;
+    static const Column * RECORDS_IN_RANGE;
+    static const Column * ROWID;
+    static const Column * ROW_GCI;
+    static const Column * ANY_VALUE;
     
     int getSizeInBytes() const;
 #endif
@@ -627,6 +707,24 @@
     const void* getFrmData() const;
     Uint32 getFrmLength() const;
 
+    /**
+     * Get Fragment Data (id, state and node group)
+     */
+    const void *getFragmentData() const;
+    Uint32 getFragmentDataLen() const;
+
+    /**
+     * Get Range or List Array (value, partition)
+     */
+    const void *getRangeListData() const;
+    Uint32 getRangeListDataLen() const;
+
+    /**
+     * Get Tablespace Data (id, version)
+     */
+    const void *getTablespaceData() const;
+    Uint32 getTablespaceDataLen() const;
+
     /** @} *******************************************************************/
 
     /** 
@@ -673,7 +771,23 @@
      * @see NdbDictionary::Table::getLogging.
      */
     void setLogging(bool); 
-   
+  
+    /**
+     * Set/Get Linear Hash Flag
+     */ 
+    void setLinearFlag(Uint32 flag);
+    bool getLinearFlag() const;
+
+    /**
+     * Set fragment count
+     */
+    void setFragmentCount(Uint32);
+
+    /**
+     * Get fragment count
+     */
+    Uint32 getFragmentCount() const;
+
     /**
      * Set fragmentation type
      */
@@ -705,6 +819,11 @@
      */
     void setMaxLoadFactor(int);
 
+    void setTablespaceName(const char * name);
+    const char * getTablespaceName() const;
+    void setTablespace(const class Tablespace &);
+    bool getTablespace(Uint32 *id= 0, Uint32 *version= 0) const;
+
     /**
      * Get table object type
      */
@@ -714,6 +833,7 @@
      * Get object status
      */
     virtual Object::Status getObjectStatus() const;
+    void setStatusInvalid() const;
 
     /**
      * Get object version
@@ -721,11 +841,52 @@
     virtual int getObjectVersion() const;
 
     /**
+     * Set/Get indicator if default number of partitions is used in table.
+     */
+    void setDefaultNoPartitionsFlag(Uint32 indicator);
+    Uint32 getDefaultNoPartitionsFlag() const;
+   
+    /**
+     * Get object id
+     */
+    virtual int getObjectId() const;
+
+    /**
      * Set frm file to store with this table
      */ 
     int setFrm(const void* data, Uint32 len);
 
     /**
+     * Set array of fragment information containing
+     * Fragment Identity
+     * Node group identity
+     * Fragment State
+     */
+    void setFragmentData(const void* data, Uint32 len);
+
+    /**
+     * Set/Get tablespace names per fragment
+     */
+    void setTablespaceNames(const void* data, Uint32 len);
+    const void *getTablespaceNames();
+    Uint32 getTablespaceNamesLen() const;
+
+    /**
+     * Set tablespace information per fragment
+     * Contains a tablespace id and a tablespace version
+     */
+    void setTablespaceData(const void* data, Uint32 len);
+
+    /**
+     * Set array of information mapping range values and list values
+     * to fragments. This is essentially a sorted map consisting of
+     * pairs of value, fragment identity. For range partitions there is
+     * one pair per fragment. For list partitions it could be any number
+     * of pairs, at least as many as there are fragments.
+     */
+    void setRangeListData(const void* data, Uint32 len);
+
+    /**
      * Set table object type
      */
     void setObjectType(Object::Type type);
@@ -753,7 +914,18 @@
 
     /** @} *******************************************************************/
 
+    /**
+     * 
+     */
+    void setRowGCIIndicator(bool value);
+    bool getRowGCIIndicator() const;
+
+    void setRowChecksumIndicator(bool value);
+    bool getRowChecksumIndicator() const;
+ 
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    const char *getMysqlName() const;
+
     void setStoredTable(bool x) { setLogging(x); }
     bool getStoredTable() const { return getLogging(); }
 
@@ -761,11 +933,58 @@
     int createTableInDb(Ndb*, bool existingEqualIsOk = true) const ;
 
     int getReplicaCount() const ;
+
+    bool getTemporary();
+    void setTemporary(bool); 
+
+    /**
+     * Check if any of column in bitmaps are disk columns
+     *   returns bitmap of different columns
+     *     bit 0 = atleast 1 pk column is set
+     *     bit 1 = atleast 1 disk column set
+     *     bit 2 = atleast 1 non disk column set
+     *   passing NULL pointer will equal to bitmap with all columns set
+     */
+    int checkColumns(const Uint32* bitmap, unsigned len_in_bytes) const;
 #endif
 
+    // these 2 are not de-doxygenated
+
+    /**
+     * This method is not needed in normal usage.
+     *
+     * Compute aggregate data on table being defined.  Required for
+     * aggregate methods such as getNoOfPrimaryKeys() to work before
+     * table has been created and retrieved via getTable().
+     *
+     * May adjust some column flags.  If no PK is so far marked as
+     * distribution key then all PK's will be marked.
+     *
+     * Returns 0 on success.  Returns -1 and sets error if an
+     * inconsistency is detected.
+     */
+    int aggregate(struct NdbError& error);
+
+    /**
+     * This method is not needed in normal usage.
+     *
+     * Validate new table definition before create.  Does aggregate()
+     * and additional checks.  There may still be errors which are
+     * detected only by NDB kernel at create table.
+     *
+     * Create table and retrieve table do validate() automatically.
+     *
+     * Returns 0 on success.  Returns -1 and sets error if an
+     * inconsistency is detected.
+     */
+    int validate(struct NdbError& error);
+
   private:
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    friend class Ndb;
+    friend class NdbDictionaryImpl;
     friend class NdbTableImpl;
+    friend class NdbEventOperationImpl;
 #endif
     class NdbTableImpl & m_impl;
     Table(NdbTableImpl&);
@@ -854,6 +1073,11 @@
      */
     virtual int getObjectVersion() const;
 
+    /**
+     * Get object id
+     */
+    virtual int getObjectId() const;
+
     /** @} *******************************************************************/
 
     /** 
@@ -940,6 +1164,9 @@
 #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
     void setStoredIndex(bool x) { setLogging(x); }
     bool getStoredIndex() const { return getLogging(); }
+
+    bool getTemporary();
+    void setTemporary(bool); 
 #endif
     
     /** @} *******************************************************************/
@@ -947,12 +1174,441 @@
   private:
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
     friend class NdbIndexImpl;
+    friend class NdbIndexStat;
 #endif
     class NdbIndexImpl & m_impl;
     Index(NdbIndexImpl&);
   };
 
   /**
+   * @brief Represents an Event in NDB Cluster
+   *
+   */
+  class Event : public Object  {
+  public:
+    /**
+     * Specifies the type of database operations an Event listens to
+     */
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    /** TableEvent must match 1 << TriggerEvent */
+#endif
+    enum TableEvent { 
+      TE_INSERT      =1<<0, ///< Insert event on table
+      TE_DELETE      =1<<1, ///< Delete event on table
+      TE_UPDATE      =1<<2, ///< Update event on table
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+      TE_SCAN        =1<<3, ///< Scan event on table
+      TE_FIRST_NON_DATA_EVENT =1<<4,
+#endif
+      TE_DROP        =1<<4, ///< Drop of table
+      TE_ALTER       =1<<5, ///< Alter of table
+      TE_CREATE      =1<<6, ///< Create of table
+      TE_GCP_COMPLETE=1<<7, ///< GCP is complete
+      TE_CLUSTER_FAILURE=1<<8, ///< Cluster is unavailable
+      TE_STOP        =1<<9, ///< Stop of event operation
+      TE_NODE_FAILURE=1<<10, ///< Node failed
+      TE_SUBSCRIBE   =1<<11, ///< Node subscribes
+      TE_UNSUBSCRIBE =1<<12, ///< Node unsubscribes
+      TE_ALL=0xFFFF         ///< Any/all event on table (not relevant when 
+                            ///< events are received)
+    };
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    enum _TableEvent { 
+      _TE_INSERT=0,
+      _TE_DELETE=1,
+      _TE_UPDATE=2,
+      _TE_SCAN=3,
+      _TE_FIRST_NON_DATA_EVENT=4,
+      _TE_DROP=4,
+      _TE_ALTER=5,
+      _TE_CREATE=6,
+      _TE_GCP_COMPLETE=7,
+      _TE_CLUSTER_FAILURE=8,
+      _TE_STOP=9,
+      _TE_NODE_FAILURE=10,
+      _TE_SUBSCRIBE=11,
+      _TE_UNSUBSCRIBE=12,
+      _TE_NUL=13, // internal (e.g. INS o DEL within same GCI)
+      _TE_ACTIVE=14 // internal (node becomes active)
+    };
+#endif
+    /**
+     *  Specifies the durability of an event
+     * (future version may supply other types)
+     */
+    enum EventDurability { 
+      ED_UNDEFINED
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+      = 0
+#endif
+#if 0 // not supported
+      ,ED_SESSION = 1, 
+      // Only this API can use it
+      // and it's deleted after api has disconnected or ndb has restarted
+      
+      ED_TEMPORARY = 2
+      // All API's can use it,
+      // But's its removed when ndb is restarted
+#endif
+      ,ED_PERMANENT    ///< All API's can use it.
+                       ///< It's still defined after a cluster system restart
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+      = 3
+#endif
+    };
+
+    /**
+     * Specifies reporting options for table events
+     */
+    enum EventReport {
+      ER_UPDATED = 0,
+      ER_ALL = 1, // except not-updated blob inlines
+      ER_SUBSCRIBE = 2
+    };
+
+    /**
+     *  Constructor
+     *  @param  name  Name of event
+     */
+    Event(const char *name);
+    /**
+     *  Constructor
+     *  @param  name  Name of event
+     *  @param  table Reference retrieved from NdbDictionary
+     */
+    Event(const char *name, const NdbDictionary::Table& table);
+    virtual ~Event();
+    /**
+     * Set unique identifier for the event
+     */
+    void setName(const char *name);
+    /**
+     * Get unique identifier for the event
+     */
+    const char *getName() const;
+    /**
+     * Get table that the event is defined on
+     *
+     * @return pointer to table or NULL if no table has been defined
+     */
+    const NdbDictionary::Table * getTable() const;
+    /**
+     * Define table on which events should be detected
+     *
+     * @note calling this method will default to detection
+     *       of events on all columns. Calling subsequent
+     *       addEventColumn calls will override this.
+     *
+     * @param table reference retrieved from NdbDictionary
+     */
+    void setTable(const NdbDictionary::Table& table);
+    /**
+     * Set table for which events should be detected
+     *
+     * @note preferred way is using setTable(const NdbDictionary::Table&)
+     *       or constructor with table object parameter
+     */
+    void setTable(const char *tableName);
+    /**
+     * Get table name for events
+     *
+     * @return table name
+     */
+    const char* getTableName() const;
+    /**
+     * Add type of event that should be detected
+     */
+    void addTableEvent(const TableEvent te);
+    /**
+     * Check if a specific table event will be detected
+     */
+    bool getTableEvent(const TableEvent te) const;
+    /**
+     * Set durability of the event
+     */
+    void setDurability(EventDurability);
+    /**
+     * Get durability of the event
+     */
+    EventDurability getDurability() const;
+    /**
+     * Set report option of the event
+     */
+    void setReport(EventReport);
+    /**
+     * Get report option of the event
+     */
+    EventReport getReport() const;
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    void addColumn(const Column &c);
+#endif
+    /**
+     * Add a column on which events should be detected
+     *
+     * @param attrId Column id
+     *
+     * @note errors will mot be detected until createEvent() is called
+     */
+    void addEventColumn(unsigned attrId);
+    /**
+     * Add a column on which events should be detected
+     *
+     * @param columnName Column name
+     *
+     * @note errors will not be detected until createEvent() is called
+     */
+    void addEventColumn(const char * columnName);
+    /**
+     * Add several columns on which events should be detected
+     *
+     * @param n Number of columns
+     * @param columnNames Column names
+     *
+     * @note errors will mot be detected until 
+     *       NdbDictionary::Dictionary::createEvent() is called
+     */
+    void addEventColumns(int n, const char ** columnNames);
+
+    /**
+     * Get no of columns defined in an Event
+     *
+     * @return Number of columns, -1 on error
+     */
+    int getNoOfEventColumns() const;
+
+    /**
+     * Get a specific column in the event
+     */
+    const Column * getEventColumn(unsigned no) const;
+
+    /**
+     * The merge events flag is false by default.  Setting it true
+     * implies that events are merged in following ways:
+     *
+     * - for given NdbEventOperation associated with this event,
+     *   events on same PK within same GCI are merged into single event
+     *
+     * - a blob table event is created for each blob attribute
+     *   and blob events are handled as part of main table events
+     *
+     * - blob post/pre data from the blob part events can be read
+     *   via NdbBlob methods as a single value
+     *
+     * NOTE: Currently this flag is not inherited by NdbEventOperation
+     * and must be set on NdbEventOperation explicitly.
+     */
+    void mergeEvents(bool flag);
+
+    /**
+     * Get object status
+     */
+    virtual Object::Status getObjectStatus() const;
+
+    /**
+     * Get object version
+     */
+    virtual int getObjectVersion() const;
+
+    /**
+     * Get object id
+     */
+    virtual int getObjectId() const;
+
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    void print();
+#endif
+
+  private:
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    friend class NdbEventImpl;
+    friend class NdbEventOperationImpl;
+#endif
+    class NdbEventImpl & m_impl;
+    Event(NdbEventImpl&);
+  };
+
+  struct AutoGrowSpecification {
+    Uint32 min_free;
+    Uint64 max_size;
+    Uint64 file_size;
+    const char * filename_pattern;
+  };
+
+  /**
+   * @class LogfileGroup
+   */
+  class LogfileGroup : public Object {
+  public:
+    LogfileGroup();
+    LogfileGroup(const LogfileGroup&);
+    virtual ~LogfileGroup();
+
+    void setName(const char * name);
+    const char* getName() const;
+
+    void setUndoBufferSize(Uint32 sz);
+    Uint32 getUndoBufferSize() const;
+    
+    void setAutoGrowSpecification(const AutoGrowSpecification&);
+    const AutoGrowSpecification& getAutoGrowSpecification() const;
+
+    Uint64 getUndoFreeWords() const;
+
+    /**
+     * Get object status
+     */
+    virtual Object::Status getObjectStatus() const;
+
+    /**
+     * Get object version
+     */
+    virtual int getObjectVersion() const;
+
+    /**
+     * Get object id
+     */
+    virtual int getObjectId() const;
+
+  private:
+    friend class NdbDictionaryImpl;
+    friend class NdbLogfileGroupImpl;
+    class NdbLogfileGroupImpl & m_impl;
+    LogfileGroup(NdbLogfileGroupImpl&);
+  };
+
+  /**
+   * @class Tablespace
+   */
+  class Tablespace : public Object {
+  public:
+    Tablespace();
+    Tablespace(const Tablespace&);
+    virtual ~Tablespace();
+
+    void setName(const char * name);
+    const char* getName() const;
+
+    void setExtentSize(Uint32 sz);
+    Uint32 getExtentSize() const;
+
+    void setAutoGrowSpecification(const AutoGrowSpecification&);
+    const AutoGrowSpecification& getAutoGrowSpecification() const;
+
+    void setDefaultLogfileGroup(const char * name);
+    void setDefaultLogfileGroup(const class LogfileGroup&);
+
+    const char * getDefaultLogfileGroup() const;
+    Uint32 getDefaultLogfileGroupId() const;
+    
+    /**
+     * Get object status
+     */
+    virtual Object::Status getObjectStatus() const;
+
+    /**
+     * Get object version
+     */
+    virtual int getObjectVersion() const;
+
+    /**
+     * Get object id
+     */
+    virtual int getObjectId() const;
+
+  private:
+    friend class NdbTablespaceImpl;
+    class NdbTablespaceImpl & m_impl;
+    Tablespace(NdbTablespaceImpl&);
+  };
+
+  class Datafile : public Object {
+  public:
+    Datafile();
+    Datafile(const Datafile&);
+    virtual ~Datafile();
+
+    void setPath(const char * name);
+    const char* getPath() const;
+  
+    void setSize(Uint64);
+    Uint64 getSize() const;
+    Uint64 getFree() const;
+    
+    void setTablespace(const char * name);
+    void setTablespace(const class Tablespace &);
+    const char * getTablespace() const;
+    void getTablespaceId(ObjectId * dst) const;
+
+    void setNode(Uint32 nodeId);
+    Uint32 getNode() const;
+
+    Uint32 getFileNo() const;
+
+    /**
+     * Get object status
+     */
+    virtual Object::Status getObjectStatus() const;
+
+    /**
+     * Get object version
+     */
+    virtual int getObjectVersion() const;
+
+    /**
+     * Get object id
+     */
+    virtual int getObjectId() const;
+
+  private:
+    friend class NdbDatafileImpl;
+    class NdbDatafileImpl & m_impl;
+    Datafile(NdbDatafileImpl&);
+  };
+
+  class Undofile : public Object {
+  public:
+    Undofile();
+    Undofile(const Undofile&);
+    virtual ~Undofile();
+
+    void setPath(const char * path);
+    const char* getPath() const;
+  
+    void setSize(Uint64);
+    Uint64 getSize() const;
+
+    void setLogfileGroup(const char * name);
+    void setLogfileGroup(const class LogfileGroup &);
+    const char * getLogfileGroup() const;
+    void getLogfileGroupId(ObjectId * dst) const;
+
+    void setNode(Uint32 nodeId);
+    Uint32 getNode() const;
+
+    Uint32 getFileNo() const;
+
+    /**
+     * Get object status
+     */
+    virtual Object::Status getObjectStatus() const;
+
+    /**
+     * Get object version
+     */
+    virtual int getObjectVersion() const;
+
+    /**
+     * Get object id
+     */
+    virtual int getObjectId() const;
+
+  private:
+    friend class NdbUndofileImpl;
+    class NdbUndofileImpl & m_impl;
+    Undofile(NdbUndofileImpl&);
+  };
+
+  /**
    * @class Dictionary
    * @brief Dictionary for defining and retreiving meta data
    */
@@ -971,7 +1627,8 @@
 	unsigned id;            ///< Id of object
         Object::Type type;      ///< Type of object
         Object::State state;    ///< State of object
-        Object::Store store;    ///< How object is stored
+        Object::Store store;    ///< How object is logged
+        Uint32 temp;            ///< Temporary status of object
 	char * database;        ///< In what database the object resides 
 	char * schema;          ///< What schema the object is defined in
 	char * name;            ///< Name of object
@@ -980,6 +1637,7 @@
           type(Object::TypeUndefined),
           state(Object::StateUndefined),
           store(Object::StoreUndefined),
+          temp(NDB_TEMP_TAB_PERMANENT),
 	  database(0),
 	  schema(0),
           name(0) {
@@ -1043,23 +1701,28 @@
      */
     const Table * getTable(const char * name) const;
 
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
     /**
-     * Get index with given name, NULL if undefined
-     * @param indexName  Name of index to get.
-     * @param tableName  Name of table that index belongs to.
-     * @return  index if successful, otherwise 0.
+     * Given main table, get blob table.
      */
-    const Index * getIndex(const char * indexName,
-			   const char * tableName) const;
+    const Table * getBlobTable(const Table *, const char * col_name);
+    const Table * getBlobTable(const Table *, Uint32 col_no);
+
+    /*
+     * Save a table definition in dictionary cache
+     * @param table Object to put into cache
+     */
+    void putTable(const Table * table);
+#endif
 
     /**
      * Get index with given name, NULL if undefined
      * @param indexName  Name of index to get.
-     * @param Table instance table that index belongs to.
+     * @param tableName  Name of table that index belongs to.
      * @return  index if successful, otherwise 0.
      */
     const Index * getIndex(const char * indexName,
-			   const Table & table) const;
+			   const char * tableName) const;
 
     /**
      * Fetch list of indexes of given table.
@@ -1070,6 +1733,43 @@
     int listIndexes(List & list, const char * tableName);
     int listIndexes(List & list, const char * tableName) const;
 
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    /**
+     * Fetch list of indexes of given table.
+     * @param list  Reference to list where to store the listed indexes
+     * @param table  Reference to table that index belongs to.
+     * @return  0 if successful, otherwise -1
+     */
+    int listIndexes(List & list, const Table &table) const;
+#endif
+
+    /** @} *******************************************************************/
+    /** 
+     * @name Events
+     * @{
+     */
+    
+    /**
+     * Create event given defined Event instance
+     * @param event Event to create
+     * @return 0 if successful otherwise -1.
+     */
+    int createEvent(const Event &event);
+
+    /**
+     * Drop event with given name
+     * @param eventName  Name of event to drop.
+     * @return 0 if successful otherwise -1.
+     */
+    int dropEvent(const char * eventName);
+    
+    /**
+     * Get event with given name.
+     * @param eventName  Name of event to get.
+     * @return an Event if successful, otherwise NULL.
+     */
+    const Event * getEvent(const char * eventName);
+
     /** @} *******************************************************************/
 
     /** 
@@ -1082,14 +1782,14 @@
 
     /**
      * Create defined table given defined Table instance
-     * @param Table instance to create
+     * @param table Table to create
      * @return 0 if successful otherwise -1.
      */
     int createTable(const Table &table);
 
     /**
      * Drop table given retrieved Table instance
-     * @param Table instance to drop
+     * @param table Table to drop
      * @return 0 if successful otherwise -1.
      */
     int dropTable(Table & table);
@@ -1144,6 +1844,7 @@
      * @return 0 if successful otherwise -1.
      */
     int createIndex(const Index &index);
+    int createIndex(const Index &index, const Table &table);
 
     /**
      * Drop index with given name
@@ -1153,25 +1854,50 @@
      */
     int dropIndex(const char * indexName,
 		  const char * tableName);
-
-    /**
-     * Drop index the defined Index instance
-     * @param Index to drop
-     * @return 0 if successful otherwise -1.
-     */
-    int dropIndex(const Index &);
-
-
+    
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
+    void removeCachedTable(const Table *table);
+    void removeCachedIndex(const Index *index);
+    void invalidateTable(const Table *table);
     /**
      * Invalidate cached index object
      */
     void invalidateIndex(const char * indexName,
                          const char * tableName);
+    void invalidateIndex(const Index *index);
+    /**
+     * Force gcp and wait for gcp complete
+     */
+    int forceGCPWait();
 #endif
 
     /** @} *******************************************************************/
 
+    /** @} *******************************************************************/
+    /** 
+     * @name Disk data objects
+     * @{
+     */
+    
+    int createLogfileGroup(const LogfileGroup &, ObjectId* = 0);
+    int dropLogfileGroup(const LogfileGroup&);
+    LogfileGroup getLogfileGroup(const char * name);
+
+    int createTablespace(const Tablespace &, ObjectId* = 0);
+    int dropTablespace(const Tablespace&);
+    Tablespace getTablespace(const char * name);
+    Tablespace getTablespace(Uint32 tablespaceId);
+
+    int createDatafile(const Datafile &, bool overwrite_existing = false, ObjectId* = 0);
+    int dropDatafile(const Datafile&);
+    Datafile getDatafile(Uint32 node, const char * path);
+    
+    int createUndofile(const Undofile &, bool overwrite_existing = false, ObjectId * = 0);
+    int dropUndofile(const Undofile&);
+    Undofile getUndofile(Uint32 node, const char * path);
+    
+    /** @} *******************************************************************/
+    
   protected:
     Dictionary(Ndb & ndb);
     ~Dictionary();
@@ -1190,6 +1916,15 @@
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
     const Table * getTable(const char * name, void **data) const;
     void set_local_table_data_size(unsigned sz);
+
+    const Index * getIndexGlobal(const char * indexName,
+                                 const Table &ndbtab) const;
+    const Table * getTableGlobal(const char * tableName) const;
+    int alterTableGlobal(const Table &f, const Table &t);
+    int dropTableGlobal(const Table &ndbtab);
+    int dropIndexGlobal(const Index &index);
+    int removeIndexGlobal(const Index &ndbidx, int invalidate) const;
+    int removeTableGlobal(const Table &ndbtab, int invalidate) const;
 #endif
   };
 };

--- 1.7.2.1/ndb/include/util/BaseString.hpp	2007-04-11 15:21:08 +02:00
+++ 1.11/storage/ndb/include/util/BaseString.hpp	2007-04-11 15:22:08 +02:00
@@ -46,6 +46,9 @@
   /** @brief Checks if the string is empty */
   bool empty() const;
 
+  /** @brief Clear a string */
+  void clear();
+
   /** @brief Convert to uppercase */
   BaseString& ndb_toupper();
 
@@ -204,6 +207,15 @@
 BaseString::empty() const
 {
   return m_len == 0;
+}
+
+inline void
+BaseString::clear()
+{
+  delete[] m_chr;
+  m_chr = new char[1];
+  m_chr[0] = 0;
+  m_len = 0;
 }
 
 inline BaseString&

--- 1.4.4.1/ndb/include/util/Vector.hpp	2007-04-11 15:21:08 +02:00
+++ 1.10/storage/ndb/include/util/Vector.hpp	2007-04-11 15:51:06 +02:00
@@ -30,6 +30,8 @@
   unsigned size() const { return m_size; };
   
   int push_back(const T &);
+  void push(const T&, unsigned pos);
+  T& set(T&, unsigned pos, T& fill_obj);
   T& back();
   
   void erase(unsigned index);
@@ -114,8 +116,31 @@
   }
   m_items[m_size] = t;
   m_size++;
+}
 
-  return 0;
+template<class T>
+void
+Vector<T>::push(const T & t, unsigned pos)
+{
+  push_back(t);
+  if (pos < m_size - 1)
+  {
+    for(unsigned i = m_size - 1; i > pos; i--)
+    {
+      m_items[i] = m_items[i-1];
+    }
+    m_items[pos] = t;
+  }
+}
+
+template<class T>
+T&
+Vector<T>::set(T & t, unsigned pos, T& fill_obj)
+{
+  fill(pos, fill_obj);
+  T& ret = m_items[pos];
+  m_items[pos] = t;
+  return ret;
 }
 
 template<class T>

--- 1.12.11.1/ndb/src/ndbapi/DictCache.cpp	2007-04-11 15:21:08 +02:00
+++ 1.33/storage/ndb/src/ndbapi/DictCache.cpp	2007-04-11 15:51:06 +02:00
@@ -26,6 +26,7 @@
 Ndb_local_table_info *
 Ndb_local_table_info::create(NdbTableImpl *table_impl, Uint32 sz)
 {
+  assert(! is_ndb_blob_table(table_impl));
   Uint32 tot_size= sizeof(Ndb_local_table_info) - sizeof(Uint64)
     + ((sz+7) & ~7); // round to Uint64
   void *data= malloc(tot_size);
@@ -43,9 +44,9 @@
 
 Ndb_local_table_info::Ndb_local_table_info(NdbTableImpl *table_impl)
 {
+  assert(! is_ndb_blob_table(table_impl));
   m_table_impl= table_impl;
-  m_first_tuple_id = ~(Uint64)0;
-  m_last_tuple_id = ~(Uint64)0;
+  m_tuple_id_range.reset();
 }
 
 Ndb_local_table_info::~Ndb_local_table_info()
@@ -62,19 +63,24 @@
 
 Ndb_local_table_info * 
 LocalDictCache::get(const char * name){
+  ASSERT_NOT_MYSQLD;
+  assert(! is_ndb_blob_table(name));
   const Uint32 len = strlen(name);
   return m_tableHash.getData(name, len);
 }
 
 void 
 LocalDictCache::put(const char * name, Ndb_local_table_info * tab_info){
-  const Uint32 id = tab_info->m_table_impl->m_tableId;
-  
+  ASSERT_NOT_MYSQLD;
+  assert(! is_ndb_blob_table(name));
+  const Uint32 id = tab_info->m_table_impl->m_id;
   m_tableHash.insertKey(name, strlen(name), id, tab_info);
 }
 
 void
 LocalDictCache::drop(const char * name){
+  ASSERT_NOT_MYSQLD;
+  assert(! is_ndb_blob_table(name));
   Ndb_local_table_info *info= m_tableHash.deleteKey(name, strlen(name));
   DBUG_ASSERT(info != 0);
   Ndb_local_table_info::destroy(info);
@@ -97,8 +103,15 @@
     Vector<TableVersion> * vers = curr->theData;
     const unsigned sz = vers->size();
     for(unsigned i = 0; i<sz ; i++){
-      if((* vers)[i].m_impl != 0)
+      TableVersion tv= (*vers)[i];
+      DBUG_PRINT("  ", ("vers[%d]: ver: %d, refCount: %d, status: %d",
+                        i, tv.m_version, tv.m_refCount, tv.m_status));
+      if(tv.m_impl != 0)
+      {
+        DBUG_PRINT("  ", ("m_impl: internalname: %s",
+                          tv.m_impl->m_internalName.c_str()));
 	delete (* vers)[i].m_impl;
+      }
     }
     delete curr->theData;
     curr->theData= NULL;
@@ -122,8 +135,8 @@
       const unsigned sz = vers->size();
       for(unsigned i = 0; i<sz ; i++){
         TableVersion tv= (*vers)[i];
-        DBUG_PRINT("  ", ("vers[%d]: ver: %d, refCount: %d, status: %d",
-                          sz, tv.m_version, tv.m_refCount, tv.m_status));
+        DBUG_PRINT("  ", ("impl: %p  vers[%d]: ver: %d, refCount: %d, status: %d",
+                          tv.m_impl, i, tv.m_version, tv.m_refCount, tv.m_status));
         if(tv.m_impl != 0)
         {
           DBUG_PRINT("  ", ("m_impl: internalname: %s",
@@ -145,6 +158,7 @@
 {
   DBUG_ENTER("GlobalDictCache::get");
   DBUG_PRINT("enter", ("name: %s", name));
+  assert(! is_ndb_blob_table(name));
 
   const Uint32 len = strlen(name);
   Vector<TableVersion> * versions = 0;
@@ -166,12 +180,29 @@
     TableVersion * ver = & versions->back();
     switch(ver->m_status){
     case OK:
+      if (ver->m_impl->m_status == NdbDictionary::Object::Invalid)
+      {
+        ver->m_status = DROPPED;
+        retreive = true; // Break loop
+        if (ver->m_refCount == 0)
+        {
+          delete ver->m_impl;
+          versions->erase(versions->size() - 1);
+        }
+        break;
+      }
       ver->m_refCount++;
+      DBUG_PRINT("info", ("Table OK tab: %p  version=%x.%x refCount=%u",
+                          ver->m_impl,
+                          ver->m_impl->m_version & 0xFFFFFF,
+                          ver->m_impl->m_version >> 24,
+                          ver->m_refCount));
       DBUG_RETURN(ver->m_impl);
     case DROPPED:
       retreive = true; // Break loop
       break;
     case RETREIVING:
+      DBUG_PRINT("info", ("Wait for retrieving thread"));
       NdbCondition_WaitTimeout(m_waitForTableCondition, m_mutex, waitTime);
       continue;
     }
@@ -188,8 +219,9 @@
   if (versions->push_back(tmp))
   {
     *error = -1;
-    DBUG_RETURN(0);
+     DBUG_RETURN(0);
   }
+  DBUG_PRINT("info", ("No table found"));
   DBUG_RETURN(0);
 }
 
@@ -197,8 +229,12 @@
 GlobalDictCache::put(const char * name, NdbTableImpl * tab)
 {
   DBUG_ENTER("GlobalDictCache::put");
-  DBUG_PRINT("enter", ("name: %s, internal_name: %s",
-                       name, tab ? tab->m_internalName.c_str() : "tab NULL"));
+  DBUG_PRINT("enter", ("tab: %p  name: %s, internal_name: %s version: %x.%x",
+                       tab, name,
+                       tab ? tab->m_internalName.c_str() : "tab NULL",
+                       tab ? tab->m_version & 0xFFFFFF : 0,
+                       tab ? tab->m_version >> 24 : 0));
+  assert(! is_ndb_blob_table(name));
 
   const Uint32 len = strlen(name);
   Vector<TableVersion> * vers = m_tableHash.getData(name, len);
@@ -230,12 +266,14 @@
     vers->erase(sz - 1);
   } 
   else if (ver.m_impl == 0) {
+    DBUG_PRINT("info", ("Table OK"));
     ver.m_impl = tab;
     ver.m_version = tab->m_version;
     ver.m_status = OK;
   } 
   else if (ver.m_impl == &f_invalid_table) 
   {
+    DBUG_PRINT("info", ("Table DROPPED invalid"));
     ver.m_impl = tab;
     ver.m_version = tab->m_version;
     ver.m_status = DROPPED;
@@ -243,6 +281,7 @@
   }
   else if(ver.m_impl == &f_altered_table)
   {
+    DBUG_PRINT("info", ("Table DROPPED altered"));
     ver.m_impl = tab;
     ver.m_version = tab->m_version;
     ver.m_status = DROPPED;
@@ -256,62 +295,6 @@
   DBUG_RETURN(tab);
 } 
 
-void
-GlobalDictCache::drop(NdbTableImpl * tab)
-{
-  DBUG_ENTER("GlobalDictCache::drop");
-  DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
-
-  unsigned i;
-  const Uint32 len = strlen(tab->m_internalName.c_str());
-  Vector<TableVersion> * vers = 
-    m_tableHash.getData(tab->m_internalName.c_str(), len);
-  if(vers == 0){
-    // Should always tried to retreive it first 
-    // and thus there should be a record
-    abort(); 
-  }
-
-  const Uint32 sz = vers->size();
-  if(sz == 0){
-    // Should always tried to retreive it first 
-    // and thus there should be a record
-    abort(); 
-  }
-
-  for(i = 0; i < sz; i++){
-    TableVersion & ver = (* vers)[i];
-    if(ver.m_impl == tab){
-      if(ver.m_refCount == 0 || ver.m_status == RETREIVING ||
-	 ver.m_version != tab->m_version){
-	DBUG_PRINT("info", ("Dropping with refCount=%d status=%d impl=%p",
-                            ver.m_refCount, ver.m_status, ver.m_impl));
-	break;
-      }
-      DBUG_PRINT("info", ("Found table to drop, i: %d, name: %s",
-                          i, ver.m_impl->m_internalName.c_str()));
-      ver.m_refCount--;
-      ver.m_status = DROPPED;
-      if(ver.m_refCount == 0){
-        DBUG_PRINT("info", ("refCount is zero, deleting m_impl"))
-	delete ver.m_impl;
-	vers->erase(i);
-      }
-      DBUG_VOID_RETURN;
-    }
-  }
-
-  for(i = 0; i<sz; i++){
-    TableVersion & ver = (* vers)[i];
-    DBUG_PRINT("info", ("%d: version: %d refCount: %d status: %d impl: %p",
-                        i, ver.m_version, ver.m_refCount,
-                        ver.m_status, ver.m_impl));
-  }
-  
-  abort();
-}
-
-
 unsigned
 GlobalDictCache::get_size()
 {
@@ -321,6 +304,10 @@
     sz += curr->theData->size();
     curr = m_tableHash.getNext(curr);
   }
+  if (sz)
+  {
+    printCache();
+  }
   return sz;
 }
 
@@ -351,10 +338,12 @@
 }
 
 void
-GlobalDictCache::release(NdbTableImpl * tab)
+GlobalDictCache::release(NdbTableImpl * tab, int invalidate)
 {
   DBUG_ENTER("GlobalDictCache::release");
-  DBUG_PRINT("enter", ("internal_name: %s", tab->m_internalName.c_str()));
+  DBUG_PRINT("enter", ("tab: %p  internal_name: %s",
+                       tab, tab->m_internalName.c_str()));
+  assert(! is_ndb_blob_table(tab));
 
   unsigned i;
   const Uint32 len = strlen(tab->m_internalName.c_str());
@@ -384,15 +373,26 @@
       }
       
       ver.m_refCount--;
+      if (ver.m_impl->m_status == NdbDictionary::Object::Invalid || invalidate)
+      {
+        ver.m_impl->m_status = NdbDictionary::Object::Invalid;
+        ver.m_status = DROPPED;
+      }
+      if (ver.m_refCount == 0 && ver.m_status == DROPPED)
+      {
+        DBUG_PRINT("info", ("refCount is zero, deleting m_impl"));
+        delete ver.m_impl;
+        vers->erase(i);
+      }
       DBUG_VOID_RETURN;
     }
   }
   
   for(i = 0; i<sz; i++){
     TableVersion & ver = (* vers)[i];
-    DBUG_PRINT("info", ("%d: version: %d refCount: %d status: %d impl: %p",
-                        i, ver.m_version, ver.m_refCount,
-                        ver.m_status, ver.m_impl));
+    ndbout_c("%d: version: %d refCount: %d status: %d impl: %p",
+	     i, ver.m_version, ver.m_refCount,
+	     ver.m_status, ver.m_impl);
   }
   
   abort();
@@ -404,39 +404,47 @@
 				 Uint32 tableVersion,
 				 bool altered)
 {
+  DBUG_ENTER("GlobalDictCache::alter_table_rep");
+  assert(! is_ndb_blob_table(name));
   const Uint32 len = strlen(name);
   Vector<TableVersion> * vers = 
     m_tableHash.getData(name, len);
   
   if(vers == 0)
   {
-    return;
+    DBUG_VOID_RETURN;
   }
 
   const Uint32 sz = vers->size();
   if(sz == 0)
   {
-    return;
+    DBUG_VOID_RETURN;
   }
   
   for(Uint32 i = 0; i < sz; i++)
   {
     TableVersion & ver = (* vers)[i];
     if(ver.m_version == tableVersion && ver.m_impl && 
-       ver.m_impl->m_tableId == tableId)
+       (Uint32) ver.m_impl->m_id == tableId)
     {
       ver.m_status = DROPPED;
       ver.m_impl->m_status = altered ? 
 	NdbDictionary::Object::Altered : NdbDictionary::Object::Invalid;
-      return;
+      if (ver.m_refCount == 0)
+      {
+        delete ver.m_impl;
+        vers->erase(i);
+      }
+      DBUG_VOID_RETURN;
     }
 
     if(i == sz - 1 && ver.m_status == RETREIVING)
     {
       ver.m_impl = altered ? &f_altered_table : &f_invalid_table;
-      return;
+      DBUG_VOID_RETURN;
     } 
   }
+  DBUG_VOID_RETURN;
 }
 
 template class Vector<GlobalDictCache::TableVersion>;

--- 1.6.10.1/ndb/src/ndbapi/DictCache.hpp	2007-04-11 15:21:08 +02:00
+++ 1.18/storage/ndb/src/ndbapi/DictCache.hpp	2007-04-11 15:51:06 +02:00
@@ -34,8 +34,7 @@
   NdbTableImpl *m_table_impl;
 
   // range of cached tuple ids per thread
-  Uint64 m_first_tuple_id;
-  Uint64 m_last_tuple_id;
+  Ndb::TupleIdRange m_tuple_id_range;
 
   Uint64 m_local_data[1]; // Must be last member. Used to access extra space.
 private:
@@ -67,11 +66,11 @@
   GlobalDictCache();
   ~GlobalDictCache();
   
+  NdbTableImpl * get(NdbTableImpl *tab);
   NdbTableImpl * get(const char * name, int *error);
   
   NdbTableImpl* put(const char * name, NdbTableImpl *);
-  void drop(NdbTableImpl *);
-  void release(NdbTableImpl *);
+  void release(NdbTableImpl *, int invalidate = 0);
 
   void alter_table_rep(const char * name, 
 		       Uint32 tableId, Uint32 tableVersion, bool altered);

--- 1.49.25.1/ndb/src/ndbapi/Ndb.cpp	2007-04-11 15:21:08 +02:00
+++ 1.91/storage/ndb/src/ndbapi/Ndb.cpp	2007-04-11 15:51:06 +02:00
@@ -27,6 +27,8 @@
 #include "NdbImpl.hpp"
 #include <NdbOperation.hpp>
 #include <NdbTransaction.hpp>
+#include <NdbEventOperation.hpp>
+#include <NdbEventOperationImpl.hpp>
 #include <NdbRecAttr.hpp>
 #include <md5_hash.hpp>
 #include <NdbSleep.h>
@@ -142,7 +144,7 @@
 //***************************************************************************
   
   int	         tReturnCode;
-  TransporterFacade *tp = TransporterFacade::instance();
+  TransporterFacade *tp = theImpl->m_transporter_facade;
 
   DBUG_ENTER("Ndb::NDB_connect");
 
@@ -177,24 +179,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) { 
-      DBUG_PRINT("info",("Sending signal to node %u", tNode));
-      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
@@ -240,10 +227,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;
@@ -603,6 +589,7 @@
 #ifdef CUSTOMER_RELEASE
   return -1;
 #else
+  DBUG_ENTER("Ndb::NdbTamper");
   CHECK_STATUS_MACRO;
   checkFailedNode();
 
@@ -624,20 +611,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);
@@ -649,12 +636,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();
@@ -665,7 +652,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) {  
@@ -673,15 +660,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
@@ -780,15 +767,18 @@
                            Uint64 & tupleId, Uint32 cacheSize)
 {
   DBUG_ENTER("Ndb::getAutoIncrementValue");
+  ASSERT_NOT_MYSQLD;
   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(-1);
   }
-  if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1)
+  const NdbTableImpl* table = info->m_table_impl;
+  TupleIdRange & range = info->m_tuple_id_range;
+  if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1)
     DBUG_RETURN(-1);
   DBUG_PRINT("info", ("value %lu", (ulong) tupleId));
   DBUG_RETURN(0);
@@ -799,31 +789,48 @@
                            Uint64 & tupleId, Uint32 cacheSize)
 {
   DBUG_ENTER("Ndb::getAutoIncrementValue");
+  ASSERT_NOT_MYSQLD;
   assert(aTable != 0);
   const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
   const BaseString& internal_tabname = table->m_internalName;
 
   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(-1);
   }
-  if (getTupleIdFromNdb(info, tupleId, cacheSize) == -1)
+  TupleIdRange & range = info->m_tuple_id_range;
+  if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1)
+    DBUG_RETURN(-1);
+  DBUG_PRINT("info", ("value %lu", (ulong)tupleId));
+  DBUG_RETURN(0);
+}
+
+int
+Ndb::getAutoIncrementValue(const NdbDictionary::Table * aTable,
+                           TupleIdRange & range, Uint64 & tupleId,
+                           Uint32 cacheSize)
+{
+  DBUG_ENTER("Ndb::getAutoIncrementValue");
+  assert(aTable != 0);
+  const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
+
+  if (getTupleIdFromNdb(table, range, tupleId, cacheSize) == -1)
     DBUG_RETURN(-1);
   DBUG_PRINT("info", ("value %lu", (ulong)tupleId));
   DBUG_RETURN(0);
 }
 
 int
-Ndb::getTupleIdFromNdb(Ndb_local_table_info* info,
-                       Uint64 & tupleId, Uint32 cacheSize)
+Ndb::getTupleIdFromNdb(const NdbTableImpl* table,
+                       TupleIdRange & range, Uint64 & tupleId, Uint32 cacheSize)
 {
   DBUG_ENTER("Ndb::getTupleIdFromNdb");
-  if (info->m_first_tuple_id != info->m_last_tuple_id)
+  if (range.m_first_tuple_id != range.m_last_tuple_id)
   {
-    assert(info->m_first_tuple_id < info->m_last_tuple_id);
-    tupleId = ++info->m_first_tuple_id;
+    assert(range.m_first_tuple_id < range.m_last_tuple_id);
+    tupleId = ++range.m_first_tuple_id;
     DBUG_PRINT("info", ("next cached value %lu", (ulong)tupleId));
   }
   else
@@ -836,7 +843,7 @@
      * and returns first tupleId in the new range.
      */
     Uint64 opValue = cacheSize;
-    if (opTupleIdOnNdb(info, opValue, 0) == -1)
+    if (opTupleIdOnNdb(table, range, opValue, 0) == -1)
       DBUG_RETURN(-1);
     tupleId = opValue;
   }
@@ -848,15 +855,18 @@
                             Uint64 & tupleId)
 {
   DBUG_ENTER("Ndb::readAutoIncrementValue");
+  ASSERT_NOT_MYSQLD;
   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(-1);
   }
-  if (readTupleIdFromNdb(info, tupleId) == -1)
+  const NdbTableImpl* table = info->m_table_impl;
+  TupleIdRange & range = info->m_tuple_id_range;
+  if (readTupleIdFromNdb(table, range, tupleId) == -1)
     DBUG_RETURN(-1);
   DBUG_PRINT("info", ("value %lu", (ulong)tupleId));
   DBUG_RETURN(0);
@@ -867,31 +877,47 @@
                             Uint64 & tupleId)
 {
   DBUG_ENTER("Ndb::readAutoIncrementValue");
+  ASSERT_NOT_MYSQLD;
   assert(aTable != 0);
   const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
   const BaseString& internal_tabname = table->m_internalName;
 
   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(-1);
   }
-  if (readTupleIdFromNdb(info, tupleId) == -1)
+  TupleIdRange & range = info->m_tuple_id_range;
+  if (readTupleIdFromNdb(table, range, tupleId) == -1)
     DBUG_RETURN(-1);
   DBUG_PRINT("info", ("value %lu", (ulong)tupleId));
   DBUG_RETURN(0);
 }
 
 int
-Ndb::readTupleIdFromNdb(Ndb_local_table_info* info,
-                        Uint64 & tupleId)
+Ndb::readAutoIncrementValue(const NdbDictionary::Table * aTable,
+                            TupleIdRange & range, Uint64 & tupleId)
+{
+  DBUG_ENTER("Ndb::readAutoIncrementValue");
+  assert(aTable != 0);
+  const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
+
+  if (readTupleIdFromNdb(table, range, tupleId) == -1)
+    DBUG_RETURN(-1);
+  DBUG_PRINT("info", ("value %lu", (ulong)tupleId));
+  DBUG_RETURN(0);
+}
+
+int
+Ndb::readTupleIdFromNdb(const NdbTableImpl* table,
+                        TupleIdRange & range, Uint64 & tupleId)
 {
   DBUG_ENTER("Ndb::readTupleIdFromNdb");
-  if (info->m_first_tuple_id != info->m_last_tuple_id)
+  if (range.m_first_tuple_id != range.m_last_tuple_id)
   {
-    assert(info->m_first_tuple_id < info->m_last_tuple_id);
-    tupleId = info->m_first_tuple_id + 1;
+    assert(range.m_first_tuple_id < range.m_last_tuple_id);
+    tupleId = range.m_first_tuple_id + 1;
   }
   else
   {
@@ -900,7 +926,7 @@
      * only if no other transactions are allowed.
      */
     Uint64 opValue = 0;
-    if (opTupleIdOnNdb(info, opValue, 3) == -1)
+    if (opTupleIdOnNdb(table, range, opValue, 3) == -1)
       DBUG_RETURN(-1);
     tupleId = opValue;
   }
@@ -912,15 +938,18 @@
                            Uint64 tupleId, bool increase)
 {
   DBUG_ENTER("Ndb::setAutoIncrementValue");
+  ASSERT_NOT_MYSQLD;
   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(-1);
   }
-  if (setTupleIdInNdb(info, tupleId, increase) == -1)
+  const NdbTableImpl* table = info->m_table_impl;
+  TupleIdRange & range = info->m_tuple_id_range;
+  if (setTupleIdInNdb(table, range, tupleId, increase) == -1)
     DBUG_RETURN(-1);
   DBUG_RETURN(0);
 }
@@ -930,36 +959,52 @@
                            Uint64 tupleId, bool increase)
 {
   DBUG_ENTER("Ndb::setAutoIncrementValue");
+  ASSERT_NOT_MYSQLD;
   assert(aTable != 0);
   const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
   const BaseString& internal_tabname = table->m_internalName;
 
   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(-1);
   }
-  if (setTupleIdInNdb(info, tupleId, increase) == -1)
+  TupleIdRange & range = info->m_tuple_id_range;
+  if (setTupleIdInNdb(table, range, tupleId, increase) == -1)
+    DBUG_RETURN(-1);
+  DBUG_RETURN(0);
+}
+
+int
+Ndb::setAutoIncrementValue(const NdbDictionary::Table * aTable,
+                           TupleIdRange & range, Uint64 tupleId,
+                           bool increase)
+{
+  DBUG_ENTER("Ndb::setAutoIncrementValue");
+  assert(aTable != 0);
+  const NdbTableImpl* table = & NdbTableImpl::getImpl(*aTable);
+
+  if (setTupleIdInNdb(table, range, tupleId, increase) == -1)
     DBUG_RETURN(-1);
   DBUG_RETURN(0);
 }
 
 int
-Ndb::setTupleIdInNdb(Ndb_local_table_info* info,
-                     Uint64 tupleId, bool increase)
+Ndb::setTupleIdInNdb(const NdbTableImpl* table,
+                     TupleIdRange & range, Uint64 tupleId, bool increase)
 {
   DBUG_ENTER("Ndb::setTupleIdInNdb");
   if (increase)
   {
-    if (info->m_first_tuple_id != info->m_last_tuple_id)
+    if (range.m_first_tuple_id != range.m_last_tuple_id)
     {
-      assert(info->m_first_tuple_id < info->m_last_tuple_id);
-      if (tupleId <= info->m_first_tuple_id + 1)
+      assert(range.m_first_tuple_id < range.m_last_tuple_id);
+      if (tupleId <= range.m_first_tuple_id + 1)
 	DBUG_RETURN(0);
-      if (tupleId <= info->m_last_tuple_id)
+      if (tupleId <= range.m_last_tuple_id)
       {
-	info->m_first_tuple_id = tupleId - 1;
+	range.m_first_tuple_id = tupleId - 1;
         DBUG_PRINT("info", 
                    ("Setting next auto increment cached value to %lu",
                     (ulong)tupleId));  
@@ -970,7 +1015,7 @@
      * if tupleId <= NEXTID, do nothing.  otherwise update NEXTID to
      * tupleId and set cached range to first = last = tupleId - 1.
      */
-    if (opTupleIdOnNdb(info, tupleId, 2) == -1)
+    if (opTupleIdOnNdb(table, range, tupleId, 2) == -1)
       DBUG_RETURN(-1);
   }
   else
@@ -978,42 +1023,62 @@
     /*
      * update NEXTID to given value.  reset cached range.
      */
-    if (opTupleIdOnNdb(info, tupleId, 1) == -1)
+    if (opTupleIdOnNdb(table, range, tupleId, 1) == -1)
       DBUG_RETURN(-1);
   }
   DBUG_RETURN(0);
 }
 
+int Ndb::initAutoIncrement()
+{
+  if (m_sys_tab_0)
+    return 0;
+
+  BaseString currentDb(getDatabaseName());
+  BaseString currentSchema(getDatabaseSchemaName());
+
+  setDatabaseName("sys");
+  setDatabaseSchemaName("def");
+
+  m_sys_tab_0 = theDictionary->getTableGlobal("SYSTAB_0");
+
+  // Restore current name space
+  setDatabaseName(currentDb.c_str());
+  setDatabaseSchemaName(currentSchema.c_str());
+
+  if (m_sys_tab_0 == NULL) {
+    assert(theDictionary->m_error.code != 0);
+    theError.code = theDictionary->m_error.code;
+    return -1;
+  }
+
+  return 0;
+}
+
 int
-Ndb::opTupleIdOnNdb(Ndb_local_table_info* info, Uint64 & opValue, Uint32 op)
+Ndb::opTupleIdOnNdb(const NdbTableImpl* table,
+                    TupleIdRange & range, Uint64 & opValue, Uint32 op)
 {
   DBUG_ENTER("Ndb::opTupleIdOnNdb");
-  Uint32 aTableId = info->m_table_impl->m_tableId;
+  Uint32 aTableId = table->m_id;
   DBUG_PRINT("enter", ("table: %u  value: %lu  op: %u",
                        aTableId, (ulong) opValue, op));
 
-  NdbTransaction*     tConnection;
-  NdbOperation*      tOperation= 0; // Compiler warning if not initialized
+  NdbTransaction*    tConnection = NULL;
+  NdbOperation*      tOperation = NULL;
   Uint64             tValue;
   NdbRecAttr*        tRecAttrResult;
 
-  NdbError savedError;
-
-  CHECK_STATUS_MACRO_ZERO;
+  CHECK_STATUS_MACRO;
 
-  BaseString currentDb(getDatabaseName());
-  BaseString currentSchema(getDatabaseSchemaName());
+  if (initAutoIncrement() == -1)
+    goto error_handler;
 
-  setDatabaseName("sys");
-  setDatabaseSchemaName("def");
   tConnection = this->startTransaction();
   if (tConnection == NULL)
-    goto error_return;
+    goto error_handler;
 
-  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;
 
@@ -1021,18 +1086,18 @@
     {
     case 0:
       tOperation->interpretedUpdateTuple();
-      tOperation->equal("SYSKEY_0", aTableId );
+      tOperation->equal("SYSKEY_0", aTableId);
       tOperation->incValue("NEXTID", opValue);
       tRecAttrResult = tOperation->getValue("NEXTID");
 
-      if (tConnection->execute( Commit ) == -1 )
+      if (tConnection->execute( NdbTransaction::Commit ) == -1 )
         goto error_handler;
 
       tValue = tRecAttrResult->u_64_value();
 
-      info->m_first_tuple_id = tValue - opValue;
-      info->m_last_tuple_id  = tValue - 1;
-      opValue = info->m_first_tuple_id; // out
+      range.m_first_tuple_id = tValue - opValue;
+      range.m_last_tuple_id  = tValue - 1;
+      opValue = range.m_first_tuple_id; // out
       break;
     case 1:
       // create on first use
@@ -1040,11 +1105,10 @@
       tOperation->equal("SYSKEY_0", aTableId );
       tOperation->setValue("NEXTID", opValue);
 
-      if (tConnection->execute( Commit ) == -1 )
+      if (tConnection->execute( NdbTransaction::Commit ) == -1 )
         goto error_handler;
 
-      info->m_first_tuple_id = ~(Uint64)0;
-      info->m_last_tuple_id  = ~(Uint64)0;
+      range.reset();
       break;
     case 2:
       tOperation->interpretedUpdateTuple();
@@ -1058,7 +1122,7 @@
       tOperation->def_label(0);
       tOperation->interpret_exit_nok(9999);
       
-      if (tConnection->execute( Commit ) == -1)
+      if (tConnection->execute( NdbTransaction::Commit ) == -1)
       {
         if (tConnection->theError.code != 9999)
           goto error_handler;
@@ -1067,15 +1131,15 @@
       {
         DBUG_PRINT("info", 
                    ("Setting next auto increment value (db) to %lu",
-                    (ulong)opValue));  
-        info->m_first_tuple_id = info->m_last_tuple_id = opValue - 1;
+                    (ulong) opValue));  
+        range.m_first_tuple_id = range.m_last_tuple_id = opValue - 1;
       }
       break;
     case 3:
       tOperation->readTuple();
       tOperation->equal("SYSKEY_0", aTableId );
       tRecAttrResult = tOperation->getValue("NEXTID");
-      if (tConnection->execute( Commit ) == -1 )
+      if (tConnection->execute( NdbTransaction::Commit ) == -1 )
         goto error_handler;
       opValue = tRecAttrResult->u_64_value(); // out
       break;
@@ -1085,29 +1149,28 @@
 
   this->closeTransaction(tConnection);
 
-  // Restore current name space
-  setDatabaseName(currentDb.c_str());
-  setDatabaseSchemaName(currentSchema.c_str());
-
   DBUG_RETURN(0);
 
-  error_handler:
+error_handler:
+  DBUG_PRINT("error", ("ndb=%d con=%d op=%d",
+             theError.code,
+             tConnection != NULL ? tConnection->theError.code : -1,
+             tOperation != NULL ? tOperation->theError.code : -1));
+
+  if (theError.code == 0 && tConnection != NULL)
     theError.code = tConnection->theError.code;
+  if (theError.code == 0 && tOperation != NULL)
+    theError.code = tOperation->theError.code;
+  DBUG_ASSERT(theError.code != 0);
 
-    savedError = theError;
+  NdbError savedError;
+  savedError = theError;
 
+  if (tConnection != NULL)
     this->closeTransaction(tConnection);
-    theError = savedError;
 
-  error_return:
-    // Restore current name space
-    setDatabaseName(currentDb.c_str());
-    setDatabaseSchemaName(currentSchema.c_str());
+  theError = savedError;
 
-  DBUG_PRINT("error", ("ndb=%d con=%d op=%d",
-             theError.code,
-             tConnection ? tConnection->theError.code : -1,
-             tOperation ? tOperation->theError.code : -1));
   DBUG_RETURN(-1);
 }
 
@@ -1128,16 +1191,23 @@
   return Data;
 #endif
 }
+
+// <internal>
+Ndb_cluster_connection &
+Ndb::get_ndb_cluster_connection()
+{
+  return theImpl->m_ndb_cluster_connection;
+}
+
 const char * Ndb::getCatalogName() const
 {
   return theImpl->m_dbname.c_str();
 }
 
-
 int 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)) {
     if (!theImpl->m_dbname.assign(a_catalog_name) ||
         theImpl->update_prefix())
     {
@@ -1153,10 +1223,10 @@
   return theImpl->m_schemaname.c_str();
 }
 
-
 int 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)) {
     if (!theImpl->m_schemaname.assign(a_schema_name) ||
         theImpl->update_prefix())
     {
@@ -1165,10 +1235,8 @@
     }
   }
 }
+// </internal>
  
-/*
-Deprecated functions
-*/
 const char * Ndb::getDatabaseName() const
 {
   return getCatalogName();
@@ -1188,6 +1256,26 @@
 {
   return 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", (int) (s1 - s0), s0);
+        setDatabaseName(buf);
+        sprintf(buf, "%.*s", (int) (s2 - (s1 + 1)), s1 + 1);
+        setDatabaseSchemaName(buf);
+        return 0;
+      }
+    }
+  }
+  return -1;
+}
  
 bool Ndb::usingFullyQualifiedNames()
 {
@@ -1250,9 +1338,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);
@@ -1264,6 +1359,35 @@
   DBUG_RETURN(ret);
 }
 
+const BaseString
+Ndb::old_internalize_index_name(const NdbTableImpl * table,
+				const char * external_name) const
+{
+  BaseString ret;
+  DBUG_ENTER("old_internalize_index_name");
+  DBUG_PRINT("enter", ("external_name: %s, table_id: %d",
+                       external_name, table ? table->m_id : ~0));
+  if (!table)
+  {
+    DBUG_PRINT("error", ("!table"));
+    DBUG_RETURN(ret);
+  }
+
+  if (fullyQualifiedNames)
+  {
+    /* Internal index name format <db>/<schema>/<tabid>/<table> */
+    ret.assfmt("%s%d%c%s",
+               theImpl->m_prefix.c_str(),
+               table->m_id,
+               table_name_separator,
+               external_name);
+  }
+  else
+    ret.assign(external_name);
+
+  DBUG_PRINT("exit", ("internal_name: %s", ret.c_str()));
+  DBUG_RETURN(ret);
+}
 
 const BaseString
 Ndb::internalize_index_name(const NdbTableImpl * table,
@@ -1272,7 +1396,7 @@
   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"));
@@ -1281,10 +1405,10 @@
 
   if (fullyQualifiedNames)
   {
-    /* Internal index name format <db>/<schema>/<tabid>/<table> */
+    /* Internal index name format sys/def/<tabid>/<table> */
     ret.assfmt("%s%d%c%s",
-               theImpl->m_prefix.c_str(),
-               table->m_tableId,
+               theImpl->m_systemPrefix.c_str(),
+               table->m_id,
                table_name_separator,
                external_name);
   }
@@ -1339,6 +1463,113 @@
   BaseString ret = BaseString(schemaName);
   delete [] schemaName;
   return ret;
+}
+
+// ToDo set event buffer size
+NdbEventOperation* Ndb::createEventOperation(const char* eventName)
+{
+  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");
+  DBUG_PRINT("info", ("name: %s", tOp->getEvent()->getTable()->getName()));
+  // 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;
+
+  DBUG_PRINT("info", ("first: %s",
+                      theImpl->m_ev_op ? theImpl->m_ev_op->getEvent()->getTable()->getName() : "<empty>"));
+  assert(theImpl->m_ev_op == 0 || theImpl->m_ev_op->m_prev == 0);
+
+  theEventBuffer->dropEventOperation(tOp);
+  DBUG_RETURN(0);
+}
+
+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;
+}
+
+int
+Ndb::pollEvents(int aMillisecondNumber, Uint64 *latestGCI)
+{
+  return theEventBuffer->pollEvents(aMillisecondNumber, latestGCI);
+}
+
+int
+Ndb::flushIncompleteEvents(Uint64 gci)
+{
+  return theEventBuffer->flushIncompleteEvents(gci);
+}
+
+NdbEventOperation *Ndb::nextEvent()
+{
+  return theEventBuffer->nextEvent();
+}
+
+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;
+}
+
+Uint64 Ndb::getLatestGCI()
+{
+  return theEventBuffer->getLatestGCI();
+}
+
+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;
+ }
+}
+
+void Ndb::setReportThreshEventFreeMem(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;
+  }
 }
 
 #ifdef VM_TRACE

--- 1.43.26.1/ndb/src/ndbapi/NdbTransaction.cpp	2007-04-11 15:21:08 +02:00
+++ 1.76/storage/ndb/src/ndbapi/NdbTransaction.cpp	2007-04-11 15:22:09 +02:00
@@ -56,11 +56,11 @@
   theCompletedLastOp(NULL),
   theNoOfOpSent(0),
   theNoOfOpCompleted(0),
-  theNoOfOpFetched(0),
   theMyRef(0),
   theTCConPtr(0),
   theTransactionId(0),
   theGlobalCheckpointId(0),
+  p_latest_trans_gci(0),
   theStatus(NotConnected),
   theCompletionStatus(NotCompleted), 
   theCommitStatus(NotStarted),
@@ -127,9 +127,10 @@
   theCompletedLastOp	  = NULL;
 
   theGlobalCheckpointId   = 0;
+  p_latest_trans_gci      =
+    theNdb->theImpl->m_ndb_cluster_connection.get_latest_trans_gci();
   theCommitStatus         = Started;
   theCompletionStatus     = NotCompleted;
-  m_abortOption           = AbortOnError;
 
   theError.code		  = 0;
   theErrorLine		  = 0;
@@ -185,12 +186,9 @@
 NdbTransaction::setOperationErrorCodeAbort(int error, int abortOption)
 {
   DBUG_ENTER("NdbTransaction::setOperationErrorCodeAbort");
-  if (abortOption == -1)
-    abortOption = m_abortOption;
   if (theTransactionIsStarted == false) {
     theCommitStatus = Aborted;
-  } else if ((abortOption == AbortOnError) && 
-	     (theCommitStatus != Committed) &&
+  } else if ((theCommitStatus != Committed) &&
              (theCommitStatus != Aborted)) {
     theCommitStatus = NeedAbort;
   }//if
@@ -272,8 +270,8 @@
 *****************************************************************************/
 int 
 NdbTransaction::execute(ExecType aTypeOfExec, 
-		       AbortOption abortOption,
-		       int forceSend)
+			NdbOperation::AbortOption abortOption,
+			int forceSend)
 {
   NdbError savedError= theError;
   DBUG_ENTER("NdbTransaction::execute");
@@ -363,40 +361,14 @@
       theCompletedLastOp = NULL;
     }
 
-    if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
+    if (executeNoBlobs(tExecType, 
+		       NdbOperation::DefaultAbortOption,
+		       forceSend) == -1)
     {
-      ret = -1;
       if(savedError.code==0)
 	savedError= theError;
       
-      /**
-       * If AO_IgnoreError, error codes arent always set on individual
-       *   operations, making postExecute impossible
-       */
-      if (abortOption == AO_IgnoreError)
-      {
-         if (theCompletedFirstOp != NULL)
-	 {
-	   if (tCompletedFirstOp != NULL)
-	   {
-	     tCompletedLastOp->next(theCompletedFirstOp);
-	     theCompletedFirstOp = tCompletedFirstOp;
-	   } 
-	 }
-	 else
-	 {
-	   theCompletedFirstOp = tCompletedFirstOp;
-	   theCompletedLastOp = tCompletedLastOp;
-	 }
-         if (tPrepOp != NULL && tRestOp != NULL) {
-           if (theFirstOpInList == NULL)
-             theFirstOpInList = tRestOp;
-           else
-             theLastOpInList->next(tRestOp);
-           theLastOpInList = tLastOp;
-        }
-	DBUG_RETURN(-1);
-      }
+      DBUG_RETURN(-1);
     }
     
 #ifdef ndb_api_crash_on_complex_blob_abort
@@ -456,9 +428,9 @@
 }
 
 int 
-NdbTransaction::executeNoBlobs(ExecType aTypeOfExec, 
-                              AbortOption abortOption,
-                              int forceSend)
+NdbTransaction::executeNoBlobs(NdbTransaction::ExecType aTypeOfExec, 
+			       NdbOperation::AbortOption abortOption,
+			       int forceSend)
 {
   DBUG_ENTER("NdbTransaction::executeNoBlobs");
   DBUG_PRINT("enter", ("aTypeOfExec: %d, abortOption: %d", 
@@ -474,7 +446,7 @@
 //------------------------------------------------------------------------
   Ndb* tNdb = theNdb;
 
-  Uint32 timeout = TransporterFacade::instance()->m_waitfor_timeout;
+  Uint32 timeout = theNdb->theImpl->m_transporter_facade->m_waitfor_timeout;
   m_waitForReply = false;
   executeAsynchPrepare(aTypeOfExec, NULL, NULL, abortOption);
   if (m_waitForReply){
@@ -536,10 +508,10 @@
 Remark:        Prepare a part of a transaction in an asynchronous manner. 
 *****************************************************************************/
 void 
-NdbTransaction::executeAsynchPrepare( ExecType           aTypeOfExec,
+NdbTransaction::executeAsynchPrepare(NdbTransaction::ExecType aTypeOfExec,
                                      NdbAsynchCallback  aCallback,
                                      void*              anyObject,
-                                     AbortOption abortOption)
+                                     NdbOperation::AbortOption abortOption)
 {
   DBUG_ENTER("NdbTransaction::executeAsynchPrepare");
   DBUG_PRINT("enter", ("aTypeOfExec: %d, aCallback: 0x%lx, anyObject: Ox%lx",
@@ -579,7 +551,6 @@
   theReturnStatus     = ReturnSuccess;
   theCallbackFunction = aCallback;
   theCallbackObject   = anyObject;
-  m_abortOption   = abortOption;
   m_waitForReply = true;
   tNdb->thePreparedTransactionsArray[tnoOfPreparedTransactions] = this;
   theTransArrayIndex = tnoOfPreparedTransactions;
@@ -674,8 +645,7 @@
   while (tOp) {
     int tReturnCode;
     NdbOperation* tNextOp = tOp->next();
-
-    tReturnCode = tOp->prepareSend(theTCConPtr, theTransactionId);
+    tReturnCode = tOp->prepareSend(theTCConPtr, theTransactionId, abortOption);
     if (tReturnCode == -1) {
       theSendStatus = sendABORTfail;
       DBUG_VOID_RETURN;
@@ -747,7 +717,7 @@
   tcHbRep->transId1      = tTransId1;
   tcHbRep->transId2      = tTransId2;
  
-  TransporterFacade *tp = TransporterFacade::instance();
+  TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
   tp->lock_mutex(); 
   const int res = tp->sendSignal(tSignal,theDBnode);
   tp->unlock_mutex(); 
@@ -853,7 +823,7 @@
  *************************************************************************/
     NdbApiSignal tSignal(tNdb->theMyRef);
     Uint32 tTransId1, tTransId2;
-    TransporterFacade *tp = TransporterFacade::instance();
+    TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
     int	  tReturnCode;
 
     tTransId1 = (Uint32) theTransactionId;
@@ -900,7 +870,7 @@
 {
   NdbApiSignal tSignal(theNdb->theMyRef);
   Uint32 tTransId1, tTransId2;
-  TransporterFacade *tp = TransporterFacade::instance(); 
+  TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
   int	  tReturnCode;
 
   tTransId1 = (Uint32) theTransactionId;
@@ -1014,7 +984,7 @@
 }//NdbTransaction::releaseScanOperations()
 
 /*****************************************************************************
-void releaseExecutedScanOperation();
+void releaseScanOperation();
 
 Remark:         Release scan op when hupp'ed trans closed (save memory)
 ******************************************************************************/
@@ -1022,8 +992,7 @@
 NdbTransaction::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
 {
   DBUG_ENTER("NdbTransaction::releaseExecutedScanOperation");
-  DBUG_PRINT("enter", ("this: 0x%lx  op=0x%lx",
-                       (long)this, (long)cursorOp));
+  DBUG_PRINT("enter", ("this: 0x%lx  op: 0x%lx", (long) this, (long) cursorOp));
   
   releaseScanOperation(&m_firstExecutedScanOp, 0, cursorOp);
   
@@ -1622,6 +1591,9 @@
     theCommitStatus = Committed;
     theCompletionStatus = CompletedSuccess;
     theGlobalCheckpointId = commitConf->gci;
+    // theGlobalCheckpointId == 0 if NoOp transaction
+    if (theGlobalCheckpointId)
+      *p_latest_trans_gci = theGlobalCheckpointId;
     return 0;
   } else {
 #ifdef NDB_NO_DROPPED_SIGNAL
@@ -1800,16 +1772,14 @@
     if (tCommitFlag == 1) {
       theCommitStatus = Committed;
       theGlobalCheckpointId = tGCI;
+      if (tGCI) // Read(dirty) only transaction doesnt get GCI
+      {
+	*p_latest_trans_gci = tGCI;
+      }
     } else if ((tNoComp >= tNoSent) &&
                (theLastExecOpInList->theCommitIndicator == 1)){
-
-
-      if (m_abortOption == AO_IgnoreError && theError.code != 0){
-	/**
-	 * There's always a TCKEYCONF when using IgnoreError
-	 */
-	return -1;
-      }
+      
+      
 /**********************************************************************/
 // We sent the transaction with Commit flag set and received a CONF with
 // no Commit flag set. This is clearly an anomaly.
@@ -1976,16 +1946,13 @@
     if (tCommitFlag == 1) {
       theCommitStatus = Committed;
       theGlobalCheckpointId = tGCI;
+      if (tGCI) // Read(dirty) only transaction doesnt get GCI
+      {
+	*p_latest_trans_gci = tGCI;
+      }
     } else if ((tNoComp >= tNoSent) &&
                (theLastExecOpInList->theCommitIndicator == 1)){
 
-      if (m_abortOption == AO_IgnoreError && theError.code != 0){
-	/**
-	 * There's always a TCKEYCONF when using IgnoreError
-	 */
-	return -1;
-      }
-
       /**********************************************************************/
       // We sent the transaction with Commit flag set and received a CONF with
       // no Commit flag set. This is clearly an anomaly.
@@ -2009,41 +1976,6 @@
   return -1;
 }//NdbTransaction::receiveTCINDXCONF()
 
-/*****************************************************************************
-int receiveTCINDXREF( NdbApiSignal* aSignal)
-
-Return Value:   Return 0 : send was succesful.
-                Return -1: In all other case.   
-Parameters:     aSignal: the signal object that contains the 
-                TCINDXREF signal from TC.
-Remark:         Handles the reception of the TCINDXREF signal.
-*****************************************************************************/
-int
-NdbTransaction::receiveTCINDXREF( NdbApiSignal* aSignal)
-{
-  if(checkState_TransId(aSignal->getDataPtr()+1)){
-    theError.code = aSignal->readData(4);	// Override any previous errors
-
-    /**********************************************************************/
-    /*	A serious error has occured. This could be due to deadlock or */
-    /*	lack of resources or simply a programming error in NDB. This  */
-    /*	transaction will be aborted. Actually it has already been     */
-    /*	and we only need to report completion and return with the     */
-    /*	error code to the application.				      */
-    /**********************************************************************/
-    theCompletionStatus = NdbTransaction::CompletedFailure;
-    theCommitStatus = NdbTransaction::Aborted;
-    theReturnStatus = NdbTransaction::ReturnFailure;
-    return 0;
-  } else {
-#ifdef NDB_NO_DROPPED_SIGNAL
-    abort();
-#endif
-  }
-
-  return -1;
-}//NdbTransaction::receiveTCINDXREF()
-
 /*******************************************************************************
 int OpCompletedFailure();
 
@@ -2053,36 +1985,15 @@
 Remark:        An operation was completed with failure.
 *******************************************************************************/
 int 
-NdbTransaction::OpCompleteFailure(Uint8 abortOption, bool setFailure)
+NdbTransaction::OpCompleteFailure(NdbOperation* op)
 {
   Uint32 tNoComp = theNoOfOpCompleted;
   Uint32 tNoSent = theNoOfOpSent;
-  if (setFailure)
-    theCompletionStatus = NdbTransaction::CompletedFailure;
+
   tNoComp++;
   theNoOfOpCompleted = tNoComp;
-  if (tNoComp == tNoSent) {
-    //------------------------------------------------------------------------
-    //If the transaction consists of only simple reads we can set
-    //Commit state Aborted.  Otherwise this simple operation cannot
-    //decide the success of the whole transaction since a simple
-    //operation is not really part of that transaction.
-    //------------------------------------------------------------------------
-    if (abortOption == AO_IgnoreError){
-      /**
-       * There's always a TCKEYCONF when using IgnoreError
-       */
-      return -1;
-    }
-    
-    return 0;	// Last operation received
-  } else if (tNoComp > tNoSent) {
-    setOperationErrorCodeAbort(4113);	// Too many operations, 
-                                        // stop waiting for more
-    return 0;
-  } else {
-    return -1;	// Continue waiting for more signals
-  }//if
+  
+  return (tNoComp == tNoSent) ? 0 : -1;
 }//NdbTransaction::OpCompleteFailure()
 
 /******************************************************************************

--- 1.34.8.1/ndb/src/ndbapi/NdbDictionary.cpp	2007-04-11 15:21:08 +02:00
+++ 1.69/storage/ndb/src/ndbapi/NdbDictionary.cpp	2007-04-11 15:51:06 +02:00
@@ -17,6 +17,32 @@
 #include "NdbDictionaryImpl.hpp"
 #include <NdbOut.hpp>
 
+NdbDictionary::ObjectId::ObjectId()
+  : m_impl(* new NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined))
+{
+}
+
+NdbDictionary::ObjectId::~ObjectId()
+{
+  NdbDictObjectImpl * tmp = &m_impl;  
+  delete tmp;
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::ObjectId::getObjectStatus() const {
+  return m_impl.m_status;
+}
+
+int 
+NdbDictionary::ObjectId::getObjectVersion() const {
+  return m_impl.m_version;
+}
+
+int 
+NdbDictionary::ObjectId::getObjectId() const {
+  return m_impl.m_id;
+}
+
 /*****************************************************************
  * Column facade
  */
@@ -222,7 +248,12 @@
 
 int
 NdbDictionary::Column::getColumnNo() const {
-  return m_impl.m_attrId;
+  return m_impl.m_column_no;
+}
+
+int
+NdbDictionary::Column::getAttrId() const {
+  return m_impl.m_attrId;;
 }
 
 bool
@@ -236,6 +267,30 @@
   return m_impl.m_attrSize * m_impl.m_arraySize;
 }
 
+void
+NdbDictionary::Column::setArrayType(ArrayType type)
+{
+  m_impl.m_arrayType = type;
+}
+
+NdbDictionary::Column::ArrayType
+NdbDictionary::Column::getArrayType() const
+{
+  return (ArrayType)m_impl.m_arrayType;
+}
+
+void
+NdbDictionary::Column::setStorageType(StorageType type)
+{
+  m_impl.m_storageType = type;
+}
+
+NdbDictionary::Column::StorageType
+NdbDictionary::Column::getStorageType() const
+{
+  return (StorageType)m_impl.m_storageType;
+}
+
 /*****************************************************************
  * Table facade
  */
@@ -246,8 +301,7 @@
 }
 
 NdbDictionary::Table::Table(const NdbDictionary::Table & org)
-  : NdbDictionary::Object(),
-    m_impl(* new NdbTableImpl(* this))
+  : Object(org), m_impl(* new NdbTableImpl(* this))
 {
   m_impl.assign(org.m_impl);
 }
@@ -283,9 +337,14 @@
   return m_impl.getName();
 }
 
+const char *
+NdbDictionary::Table::getMysqlName() const {
+  return m_impl.getMysqlName();
+}
+
 int
 NdbDictionary::Table::getTableId() const {
-  return m_impl.m_tableId;
+  return m_impl.m_id;
 }
 
 int
@@ -301,12 +360,6 @@
   {
     return -1;
   }
-  if(c.getPrimaryKey()){
-    m_impl.m_noOfKeys++;
-  }
-  if (col->getBlobType()) {
-    m_impl.m_noOfBlobs++;
-  }
   if (m_impl.buildColumnHash())
   {
     return -1;
@@ -420,6 +473,18 @@
   return m_impl.m_min_rows;
 }
 
+void
+NdbDictionary::Table::setDefaultNoPartitionsFlag(Uint32 flag)
+{
+  m_impl.m_default_no_part_flag = flag;;
+}
+
+Uint32
+NdbDictionary::Table::getDefaultNoPartitionsFlag() const
+{
+  return m_impl.m_default_no_part_flag;
+}
+
 const char*
 NdbDictionary::Table::getPrimaryKey(int no) const {
   int count = 0;
@@ -434,12 +499,12 @@
 
 const void* 
 NdbDictionary::Table::getFrmData() const {
-  return m_impl.m_frm.get_data();
+  return m_impl.getFrmData();
 }
 
 Uint32
 NdbDictionary::Table::getFrmLength() const {
-  return m_impl.m_frm.length();
+  return m_impl.getFrmLength();
 }
 
 enum NdbDictionary::Table::SingleUserMode
@@ -454,9 +519,99 @@
   m_impl.m_single_user_mode = (Uint8)mode;
 }
 
+void
+NdbDictionary::Table::setTablespaceNames(const void *data, Uint32 len)
+{
+  m_impl.setTablespaceNames(data, len);
+}
+
+const void*
+NdbDictionary::Table::getTablespaceNames()
+{
+  return m_impl.getTablespaceNames();
+}
+
+Uint32
+NdbDictionary::Table::getTablespaceNamesLen() const
+{
+  return m_impl.getTablespaceNamesLen();
+}
+
+void
+NdbDictionary::Table::setLinearFlag(Uint32 flag)
+{
+  m_impl.m_linear_flag = flag;
+}
+
+bool
+NdbDictionary::Table::getLinearFlag() const
+{
+  return m_impl.m_linear_flag;
+}
+
+void
+NdbDictionary::Table::setFragmentCount(Uint32 count)
+{
+  m_impl.setFragmentCount(count);
+}
+
+Uint32
+NdbDictionary::Table::getFragmentCount() const
+{
+  return m_impl.getFragmentCount();
+}
+
 int
 NdbDictionary::Table::setFrm(const void* data, Uint32 len){
-  return m_impl.m_frm.assign(data, len);
+  return m_impl.setFrm(data, len);
+}
+
+const void* 
+NdbDictionary::Table::getFragmentData() const {
+  return m_impl.getFragmentData();
+}
+
+Uint32
+NdbDictionary::Table::getFragmentDataLen() const {
+  return m_impl.getFragmentDataLen();
+}
+
+void
+NdbDictionary::Table::setFragmentData(const void* data, Uint32 len)
+{
+  m_impl.setFragmentData(data, len);
+}
+
+const void* 
+NdbDictionary::Table::getTablespaceData() const {
+  return m_impl.getTablespaceData();
+}
+
+Uint32
+NdbDictionary::Table::getTablespaceDataLen() const {
+  return m_impl.getTablespaceDataLen();
+}
+
+void
+NdbDictionary::Table::setTablespaceData(const void* data, Uint32 len)
+{
+  m_impl.setTablespaceData(data, len);
+}
+
+const void* 
+NdbDictionary::Table::getRangeListData() const {
+  return m_impl.getRangeListData();
+}
+
+Uint32
+NdbDictionary::Table::getRangeListDataLen() const {
+  return m_impl.getRangeListDataLen();
+}
+
+void
+NdbDictionary::Table::setRangeListData(const void* data, Uint32 len)
+{
+  m_impl.setRangeListData(data, len);
 }
 
 NdbDictionary::Object::Status
@@ -464,11 +619,21 @@
   return m_impl.m_status;
 }
 
+void
+NdbDictionary::Table::setStatusInvalid() const {
+  m_impl.m_status = NdbDictionary::Object::Invalid;
+}
+
 int 
 NdbDictionary::Table::getObjectVersion() const {
   return m_impl.m_version;
 }
 
+int 
+NdbDictionary::Table::getObjectId() const {
+  return m_impl.m_id;
+}
+
 bool
 NdbDictionary::Table::equal(const NdbDictionary::Table & col) const {
   return m_impl.equal(col.m_impl);
@@ -489,6 +654,16 @@
   return m_impl.m_replicaCount;
 }
 
+bool
+NdbDictionary::Table::getTemporary() {
+  return m_impl.m_temporary;
+}
+
+void
+NdbDictionary::Table::setTemporary(bool val) {
+  m_impl.m_temporary = val;
+}
+
 int
 NdbDictionary::Table::createTableInDb(Ndb* pNdb, bool equalOk) const {  
   const NdbDictionary::Table * pTab = 
@@ -500,6 +675,71 @@
   return pNdb->getDictionary()->createTable(* this);
 }
 
+bool
+NdbDictionary::Table::getTablespace(Uint32 *id, Uint32 *version) const 
+{
+  if (m_impl.m_tablespace_id == RNIL)
+    return false;
+  if (id)
+    *id= m_impl.m_tablespace_id;
+  if (version)
+    *version= m_impl.m_version;
+  return true;
+}
+
+const char *
+NdbDictionary::Table::getTablespaceName() const 
+{
+  return m_impl.m_tablespace_name.c_str();
+}
+
+void 
+NdbDictionary::Table::setTablespaceName(const char * name){
+  m_impl.m_tablespace_id = ~0;
+  m_impl.m_tablespace_version = ~0;
+  m_impl.m_tablespace_name.assign(name);
+}
+
+void 
+NdbDictionary::Table::setTablespace(const NdbDictionary::Tablespace & ts){
+  m_impl.m_tablespace_id = NdbTablespaceImpl::getImpl(ts).m_id;
+  m_impl.m_tablespace_version = ts.getObjectVersion();
+  m_impl.m_tablespace_name.assign(ts.getName());
+}
+
+void
+NdbDictionary::Table::setRowChecksumIndicator(bool val){
+  m_impl.m_row_checksum = val;
+}
+
+bool 
+NdbDictionary::Table::getRowChecksumIndicator() const {
+  return m_impl.m_row_checksum;
+}
+
+void
+NdbDictionary::Table::setRowGCIIndicator(bool val){
+  m_impl.m_row_gci = val;
+}
+
+bool 
+NdbDictionary::Table::getRowGCIIndicator() const {
+  return m_impl.m_row_gci;
+}
+
+int
+NdbDictionary::Table::aggregate(NdbError& error)
+{
+  return m_impl.aggregate(error);
+}
+
+int
+NdbDictionary::Table::validate(NdbError& error)
+{
+  return m_impl.validate(error);
+}
+
+
 /*****************************************************************
  * Index facade
  */
@@ -623,12 +863,12 @@
 
 void
 NdbDictionary::Index::setType(NdbDictionary::Index::Type t){
-  m_impl.m_type = t;
+  m_impl.m_type = (NdbDictionary::Object::Type)t;
 }
 
 NdbDictionary::Index::Type
 NdbDictionary::Index::getType() const {
-  return m_impl.m_type;
+  return (NdbDictionary::Index::Type)m_impl.m_type;
 }
 
 void
@@ -636,6 +876,16 @@
   m_impl.m_logging = val;
 }
 
+bool
+NdbDictionary::Index::getTemporary(){
+  return m_impl.m_temporary;
+}
+
+void
+NdbDictionary::Index::setTemporary(bool val){
+  m_impl.m_temporary = val;
+}
+
 bool 
 NdbDictionary::Index::getLogging() const {
   return m_impl.m_logging;
@@ -643,14 +893,543 @@
 
 NdbDictionary::Object::Status
 NdbDictionary::Index::getObjectStatus() const {
-  return m_impl.m_status;
+  return m_impl.m_table->m_status;
 }
 
 int 
 NdbDictionary::Index::getObjectVersion() const {
+  return m_impl.m_table->m_version;
+}
+
+int 
+NdbDictionary::Index::getObjectId() const {
+  return m_impl.m_table->m_id;
+}
+
+
+/*****************************************************************
+ * Event facade
+ */
+NdbDictionary::Event::Event(const char * name)
+  : m_impl(* new NdbEventImpl(* this))
+{
+  setName(name);
+}
+
+NdbDictionary::Event::Event(const char * name, const Table& table)
+  : m_impl(* new NdbEventImpl(* this))
+{
+  setName(name);
+  setTable(table);
+}
+
+NdbDictionary::Event::Event(NdbEventImpl & impl)
+  : m_impl(impl) 
+{
+}
+
+NdbDictionary::Event::~Event()
+{
+  NdbEventImpl * tmp = &m_impl;
+  if(this != tmp){
+    delete tmp;
+  }
+}
+
+void 
+NdbDictionary::Event::setName(const char * name)
+{
+  m_impl.setName(name);
+}
+
+const char *
+NdbDictionary::Event::getName() const
+{
+  return m_impl.getName();
+}
+
+void 
+NdbDictionary::Event::setTable(const Table& table)
+{
+  m_impl.setTable(table);
+}
+
+const NdbDictionary::Table *
+NdbDictionary::Event::getTable() const
+{
+  return m_impl.getTable();
+}
+
+void 
+NdbDictionary::Event::setTable(const char * table)
+{
+  m_impl.setTable(table);
+}
+
+const char*
+NdbDictionary::Event::getTableName() const
+{
+  return m_impl.getTableName();
+}
+
+void
+NdbDictionary::Event::addTableEvent(const TableEvent t)
+{
+  m_impl.addTableEvent(t);
+}
+
+bool
+NdbDictionary::Event::getTableEvent(const TableEvent t) const
+{
+  return m_impl.getTableEvent(t);
+}
+
+void
+NdbDictionary::Event::setDurability(EventDurability d)
+{
+  m_impl.setDurability(d);
+}
+
+NdbDictionary::Event::EventDurability
+NdbDictionary::Event::getDurability() const
+{
+  return m_impl.getDurability();
+}
+
+void
+NdbDictionary::Event::setReport(EventReport r)
+{
+  m_impl.setReport(r);
+}
+
+NdbDictionary::Event::EventReport
+NdbDictionary::Event::getReport() const
+{
+  return m_impl.getReport();
+}
+
+void
+NdbDictionary::Event::addColumn(const Column & c){
+  NdbColumnImpl* col = new NdbColumnImpl;
+  (* col) = NdbColumnImpl::getImpl(c);
+  m_impl.m_columns.push_back(col);
+}
+
+void
+NdbDictionary::Event::addEventColumn(unsigned attrId)
+{
+  m_impl.m_attrIds.push_back(attrId);
+}
+
+void
+NdbDictionary::Event::addEventColumn(const char * name)
+{
+  const Column c(name);
+  addColumn(c);
+}
+
+void
+NdbDictionary::Event::addEventColumns(int n, const char ** names)
+{
+  for (int i = 0; i < n; i++)
+    addEventColumn(names[i]);
+}
+
+int NdbDictionary::Event::getNoOfEventColumns() const
+{
+  return m_impl.getNoOfEventColumns();
+}
+
+const NdbDictionary::Column *
+NdbDictionary::Event::getEventColumn(unsigned no) const
+{
+  return m_impl.getEventColumn(no);
+}
+
+void NdbDictionary::Event::mergeEvents(bool flag)
+{
+  m_impl.m_mergeEvents = flag;
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::Event::getObjectStatus() const
+{
+  return m_impl.m_status;
+}
+
+int 
+NdbDictionary::Event::getObjectVersion() const
+{
   return m_impl.m_version;
 }
 
+int 
+NdbDictionary::Event::getObjectId() const {
+  return m_impl.m_id;
+}
+
+void NdbDictionary::Event::print()
+{
+  m_impl.print();
+}
+
+/*****************************************************************
+ * Tablespace facade
+ */
+NdbDictionary::Tablespace::Tablespace()
+  : m_impl(* new NdbTablespaceImpl(* this))
+{
+}
+
+NdbDictionary::Tablespace::Tablespace(NdbTablespaceImpl & impl)
+  : m_impl(impl) 
+{
+}
+
+NdbDictionary::Tablespace::Tablespace(const NdbDictionary::Tablespace & org)
+  : Object(org), m_impl(* new NdbTablespaceImpl(* this))
+{
+  m_impl.assign(org.m_impl);
+}
+
+NdbDictionary::Tablespace::~Tablespace(){
+  NdbTablespaceImpl * tmp = &m_impl;  
+  if(this != tmp){
+    delete tmp;
+  }
+}
+
+void 
+NdbDictionary::Tablespace::setName(const char * name){
+  m_impl.m_name.assign(name);
+}
+
+const char * 
+NdbDictionary::Tablespace::getName() const {
+  return m_impl.m_name.c_str();
+}
+
+void
+NdbDictionary::Tablespace::setAutoGrowSpecification
+(const NdbDictionary::AutoGrowSpecification& spec){
+  m_impl.m_grow_spec = spec;
+}
+const NdbDictionary::AutoGrowSpecification& 
+NdbDictionary::Tablespace::getAutoGrowSpecification() const {
+  return m_impl.m_grow_spec;
+}
+
+void
+NdbDictionary::Tablespace::setExtentSize(Uint32 sz){
+  m_impl.m_extent_size = sz;
+}
+
+Uint32
+NdbDictionary::Tablespace::getExtentSize() const {
+  return m_impl.m_extent_size;
+}
+
+void
+NdbDictionary::Tablespace::setDefaultLogfileGroup(const char * name){
+  m_impl.m_logfile_group_id = ~0;
+  m_impl.m_logfile_group_version = ~0;
+  m_impl.m_logfile_group_name.assign(name);
+}
+
+void
+NdbDictionary::Tablespace::setDefaultLogfileGroup
+(const NdbDictionary::LogfileGroup & lg){
+  m_impl.m_logfile_group_id = NdbLogfileGroupImpl::getImpl(lg).m_id;
+  m_impl.m_logfile_group_version = lg.getObjectVersion();
+  m_impl.m_logfile_group_name.assign(lg.getName());
+}
+
+const char * 
+NdbDictionary::Tablespace::getDefaultLogfileGroup() const {
+  return m_impl.m_logfile_group_name.c_str();
+}
+
+Uint32
+NdbDictionary::Tablespace::getDefaultLogfileGroupId() const {
+  return m_impl.m_logfile_group_id;
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::Tablespace::getObjectStatus() const {
+  return m_impl.m_status;
+}
+
+int 
+NdbDictionary::Tablespace::getObjectVersion() const {
+  return m_impl.m_version;
+}
+
+int 
+NdbDictionary::Tablespace::getObjectId() const {
+  return m_impl.m_id;
+}
+
+/*****************************************************************
+ * LogfileGroup facade
+ */
+NdbDictionary::LogfileGroup::LogfileGroup()
+  : m_impl(* new NdbLogfileGroupImpl(* this))
+{
+}
+
+NdbDictionary::LogfileGroup::LogfileGroup(NdbLogfileGroupImpl & impl)
+  : m_impl(impl) 
+{
+}
+
+NdbDictionary::LogfileGroup::LogfileGroup(const NdbDictionary::LogfileGroup & org)
+  : Object(org), m_impl(* new NdbLogfileGroupImpl(* this)) 
+{
+  m_impl.assign(org.m_impl);
+}
+
+NdbDictionary::LogfileGroup::~LogfileGroup(){
+  NdbLogfileGroupImpl * tmp = &m_impl;  
+  if(this != tmp){
+    delete tmp;
+  }
+}
+
+void 
+NdbDictionary::LogfileGroup::setName(const char * name){
+  m_impl.m_name.assign(name);
+}
+
+const char * 
+NdbDictionary::LogfileGroup::getName() const {
+  return m_impl.m_name.c_str();
+}
+
+void
+NdbDictionary::LogfileGroup::setUndoBufferSize(Uint32 sz){
+  m_impl.m_undo_buffer_size = sz;
+}
+
+Uint32
+NdbDictionary::LogfileGroup::getUndoBufferSize() const {
+  return m_impl.m_undo_buffer_size;
+}
+
+void
+NdbDictionary::LogfileGroup::setAutoGrowSpecification
+(const NdbDictionary::AutoGrowSpecification& spec){
+  m_impl.m_grow_spec = spec;
+}
+const NdbDictionary::AutoGrowSpecification& 
+NdbDictionary::LogfileGroup::getAutoGrowSpecification() const {
+  return m_impl.m_grow_spec;
+}
+
+Uint64 NdbDictionary::LogfileGroup::getUndoFreeWords() const {
+  return m_impl.m_undo_free_words;
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::LogfileGroup::getObjectStatus() const {
+  return m_impl.m_status;
+}
+
+int 
+NdbDictionary::LogfileGroup::getObjectVersion() const {
+  return m_impl.m_version;
+}
+
+int 
+NdbDictionary::LogfileGroup::getObjectId() const {
+  return m_impl.m_id;
+}
+
+/*****************************************************************
+ * Datafile facade
+ */
+NdbDictionary::Datafile::Datafile()
+  : m_impl(* new NdbDatafileImpl(* this))
+{
+}
+
+NdbDictionary::Datafile::Datafile(NdbDatafileImpl & impl)
+  : m_impl(impl) 
+{
+}
+
+NdbDictionary::Datafile::Datafile(const NdbDictionary::Datafile & org)
+  : Object(org), m_impl(* new NdbDatafileImpl(* this)) 
+{
+  m_impl.assign(org.m_impl);
+}
+
+NdbDictionary::Datafile::~Datafile(){
+  NdbDatafileImpl * tmp = &m_impl;  
+  if(this != tmp){
+    delete tmp;
+  }
+}
+
+void 
+NdbDictionary::Datafile::setPath(const char * path){
+  m_impl.m_path.assign(path);
+}
+
+const char * 
+NdbDictionary::Datafile::getPath() const {
+  return m_impl.m_path.c_str();
+}
+
+void 
+NdbDictionary::Datafile::setSize(Uint64 sz){
+  m_impl.m_size = sz;
+}
+
+Uint64
+NdbDictionary::Datafile::getSize() const {
+  return m_impl.m_size;
+}
+
+Uint64
+NdbDictionary::Datafile::getFree() const {
+  return m_impl.m_free;
+}
+
+void 
+NdbDictionary::Datafile::setTablespace(const char * tablespace){
+  m_impl.m_filegroup_id = ~0;
+  m_impl.m_filegroup_version = ~0;
+  m_impl.m_filegroup_name.assign(tablespace);
+}
+
+void 
+NdbDictionary::Datafile::setTablespace(const NdbDictionary::Tablespace & ts){
+  m_impl.m_filegroup_id = NdbTablespaceImpl::getImpl(ts).m_id;
+  m_impl.m_filegroup_version = ts.getObjectVersion();
+  m_impl.m_filegroup_name.assign(ts.getName());
+}
+
+const char *
+NdbDictionary::Datafile::getTablespace() const {
+  return m_impl.m_filegroup_name.c_str();
+}
+
+void
+NdbDictionary::Datafile::getTablespaceId(NdbDictionary::ObjectId* dst) const 
+{
+  if (dst)
+  {
+    NdbDictObjectImpl::getImpl(* dst).m_id = m_impl.m_filegroup_id;
+    NdbDictObjectImpl::getImpl(* dst).m_version = m_impl.m_filegroup_version;
+  }
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::Datafile::getObjectStatus() const {
+  return m_impl.m_status;
+}
+
+int 
+NdbDictionary::Datafile::getObjectVersion() const {
+  return m_impl.m_version;
+}
+
+int 
+NdbDictionary::Datafile::getObjectId() const {
+  return m_impl.m_id;
+}
+
+/*****************************************************************
+ * Undofile facade
+ */
+NdbDictionary::Undofile::Undofile()
+  : m_impl(* new NdbUndofileImpl(* this))
+{
+}
+
+NdbDictionary::Undofile::Undofile(NdbUndofileImpl & impl)
+  : m_impl(impl) 
+{
+}
+
+NdbDictionary::Undofile::Undofile(const NdbDictionary::Undofile & org)
+  : Object(org), m_impl(* new NdbUndofileImpl(* this))
+{
+  m_impl.assign(org.m_impl);
+}
+
+NdbDictionary::Undofile::~Undofile(){
+  NdbUndofileImpl * tmp = &m_impl;  
+  if(this != tmp){
+    delete tmp;
+  }
+}
+
+void 
+NdbDictionary::Undofile::setPath(const char * path){
+  m_impl.m_path.assign(path);
+}
+
+const char * 
+NdbDictionary::Undofile::getPath() const {
+  return m_impl.m_path.c_str();
+}
+
+void 
+NdbDictionary::Undofile::setSize(Uint64 sz){
+  m_impl.m_size = sz;
+}
+
+Uint64
+NdbDictionary::Undofile::getSize() const {
+  return m_impl.m_size;
+}
+
+void 
+NdbDictionary::Undofile::setLogfileGroup(const char * logfileGroup){
+  m_impl.m_filegroup_id = ~0;
+  m_impl.m_filegroup_version = ~0;
+  m_impl.m_filegroup_name.assign(logfileGroup);
+}
+
+void 
+NdbDictionary::Undofile::setLogfileGroup
+(const NdbDictionary::LogfileGroup & ts){
+  m_impl.m_filegroup_id = NdbLogfileGroupImpl::getImpl(ts).m_id;
+  m_impl.m_filegroup_version = ts.getObjectVersion();
+  m_impl.m_filegroup_name.assign(ts.getName());
+}
+
+const char *
+NdbDictionary::Undofile::getLogfileGroup() const {
+  return m_impl.m_filegroup_name.c_str();
+}
+
+void
+NdbDictionary::Undofile::getLogfileGroupId(NdbDictionary::ObjectId * dst)const 
+{
+  if (dst)
+  {
+    NdbDictObjectImpl::getImpl(* dst).m_id = m_impl.m_filegroup_id;
+    NdbDictObjectImpl::getImpl(* dst).m_version = m_impl.m_filegroup_version;
+  }
+}
+
+NdbDictionary::Object::Status
+NdbDictionary::Undofile::getObjectStatus() const {
+  return m_impl.m_status;
+}
+
+int 
+NdbDictionary::Undofile::getObjectVersion() const {
+  return m_impl.m_version;
+}
+
+int 
+NdbDictionary::Undofile::getObjectId() const {
+  return m_impl.m_id;
+}
+
 /*****************************************************************
  * Dictionary facade
  */
@@ -671,8 +1450,10 @@
 }
 
 int 
-NdbDictionary::Dictionary::createTable(const Table & t){
-  return m_impl.createTable(NdbTableImpl::getImpl(t));
+NdbDictionary::Dictionary::createTable(const Table & t)
+{
+  DBUG_ENTER("NdbDictionary::Dictionary::createTable");
+  DBUG_RETURN(m_impl.createTable(NdbTableImpl::getImpl(t)));
 }
 
 int
@@ -681,6 +1462,11 @@
 }
 
 int
+NdbDictionary::Dictionary::dropTableGlobal(const Table & t){
+  return m_impl.dropTableGlobal(NdbTableImpl::getImpl(t));
+}
+
+int
 NdbDictionary::Dictionary::dropTable(const char * name){
   return m_impl.dropTable(name);
 }
@@ -690,6 +1476,14 @@
   return m_impl.alterTable(NdbTableImpl::getImpl(t));
 }
 
+int
+NdbDictionary::Dictionary::alterTableGlobal(const Table & f,
+                                            const Table & t)
+{
+  return m_impl.alterTableGlobal(NdbTableImpl::getImpl(f),
+                                 NdbTableImpl::getImpl(t));
+}
+
 const NdbDictionary::Table * 
 NdbDictionary::Dictionary::getTable(const char * name, void **data) const
 {
@@ -699,6 +1493,47 @@
   return 0;
 }
 
+const NdbDictionary::Index * 
+NdbDictionary::Dictionary::getIndexGlobal(const char * indexName,
+                                          const Table &ndbtab) const
+{
+  NdbIndexImpl * i = m_impl.getIndexGlobal(indexName,
+                                           NdbTableImpl::getImpl(ndbtab));
+  if(i)
+    return i->m_facade;
+  return 0;
+}
+
+const NdbDictionary::Table * 
+NdbDictionary::Dictionary::getTableGlobal(const char * name) const
+{
+  NdbTableImpl * t = m_impl.getTableGlobal(name);
+  if(t)
+    return t->m_facade;
+  return 0;
+}
+
+int
+NdbDictionary::Dictionary::removeIndexGlobal(const Index &ndbidx,
+                                             int invalidate) const
+{
+  return m_impl.releaseIndexGlobal(NdbIndexImpl::getImpl(ndbidx), invalidate);
+}
+
+int
+NdbDictionary::Dictionary::removeTableGlobal(const Table &ndbtab,
+                                             int invalidate) const
+{
+  return m_impl.releaseTableGlobal(NdbTableImpl::getImpl(ndbtab), invalidate);
+}
+
+void NdbDictionary::Dictionary::putTable(const NdbDictionary::Table * table)
+{
+ NdbDictionary::Table  *copy_table = new NdbDictionary::Table;
+  *copy_table = *table;
+  m_impl.putTable(&NdbTableImpl::getImpl(*copy_table));
+}
+
 void NdbDictionary::Dictionary::set_local_table_data_size(unsigned sz)
 {
   m_impl.m_local_table_data_size= sz;
@@ -710,6 +1545,25 @@
   return getTable(name, 0);
 }
 
+const NdbDictionary::Table *
+NdbDictionary::Dictionary::getBlobTable(const NdbDictionary::Table* table,
+                                        const char* col_name)
+{
+  const NdbDictionary::Column* col = table->getColumn(col_name);
+  if (col == NULL) {
+    m_impl.m_error.code = 4318;
+    return NULL;
+  }
+  return getBlobTable(table, col->getColumnNo());
+}
+
+const NdbDictionary::Table *
+NdbDictionary::Dictionary::getBlobTable(const NdbDictionary::Table* table,
+                                        Uint32 col_no)
+{
+  return m_impl.getBlobTable(NdbTableImpl::getImpl(*table), col_no);
+}
+
 void
 NdbDictionary::Dictionary::invalidateTable(const char * name){
   DBUG_ENTER("NdbDictionaryImpl::invalidateTable");
@@ -720,18 +1574,37 @@
 }
 
 void
+NdbDictionary::Dictionary::invalidateTable(const Table *table){
+  NdbTableImpl &t = NdbTableImpl::getImpl(*table);
+  m_impl.invalidateObject(t);
+}
+
+void
 NdbDictionary::Dictionary::removeCachedTable(const char * name){
   NdbTableImpl * t = m_impl.getTable(name);
   if(t)
     m_impl.removeCachedObject(* t);
 }
 
+void
+NdbDictionary::Dictionary::removeCachedTable(const Table *table){
+  NdbTableImpl &t = NdbTableImpl::getImpl(*table);
+  m_impl.removeCachedObject(t);
+}
+
 int
 NdbDictionary::Dictionary::createIndex(const Index & ind)
 {
   return m_impl.createIndex(NdbIndexImpl::getImpl(ind));
 }
 
+int
+NdbDictionary::Dictionary::createIndex(const Index & ind, const Table & tab)
+{
+  return m_impl.createIndex(NdbIndexImpl::getImpl(ind),
+                            NdbTableImpl::getImpl(tab));
+}
+
 int 
 NdbDictionary::Dictionary::dropIndex(const char * indexName,
 				     const char * tableName)
@@ -740,9 +1613,9 @@
 }
 
 int 
-NdbDictionary::Dictionary::dropIndex(const Index & ind)
+NdbDictionary::Dictionary::dropIndexGlobal(const Index &ind)
 {
-  return m_impl.dropIndex(NdbIndexImpl::getImpl(ind));
+  return m_impl.dropIndexGlobal(NdbIndexImpl::getImpl(ind));
 }
 
 const NdbDictionary::Index * 
@@ -755,14 +1628,13 @@
   return 0;
 }
 
-const NdbDictionary::Index * 
-NdbDictionary::Dictionary::getIndex(const char * indexName,
-				    const Table & t) const
-{
-  NdbIndexImpl * i = m_impl.getIndex(indexName, & NdbTableImpl::getImpl(t));
-  if(i)
-    return i->m_facade;
-  return 0;
+void
+NdbDictionary::Dictionary::invalidateIndex(const Index *index){
+  DBUG_ENTER("NdbDictionary::Dictionary::invalidateIndex");
+  NdbIndexImpl &i = NdbIndexImpl::getImpl(*index);
+  assert(i.m_table != 0);
+  m_impl.invalidateObject(* i.m_table);
+  DBUG_VOID_RETURN;
 }
 
 void
@@ -777,6 +1649,21 @@
   DBUG_VOID_RETURN;
 }
 
+int
+NdbDictionary::Dictionary::forceGCPWait()
+{
+  return m_impl.forceGCPWait();
+}
+
+void
+NdbDictionary::Dictionary::removeCachedIndex(const Index *index){
+  DBUG_ENTER("NdbDictionary::Dictionary::removeCachedIndex");
+  NdbIndexImpl &i = NdbIndexImpl::getImpl(*index);
+  assert(i.m_table != 0);
+  m_impl.removeCachedObject(* i.m_table);
+  DBUG_VOID_RETURN;
+}
+
 void
 NdbDictionary::Dictionary::removeCachedIndex(const char * indexName,
 					     const char * tableName){
@@ -800,6 +1687,28 @@
   return 0;
 }
 
+
+int
+NdbDictionary::Dictionary::createEvent(const Event & ev)
+{
+  return m_impl.createEvent(NdbEventImpl::getImpl(ev));
+}
+
+int 
+NdbDictionary::Dictionary::dropEvent(const char * eventName)
+{
+  return m_impl.dropEvent(eventName);
+}
+
+const NdbDictionary::Event *
+NdbDictionary::Dictionary::getEvent(const char * eventName)
+{
+  NdbEventImpl * t = m_impl.getEvent(eventName);
+  if(t)
+    return t->m_facade;
+  return 0;
+}
+
 int
 NdbDictionary::Dictionary::listObjects(List& list, Object::Type type)
 {
@@ -835,6 +1744,14 @@
   return m_impl.listIndexes(list, tab->getTableId());
 }
 
+int
+NdbDictionary::Dictionary::listIndexes(List& list,
+				       const NdbDictionary::Table &table) const
+{
+  return m_impl.listIndexes(list, table.getTableId());
+}
+
+
 const struct NdbError & 
 NdbDictionary::Dictionary::getNdbError() const {
   return m_impl.getNdbError();
@@ -966,6 +1883,7 @@
       break;
     }
   }
+
   if (col.getPrimaryKey())
     out << " PRIMARY KEY";
   else if (! col.getNullable())
@@ -976,12 +1894,143 @@
   if(col.getDistributionKey())
     out << " DISTRIBUTION KEY";
 
+  switch (col.getArrayType()) {
+  case NDB_ARRAYTYPE_FIXED:
+    out << " AT=FIXED";
+    break;
+  case NDB_ARRAYTYPE_SHORT_VAR:
+    out << " AT=SHORT_VAR";
+    break;
+  case NDB_ARRAYTYPE_MEDIUM_VAR:
+    out << " AT=MEDIUM_VAR";
+    break;
+  default:
+    out << " AT=" << (int)col.getArrayType() << "?";
+    break;
+  }
+
+  switch (col.getStorageType()) {
+  case NDB_STORAGETYPE_MEMORY:
+    out << " ST=MEMORY";
+    break;
+  case NDB_STORAGETYPE_DISK:
+    out << " ST=DISK";
+    break;
+  default:
+    out << " ST=" << (int)col.getStorageType() << "?";
+    break;
+  }
+
   return out;
 }
 
-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;
+int
+NdbDictionary::Dictionary::createLogfileGroup(const LogfileGroup & lg,
+					      ObjectId * obj)
+{
+  return m_impl.createLogfileGroup(NdbLogfileGroupImpl::getImpl(lg),
+				   obj ? 
+				   & NdbDictObjectImpl::getImpl(* obj) : 0);
+}
+
+int
+NdbDictionary::Dictionary::dropLogfileGroup(const LogfileGroup & lg)
+{
+  return m_impl.dropLogfileGroup(NdbLogfileGroupImpl::getImpl(lg));
+}
+
+NdbDictionary::LogfileGroup
+NdbDictionary::Dictionary::getLogfileGroup(const char * name)
+{
+  NdbDictionary::LogfileGroup tmp;
+  m_impl.m_receiver.get_filegroup(NdbLogfileGroupImpl::getImpl(tmp), 
+				  NdbDictionary::Object::LogfileGroup, name);
+  return tmp;
+}
+
+int
+NdbDictionary::Dictionary::createTablespace(const Tablespace & lg,
+					    ObjectId * obj)
+{
+  return m_impl.createTablespace(NdbTablespaceImpl::getImpl(lg),
+				 obj ? 
+				 & NdbDictObjectImpl::getImpl(* obj) : 0);
+}
+
+int
+NdbDictionary::Dictionary::dropTablespace(const Tablespace & lg)
+{
+  return m_impl.dropTablespace(NdbTablespaceImpl::getImpl(lg));
+}
+
+NdbDictionary::Tablespace
+NdbDictionary::Dictionary::getTablespace(const char * name)
+{
+  NdbDictionary::Tablespace tmp;
+  m_impl.m_receiver.get_filegroup(NdbTablespaceImpl::getImpl(tmp), 
+				  NdbDictionary::Object::Tablespace, name);
+  return tmp;
+}
+
+NdbDictionary::Tablespace
+NdbDictionary::Dictionary::getTablespace(Uint32 tablespaceId)
+{
+  NdbDictionary::Tablespace tmp;
+  m_impl.m_receiver.get_filegroup(NdbTablespaceImpl::getImpl(tmp), 
+				  NdbDictionary::Object::Tablespace,
+                                  tablespaceId);
+  return tmp;
+}
+
+int
+NdbDictionary::Dictionary::createDatafile(const Datafile & df, 
+					  bool force,
+					  ObjectId * obj)
+{
+  return m_impl.createDatafile(NdbDatafileImpl::getImpl(df), 
+			       force,
+			       obj ? & NdbDictObjectImpl::getImpl(* obj) : 0);
+}
+
+int
+NdbDictionary::Dictionary::dropDatafile(const Datafile& df)
+{
+  return m_impl.dropDatafile(NdbDatafileImpl::getImpl(df));
+}
+
+NdbDictionary::Datafile
+NdbDictionary::Dictionary::getDatafile(Uint32 node, const char * path)
+{
+  NdbDictionary::Datafile tmp;
+  m_impl.m_receiver.get_file(NdbDatafileImpl::getImpl(tmp),
+			     NdbDictionary::Object::Datafile,
+			     node ? (int)node : -1, path);
+  return tmp;
+}
+
+int
+NdbDictionary::Dictionary::createUndofile(const Undofile & df, 
+					  bool force,
+					  ObjectId * obj)
+{
+  return m_impl.createUndofile(NdbUndofileImpl::getImpl(df), 
+			       force,
+			       obj ? & NdbDictObjectImpl::getImpl(* obj) : 0);
+}
+
+int
+NdbDictionary::Dictionary::dropUndofile(const Undofile& df)
+{
+  return m_impl.dropUndofile(NdbUndofileImpl::getImpl(df));
+}
+
+NdbDictionary::Undofile
+NdbDictionary::Dictionary::getUndofile(Uint32 node, const char * path)
+{
+  NdbDictionary::Undofile tmp;
+  m_impl.m_receiver.get_file(NdbUndofileImpl::getImpl(tmp),
+			     NdbDictionary::Object::Undofile,
+			     node ? (int)node : -1, path);
+  return tmp;
+}
+

--- 1.74.34.1/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2007-04-11 15:21:08 +02:00
+++ 1.166/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp	2007-04-11 15:51:06 +02:00
@@ -28,17 +28,47 @@
 #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>
+#include <NdbEventOperation.hpp>
+#include "NdbEventOperationImpl.hpp"
 #include <NdbBlob.hpp>
 #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  return %d", (a).code, b));\
+   DBUG_RETURN(b);\
+}
+
+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
 
 /**
@@ -47,18 +77,26 @@
 NdbColumnImpl::NdbColumnImpl()
   : NdbDictionary::Column(* this), m_attrId(-1), m_facade(this)
 {
+  DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
+  DBUG_PRINT("info", ("this: %p", this));
   init();
+  DBUG_VOID_RETURN;
 }
 
 NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
   : NdbDictionary::Column(* this), m_attrId(-1), m_facade(&f)
 {
+  DBUG_ENTER("NdbColumnImpl::NdbColumnImpl");
+  DBUG_PRINT("info", ("this: %p", this));
   init();
+  DBUG_VOID_RETURN;
 }
 
 NdbColumnImpl&
 NdbColumnImpl::operator=(const NdbColumnImpl& col)
 {
+  DBUG_ENTER("NdbColumnImpl::operator=");
+  DBUG_PRINT("info", ("this: %p  &col: %p", this, &col));
   m_attrId = col.m_attrId;
   m_name = col.m_name;
   m_type = col.m_type;
@@ -74,11 +112,20 @@
   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 {
+    if (m_blobTable == NULL)
+      m_blobTable = new NdbTableImpl();
+    m_blobTable->assign(*col.m_blobTable);
+  }
+  m_column_no = col.m_column_no;
   // Do not copy m_facade !!
 
-  return *this;
+  DBUG_RETURN(*this);
 }
 
 void
@@ -105,6 +152,7 @@
     m_scale = 0;
     m_length = 1;
     m_cs = NULL;
+    m_arrayType = NDB_ARRAYTYPE_FIXED;
     break;
   case Olddecimal:
   case Olddecimalunsigned:
@@ -114,34 +162,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:
@@ -150,24 +221,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:
@@ -184,16 +259,28 @@
   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()
 {
+  DBUG_ENTER("NdbColumnImpl::~NdbColumnImpl");
+  DBUG_PRINT("info", ("this: %p", this));
+  if (m_blobTable != NULL)
+    delete m_blobTable;
+  m_blobTable = NULL;
+  DBUG_VOID_RETURN;
 }
 
 bool
 NdbColumnImpl::equal(const NdbColumnImpl& col) const 
 {
   DBUG_ENTER("NdbColumnImpl::equal");
+  DBUG_PRINT("info", ("this: %p  &col: %p", this, &col));
   if(strcmp(m_name.c_str(), col.m_name.c_str()) != 0){
     DBUG_RETURN(false);
   }
@@ -206,13 +293,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 (m_distributionKey != col.m_distributionKey) {
       DBUG_RETURN(false);
     }
   }
-#endif
   if (m_precision != col.m_precision ||
       m_scale != col.m_scale ||
       m_length != col.m_length ||
@@ -226,11 +311,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")){
@@ -238,9 +327,14 @@
     col->m_impl.m_attrId = AttributeHeader::FRAGMENT;
     col->m_impl.m_attrSize = 4;
     col->m_impl.m_arraySize = 1;
-  } else if(!strcmp(name, "NDB$FRAGMENT_MEMORY")){
+  } else if(!strcmp(name, "NDB$FRAGMENT_FIXED_MEMORY")){
+    col->setType(NdbDictionary::Column::Bigunsigned);
+    col->m_impl.m_attrId = AttributeHeader::FRAGMENT_FIXED_MEMORY;
+    col->m_impl.m_attrSize = 8;
+    col->m_impl.m_arraySize = 1;
+  } else if(!strcmp(name, "NDB$FRAGMENT_VARSIZED_MEMORY")){
     col->setType(NdbDictionary::Column::Bigunsigned);
-    col->m_impl.m_attrId = AttributeHeader::FRAGMENT_MEMORY;
+    col->m_impl.m_attrId = AttributeHeader::FRAGMENT_VARSIZED_MEMORY;
     col->m_impl.m_attrSize = 8;
     col->m_impl.m_arraySize = 1;
   } else if(!strcmp(name, "NDB$ROW_COUNT")){
@@ -263,9 +357,36 @@
     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 if(!strcmp(name, "NDB$ANY_VALUE")){
+    col->setType(NdbDictionary::Column::Unsigned);
+    col->m_impl.m_attrId = AttributeHeader::ANY_VALUE;
+    col->m_impl.m_attrSize = 4;
+    col->m_impl.m_arraySize = 1;
   } else {
     abort();
   }
+  col->m_impl.m_storageType = NDB_STORAGETYPE_MEMORY;
   return col;
 }
 
@@ -274,50 +395,86 @@
  */
 
 NdbTableImpl::NdbTableImpl()
-  : NdbDictionary::Table(* this), m_facade(this)
+  : NdbDictionary::Table(* this), 
+    NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(this)
 {
+  DBUG_ENTER("NdbTableImpl::NdbTableImpl");
+  DBUG_PRINT("info", ("this: %p", this));
   init();
+  DBUG_VOID_RETURN;
 }
 
 NdbTableImpl::NdbTableImpl(NdbDictionary::Table & f)
-  : NdbDictionary::Table(* this), m_facade(&f)
+  : NdbDictionary::Table(* this), 
+    NdbDictObjectImpl(NdbDictionary::Object::UserTable), m_facade(&f)
 {
+  DBUG_ENTER("NdbTableImpl::NdbTableImpl");
+  DBUG_PRINT("info", ("this: %p", this));
   init();
+  DBUG_VOID_RETURN;
 }
 
 NdbTableImpl::~NdbTableImpl()
 {
+  DBUG_ENTER("NdbTableImpl::~NdbTableImpl");
+  DBUG_PRINT("info", ("this: %p", this));
   if (m_index != 0) {
     delete m_index;
     m_index = 0;
   }
   for (unsigned i = 0; i < m_columns.size(); i++)
-    delete m_columns[i];  
+    delete m_columns[i];
+  DBUG_VOID_RETURN;
 }
 
 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_default_no_part_flag = 1;
   m_logging= true;
+  m_temporary = false;
+  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_min_rows = 0;
   m_max_rows = 0;
+  m_tablespace_name.clear();
+  m_tablespace_id = ~0;
+  m_tablespace_version = ~0;
   m_single_user_mode = 0;
 }
 
@@ -328,56 +485,190 @@
   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_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()));
+  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_temporary != obj.m_temporary)
+  {
+    DBUG_PRINT("info",("m_temporary %d != %d",m_temporary,obj.m_temporary));
+    DBUG_RETURN(false);
+  }
+
+  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));
+    DBUG_RETURN(false);
+  }
+
+  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_maxLoadFactor != obj.m_maxLoadFactor){
-    DBUG_PRINT("info",("m_maxLoadFactor %d != %d",m_maxLoadFactor,obj.m_maxLoadFactor));
+  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);
+    }
+  }
   
   if(m_single_user_mode != obj.m_single_user_mode)
   {
@@ -387,24 +678,51 @@
     DBUG_RETURN(false);
   }
 
-   DBUG_RETURN(true);
+  DBUG_RETURN(true);
 }
 
 int
 NdbTableImpl::assign(const NdbTableImpl& org)
 {
-  m_tableId = org.m_tableId;
+  DBUG_ENTER("NdbColumnImpl::assign");
+  DBUG_PRINT("info", ("this: %p  &org: %p", this, &org));
+  /* m_changeMask intentionally not copied */
+  m_primaryTableId = org.m_primaryTableId;
   if (!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()))
+      updateMysqlName())
   {
     return -1;
   }
-  m_fragmentType = org.m_fragmentType;
-  m_fragmentCount = org.m_fragmentCount;
+  // 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_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());
 
-  for(unsigned i = 0; i<org.m_columns.size(); i++){
+  m_fragmentType = org.m_fragmentType;
+  /*
+    m_columnHashMask, m_columnHash, m_hashValueMask, m_hashpointerValue
+    is state calculated by computeAggregates and buildColumnHash
+  */
+  unsigned i;
+  for(i = 0; i < m_columns.size(); i++)
+  {
+    delete m_columns[i];
+  }
+  m_columns.clear();
+  for(i = 0; i < org.m_columns.size(); i++)
+  {
     NdbColumnImpl * col = new NdbColumnImpl();
     if (col == NULL)
     {
@@ -420,28 +738,46 @@
     }
   }
 
+  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_temporary = org.m_temporary;
+  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;
+  
   m_single_user_mode = org.m_single_user_mode;
 
   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_max_rows = org.m_max_rows;
   m_min_rows = org.m_min_rows;
 
-  return 0;
+  m_tablespace_name = org.m_tablespace_name;
+  m_tablespace_id= org.m_tablespace_id;
+  m_tablespace_version = org.m_tablespace_version;
+  DBUG_RETURN(0);
 }
 
 int NdbTableImpl::setName(const char * name)
@@ -458,11 +794,215 @@
     return m_newExternalName.c_str();
 }
 
+void
+NdbTableImpl::computeAggregates()
+{
+  m_noOfKeys = 0;
+  m_keyLenInWords = 0;
+  m_noOfDistributionKeys = 0;
+  m_noOfBlobs = 0;
+  m_noOfDiskColumns = 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)
+      m_noOfDistributionKeys++; // XXX check PK
+    
+    if (col->getBlobType())
+      m_noOfBlobs++;
+
+    if (col->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
+      m_noOfDiskColumns++;
+    
+    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;
+        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--;
+    }
+  }
+}
+
+// TODO add error checks
+// TODO use these internally at create and retrieve
+int
+NdbTableImpl::aggregate(NdbError& error)
+{
+  computeAggregates();
+  return 0;
+}
+int
+NdbTableImpl::validate(NdbError& error)
+{
+  if (aggregate(error) == -1)
+    return -1;
+  return 0;
+}
+
+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("");
+}
 
 int
 NdbTableImpl::buildColumnHash(){
   const Uint32 size = m_columns.size();
-
   int i;
   for(i = 31; i >= 0; i--){
     if(((1 << i) & size) != 0){
@@ -546,46 +1086,111 @@
 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;
 }
+
+int
+NdbDictionary::Table::checkColumns(const Uint32* map, Uint32 len) const
+{
+  int ret = 0;
+  Uint32 colCnt = m_impl.m_columns.size();
+  if (map == 0)
+  {
+    ret |= 1;
+    ret |= (m_impl.m_noOfDiskColumns) ? 2 : 0;
+    ret |= (colCnt > m_impl.m_noOfDiskColumns) ? 4 : 0;
+    return ret;
+  }
+
+  NdbColumnImpl** cols = m_impl.m_columns.getBase();
+  const char * ptr = reinterpret_cast<const char*>(map);
+  const char * end = ptr + len;
+  Uint32 no = 0;
+  while (ptr < end)
+  {
+    Uint32 val = (Uint32)* ptr;
+    Uint32 idx = 1;
+    for (Uint32 i = 0; i<8; i++)
+    {
+      if (val & idx)
+      {
+	if (cols[no]->getPrimaryKey())
+	  ret |= 1;
+	else
+	{
+	  if (cols[no]->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
+	    ret |= 2;
+	  else
+	    ret |= 4;
+	}
+      }
+      no ++;
+      idx *= 2; 
+      if (no == colCnt)
+	return ret;
+    }
+    
+    ptr++;
+  }
+  return ret;
+}
+
+
   
 /**
  * NdbIndexImpl
  */
 
 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_temporary= false;
   m_table= NULL;
 }
 
@@ -624,6 +1229,167 @@
 }
 
 /**
+ * NdbEventImpl
+ */
+
+NdbEventImpl::NdbEventImpl() : 
+  NdbDictionary::Event(* this),
+  NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(this)
+{
+  DBUG_ENTER("NdbEventImpl::NdbEventImpl");
+  DBUG_PRINT("info", ("this: %p", this));
+  init();
+  DBUG_VOID_RETURN;
+}
+
+NdbEventImpl::NdbEventImpl(NdbDictionary::Event & f) : 
+  NdbDictionary::Event(* this),
+  NdbDictObjectImpl(NdbDictionary::Object::TypeUndefined), m_facade(&f)
+{
+  DBUG_ENTER("NdbEventImpl::NdbEventImpl");
+  DBUG_PRINT("info", ("this: %p", this));
+  init();
+  DBUG_VOID_RETURN;
+}
+
+void NdbEventImpl::init()
+{
+  m_eventId= RNIL;
+  m_eventKey= RNIL;
+  mi_type= 0;
+  m_dur= NdbDictionary::Event::ED_UNDEFINED;
+  m_mergeEvents = false;
+  m_tableImpl= NULL;
+  m_rep= NdbDictionary::Event::ER_UPDATED;
+}
+
+NdbEventImpl::~NdbEventImpl()
+{
+  DBUG_ENTER("NdbEventImpl::~NdbEventImpl");
+  DBUG_PRINT("info", ("this: %p", this));
+  for (unsigned i = 0; i < m_columns.size(); i++)
+    delete  m_columns[i];
+  if (m_tableImpl)
+    delete m_tableImpl;
+  DBUG_VOID_RETURN;
+}
+
+void NdbEventImpl::setName(const char * name)
+{
+  m_name.assign(name);
+}
+
+const char *NdbEventImpl::getName() const
+{
+  return m_name.c_str();
+}
+
+void 
+NdbEventImpl::setTable(const NdbDictionary::Table& table)
+{
+  setTable(&NdbTableImpl::getImpl(table));
+  m_tableName.assign(m_tableImpl->getName());
+}
+
+void 
+NdbEventImpl::setTable(NdbTableImpl *tableImpl)
+{
+  DBUG_ENTER("NdbEventImpl::setTable");
+  DBUG_PRINT("info", ("this: %p  tableImpl: %p", this, 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);
+  DBUG_VOID_RETURN;
+}
+
+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);
+}
+
+const char *
+NdbEventImpl::getTableName() const
+{
+  return m_tableName.c_str();
+}
+
+void
+NdbEventImpl::addTableEvent(const NdbDictionary::Event::TableEvent t =  NdbDictionary::Event::TE_ALL)
+{
+  mi_type |= (unsigned)t;
+}
+
+bool
+NdbEventImpl::getTableEvent(const NdbDictionary::Event::TableEvent t) const
+{
+  return (mi_type & (unsigned)t) == (unsigned)t;
+}
+
+void
+NdbEventImpl::setDurability(NdbDictionary::Event::EventDurability d)
+{
+  m_dur = d;
+}
+
+NdbDictionary::Event::EventDurability
+NdbEventImpl::getDurability() const
+{
+  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
  */
 
@@ -648,8 +1414,6 @@
   m_local_table_data_size= 0;
 }
 
-static int f_dictionary_count = 0;
-
 NdbDictionaryImpl::~NdbDictionaryImpl()
 {
   NdbElement_t<Ndb_local_table_info> * curr = m_localHash.m_tableHash.getNext(0);
@@ -662,58 +1426,131 @@
       
       curr = m_localHash.m_tableHash.getNext(curr);
     }
-    
-    m_globalHash->lock();
-    if(--f_dictionary_count == 0){
-      delete NdbDictionary::Column::FRAGMENT; 
-      delete NdbDictionary::Column::FRAGMENT_MEMORY;
-      delete NdbDictionary::Column::ROW_COUNT;
-      delete NdbDictionary::Column::COMMIT_COUNT;
-      delete NdbDictionary::Column::ROW_SIZE;
-      delete NdbDictionary::Column::RANGE_NO;
-      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;
-    }
-    m_globalHash->unlock();
   } else {
     assert(curr == 0);
   }
 }
 
-Ndb_local_table_info *
-NdbDictionaryImpl::fetchGlobalTableImpl(const BaseString& internalTableName)
+NdbTableImpl *
+NdbDictionaryImpl::fetchGlobalTableImplRef(const GlobalCacheInitObject &obj)
 {
+  DBUG_ENTER("fetchGlobalTableImplRef");
   NdbTableImpl *impl;
   int error= 0;
 
   m_globalHash->lock();
-  impl = m_globalHash->get(internalTableName.c_str(), &error);
+  impl = m_globalHash->get(obj.m_name.c_str(), &error);
   m_globalHash->unlock();
 
   if (impl == 0){
     if (error == 0)
-      impl = m_receiver.getTable(internalTableName,
+      impl = m_receiver.getTable(obj.m_name.c_str(),
                                  m_ndb.usingFullyQualifiedNames());
     else
       m_error.code = 4000;
+    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_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
@@ -735,22 +1572,6 @@
 {
   m_globalHash = &tf->m_globalDictCache;
   if(m_receiver.setTransporter(ndb, tf)){
-    m_globalHash->lock();
-    if(f_dictionary_count++ == 0){
-      NdbDictionary::Column::FRAGMENT= 
-	NdbColumnImpl::create_psuedo("NDB$FRAGMENT");
-      NdbDictionary::Column::FRAGMENT_MEMORY= 
-	NdbColumnImpl::create_psuedo("NDB$FRAGMENT_MEMORY");
-      NdbDictionary::Column::ROW_COUNT= 
-	NdbColumnImpl::create_psuedo("NDB$ROW_COUNT");
-      NdbDictionary::Column::COMMIT_COUNT= 
-	NdbColumnImpl::create_psuedo("NDB$COMMIT_COUNT");
-      NdbDictionary::Column::ROW_SIZE=
-	NdbColumnImpl::create_psuedo("NDB$ROW_SIZE");
-      NdbDictionary::Column::RANGE_NO= 
-	NdbColumnImpl::create_psuedo("NDB$RANGE_NO");
-    }
-    m_globalHash->unlock();
     return true;
   }
   return false;
@@ -760,9 +1581,21 @@
 NdbDictionaryImpl::getIndexTable(NdbIndexImpl * index,
 				 NdbTableImpl * table)
 {
+  const char *current_db= m_ndb.getDatabaseName();
+  NdbTableImpl *index_table;
   const BaseString internalName(
     m_ndb.internalize_index_name(table, index->getName()));
-  return getTable(m_ndb.externalizeTableName(internalName.c_str()));
+  // Get index table in system database
+  m_ndb.setDatabaseName(NDB_SYSTEM_DATABASE);
+  index_table= getTable(m_ndb.externalizeTableName(internalName.c_str()));
+  m_ndb.setDatabaseName(current_db);
+  if (!index_table)
+  {
+    // Index table not found
+    // Try geting index table in current database (old format)
+    index_table= getTable(m_ndb.externalizeTableName(internalName.c_str()));    
+  }
+  return index_table;
 }
 
 #if 0
@@ -850,9 +1683,63 @@
   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_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;
+  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();
   }
@@ -874,73 +1761,57 @@
 }
 
 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_error.code= 4007;
-	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"));
+      m_error.code = 4007;
+      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);
     }
@@ -948,37 +1819,45 @@
     /**
      * Handle error codes
      */
-    if(m_waiter.m_state == WAIT_NODE_FAILURE)
+    if(ret_val == -2) //WAIT_NODE_FAILURE
     {
       m_error.code = 4013;
       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
 
@@ -989,8 +1868,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 =
@@ -1002,8 +1881,6 @@
 
   return getTable(&tSignal, 0, 0, fullyQualifiedNames);
 }
-#endif
-
 
 /*
   Get dictionary information for a table using table name as the reference
@@ -1062,29 +1939,30 @@
 			   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)
   {
     if (rt->buildColumnHash())
     {
       m_error.code = 4000;
       delete rt;
       return NULL;
-    }
+     }
   }
+  
   return rt;
 }
 
@@ -1123,8 +2001,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);
 }
@@ -1172,6 +2051,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 }
 };
 
@@ -1186,6 +2068,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 }
 };
 
@@ -1204,7 +2090,7 @@
 static const
 ApiKernelMapping
 objectStoreMapping[] = {
-  { DictTabInfo::StoreTemporary,     NdbDictionary::Object::StoreTemporary },
+  { DictTabInfo::StoreNotLogged,     NdbDictionary::Object::StoreNotLogged },
   { DictTabInfo::StorePermanent,     NdbDictionary::Object::StorePermanent },
   { -1, -1 }
 };
@@ -1220,74 +2106,96 @@
 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;
   if (!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))
   {
     DBUG_RETURN(4000);
   }
+  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);
   
-  Uint64 max_rows = ((Uint64)tableDesc.MaxRowsHigh) << 32;
-  max_rows += tableDesc.MaxRowsLow;
+  Uint64 max_rows = ((Uint64)tableDesc->MaxRowsHigh) << 32;
+  max_rows += tableDesc->MaxRowsLow;
   impl->m_max_rows = max_rows;
-  Uint64 min_rows = ((Uint64)tableDesc.MinRowsHigh) << 32;
-  min_rows += tableDesc.MinRowsLow;
+  Uint64 min_rows = ((Uint64)tableDesc->MinRowsHigh) << 32;
+  min_rows += tableDesc->MinRowsLow;
   impl->m_min_rows = min_rows;
-  impl->m_logging = tableDesc.TableLoggedFlag;
-  impl->m_kvalue = tableDesc.TableKValue;
-  impl->m_minLoadFactor = tableDesc.MinLoadFactor;
-  impl->m_maxLoadFactor = tableDesc.MaxLoadFactor;
-  impl->m_single_user_mode = tableDesc.SingleUserMode;
+  impl->m_default_no_part_flag = tableDesc->DefaultNoPartFlag;
+  impl->m_linear_flag = tableDesc->LinearHashFlag;
+  impl->m_logging = tableDesc->TableLoggedFlag;
+  impl->m_temporary = tableDesc->TableTemporaryFlag;
+  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_single_user_mode = tableDesc->SingleUserMode;
 
-  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);
     if (!impl->m_primaryTable.assign(externalPrimary))
     {
       DBUG_RETURN(4000);
     }
   }
   
-  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, 
@@ -1296,6 +2204,7 @@
 				 true, true);
     if(s != SimpleProperties::Break){
       delete impl;
+      NdbMem_Free((void*)tableDesc);
       DBUG_RETURN(703);
     }
     
@@ -1307,6 +2216,7 @@
     if (! attrDesc.translateExtType()) {
       delete col;
       delete impl;
+      NdbMem_Free((void*)tableDesc);
       DBUG_RETURN(703);
     }
     col->m_type = (NdbDictionary::Column::Type)attrDesc.AttributeExtType;
@@ -1319,6 +2229,7 @@
     if (col->getCharType() != (cs_number != 0)) {
       delete col;
       delete impl;
+      NdbMem_Free((void*)tableDesc);
       DBUG_RETURN(703);
     }
     if (col->getCharType()) {
@@ -1326,21 +2237,24 @@
       if (col->m_cs == NULL) {
         delete col;
         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 != 0);
     col->m_nullable = attrDesc.AttributeNullableFlag;
-    col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false);
+    col->m_autoIncrement = (attrDesc.AttributeAutoIncrement != 0);
     col->m_autoIncrementInitialValue = ~0;
     if (!col->m_defaultValue.assign(attrDesc.AttributeDefaultValue))
     {
@@ -1349,48 +2263,32 @@
       DBUG_RETURN(4000);
     }
 
-    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));
+    Uint32 pos = 2;
+    for(i = 0; i < (Uint32) fragCount;i++)
     {
-      if (impl->m_fragments.push_back(tableDesc.FragmentData[i+2]))
+      pos++; // skip logpart
+      for (Uint32 j = 0; j<(Uint32)replicaCount; j++)
       {
-        delete impl;
-        DBUG_RETURN(4000);
+	if (impl->m_fragments.push_back(ntohs(tableDesc->ReplicaData[pos++])))
+	{
+          delete impl;
+          DBUG_RETURN(4000);
+        }
       }
     }
 
@@ -1403,23 +2301,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);
 }
 
@@ -1429,79 +2330,109 @@
 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);
   }
-  if (createBlobTables(*(info->m_table_impl)) != 0) {
+
+  // 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
+      // the tuple id range is not used on input
+      Ndb::TupleIdRange range;
+      if (m_ndb.setTupleIdInNdb(&t, range, initialValue, false) == -1) {
+        assert(m_ndb.theError.code != 0);
+        m_error.code = m_ndb.theError.code;
+        delete t2;
+        DBUG_RETURN(-1);
+      }
+    }
+  }
+
+  // blob tables - use "t2" to get values set by kernel
+  if (t2->m_noOfBlobs != 0 && createBlobTables(t, *t2) != 0) {
     int save_code = m_error.code;
-    (void)dropTable(t);
-    m_error.code= save_code;
-    return -1;
+    (void)dropTableGlobal(*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)
+NdbDictionaryImpl::createBlobTables(NdbTableImpl& orig, 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;
+    NdbDictionary::Column::StorageType 
+      d = NdbDictionary::Column::StorageTypeDisk;
+    if (orig.m_columns[i]->getStorageType() == d)
+      bt.getColumn("DATA")->setStorageType(d);
+    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)
@@ -1511,30 +2442,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 
@@ -1542,8 +2486,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);
@@ -1553,16 +2501,82 @@
     m_error.code= 4318;
     DBUG_RETURN(-1);
   }
-
+  
+  // Check if any changes for alter table
+  
+  // Name change
   if (!impl.m_newExternalName.empty()) {
-    if (!impl.m_externalName.assign(impl.m_newExternalName))
+    if (alter)
+    {
+      AlterTableReq::setNameFlag(impl.m_changeMask, true);
+    }
+    if (impl.m_externalName.assign(impl.m_newExternalName))
     {
       m_error.code= 4000;
       DBUG_RETURN(-1);
     }
-    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();
 
@@ -1573,67 +2587,174 @@
     m_error.code= 4000;
     DBUG_RETURN(-1);
   }
-  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->TableTemporaryFlag = impl.m_temporary;
+  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->MinRowsHigh = (Uint32)(impl.m_min_rows >> 32);
+  tmpTab->MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF);
+  tmpTab->DefaultNoPartFlag = impl.m_default_no_part_flag;
+  tmpTab->LinearHashFlag = impl.m_linear_flag;
+  tmpTab->SingleUserMode = impl.m_single_user_mode;
 
-  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.MaxRowsHigh = (Uint32)(impl.m_max_rows >> 32);
-  tmpTab.MaxRowsLow = (Uint32)(impl.m_max_rows & 0xFFFFFFFF);
-  tmpTab.MinRowsHigh = (Uint32)(impl.m_min_rows >> 32);
-  tmpTab.MinRowsLow = (Uint32)(impl.m_min_rows & 0xFFFFFFFF);
-
-  tmpTab.SingleUserMode = impl.m_single_user_mode;
-
-  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
+      if (m_error.code == 723)
+	m_error.code = 755;
+      
+      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;
@@ -1643,10 +2764,12 @@
     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;
@@ -1655,7 +2778,19 @@
     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;
@@ -1675,8 +2810,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()) {
@@ -1694,137 +2835,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, false) == -1) {
-        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);
@@ -1838,6 +2931,7 @@
 {
   DBUG_ENTER("NdbDictionaryImpl::dropTable");
   DBUG_PRINT("enter",("name: %s", name));
+  ASSERT_NOT_MYSQLD;
   NdbTableImpl * tab = getTable(name);
   if(tab == 0){
     DBUG_RETURN(-1);
@@ -1847,16 +2941,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);
 }
 
@@ -1869,13 +2961,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++) {
@@ -1893,14 +2986,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;
@@ -1910,6 +3002,49 @@
 }
 
 int
+NdbDictionaryImpl::dropTableGlobal(NdbTableImpl & impl)
+{
+  int res;
+  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");
@@ -1917,15 +3052,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);
 }
@@ -1938,28 +3079,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;
@@ -1983,7 +3117,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);  
@@ -1996,10 +3130,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);
 }
@@ -2008,67 +3142,22 @@
 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;
-}
-
-/*****************************************************************
- * Get index info
- */
-NdbIndexImpl*
-NdbDictionaryImpl::getIndexImpl(const char * externalName,
-				const BaseString& internalName)
-{
-  Ndb_local_table_info * info = get_local_table_info(internalName,
-						     false);
-  if(info == 0){
-    m_error.code = 4243;
-    return 0;
-  }
-  NdbTableImpl * tab = info->m_table_impl;
-
-  if(tab->m_indexType == NdbDictionary::Index::Undefined){
-    // Not an index
-    m_error.code = 4243;
-    return 0;
-  }
-
-  NdbTableImpl* prim = getTable(tab->m_primaryTable.c_str());
-  if(prim == 0){
-    m_error.code = 4243;
-    return 0;
-  }
-
-  /**
-   * Create index impl
-   */
-  NdbIndexImpl* idx;
-  if(NdbDictInterface::create_index_obj_from_table(&idx, tab, prim) == 0){
-    idx->m_table = tab;
-    if (!idx->m_externalName.assign(externalName) ||
-        !idx->m_internalName.assign(internalName))
-    {
-      delete idx;
-      m_error.code = 4000;
-      return 0;
-    }
-    // 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;
-  }
-  m_error.code = 4000;
-  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();
   if (idx == NULL)
   {
@@ -2077,7 +3166,7 @@
   }
   idx->m_version = tab->m_version;
   idx->m_status = tab->m_status;
-  idx->m_indexId = tab->m_tableId;
+  idx->m_id = tab->m_id;
   if (!idx->m_externalName.assign(tab->getName()) ||
       !idx->m_tableName.assign(prim->m_externalName))
   {
@@ -2085,8 +3174,9 @@
     errno = ENOMEM;
     return -1;
   }
-  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;
+  idx->m_temporary = tab->m_temporary;
   // skip last attribute (NDB$PK or NDB$TNODE)
 
   const Uint32 distKeys = prim->m_noOfDistributionKeys;
@@ -2122,7 +3212,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())))
     {
@@ -2141,8 +3231,12 @@
       tab->m_columns[i]->m_distributionKey = 0;
   }
 
+  idx->m_table_id = prim->getObjectId();
+  idx->m_table_version = prim->getObjectVersion();
+  
   * dst = idx;
-  return 0;
+  DBUG_PRINT("exit", ("m_id: %d  m_version: %d", idx->m_id, idx->m_version));
+  DBUG_RETURN(0);
 }
 
 /*****************************************************************
@@ -2151,6 +3245,7 @@
 int
 NdbDictionaryImpl::createIndex(NdbIndexImpl &ix)
 {
+  ASSERT_NOT_MYSQLD;
   NdbTableImpl* tab = getTable(ix.getTable());
   if(tab == 0){
     m_error.code = 4249;
@@ -2160,9 +3255,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();
@@ -2176,14 +3277,9 @@
   }
   const BaseString internalName(
     ndb.internalize_index_name(&table, impl.getName()));
-  if (!impl.m_internalName.assign(internalName))
-  {
-    m_error.code = 4000;
-    return -1;
-  }
-
   w.add(DictTabInfo::TableName, internalName.c_str());
   w.add(DictTabInfo::TableLoggedFlag, impl.m_logging);
+  w.add(DictTabInfo::TableTemporaryFlag, impl.m_temporary);
 
   NdbApiSignal tSignal(m_reference);
   tSignal.theReceiversBlockNumber = DBDICT;
@@ -2206,7 +3302,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();
@@ -2217,7 +3313,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
@@ -2230,44 +3326,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;
@@ -2281,12 +3368,13 @@
 NdbDictionaryImpl::dropIndex(const char * indexName, 
 			     const char * tableName)
 {
+  ASSERT_NOT_MYSQLD;
   NdbIndexImpl * idx = getIndex(indexName, tableName);
   if (idx == 0) {
     m_error.code = 4243;
     return -1;
   }
-  int ret = dropIndex(*idx);
+  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) {
@@ -2298,8 +3386,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);
   }
@@ -2308,29 +3395,62 @@
 }
 
 int
-NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl)
+NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
 {
+  const char * indexName = impl.getName();
+  if (tableName || m_ndb.usingFullyQualifiedNames()) {
     NdbTableImpl * timpl = impl.m_table;
     
     if (timpl == 0) {
       m_error.code = 709;
       return -1;
     }
-    int ret = m_receiver.dropIndex(impl, *timpl);
-    if(ret == 0){
-      m_localHash.drop(timpl->m_internalName.c_str());
+
+    const BaseString internalIndexName((tableName)
+      ?
+      m_ndb.internalize_index_name(getTable(tableName), indexName)
+      :
+      m_ndb.internalize_table_name(indexName)); // Index is also a table
+
+    if(impl.m_status == NdbDictionary::Object::New){
+      return dropIndex(indexName, tableName);
+    }
+
+    int ret= dropIndexGlobal(impl);
+    if (ret == 0)
+    {
       m_globalHash->lock();
-      timpl->m_status = NdbDictionary::Object::Invalid;
-      m_globalHash->drop(timpl);
+      m_globalHash->release(impl.m_table, 1);
       m_globalHash->unlock();
+      m_localHash.drop(internalIndexName.c_str());
     }
     return ret;
+  }
+
+  m_error.code = 4243;
+  return -1;
+}
+
+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;
@@ -2341,28 +3461,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
@@ -2376,7 +3488,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;
@@ -2384,6 +3496,696 @@
 }
 
 /*****************************************************************
+ * Create event
+ */
+
+int
+NdbDictionaryImpl::createEvent(NdbEventImpl & evnt)
+{
+  DBUG_ENTER("NdbDictionaryImpl::createEvent");
+  int i;
+  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);
+  }
+
+  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++) {
+    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.getTableName());
+      m_error.code= 4713;
+      ERR_RETURN(getNdbError(), -1);
+    }
+  }
+
+  evnt.m_attrIds.clear();
+
+  attributeList_sz = evnt.m_columns.size();
+
+  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();
+
+  for(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;
+      ERR_RETURN(getNdbError(), -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(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(i = 1; i<attributeList_sz; i++) {
+    if (evnt.m_columns[i-1]->m_attrId == evnt.m_columns[i]->m_attrId) {
+      m_error.code= 4258;
+      ERR_RETURN(getNdbError(), -1);
+    }
+  }
+  
+#ifdef EVENT_DEBUG
+  char buf[128] = {0};
+  evnt.m_attrListBitmask.getText(buf);
+  ndbout_c("createEvent: mask = %s", buf);
+#endif
+
+  // NdbDictInterface m_receiver;
+  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
+NdbDictInterface::createEvent(class Ndb & ndb,
+			      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;
+  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 {
+    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_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_name.c_str()) + 1;
+  if(len > MAX_TAB_NAME_SIZE) {
+    m_error.code= 4241;
+    ERR_RETURN(getNdbError(), -1);
+  }
+
+  w.add(SimpleProperties::StringValue, evnt.m_name.c_str());
+
+  if (getFlag == 0)
+  {
+    const BaseString internal_tabname(
+      ndb.internalize_table_name(evnt.m_tableName.c_str()));
+    w.add(SimpleProperties::StringValue,
+	 internal_tabname.c_str());
+  }
+
+  LinearSectionPtr ptr[1];
+  ptr[0].p = (Uint32*)m_buffer.get_data();
+  ptr[0].sz = (m_buffer.length()+3) >> 2;
+
+  int ret = dictSignal(&tSignal,ptr, 1,
+		       0, // master
+		       WAIT_CREATE_INDX_REQ,
+		       DICT_WAITFOR_TIMEOUT, 100,
+		       0, -1);
+
+  if (ret) {
+    ERR_RETURN(getNdbError(), 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();
+
+  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_attrListBitmask = evntConf->getAttrListBitmask();
+    evnt.mi_type           = evntConf->getEventType();
+    evnt.setTable(dataPtr);
+  } else {
+    if ((Uint32) 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*************");
+      ERR_RETURN(getNdbError(), 1);
+    }
+  }
+
+  DBUG_RETURN(0);
+}
+
+int
+NdbDictionaryImpl::executeSubscribeEvent(NdbEventOperationImpl & ev_op)
+{
+  // NdbDictInterface m_receiver;
+  return m_receiver.executeSubscribeEvent(m_ndb, ev_op);
+}
+
+int
+NdbDictInterface::executeSubscribeEvent(class Ndb & ndb,
+					NdbEventOperationImpl & ev_op)
+{
+  DBUG_ENTER("NdbDictInterface::executeSubscribeEvent");
+  NdbApiSignal tSignal(m_reference);
+  tSignal.theReceiversBlockNumber = DBDICT;
+  tSignal.theVerId_signalNumber   = GSN_SUB_START_REQ;
+  tSignal.theLength = SubStartReq::SignalLength2;
+  
+  SubStartReq * req = CAST_PTR(SubStartReq, tSignal.getDataPtrSend());
+
+  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(NdbEventOperationImpl & ev_op)
+{
+  // NdbDictInterface m_receiver;
+  return m_receiver.stopSubscribeEvent(m_ndb, ev_op);
+}
+
+int
+NdbDictInterface::stopSubscribeEvent(class Ndb & ndb,
+				     NdbEventOperationImpl & ev_op)
+{
+  DBUG_ENTER("NdbDictInterface::stopSubscribeEvent");
+
+  NdbApiSignal tSignal(m_reference);
+  //  tSignal.theReceiversBlockNumber = SUMA;
+  tSignal.theReceiversBlockNumber = DBDICT;
+  tSignal.theVerId_signalNumber   = GSN_SUB_STOP_REQ;
+  tSignal.theLength = SubStopReq::SignalLength;
+  
+  SubStopReq * req = CAST_PTR(SubStopReq, tSignal.getDataPtrSend());
+
+  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, NdbTableImpl* tab)
+{
+  DBUG_ENTER("NdbDictionaryImpl::getEvent");
+  DBUG_PRINT("enter",("eventName= %s", eventName));
+
+  NdbEventImpl *ev =  new NdbEventImpl();
+  if (ev == NULL) {
+    DBUG_RETURN(NULL);
+  }
+
+  ev->setName(eventName);
+
+  int ret = m_receiver.createEvent(m_ndb, *ev, 1 /* getFlag set */);
+
+  if (ret) {
+    delete ev;
+    DBUG_RETURN(NULL);
+  }
+
+  // We only have the table name with internal name
+  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) ||
+        ((Uint32) 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);
+      }
+    }
+    ev->setTable(tab);
+    releaseTableGlobal(*tab, 0);
+  }
+  else
+    ev->setTable(tab);
+  tab = 0;
+
+  ev->setTable(m_ndb.externalizeTableName(ev->getTableName()));  
+  // get the columns from the attrListBitmask
+  NdbTableImpl &table = *ev->m_tableImpl;
+  AttributeMask & mask = ev->m_attrListBitmask;
+  unsigned attributeList_sz = mask.count();
+
+  DBUG_PRINT("info",("Table: id: %d version: %d", 
+                     table.m_id, table.m_version));
+
+  if ((Uint32) 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);
+  DBUG_PRINT("info",("attributeList_sz= %d, mask= %s", 
+                     attributeList_sz, buf));
+#endif
+
+  
+  if ( attributeList_sz > (uint) table.getNoOfColumns() )
+  {
+    m_error.code = 241;
+    DBUG_PRINT("error",("Invalid version, too many columns"));
+    delete ev;
+    DBUG_RETURN(NULL);
+  }
+
+  assert( (int)attributeList_sz <= table.getNoOfColumns() );
+  for(unsigned id= 0; ev->m_columns.size() < attributeList_sz; id++) {
+    if ( id >= (uint) table.getNoOfColumns())
+    {
+      m_error.code = 241;
+      DBUG_PRINT("error",("Invalid version, column %d out of range", id));
+      delete ev;
+      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);
+}
+
+// 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
+NdbDictInterface::execCREATE_EVNT_CONF(NdbApiSignal * signal,
+				       LinearSectionPtr ptr[3])
+{
+  DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_CONF");
+
+  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);
+  }
+
+  const CreateEvntConf * const createEvntConf=
+    CAST_CONSTPTR(CreateEvntConf, signal->getDataPtr());
+
+  Uint32 subscriptionId = createEvntConf->getEventId();
+  Uint32 subscriptionKey = createEvntConf->getEventKey();
+
+  DBUG_PRINT("info",("nodeid=%d,subscriptionId=%d,subscriptionKey=%d",
+		     refToNode(signal->theSendersBlockRef),
+		     subscriptionId,subscriptionKey));
+  m_waiter.signal(NO_WAIT);
+  DBUG_VOID_RETURN;
+}
+
+void
+NdbDictInterface::execCREATE_EVNT_REF(NdbApiSignal * signal,
+				      LinearSectionPtr ptr[3])
+{
+  DBUG_ENTER("NdbDictInterface::execCREATE_EVNT_REF");
+
+  const CreateEvntRef* const ref=
+    CAST_CONSTPTR(CreateEvntRef, signal->getDataPtr());
+  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;
+}
+
+void
+NdbDictInterface::execSUB_STOP_CONF(NdbApiSignal * signal,
+				      LinearSectionPtr ptr[3])
+{
+  DBUG_ENTER("NdbDictInterface::execSUB_STOP_CONF");
+  const SubStopConf * const subStopConf=
+    CAST_CONSTPTR(SubStopConf, signal->getDataPtr());
+
+  Uint32 subscriptionId = subStopConf->subscriptionId;
+  Uint32 subscriptionKey = subStopConf->subscriptionKey;
+  Uint32 subscriberData = subStopConf->subscriberData;
+
+  DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
+		     subscriptionId,subscriptionKey,subscriberData));
+  m_waiter.signal(NO_WAIT);
+  DBUG_VOID_RETURN;
+}
+
+void
+NdbDictInterface::execSUB_STOP_REF(NdbApiSignal * signal,
+				     LinearSectionPtr ptr[3])
+{
+  DBUG_ENTER("NdbDictInterface::execSUB_STOP_REF");
+  const SubStopRef * const subStopRef=
+    CAST_CONSTPTR(SubStopRef, signal->getDataPtr());
+
+  Uint32 subscriptionId = subStopRef->subscriptionId;
+  Uint32 subscriptionKey = subStopRef->subscriptionKey;
+  Uint32 subscriberData = subStopRef->subscriberData;
+  m_error.code= subStopRef->errorCode;
+
+  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;
+}
+
+void
+NdbDictInterface::execSUB_START_CONF(NdbApiSignal * signal,
+				     LinearSectionPtr ptr[3])
+{
+  DBUG_ENTER("NdbDictInterface::execSUB_START_CONF");
+  const SubStartConf * const subStartConf=
+    CAST_CONSTPTR(SubStartConf, signal->getDataPtr());
+
+  Uint32 subscriptionId = subStartConf->subscriptionId;
+  Uint32 subscriptionKey = subStartConf->subscriptionKey;
+  SubscriptionData::Part part = 
+    (SubscriptionData::Part)subStartConf->part;
+  Uint32 subscriberData = subStartConf->subscriberData;
+
+  switch(part) {
+  case SubscriptionData::MetaData: {
+    DBUG_PRINT("error",("SubscriptionData::MetaData"));
+    m_error.code= 1;
+    break;
+  }
+  case SubscriptionData::TableData: {
+    DBUG_PRINT("info",("SubscriptionData::TableData"));
+    break;
+  }
+  default: {
+    DBUG_PRINT("error",("wrong data"));
+    m_error.code= 2;
+    break;
+  }
+  }
+  DBUG_PRINT("info",("subscriptionId=%d,subscriptionKey=%d,subscriberData=%d",
+		     subscriptionId,subscriptionKey,subscriberData));
+  m_waiter.signal(NO_WAIT);
+  DBUG_VOID_RETURN;
+}
+
+void
+NdbDictInterface::execSUB_START_REF(NdbApiSignal * signal,
+				    LinearSectionPtr ptr[3])
+{
+  DBUG_ENTER("NdbDictInterface::execSUB_START_REF");
+  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;
+}
+
+/*****************************************************************
+ * Drop event
+ */
+int 
+NdbDictionaryImpl::dropEvent(const char * eventName)
+{
+  DBUG_ENTER("NdbDictionaryImpl::dropEvent");
+  DBUG_PRINT("info", ("name=%s", eventName));
+
+  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);
+      delete 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
+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_name.c_str());
+
+  LinearSectionPtr ptr[1];
+  ptr[0].p = (Uint32*)m_buffer.get_data();
+  ptr[0].sz = (m_buffer.length()+3) >> 2;
+
+  return dictSignal(&tSignal,ptr, 1,
+		    0 /*use masternode id*/,
+		    WAIT_CREATE_INDX_REQ,
+		    -1, 100,
+		    0, -1);
+}
+
+void
+NdbDictInterface::execDROP_EVNT_CONF(NdbApiSignal * signal,
+				     LinearSectionPtr ptr[3])
+{
+  DBUG_ENTER("NdbDictInterface::execDROP_EVNT_CONF");
+  m_waiter.signal(NO_WAIT);  
+  DBUG_VOID_RETURN;
+}
+
+void
+NdbDictInterface::execDROP_EVNT_REF(NdbApiSignal * signal,
+				    LinearSectionPtr ptr[3])
+{
+  DBUG_ENTER("NdbDictInterface::execDROP_EVNT_REF");
+  const DropEvntRef* const ref=
+    CAST_CONSTPTR(DropEvntRef, signal->getDataPtr());
+  m_error.code= ref->getErrorCode();
+
+  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;
+}
+
+/*****************************************************************
  * List objects or indexes
  */
 int
@@ -2461,6 +4263,7 @@
       getApiConstant(ListTablesConf::getTableState(d), objectStateMapping, 0);
     element.store = (NdbDictionary::Object::Store)
       getApiConstant(ListTablesConf::getTableStore(d), objectStoreMapping, 0);
+    element.temp = ListTablesConf::getTableTemp(d);
     // table or index name
     Uint32 n = (data[pos++] + 3) >> 2;
     BaseString databaseName;
@@ -2546,26 +4349,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;
   }
@@ -2588,6 +4393,842 @@
   }
 }
 
+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])
+{
+  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,
+				  NdbDictObjectImpl* obj)
+  
+{
+  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, force, obj));
+  }
+  
+  
+  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, obj));
+  }
+  DBUG_RETURN(-1); 
+}
+
+int
+NdbDictionaryImpl::dropDatafile(const NdbDatafileImpl & file){
+  return m_receiver.drop_file(file);
+}
+
+int
+NdbDictionaryImpl::createUndofile(const NdbUndofileImpl & file, 
+				  bool force,
+				  NdbDictObjectImpl* obj)
+{
+  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, force, obj));
+  }
+  
+  
+  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, obj));
+  }
+  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,
+				    NdbDictObjectImpl* obj)
+{
+  return m_receiver.create_filegroup(fg, obj);
+}
+
+int
+NdbDictionaryImpl::dropTablespace(const NdbTablespaceImpl & fg)
+{
+  return m_receiver.drop_filegroup(fg);
+}
+
+int
+NdbDictionaryImpl::createLogfileGroup(const NdbLogfileGroupImpl & fg,
+				      NdbDictObjectImpl* obj)
+{
+  return m_receiver.create_filegroup(fg, obj);
+}
+
+int
+NdbDictionaryImpl::dropLogfileGroup(const NdbLogfileGroupImpl & fg)
+{
+  return m_receiver.drop_filegroup(fg);
+}
+
+int
+NdbDictInterface::create_file(const NdbFileImpl & file,
+			      const NdbFilegroupImpl & group,
+			      bool overwrite,
+			      NdbDictObjectImpl* obj)
+{
+  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.
+  */
+  int ret = dictSignal(&tSignal, ptr, 1,
+		       0, // master
+		       WAIT_CREATE_INDX_REQ,
+		       -1, 100,
+		       err);
+
+  if (ret == 0 && obj)
+  {
+    Uint32* data = (Uint32*)m_buffer.get_data();
+    obj->m_id = data[0];
+    obj->m_version = data[1];
+  }
+
+  DBUG_RETURN(ret);
+}
+
+void
+NdbDictInterface::execCREATE_FILE_CONF(NdbApiSignal * signal,
+				       LinearSectionPtr ptr[3])
+{
+  const CreateFileConf* conf=
+    CAST_CONSTPTR(CreateFileConf, signal->getDataPtr());
+  m_buffer.grow(4 * 2); // 2 words
+  Uint32* data = (Uint32*)m_buffer.get_data();
+  data[0] = conf->fileId;
+  data[1] = conf->fileVersion;
+  
+  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,
+				   NdbDictObjectImpl* obj)
+{
+  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};
+  int ret = dictSignal(&tSignal, ptr, 1,
+		       0, // master
+		       WAIT_CREATE_INDX_REQ,
+		       DICT_WAITFOR_TIMEOUT, 100,
+		       err);
+  
+  if (ret == 0 && obj)
+  {
+    Uint32* data = (Uint32*)m_buffer.get_data();
+    obj->m_id = data[0];
+    obj->m_version = data[1];
+  }
+  
+  DBUG_RETURN(ret);
+}
+
+void
+NdbDictInterface::execCREATE_FILEGROUP_CONF(NdbApiSignal * signal,
+					    LinearSectionPtr ptr[3])
+{
+  const CreateFilegroupConf* conf=
+    CAST_CONSTPTR(CreateFilegroupConf, signal->getDataPtr());
+  m_buffer.grow(4 * 2); // 2 words
+  Uint32* data = (Uint32*)m_buffer.get_data();
+  data[0] = conf->filegroupId;
+  data[1] = conf->filegroupVersion;
+  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>;
@@ -2595,3 +5236,15 @@
 template class Vector<NdbTableImpl*>;
 template class Vector<NdbColumnImpl*>;
 
+const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT = 0;
+const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_FIXED_MEMORY = 0;
+const NdbDictionary::Column * NdbDictionary::Column::FRAGMENT_VARSIZED_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;
+const NdbDictionary::Column * NdbDictionary::Column::ANY_VALUE = 0;

--- 1.30.13.1/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2007-04-11 15:21:08 +02:00
+++ 1.73/storage/ndb/src/ndbapi/NdbDictionaryImpl.hpp	2007-04-11 15:51:06 +02:00
@@ -29,15 +29,37 @@
 #include "NdbWaiter.hpp"
 #include "DictCache.hpp"
 
+bool
+is_ndb_blob_table(const char* name, Uint32* ptab_id = 0, Uint32* pcol_no = 0);
+bool
+is_ndb_blob_table(const class NdbTableImpl* t);
+
+extern int ndb_dictionary_is_mysqld;
+#define ASSERT_NOT_MYSQLD assert(ndb_dictionary_is_mysqld == 0)
+
 class NdbDictObjectImpl {
 public:
+  int m_id;
   Uint32 m_version;
+  NdbDictionary::Object::Type m_type;
   NdbDictionary::Object::Status m_status;
   
   bool change();
+  
+  static NdbDictObjectImpl & getImpl(NdbDictionary::ObjectId & t) { 
+    return t.m_impl;
+  }
+  static const NdbDictObjectImpl & getImpl(const NdbDictionary::ObjectId & t){
+    return t.m_impl;
+  }
+  
 protected:
-  NdbDictObjectImpl() :
+  friend class NdbDictionary::ObjectId;
+
+  NdbDictObjectImpl(NdbDictionary::Object::Type type) :
+    m_type(type),
     m_status(NdbDictionary::Object::New) {
+    m_id = -1;
   }
 };
 
@@ -58,6 +80,7 @@
   int m_precision;
   int m_scale;
   int m_length;
+  int m_column_no;
   CHARSET_INFO * m_cs;          // not const in MySQL
   
   bool m_pk;
@@ -72,7 +95,13 @@
    * Internal types and sizes, and aggregates
    */
   Uint32 m_attrSize;            // element size (size when arraySize==1)
-  Uint32 m_arraySize;           // length or length+2 for Var* types
+  Uint32 m_arraySize;           // length or maxlength+1/2 for Var* types
+  Uint32 m_arrayType;           // NDB_ARRAYTYPE_FIXED or _VAR
+  Uint32 m_storageType;         // NDB_STORAGETYPE_MEMORY or _DISK
+  /*
+   * NdbTableImpl: if m_pk, 0-based index of key in m_attrId order
+   * NdbIndexImpl: m_column_no of primary table column
+   */
   Uint32 m_keyInfoPos;
   // TODO: use bits in attr desc 2
   bool getInterpretableType() const ;
@@ -89,10 +118,9 @@
   static const NdbColumnImpl & getImpl(const NdbDictionary::Column & t);
   NdbDictionary::Column * m_facade;
 
-  static NdbDictionary::Column * create_psuedo(const char *);
+  static NdbDictionary::Column * create_pseudo(const char *);
 
   // Get total length in bytes, used by NdbOperation
-  // backported from 5.1
   bool get_var_length(const void* value, Uint32& len) const;
 };
 
@@ -105,13 +133,46 @@
   void init();
   int setName(const char * name);
   const char * getName() const;
+  void setFragmentCount(Uint32 count);
+  Uint32 getFragmentCount() const;
+  void setFrm(const void* data, Uint32 len);
+  const void * getFrmData() const;
+  Uint32 getFrmLength() const;
+  void setFragmentData(const void* data, Uint32 len);
+  const void * getFragmentData() const;
+  Uint32 getFragmentDataLen() const;
+  void setTablespaceNames(const void* data, Uint32 len);
+  Uint32 getTablespaceNamesLen() const;
+  const void * getTablespaceNames() const;
+  void setTablespaceData(const void* data, Uint32 len);
+  const void * getTablespaceData() const;
+  Uint32 getTablespaceDataLen() const;
+  void setRangeListData(const void* data, Uint32 len);
+  const void * getRangeListData() const;
+  Uint32 getRangeListDataLen() const;
+
+  const char * getMysqlName() const;
+  void updateMysqlName();
+
+  int aggregate(NdbError& error);
+  int validate(NdbError& error);
 
   Uint32 m_changeMask;
-  Uint32 m_tableId;
+  Uint32 m_primaryTableId;
   BaseString m_internalName;
   BaseString m_externalName;
+  BaseString m_mysqlName;
   BaseString m_newExternalName; // Used for alter table
   UtilBuffer m_frm; 
+  UtilBuffer m_newFrm;       // Used for alter table
+  UtilBuffer m_ts_name;      //Tablespace Names
+  UtilBuffer m_new_ts_name;  //Tablespace Names
+  UtilBuffer m_ts;           //TablespaceData
+  UtilBuffer m_new_ts;       //TablespaceData
+  UtilBuffer m_fd;           //FragmentData
+  UtilBuffer m_new_fd;       //FragmentData
+  UtilBuffer m_range;        //Range Or List Array
+  UtilBuffer m_new_range;    //Range Or List Array
   NdbDictionary::Object::FragmentType m_fragmentType;
 
   /**
@@ -120,6 +181,7 @@
   Uint32 m_columnHashMask;
   Vector<Uint32> m_columnHash;
   Vector<NdbColumnImpl *> m_columns;
+  void computeAggregates();
   int buildColumnHash(); 
 
   /**
@@ -131,8 +193,12 @@
 
   Uint64 m_max_rows;
   Uint64 m_min_rows;
-
+  Uint32 m_default_no_part_flag;
+  bool m_linear_flag;
   bool m_logging;
+  bool m_temporary;
+  bool m_row_gci;
+  bool m_row_checksum;
   int m_kvalue;
   int m_minLoadFactor;
   int m_maxLoadFactor;
@@ -140,7 +206,6 @@
   Uint16 m_fragmentCount;
   Uint8 m_single_user_mode;
 
-  NdbDictionaryImpl * m_dictionary;
   NdbIndexImpl * m_index;
   NdbColumnImpl * getColumn(unsigned attrId);
   NdbColumnImpl * getColumn(const char * name);
@@ -151,15 +216,16 @@
    * Index only stuff
    */
   BaseString m_primaryTable;
-  NdbDictionary::Index::Type m_indexType;
+  NdbDictionary::Object::Type m_indexType;
 
   /**
    * Aggregates
    */
   Uint8 m_noOfKeys;
+  // if all pk = dk then this is zero!
   Uint8 m_noOfDistributionKeys;
   Uint8 m_noOfBlobs;
-  
+  Uint8 m_noOfDiskColumns;
   Uint8 m_replicaCount;
 
   /**
@@ -176,6 +242,13 @@
    * Return count
    */
   Uint32 get_nodes(Uint32 hashValue, const Uint16** nodes) const ;
+
+  /**
+   * Disk stuff
+   */
+  BaseString m_tablespace_name;
+  Uint32 m_tablespace_id;
+  Uint32 m_tablespace_version;
 };
 
 class NdbIndexImpl : public NdbDictionary::Index, public NdbDictObjectImpl {
@@ -191,15 +264,16 @@
   const char * getTable() const;
   const NdbTableImpl * getIndexTable() const;
 
-  Uint32 m_indexId;
   BaseString m_internalName;
   BaseString m_externalName;
   BaseString m_tableName;
+  Uint32 m_table_id;
+  Uint32 m_table_version;
   Vector<NdbColumnImpl *> m_columns;
   Vector<int> m_key_ids;
-  NdbDictionary::Index::Type m_type;
 
   bool m_logging;
+  bool m_temporary;
   
   NdbTableImpl * m_table;
   
@@ -208,6 +282,147 @@
   NdbDictionary::Index * m_facade;
 };
 
+class NdbEventImpl : public NdbDictionary::Event, public NdbDictObjectImpl {
+  friend class NdbDictInterface;
+  friend class NdbDictionaryImpl;
+  friend class NdbEventOperation;
+  friend class NdbEventOperationImpl;
+  friend class NdbEventBuffer;
+  friend class EventBufData_hash;
+  friend class NdbBlob;
+public:
+  NdbEventImpl();
+  NdbEventImpl(NdbDictionary::Event &);
+  ~NdbEventImpl();
+
+  void init();
+  void setName(const char * name);
+  const char * getName() const;
+  void setTable(const NdbDictionary::Table& table);
+  const NdbDictionary::Table * getTable() const;
+  void setTable(const char * table);
+  const char * getTableName() const;
+  void addTableEvent(const NdbDictionary::Event::TableEvent t);
+  bool getTableEvent(const NdbDictionary::Event::TableEvent t) const;
+  void setDurability(NdbDictionary::Event::EventDurability d);
+  NdbDictionary::Event::EventDurability  getDurability() const;
+  void setReport(NdbDictionary::Event::EventReport r);
+  NdbDictionary::Event::EventReport  getReport() const;
+  int getNoOfEventColumns() const;
+  const NdbDictionary::Column * getEventColumn(unsigned no) const;
+
+  void print() {
+    ndbout_c("NdbEventImpl: id=%d, key=%d",
+	     m_eventId,
+	     m_eventKey);
+  };
+
+  Uint32 m_eventId;
+  Uint32 m_eventKey;
+  AttributeMask m_attrListBitmask;
+  Uint32 m_table_id;
+  Uint32 m_table_version;
+  BaseString m_name;
+  Uint32 mi_type;
+  NdbDictionary::Event::EventDurability m_dur;
+  NdbDictionary::Event::EventReport m_rep;
+  bool m_mergeEvents;
+
+  BaseString m_tableName;
+  Vector<NdbColumnImpl *> m_columns;
+  Vector<unsigned> m_attrIds;
+
+  static NdbEventImpl & getImpl(NdbDictionary::Event & t);
+  static NdbEventImpl & getImpl(const NdbDictionary::Event & t);
+  NdbDictionary::Event * m_facade;
+private:
+  NdbTableImpl *m_tableImpl;
+  void setTable(NdbTableImpl *tableImpl);
+};
+
+struct NdbFilegroupImpl : public NdbDictObjectImpl {
+  NdbFilegroupImpl(NdbDictionary::Object::Type t);
+
+  BaseString m_name;
+  NdbDictionary::AutoGrowSpecification m_grow_spec;
+
Thread
bk commit into 5.1 tree (tomas:1.2573)tomas11 Apr