List:Commits« Previous MessageNext Message »
From:Stewart Smith Date:October 5 2006 1:13pm
Subject:bk commit into 5.1 tree (stewart:1.2302)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of stewart. When stewart 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, 2006-10-05 23:13:29+10:00, stewart@willster.(none) +29 -0
  Merge willster.(none):/home/stewart/Documents/MySQL/5.0/bug21154
  into  willster.(none):/home/stewart/Documents/MySQL/5.1/bug13987
  
  Merge 5.0-ndb into 5.1-ndb
  MERGE: 1.1810.2096.6

  mysql-test/r/ndb_config.result@stripped, 2006-10-05 23:13:26+10:00, stewart@willster.(none) +1 -0
    manual merge
    MERGE: 1.6.1.1

  mysql-test/t/ndb_config.test@stripped, 2006-10-05 23:13:26+10:00, stewart@willster.(none) +1 -0
    manual merge
    MERGE: 1.11.1.1

  storage/ndb/include/mgmapi/mgmapi.h@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.42.12.2

  storage/ndb/include/mgmapi/mgmapi.h@stripped, 2006-10-05 23:09:25+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/include/mgmapi/mgmapi.h -> storage/ndb/include/mgmapi/mgmapi.h

  storage/ndb/include/mgmapi/mgmapi_debug.h@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.7.1.2

  storage/ndb/include/mgmapi/mgmapi_debug.h@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/include/mgmapi/mgmapi_debug.h -> storage/ndb/include/mgmapi/mgmapi_debug.h

  storage/ndb/include/util/InputStream.hpp@stripped, 2006-10-05 23:13:26+10:00, stewart@willster.(none) +0 -1
    manual merge
    MERGE: 1.3.1.2

  storage/ndb/include/util/InputStream.hpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/include/util/InputStream.hpp -> storage/ndb/include/util/InputStream.hpp

  storage/ndb/include/util/Parser.hpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.3.2.2

  storage/ndb/include/util/Parser.hpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/include/util/Parser.hpp -> storage/ndb/include/util/Parser.hpp

  storage/ndb/include/util/socket_io.h@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.3.1.2

  storage/ndb/include/util/socket_io.h@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/include/util/socket_io.h -> storage/ndb/include/util/socket_io.h

  storage/ndb/src/common/util/InputStream.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.3.1.2

  storage/ndb/src/common/util/InputStream.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/common/util/InputStream.cpp -> storage/ndb/src/common/util/InputStream.cpp

  storage/ndb/src/common/util/Parser.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.6.4.2

  storage/ndb/src/common/util/Parser.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/common/util/Parser.cpp -> storage/ndb/src/common/util/Parser.cpp

  storage/ndb/src/common/util/socket_io.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.7.2.2

  storage/ndb/src/common/util/socket_io.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/common/util/socket_io.cpp -> storage/ndb/src/common/util/socket_io.cpp

  storage/ndb/src/cw/cpcd/main.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.7.4.2

  storage/ndb/src/cw/cpcd/main.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/cw/cpcd/main.cpp -> storage/ndb/src/cw/cpcd/main.cpp

  storage/ndb/src/kernel/vm/Configuration.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.39.8.2

  storage/ndb/src/kernel/vm/Configuration.cpp@stripped, 2006-10-05 23:09:25+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/kernel/vm/Configuration.cpp -> storage/ndb/src/kernel/vm/Configuration.cpp

  storage/ndb/src/mgmapi/mgmapi.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.44.26.2

  storage/ndb/src/mgmapi/mgmapi.cpp@stripped, 2006-10-05 23:09:25+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/mgmapi/mgmapi.cpp -> storage/ndb/src/mgmapi/mgmapi.cpp

  storage/ndb/src/mgmclient/main.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.20.4.2

  storage/ndb/src/mgmclient/main.cpp@stripped, 2006-10-05 23:09:25+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/mgmclient/main.cpp -> storage/ndb/src/mgmclient/main.cpp

  storage/ndb/src/mgmsrv/Services.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.45.30.2

  storage/ndb/src/mgmsrv/Services.cpp@stripped, 2006-10-05 23:09:25+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/mgmsrv/Services.cpp -> storage/ndb/src/mgmsrv/Services.cpp

  storage/ndb/src/mgmsrv/Services.hpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.13.7.2

  storage/ndb/src/mgmsrv/Services.hpp@stripped, 2006-10-05 23:09:25+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/mgmsrv/Services.hpp -> storage/ndb/src/mgmsrv/Services.hpp

  storage/ndb/src/mgmsrv/main.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.41.7.2

  storage/ndb/src/mgmsrv/main.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/mgmsrv/main.cpp -> storage/ndb/src/mgmsrv/main.cpp

  storage/ndb/src/ndbapi/NdbTransaction.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -2
    Auto merged
    MERGE: 1.43.9.2

  storage/ndb/src/ndbapi/NdbTransaction.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/src/ndbapi/NdbTransaction.cpp -> storage/ndb/src/ndbapi/NdbTransaction.cpp

  storage/ndb/test/ndbapi/testMgm.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.4.1.2

  storage/ndb/test/ndbapi/testMgm.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/test/ndbapi/testMgm.cpp -> storage/ndb/test/ndbapi/testMgm.cpp

  storage/ndb/tools/delete_all.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.16.3.2

  storage/ndb/tools/delete_all.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/delete_all.cpp -> storage/ndb/tools/delete_all.cpp

  storage/ndb/tools/desc.cpp@stripped, 2006-10-05 23:13:26+10:00, stewart@willster.(none) +0 -0
    manual merge
    MERGE: 1.18.2.2

  storage/ndb/tools/desc.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/desc.cpp -> storage/ndb/tools/desc.cpp

  storage/ndb/tools/drop_index.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.13.3.2

  storage/ndb/tools/drop_index.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/drop_index.cpp -> storage/ndb/tools/drop_index.cpp

  storage/ndb/tools/drop_tab.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.14.1.2

  storage/ndb/tools/drop_tab.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/drop_tab.cpp -> storage/ndb/tools/drop_tab.cpp

  storage/ndb/tools/listTables.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.20.3.2

  storage/ndb/tools/listTables.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/listTables.cpp -> storage/ndb/tools/listTables.cpp

  storage/ndb/tools/ndb_condig.cpp@stripped, 2006-10-05 23:13:26+10:00, stewart@willster.(none) +0 -1
    manual merge
    MERGE: 1.4.7.6

  storage/ndb/tools/ndb_condig.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/ndb_config.cpp -> storage/ndb/tools/ndb_condig.cpp

  storage/ndb/tools/restore/restore_main.cpp@stripped, 2006-10-05 23:13:26+10:00, stewart@willster.(none) +1 -0
    manual merge
    MERGE: 1.29.8.2

  storage/ndb/tools/restore/restore_main.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/restore/restore_main.cpp -> storage/ndb/tools/restore/restore_main.cpp

  storage/ndb/tools/select_all.cpp@stripped, 2006-10-05 23:13:26+10:00, stewart@willster.(none) +0 -0
    manual merge
    MERGE: 1.22.1.2

  storage/ndb/tools/select_all.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/select_all.cpp -> storage/ndb/tools/select_all.cpp

  storage/ndb/tools/select_count.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.19.1.2

  storage/ndb/tools/select_count.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/select_count.cpp -> storage/ndb/tools/select_count.cpp

  storage/ndb/tools/waiter.cpp@stripped, 2006-10-05 23:09:27+10:00, stewart@willster.(none) +0 -0
    Auto merged
    MERGE: 1.23.2.2

  storage/ndb/tools/waiter.cpp@stripped, 2006-10-05 23:09:26+10:00, stewart@willster.(none) +0 -0
    Merge rename: ndb/tools/waiter.cpp -> storage/ndb/tools/waiter.cpp

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	stewart
# Host:	willster.(none)
# Root:	/home/stewart/Documents/MySQL/5.1/bug13987/RESYNC

--- 1.9/mysql-test/r/ndb_config.result	2006-10-05 23:13:37 +10:00
+++ 1.10/mysql-test/r/ndb_config.result	2006-10-05 23:13:37 +10:00
@@ -8,3 +8,7 @@
 ndbd,1,localhost ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndb_mgmd,5,localhost mysqld,6, mysqld,7, mysqld,8, mysqld,9, mysqld,10,
 ndbd,2,localhost ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndb_mgmd,6,localhost mysqld,1, mysqld,7, mysqld,8, mysqld,9, mysqld,10,
 ndbd,3,localhost ndbd,4,localhost ndbd,5,localhost ndbd,6,localhost ndb_mgmd,1,localhost ndb_mgmd,2,localhost mysqld,11, mysqld,12, mysqld,13, mysqld,14, mysqld,15,
+shm,3,4,35,3 shm,3,5,35,3 shm,3,6,35,3 shm,4,5,35,4 shm,4,6,35,4 shm,5,6,35,5 tcp,11,3,55,3 tcp,11,4,55,4 tcp,11,5,55,5 tcp,11,6,55,6 tcp,12,3,55,3 tcp,12,4,55,4 tcp,12,5,55,5 tcp,12,6,55,6 tcp,13,3,55,3 tcp,13,4,55,4 tcp,13,5,55,5 tcp,13,6,55,6 tcp,14,3,55,3 tcp,14,4,55,4 tcp,14,5,55,5 tcp,14,6,55,6 tcp,15,3,55,3 tcp,15,4,55,4 tcp,15,5,55,5 tcp,15,6,55,6 tcp,1,3,55,1 tcp,1,4,55,1 tcp,1,5,55,1 tcp,1,6,55,1 tcp,2,3,55,2 tcp,2,4,55,2 tcp,2,5,55,2 tcp,2,6,55,2
+1 2 3
+
+1 2 3

--- 1.13/mysql-test/t/ndb_config.test	2006-10-05 23:13:37 +10:00
+++ 1.14/mysql-test/t/ndb_config.test	2006-10-05 23:13:37 +10:00
@@ -15,3 +15,9 @@
 --exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster0 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
 --exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster1 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
 --exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --query=type,nodeid,host --mycnf 2> /dev/null
+--exec $NDB_TOOLS_DIR/ndb_config --defaults-group-suffix=.cluster2 --defaults-file=$MYSQL_TEST_DIR/std_data/ndb_config_mycnf2.cnf --ndb-shm --connections --query=type,nodeid1,nodeid2,group,nodeidserver --mycnf 2> /dev/null
+
+
+--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=nodeid --host=localhost --config-file=$NDB_BACKUP_DIR/config.ini 2> /dev/null
+--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=nodeid --host=1.2.3.4   --config-file=$NDB_BACKUP_DIR/config.ini 2> /dev/null
+--exec $NDB_TOOLS_DIR/ndb_config --no-defaults --query=nodeid --host=127.0.0.1 --config-file=$NDB_BACKUP_DIR/config.ini 2> /dev/null

--- 1.42.12.1/ndb/include/mgmapi/mgmapi.h	2006-10-05 23:13:37 +10:00
+++ 1.56/storage/ndb/include/mgmapi/mgmapi.h	2006-10-05 23:13:37 +10:00
@@ -171,7 +171,6 @@
     = NODE_TYPE_MGM
 #endif
 #ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
-    ,NDB_MGM_NODE_TYPE_REP = NODE_TYPE_REP  /** A replication node */
     ,NDB_MGM_NODE_TYPE_MIN     = 0          /** Min valid value*/
     ,NDB_MGM_NODE_TYPE_MAX     = 3          /** Max valid value*/
 #endif
@@ -231,7 +230,9 @@
     NDB_MGM_SERVER_NOT_CONNECTED = 1010,
     /** Could not connect to socker */
     NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET = 1011,
-
+    /** Could not bind local address */
+    NDB_MGM_BIND_ADDRESS = 1012,
+    
     /* Alloc node id failures */
     /** Generic error, retry may succeed */
     NDB_MGM_ALLOCID_ERROR = 1101,
@@ -516,6 +517,15 @@
   const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
 
   /**
+   * Set local bindaddress
+   * @param arg - Srting of form "host[:port]"
+   * @note must be called before connect
+   * @note Error on binding local address will not be reported until connect
+   * @return 0 on success
+   */
+  int ndb_mgm_set_bindaddress(NdbMgmHandle, const char * arg);
+
+  /**
    * Gets the connectstring used for a connection
    *
    * @note This function returns the default connectstring if no call to 
@@ -862,6 +872,15 @@
 				      enum ndb_mgm_event_category category,
 				      int level,
 				      struct ndb_mgm_reply* reply);
+  /**
+   * get log category and levels 
+   *
+   * @param   handle        NDB management handle.
+   * @return                A vector of twelve elements,
+   *                        where each element contains
+   *                        loglevel of corresponding category
+   */
+  const unsigned int *ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle);
 
   /** @} *********************************************************************/
   /**
@@ -897,16 +916,6 @@
 				enum ndb_mgm_event_category category,
 				int level,
 				struct ndb_mgm_reply* reply);
-
-  /**
-   * Returns the port number where statistics information is sent
-   *
-   * @param   handle        NDB management handle.
-   * @param   reply         Reply message.
-   * @return                -1 on error.
-   */
-  int ndb_mgm_get_stat_port(NdbMgmHandle handle,
-			    struct ndb_mgm_reply* reply);
 #endif
 
   /**
@@ -1154,6 +1163,11 @@
 				      enum ndb_mgm_event_category c,
 				      int l, struct ndb_mgm_reply* r)
   { return ndb_mgm_set_clusterlog_loglevel(h,n,c,l,r); }
+
+  inline
+  const unsigned int *ndb_mgm_get_loglevel_clusterlog(NdbMgmHandle h)
+  { return ndb_mgm_get_clusterlog_loglevel(h); }
+
 #endif
 
 #ifdef __cplusplus

--- 1.7.1.1/ndb/include/mgmapi/mgmapi_debug.h	2006-10-05 23:13:37 +10:00
+++ 1.10/storage/ndb/include/mgmapi/mgmapi_debug.h	2006-10-05 23:13:37 +10:00
@@ -101,7 +101,7 @@
    */
   int ndb_mgm_dump_state(NdbMgmHandle handle,
 			 int nodeId,
-			 int * args,
+			 const int * args,
 			 int num_args,
 			 struct ndb_mgm_reply* reply);
     

--- 1.3.1.1/ndb/include/util/InputStream.hpp	2006-10-05 23:13:37 +10:00
+++ 1.6/storage/ndb/include/util/InputStream.hpp	2006-10-05 23:13:37 +10:00
@@ -41,6 +41,7 @@
   FILE * f;
 public:
   FileInputStream(FILE * file = stdin);
+  virtual ~FileInputStream() {}
   char* gets(char * buf, int bufLen); 
 };
 
@@ -52,6 +53,7 @@
   bool m_startover;
 public:
   SocketInputStream(NDB_SOCKET_TYPE socket, unsigned readTimeout = 1000);
+  virtual ~SocketInputStream() {}
   char* gets(char * buf, int bufLen);
 };
 

--- 1.29.8.1/ndb/tools/restore/restore_main.cpp	2006-10-05 23:13:37 +10:00
+++ 1.47/storage/ndb/tools/restore/restore_main.cpp	2006-10-05 23:13:37 +10:00
@@ -19,6 +19,7 @@
 #include <Vector.hpp>
 #include <ndb_limits.h>
 #include <NdbTCP.h>
+#include <NdbMem.h>
 #include <NdbOut.hpp>
 #include <NDBT_ReturnCodes.h>
 
@@ -37,11 +38,17 @@
 
 static const char* ga_backupPath = "." DIR_SEPARATOR;
 
+static const char *opt_nodegroup_map_str= 0;
+static unsigned opt_nodegroup_map_len= 0;
+static NODE_GROUP_MAP opt_nodegroup_map[MAX_NODE_GROUP_MAPS];
+#define OPT_NDB_NODEGROUP_MAP 'z'
+
 NDB_STD_OPTS_VARS;
 
 /**
  * print and restore flags
  */
+static bool ga_restore_epoch = false;
 static bool ga_restore = false;
 static bool ga_print = false;
 static int _print = 0;
@@ -50,6 +57,7 @@
 static int _print_log = 0;
 static int _restore_data = 0;
 static int _restore_meta = 0;
+static int _no_restore_disk = 0;
 BaseString g_options("ndb_restore");
 
 const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 };
@@ -74,6 +82,16 @@
     "Restore meta data into NDB Cluster using NDBAPI",
     (gptr*) &_restore_meta, (gptr*) &_restore_meta,  0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "no-restore-disk-objects", 'd',
+    "Dont restore disk objects (tablespace/logfilegroups etc)",
+    (gptr*) &_no_restore_disk, (gptr*) &_no_restore_disk,  0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "restore_epoch", 'e', 
+    "Restore epoch info into the status table. Convenient on a MySQL Cluster "
+    "replication slave, for starting replication. The row in "
+    NDB_REP_DB "." NDB_APPLY_TABLE " with id 0 will be updated/inserted.", 
+    (gptr*) &ga_restore_epoch, (gptr*) &ga_restore_epoch,  0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
   { "parallelism", 'p',
     "No of parallel transactions during restore of data."
     "(parallelism can be 1 to 1024)", 
@@ -91,13 +109,131 @@
   { "print_log", 259, "Print log to stdout",
     (gptr*) &_print_log, (gptr*) &_print_log,  0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "backup_path", 260, "Path to backup files",
+    (gptr*) &ga_backupPath, (gptr*) &ga_backupPath, 0,
+    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
   { "dont_ignore_systab_0", 'f',
     "Experimental. Do not ignore system table during restore.", 
     (gptr*) &ga_dont_ignore_systab_0, (gptr*) &ga_dont_ignore_systab_0, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "ndb-nodegroup-map", OPT_NDB_NODEGROUP_MAP,
+    "Nodegroup map for ndbcluster. Syntax: list of (source_ng, dest_ng)",
+    (gptr*) &opt_nodegroup_map_str,
+    (gptr*) &opt_nodegroup_map_str,
+    0,
+    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
+
+static char* analyse_one_map(char *map_str, uint16 *source, uint16 *dest)
+{
+  char *end_ptr;
+  int number;
+  DBUG_ENTER("analyse_one_map");
+  /*
+    Search for pattern ( source_ng , dest_ng )
+  */
+
+  while (isspace(*map_str)) map_str++;
+
+  if (*map_str != '(')
+  {
+    DBUG_RETURN(NULL);
+  }
+  map_str++;
+
+  while (isspace(*map_str)) map_str++;
+
+  number= strtol(map_str, &end_ptr, 10);
+  if (!end_ptr || number < 0 || number >= MAX_NODE_GROUP_MAPS)
+  {
+    DBUG_RETURN(NULL);
+  }
+  *source= (uint16)number;
+  map_str= end_ptr;
+
+  while (isspace(*map_str)) map_str++;
+
+  if (*map_str != ',')
+  {
+    DBUG_RETURN(NULL);
+  }
+  map_str++;
+
+  number= strtol(map_str, &end_ptr, 10);
+  if (!end_ptr || number < 0 || number >= UNDEF_NODEGROUP)
+  {
+    DBUG_RETURN(NULL);
+  }
+  *dest= (uint16)number;
+  map_str= end_ptr;
+
+  if (*map_str != ')')
+  {
+    DBUG_RETURN(NULL);
+  }
+  map_str++;
+
+  while (isspace(*map_str)) map_str++;
+  DBUG_RETURN(map_str);
+}
+
+static bool insert_ng_map(NODE_GROUP_MAP *ng_map,
+                          uint16 source_ng, uint16 dest_ng)
+{
+  uint index= source_ng;
+  uint ng_index= ng_map[index].no_maps;
+
+  opt_nodegroup_map_len++;
+  if (ng_index >= MAX_MAPS_PER_NODE_GROUP)
+    return true;
+  ng_map[index].no_maps++;
+  ng_map[index].map_array[ng_index]= dest_ng;
+  return false;
+}
+
+static void init_nodegroup_map()
+{
+  uint i,j;
+  NODE_GROUP_MAP *ng_map = &opt_nodegroup_map[0];
+
+  for (i = 0; i < MAX_NODE_GROUP_MAPS; i++)
+  {
+    ng_map[i].no_maps= 0;
+    for (j= 0; j < MAX_MAPS_PER_NODE_GROUP; j++)
+      ng_map[i].map_array[j]= UNDEF_NODEGROUP;
+  }
+}
+
+static bool analyse_nodegroup_map(const char *ng_map_str,
+                                  NODE_GROUP_MAP *ng_map)
+{
+  uint16 source_ng, dest_ng;
+  char *local_str= (char*)ng_map_str;
+  DBUG_ENTER("analyse_nodegroup_map");
+
+  do
+  {
+    if (!local_str)
+    {
+      DBUG_RETURN(TRUE);
+    }
+    local_str= analyse_one_map(local_str, &source_ng, &dest_ng);
+    if (!local_str)
+    {
+      DBUG_RETURN(TRUE);
+    }
+    if (insert_ng_map(ng_map, source_ng, dest_ng))
+    {
+      DBUG_RETURN(TRUE);
+    }
+    if (!(*local_str))
+      break;
+  } while (TRUE);
+  DBUG_RETURN(FALSE);
+}
+
 static void short_usage_sub(void)
 {
   printf("Usage: %s [OPTIONS] [<path to backup files>]\n", my_progname);
@@ -126,6 +262,7 @@
       printf("Error in --nodeid,-n setting, see --help\n");
       exit(NDBT_ProgramExit(NDBT_WRONGARGS));
     }
+    info << "Nodeid = " << ga_nodeId << endl;
     break;
   case 'b':
     if (ga_backupId == 0)
@@ -133,6 +270,20 @@
       printf("Error in --backupid,-b setting, see --help\n");
       exit(NDBT_ProgramExit(NDBT_WRONGARGS));
     }
+    info << "Backup Id = " << ga_backupId << endl;
+    break;
+  case OPT_NDB_NODEGROUP_MAP:
+    /*
+      This option is used to set a map from nodegroup in original cluster
+      to nodegroup in new cluster.
+    */
+    opt_nodegroup_map_len= 0;
+    info << "Analyse node group map" << endl;
+    if (analyse_nodegroup_map(opt_nodegroup_map_str,
+                              &opt_nodegroup_map[0]))
+    {
+      exit(NDBT_ProgramExit(NDBT_WRONGARGS));
+    }
     break;
   }
   return 0;
@@ -140,17 +291,55 @@
 bool
 readArguments(int *pargc, char*** pargv) 
 {
+  Uint32 i;
+  debug << "Load defaults" << endl;
+  const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 };
+
+  init_nodegroup_map();
   load_defaults("my",load_default_groups,pargc,pargv);
+  debug << "handle_options" << endl;
   if (handle_options(pargc, pargv, my_long_options, get_one_option))
   {
     exit(NDBT_ProgramExit(NDBT_WRONGARGS));
   }
+  for (i = 0; i < MAX_NODE_GROUP_MAPS; i++)
+    opt_nodegroup_map[i].curr_index = 0;
+
+#if 0
+  /*
+    Test code written t{
+o verify nodegroup mapping
+  */
+  printf("Handled options successfully\n");
+  Uint16 map_ng[16];
+  Uint32 j;
+  for (j = 0; j < 4; j++)
+  {
+  for (i = 0; i < 4 ; i++)
+    map_ng[i] = i;
+  map_nodegroups(&map_ng[0], (Uint32)4);
+  for (i = 0; i < 4 ; i++)
+    printf("NG %u mapped to %u \n", i, map_ng[i]);
+  }
+  for (j = 0; j < 4; j++)
+  {
+  for (i = 0; i < 8 ; i++)
+    map_ng[i] = i >> 1;
+  map_nodegroups(&map_ng[0], (Uint32)8);
+  for (i = 0; i < 8 ; i++)
+    printf("NG %u mapped to %u \n", i >> 1, map_ng[i]);
+  }
+  exit(NDBT_ProgramExit(NDBT_WRONGARGS));
+#endif
 
-  BackupPrinter* printer = new BackupPrinter();
+  BackupPrinter* printer = new BackupPrinter(opt_nodegroup_map,
+                                             opt_nodegroup_map_len);
   if (printer == NULL)
     return false;
 
-  BackupRestore* restore = new BackupRestore(ga_nParallelism);
+  BackupRestore* restore = new BackupRestore(opt_nodegroup_map,
+                                             opt_nodegroup_map_len,
+                                             ga_nParallelism);
   if (restore == NULL) 
   {
     delete printer;
@@ -191,6 +380,16 @@
     restore->m_restore_meta = true;
   }
 
+  if (_no_restore_disk)
+  {
+    restore->m_no_restore_disk = true;
+  }
+  
+  if (ga_restore_epoch)
+  {
+    restore->m_restore_epoch = true;
+  }
+
   {
     BackupConsumer * c = printer;
     g_consumers.push_back(c);
@@ -204,7 +403,7 @@
   {
     ga_backupPath = *pargv[0];
   }
-
+  info << "backup path = " << ga_backupPath << endl;
   return true;
 }
 
@@ -216,14 +415,17 @@
   g_consumers.clear();
 }
 
-static bool
-checkSysTable(const char *tableName) 
+static inline bool
+checkSysTable(const TableS* table)
+{
+  return ga_dont_ignore_systab_0 || ! table->getSysTable();
+}
+
+static inline bool
+checkSysTable(const RestoreMetaData& metaData, uint i)
 {
-  return ga_dont_ignore_systab_0 ||
-    (strcmp(tableName, "SYSTAB_0") != 0 &&
-     strcmp(tableName, "NDB$EVENTS_0") != 0 &&
-     strcmp(tableName, "sys/def/SYSTAB_0") != 0 &&
-     strcmp(tableName, "sys/def/NDB$EVENTS_0") != 0);
+  assert(i < metaData.getNoOfTables());
+  return checkSysTable(metaData[i]);
 }
 
 static void
@@ -248,6 +450,7 @@
 {
   NDB_INIT(argv[0]);
 
+  debug << "Start readArguments" << endl;
   if (!readArguments(&argc, &argv))
   {
     exitHandler(NDBT_FAILED);
@@ -259,6 +462,10 @@
     g_options.appfmt(" -m");
   if (_restore_data)
     g_options.appfmt(" -r");
+  if (ga_restore_epoch)
+    g_options.appfmt(" -e");
+  if (_no_restore_disk)
+    g_options.appfmt(" -d");
   g_options.appfmt(" -p %d", ga_nParallelism);
 
   g_connect_string = opt_connect_str;
@@ -266,10 +473,11 @@
   /**
    * we must always load meta data, even if we will only print it to stdout
    */
+  debug << "Start restoring meta data" << endl;
   RestoreMetaData metaData(ga_backupPath, ga_nodeId, ga_backupId);
   if (!metaData.readHeader())
   {
-    ndbout << "Failed to read " << metaData.getFilename() << endl << endl;
+    err << "Failed to read " << metaData.getFilename() << endl << endl;
     exitHandler(NDBT_FAILED);
   }
 
@@ -277,66 +485,98 @@
   const Uint32 version = tmp.NdbVersion;
   
   char buf[NDB_VERSION_STRING_BUF_SZ];
-  ndbout << "Ndb version in backup files: " 
+  info << "Ndb version in backup files: " 
 	 <<  getVersionString(version, 0, buf, sizeof(buf)) << endl;
-  
+
   /**
    * check wheater we can restore the backup (right version).
    */
+  // in these versions there was an error in how replica info was
+  // stored on disk
+  if (version >= MAKE_VERSION(5,1,3) && version <= MAKE_VERSION(5,1,9))
+  {
+    err << "Restore program incompatible with backup versions between "
+        << getVersionString(MAKE_VERSION(5,1,3), 0, buf, sizeof(buf))
+        << " and "
+        << getVersionString(MAKE_VERSION(5,1,9), 0, buf, sizeof(buf))
+        << endl;
+    exitHandler(NDBT_FAILED);
+  }
+
+  if (version > NDB_VERSION)
+  {
+    err << "Restore program older than backup version. Not supported. "
+        << "Use new restore program" << endl;
+    exitHandler(NDBT_FAILED);
+  }
+
+  debug << "Load content" << endl;
   int res  = metaData.loadContent();
   
   if (res == 0)
   {
-    ndbout_c("Restore: Failed to load content");
+    err << "Restore: Failed to load content" << endl;
     exitHandler(NDBT_FAILED);
   }
-  
+  debug << "Get no of Tables" << endl; 
   if (metaData.getNoOfTables() == 0) 
   {
-    ndbout_c("Restore: The backup contains no tables ");
+    err << "The backup contains no tables" << endl;
     exitHandler(NDBT_FAILED);
   }
-
+  debug << "Validate Footer" << endl;
 
   if (!metaData.validateFooter()) 
   {
-    ndbout_c("Restore: Failed to validate footer.");
+    err << "Restore: Failed to validate footer." << endl;
     exitHandler(NDBT_FAILED);
   }
-
+  debug << "Init Backup objects" << endl;
   Uint32 i;
   for(i= 0; i < g_consumers.size(); i++)
   {
     if (!g_consumers[i]->init())
     {
       clearConsumers();
+      err << "Failed to initialize consumers" << endl;
       exitHandler(NDBT_FAILED);
     }
 
   }
-
+  debug << "Restore objects (tablespaces, ..)" << endl;
+  for(i = 0; i<metaData.getNoOfObjects(); i++)
+  {
+    for(Uint32 j= 0; j < g_consumers.size(); j++)
+      if (!g_consumers[j]->object(metaData.getObjType(i),
+				  metaData.getObjPtr(i)))
+      {
+	err << "Restore: Failed to restore table: ";
+        err << metaData[i]->getTableName() << " ... Exiting " << endl;
+	exitHandler(NDBT_FAILED);
+      } 
+  }
+  debug << "Restoring tables" << endl; 
   for(i = 0; i<metaData.getNoOfTables(); i++)
   {
-    if (checkSysTable(metaData[i]->getTableName()))
+    if (checkSysTable(metaData, i))
     {
       for(Uint32 j= 0; j < g_consumers.size(); j++)
 	if (!g_consumers[j]->table(* metaData[i]))
 	{
-	  ndbout_c("Restore: Failed to restore table: %s. "
-		   "Exiting...", 
-		   metaData[i]->getTableName());
+	  err << "Restore: Failed to restore table: ";
+          err << metaData[i]->getTableName() << " ... Exiting " << endl;
 	  exitHandler(NDBT_FAILED);
 	} 
     }
   }
-  
+  debug << "Close tables" << endl; 
   for(i= 0; i < g_consumers.size(); i++)
     if (!g_consumers[i]->endOfTables())
     {
-      ndbout_c("Restore: Failed while closing tables");
+      err << "Restore: Failed while closing tables" << endl;
       exitHandler(NDBT_FAILED);
     } 
-  
+  debug << "Iterate over data" << endl; 
   if (ga_restore || ga_print) 
   {
     if(_restore_data || _print_data)
@@ -346,30 +586,30 @@
       // Read data file header
       if (!dataIter.readHeader())
       {
-	ndbout << "Failed to read header of data file. Exiting..." ;
+	err << "Failed to read header of data file. Exiting..." << endl;
 	exitHandler(NDBT_FAILED);
       }
       
-      
-      while (dataIter.readFragmentHeader(res= 0))
+      Uint32 fragmentId; 
+      while (dataIter.readFragmentHeader(res= 0, &fragmentId))
       {
 	const TupleS* tuple;
 	while ((tuple = dataIter.getNextTuple(res= 1)) != 0)
 	{
-	  if (checkSysTable(tuple->getTable()->getTableName()))
+	  if (checkSysTable(tuple->getTable()))
 	    for(Uint32 i= 0; i < g_consumers.size(); i++) 
-	      g_consumers[i]->tuple(* tuple);
+	      g_consumers[i]->tuple(* tuple, fragmentId);
 	} // while (tuple != NULL);
 	
 	if (res < 0)
 	{
-	  ndbout_c("Restore: An error occured while restoring data. "
-		   "Exiting...");
+	  err <<" Restore: An error occured while restoring data. Exiting...";
+          err << endl;
 	  exitHandler(NDBT_FAILED);
 	}
 	if (!dataIter.validateFragmentFooter()) {
-	  ndbout_c("Restore: Error validating fragment footer. "
-		   "Exiting...");
+	  err << "Restore: Error validating fragment footer. ";
+          err << "Exiting..." << endl;
 	  exitHandler(NDBT_FAILED);
 	}
       } // while (dataIter.readFragmentHeader(res))
@@ -377,7 +617,7 @@
       if (res < 0)
       {
 	err << "Restore: An error occured while restoring data. Exiting... "
-	    << "res=" << res << endl;
+	    << "res= " << res << endl;
 	exitHandler(NDBT_FAILED);
       }
       
@@ -400,7 +640,7 @@
       const LogEntry * logEntry = 0;
       while ((logEntry = logIter.getNextLogEntry(res= 0)) != 0)
       {
-	if (checkSysTable(logEntry->m_table->getTableName()))
+	if (checkSysTable(logEntry->m_table))
 	  for(Uint32 i= 0; i < g_consumers.size(); i++)
 	    g_consumers[i]->logEntry(* logEntry);
       }
@@ -419,20 +659,41 @@
     {
       for(i = 0; i<metaData.getNoOfTables(); i++)
       {
-	if (checkSysTable(metaData[i]->getTableName()))
+	if (checkSysTable(metaData, i))
 	{
 	  for(Uint32 j= 0; j < g_consumers.size(); j++)
 	    if (!g_consumers[j]->finalize_table(* metaData[i]))
 	    {
-	      ndbout_c("Restore: Failed to finalize restore table: %s. "
-		       "Exiting...", 
-		       metaData[i]->getTableName());
+	      err << "Restore: Failed to finalize restore table: %s. ";
+              err << "Exiting... " << metaData[i]->getTableName() << endl;
 	      exitHandler(NDBT_FAILED);
 	    } 
 	}
       }
     }
   }
+
+  if (ga_restore_epoch)
+  {
+    for (i= 0; i < g_consumers.size(); i++)
+      if (!g_consumers[i]->update_apply_status(metaData))
+      {
+	err << "Restore: Failed to restore epoch" << endl;
+	return -1;
+      }
+  }
+
+  for(Uint32 i= 0; i < g_consumers.size(); i++) 
+  {
+    if (g_consumers[i]->has_temp_error())
+    {
+      clearConsumers();
+      ndbout_c("\nRestore successful, but encountered temporary error, "
+               "please look at configuration.");
+      return NDBT_ProgramExit(NDBT_TEMPORARY);
+    }               
+  }
+
   clearConsumers();
   return NDBT_ProgramExit(NDBT_OK);
 } // main

--- 1.39.8.1/ndb/src/kernel/vm/Configuration.cpp	2006-10-05 23:13:37 +10:00
+++ 1.51/storage/ndb/src/kernel/vm/Configuration.cpp	2006-10-05 23:13:37 +10:00
@@ -58,7 +58,8 @@
 // XXX should be my_bool ???
 static int _daemon, _no_daemon, _foreground,  _initial, _no_start;
 static int _initialstart;
-static const char* _nowait_nodes;
+static const char* _nowait_nodes = 0;
+static const char* _bind_address = 0;
 
 extern Uint32 g_start_type;
 extern NdbNodeBitmask g_nowait_nodes;
@@ -100,6 +101,10 @@
     "Perform initial start",
     (gptr*) &_initialstart, (gptr*) &_initialstart, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "bind-address", OPT_NOWAIT_NODES, 
+    "Local bind address",
+    (gptr*) &_bind_address, (gptr*) &_bind_address, 0,
+    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 static void short_usage_sub(void)
@@ -260,7 +265,9 @@
 
   m_mgmd_port= 0;
   m_config_retriever= new ConfigRetriever(getConnectString(),
-					  NDB_VERSION, NODE_TYPE_DB);
+					  NDB_VERSION, 
+					  NODE_TYPE_DB,
+					  _bind_address);
 
   if (m_config_retriever->hasError())
   {
@@ -662,13 +669,9 @@
     case NODE_TYPE_API:
       noOfAPINodes++; // No of API processes
       break;
-    case NODE_TYPE_REP:
-      break;
     case NODE_TYPE_MGM:
       noOfMGMNodes++; // No of MGM processes
       break;
-    case NODE_TYPE_EXT_REP:
-      break;
     default:
       BaseString::snprintf(buf, sizeof(buf), "Unknown node type: %d", nodeType);
       ERROR_SET(fatal, NDBD_EXIT_INVALID_CONFIG, msg, buf);
@@ -733,14 +736,14 @@
      */
     // Can keep 65536 pages (= 0.5 GByte)
     cfg.put(CFG_ACC_DIR_RANGE, 
-	    4 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas); 
+	    2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas); 
     
     cfg.put(CFG_ACC_DIR_ARRAY,
 	    (noOfIndexPages >> 8) + 
-	    4 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
+	    2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
     
     cfg.put(CFG_ACC_FRAGMENT,
-	    2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
+	    NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
     
     /*-----------------------------------------------------------------------*/
     // The extra operation records added are used by the scan and node 
@@ -756,14 +759,11 @@
     
     cfg.put(CFG_ACC_OVERFLOW_RECS,
 	    noOfIndexPages + 
-	    2 * NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
+	    NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
     
     cfg.put(CFG_ACC_PAGE8, 
 	    noOfIndexPages + 32);
     
-    cfg.put(CFG_ACC_ROOT_FRAG, 
-	    NO_OF_FRAG_PER_NODE * noOfAccTables* noOfReplicas);
-    
     cfg.put(CFG_ACC_TABLE, noOfAccTables);
     
     cfg.put(CFG_ACC_SCAN, noOfLocalScanRecords);
@@ -846,7 +846,7 @@
      * Tup Size Alt values
      */
     cfg.put(CFG_TUP_FRAG, 
-	    2 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
+	    NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
     
     cfg.put(CFG_TUP_OP_RECS, 
 	    noOfLocalOperations + 50);
@@ -855,14 +855,14 @@
 	    noOfDataPages);
     
     cfg.put(CFG_TUP_PAGE_RANGE, 
-	    4 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
+	    2 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas);
     
     cfg.put(CFG_TUP_TABLE, 
 	    noOfMetaTables);
     
     cfg.put(CFG_TUP_TABLE_DESC, 
-	    2 * 6 * NO_OF_FRAG_PER_NODE * noOfAttributes * noOfReplicas +
-	    2 * 10 * NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas );
+	    6 * NO_OF_FRAG_PER_NODE * noOfAttributes * noOfReplicas +
+	    10 * NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas );
     
     cfg.put(CFG_TUP_STORED_PROC,
 	    noOfLocalScanRecords);
@@ -876,7 +876,7 @@
 	    noOfMetaTables /*noOfOrderedIndexes*/);
     
     cfg.put(CFG_TUX_FRAGMENT,
-	    2 * NO_OF_FRAG_PER_NODE * noOfOrderedIndexes * noOfReplicas);
+	    NO_OF_FRAG_PER_NODE * noOfOrderedIndexes * noOfReplicas);
     
     cfg.put(CFG_TUX_ATTRIBUTE, 
 	    noOfOrderedIndexes * 4);

--- 1.44.26.1/ndb/src/mgmapi/mgmapi.cpp	2006-10-05 23:13:37 +10:00
+++ 1.73/storage/ndb/src/mgmapi/mgmapi.cpp	2006-10-05 23:13:37 +10:00
@@ -107,6 +107,7 @@
   int mgmd_version_major;
   int mgmd_version_minor;
   int mgmd_version_build;
+  char * m_bindaddress;
 };
 
 #define SET_ERROR(h, e, s) setError(h, e, __LINE__, s)
@@ -142,6 +143,12 @@
     return ret; \
   }
 
+#define DBUG_CHECK_REPLY(reply, ret) \
+  if (reply == NULL) { \
+    SET_ERROR(handle, NDB_MGM_ILLEGAL_SERVER_REPLY, ""); \
+    DBUG_RETURN(ret);                                    \
+  }
+
 /*****************************************************************************
  * Handles
  *****************************************************************************/
@@ -162,6 +169,7 @@
   h->cfg_i           = -1;
   h->errstream       = stdout;
   h->m_name          = 0;
+  h->m_bindaddress   = 0;
 
   strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
 
@@ -202,13 +210,29 @@
     handle->cfg.~LocalConfig();
     new (&(handle->cfg)) LocalConfig;
     handle->cfg.init(0, 0); /* reset the LocalConfig */
-    SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, "");
+    SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, mgmsrv ? mgmsrv : "");
     DBUG_RETURN(-1);
   }
   handle->cfg_i= -1;
   DBUG_RETURN(0);
 }
 
+extern "C"
+int
+ndb_mgm_set_bindaddress(NdbMgmHandle handle, const char * arg)
+{
+  DBUG_ENTER("ndb_mgm_set_bindaddress");
+  if (handle->m_bindaddress)
+    free(handle->m_bindaddress);
+
+  if (arg)
+    handle->m_bindaddress = strdup(arg);
+  else
+    handle->m_bindaddress = 0;
+
+  DBUG_RETURN(0);
+}
+
 /**
  * Destroy a handle
  */
@@ -235,6 +259,8 @@
 #endif
   (*handle)->cfg.~LocalConfig();
   my_free((*handle)->m_name, MYF(MY_ALLOW_ZERO_PTR));
+  if ((*handle)->m_bindaddress)
+    free((*handle)->m_bindaddress);
   my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
   * handle = 0;
   DBUG_VOID_RETURN;
@@ -427,6 +453,7 @@
   BaseString::snprintf(logname, 64, "mgmapi.log");
   handle->logfile = fopen(logname, "w");
 #endif
+  char buf[1024];
 
   /**
    * Do connect
@@ -434,6 +461,50 @@
   LocalConfig &cfg= handle->cfg;
   NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
   Uint32 i;
+  int binderror = 0;
+  SocketClient s(0, 0);
+  if (!s.init())
+  {
+    fprintf(handle->errstream, 
+	    "Unable to create socket, "
+	    "while trying to connect with connect string: %s\n",
+	    cfg.makeConnectString(buf,sizeof(buf)));
+
+    setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
+	    "Unable to create socket, "
+	    "while trying to connect with connect string: %s\n",
+	    cfg.makeConnectString(buf,sizeof(buf)));
+    DBUG_RETURN(-1);
+  }
+
+  if (handle->m_bindaddress)
+  {
+    BaseString::snprintf(buf, sizeof(buf), handle->m_bindaddress);
+    unsigned short portno = 0;
+    char * port = strchr(buf, ':');
+    if (port != 0)
+    {
+      portno = atoi(port+1);
+      * port = 0;
+    }
+    int err;
+    if ((err = s.bind(buf, portno)) != 0)
+    {
+      fprintf(handle->errstream, 
+	      "Unable to bind local address %s errno: %d, "
+	      "while trying to connect with connect string: %s\n",
+	      handle->m_bindaddress, err,
+	      cfg.makeConnectString(buf,sizeof(buf)));
+      
+      setError(handle, NDB_MGM_BIND_ADDRESS, __LINE__,
+	       "Unable to bind local address %s errno: %d, "
+	       "while trying to connect with connect string: %s\n",
+	       handle->m_bindaddress, err,
+	       cfg.makeConnectString(buf,sizeof(buf)));
+      DBUG_RETURN(-1);
+    }
+  }
+  
   while (sockfd == NDB_INVALID_SOCKET)
   {
     // do all the mgmt servers
@@ -441,8 +512,7 @@
     {
       if (cfg.ids[i].type != MgmId_TCP)
 	continue;
-      SocketClient s(cfg.ids[i].name.c_str(), cfg.ids[i].port);
-      sockfd = s.connect();
+      sockfd = s.connect(cfg.ids[i].name.c_str(), cfg.ids[i].port);
       if (sockfd != NDB_INVALID_SOCKET)
 	break;
     }
@@ -450,19 +520,17 @@
       break;
 #ifndef DBUG_OFF
     {
-      char buf[1024];
       DBUG_PRINT("info",("Unable to connect with connect string: %s",
 			 cfg.makeConnectString(buf,sizeof(buf))));
     }
 #endif
     if (verbose > 0) {
-      char buf[1024];
-      fprintf(handle->errstream, "Unable to connect with connect string: %s\n",
+      fprintf(handle->errstream, 
+	      "Unable to connect with connect string: %s\n",
 	      cfg.makeConnectString(buf,sizeof(buf)));
       verbose= -1;
     }
     if (no_retries == 0) {
-      char buf[1024];
       setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
 	       "Unable to connect with connect string: %s",
 	       cfg.makeConnectString(buf,sizeof(buf)));
@@ -1194,7 +1262,7 @@
 ndb_mgm_get_clusterlog_severity_filter(NdbMgmHandle handle) 
 {
   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_severity_filter");
-  static unsigned int enabled[(int)NDB_MGM_EVENT_SEVERITY_ALL]=
+  unsigned int enabled[(int)NDB_MGM_EVENT_SEVERITY_ALL]=
     {0,0,0,0,0,0,0};
   const ParserRow<ParserDummy> getinfo_reply[] = {
     MGM_CMD("clusterlog", NULL, ""),
@@ -1306,6 +1374,45 @@
   return 0;
 }
 
+static const char *clusterlog_names[]=
+  { "startup", "shutdown", "statistics", "checkpoint", "noderestart", "connection", "info", "warning", "error", "congestion", "debug", "backup" };
+
+extern "C"
+const unsigned int *
+ndb_mgm_get_clusterlog_loglevel(NdbMgmHandle handle)
+{
+  SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_clusterlog_loglevel");
+  int loglevel_count = CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1 ;
+  static unsigned int loglevel[CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1] = {0,0,0,0,0,0,0,0,0,0,0,0};
+  const ParserRow<ParserDummy> getloglevel_reply[] = {
+    MGM_CMD("get cluster loglevel", NULL, ""),
+    MGM_ARG(clusterlog_names[0], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[1], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[2], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[3], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[4], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[5], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[6], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[7], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[8], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[9], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[10], Int, Mandatory, ""),
+    MGM_ARG(clusterlog_names[11], Int, Mandatory, ""),
+  };
+  CHECK_HANDLE(handle, NULL);
+  CHECK_CONNECTED(handle, NULL);
+
+  Properties args;
+  const Properties *reply;
+  reply = ndb_mgm_call(handle, getloglevel_reply, "get cluster loglevel", &args);
+  CHECK_REPLY(reply, NULL);
+
+  for(int i=0; i < loglevel_count; i++) {
+    reply->get(clusterlog_names[i], &loglevel[i]);
+  }
+  return loglevel;
+}
+
 extern "C"
 int 
 ndb_mgm_set_clusterlog_loglevel(NdbMgmHandle handle, int nodeId,
@@ -1443,34 +1550,7 @@
 
 extern "C"
 int 
-ndb_mgm_get_stat_port(NdbMgmHandle handle, struct ndb_mgm_reply* /*reply*/)
-{
-  SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_get_stat_port");
-  const ParserRow<ParserDummy> stat_reply[] = {
-    MGM_CMD("error", NULL, ""),
-    MGM_ARG("result", String, Mandatory, "Error message"),
-    MGM_CMD("get statport reply", NULL, ""),
-    MGM_ARG("tcpport", Int, Mandatory, "TCP port for statistics"),
-    MGM_END()
-  };
-  CHECK_HANDLE(handle, -1);
-  CHECK_CONNECTED(handle, -1);
-  
-  Properties args;
-  const Properties *reply;
-  reply = ndb_mgm_call(handle, stat_reply, "get statport", &args);
-  CHECK_REPLY(reply, -1);
-
-  Uint32 port;
-  reply->get("tcpport", &port);
-
-  delete reply;
-  return port;
-}
-
-extern "C"
-int 
-ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, int* _args,
+ndb_mgm_dump_state(NdbMgmHandle handle, int nodeId, const int * _args,
 		   int _num_args, struct ndb_mgm_reply* /* reply */) 
 {
   SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_dump_state");
@@ -2319,9 +2399,9 @@
 				     int param,
 				     int value,
 				     struct ndb_mgm_reply* mgmreply){
-  DBUG_ENTER("ndb_mgm_set_connection_int_parameter");
   CHECK_HANDLE(handle, 0);
   CHECK_CONNECTED(handle, 0);
+  DBUG_ENTER("ndb_mgm_set_connection_int_parameter");
   
   Properties args;
   args.put("node1", node1);
@@ -2338,7 +2418,7 @@
   
   const Properties *prop;
   prop= ndb_mgm_call(handle, reply, "set connection parameter", &args);
-  CHECK_REPLY(prop, -1);
+  DBUG_CHECK_REPLY(prop, -1);
 
   int res= -1;
   do {
@@ -2362,9 +2442,9 @@
 				     int param,
 				     int *value,
 				     struct ndb_mgm_reply* mgmreply){
-  DBUG_ENTER("ndb_mgm_get_connection_int_parameter");
   CHECK_HANDLE(handle, -1);
   CHECK_CONNECTED(handle, -2);
+  DBUG_ENTER("ndb_mgm_get_connection_int_parameter");
   
   Properties args;
   args.put("node1", node1);
@@ -2380,7 +2460,7 @@
   
   const Properties *prop;
   prop = ndb_mgm_call(handle, reply, "get connection parameter", &args);
-  CHECK_REPLY(prop, -3);
+  DBUG_CHECK_REPLY(prop, -3);
 
   int res= -1;
   do {
@@ -2428,9 +2508,9 @@
 {
   Uint32 nodeid=0;
 
-  DBUG_ENTER("ndb_mgm_get_mgmd_nodeid");
   CHECK_HANDLE(handle, 0);
   CHECK_CONNECTED(handle, 0);
+  DBUG_ENTER("ndb_mgm_get_mgmd_nodeid");
   
   Properties args;
 
@@ -2442,7 +2522,7 @@
   
   const Properties *prop;
   prop = ndb_mgm_call(handle, reply, "get mgmd nodeid", &args);
-  CHECK_REPLY(prop, 0);
+  DBUG_CHECK_REPLY(prop, 0);
 
   if(!prop->get("nodeid",&nodeid)){
     fprintf(handle->errstream, "Unable to get value\n");
@@ -2456,9 +2536,9 @@
 extern "C"
 int ndb_mgm_report_event(NdbMgmHandle handle, Uint32 *data, Uint32 length)
 {
-  DBUG_ENTER("ndb_mgm_report_event");
   CHECK_HANDLE(handle, 0);
   CHECK_CONNECTED(handle, 0);
+  DBUG_ENTER("ndb_mgm_report_event");
 
   Properties args;
   args.put("length", length);
@@ -2477,7 +2557,7 @@
   
   const Properties *prop;
   prop = ndb_mgm_call(handle, reply, "report event", &args);
-  CHECK_REPLY(prop, -1);
+  DBUG_CHECK_REPLY(prop, -1);
 
   DBUG_RETURN(0);
 }
@@ -2485,9 +2565,9 @@
 extern "C"
 int ndb_mgm_end_session(NdbMgmHandle handle)
 {
-  DBUG_ENTER("ndb_mgm_end_session");
   CHECK_HANDLE(handle, 0);
   CHECK_CONNECTED(handle, 0);
+  DBUG_ENTER("ndb_mgm_end_session");
 
   SocketOutputStream s_output(handle->socket);
   s_output.println("end session");

--- 1.20.4.1/ndb/src/mgmclient/main.cpp	2006-10-05 23:13:38 +10:00
+++ 1.26/storage/ndb/src/mgmclient/main.cpp	2006-10-05 23:13:38 +10:00
@@ -19,7 +19,7 @@
 
 // copied from mysql.cc to get readline
 extern "C" {
-#if defined( __WIN__) || defined(OS2)
+#if defined( __WIN__)
 #include <conio.h>
 #elif !defined(__NETWARE__)
 #include <readline/readline.h>
@@ -124,7 +124,7 @@
     line_read= strdup(linebuffer);
   }
 #endif
-  return com->execute(line_read,_try_reconnect);
+  return com->execute(line_read, _try_reconnect, 1);
 }
 
 int main(int argc, char** argv){
@@ -165,7 +165,7 @@
   }
   else
   {
-    com->execute(opt_execute_str,_try_reconnect, &ret);
+    com->execute(opt_execute_str,_try_reconnect, 0, &ret);
   }
   delete com;
 

--- 1.45.30.1/ndb/src/mgmsrv/Services.cpp	2006-10-05 23:13:38 +10:00
+++ 1.75/storage/ndb/src/mgmsrv/Services.cpp	2006-10-05 23:13:38 +10:00
@@ -33,6 +33,7 @@
 #include "../mgmapi/ndb_logevent.hpp"
 
 #include <base64.h>
+#include <ndberror.h>
 
 extern bool g_StopServer;
 extern bool g_RestartServer;
@@ -122,8 +123,6 @@
 
 const
 ParserRow<MgmApiSession> commands[] = {
-  MGM_CMD("get statport", &MgmApiSession::getStatPort, ""),
-  
   MGM_CMD("get config", &MgmApiSession::getConfig, ""),
     MGM_ARG("version", Int, Mandatory, "Configuration version number"),
     MGM_ARG("node", Int, Optional, "Node ID"),
@@ -146,6 +145,7 @@
   MGM_CMD("get status", &MgmApiSession::getStatus, ""),
 
   MGM_CMD("get info clusterlog", &MgmApiSession::getInfoClusterLog, ""),
+  MGM_CMD("get cluster loglevel", &MgmApiSession::getClusterLogLevel, ""),
 
   MGM_CMD("restart node", &MgmApiSession::restart_v1, ""),
     MGM_ARG("node", String, Mandatory, "Nodes to restart"),
@@ -527,7 +527,8 @@
     NDB_TICKS tick= 0;
     /* only report error on second attempt as not to clog the cluster log */
     while (!m_mgmsrv.alloc_node_id(&tmp, (enum ndb_mgm_node_type)nodetype, 
-                                   (struct sockaddr*)&addr, &addrlen, error_code, error_string,
+                                   (struct sockaddr*)&addr, &addrlen,
+                                   error_code, error_string,
                                    tick == 0 ? 0 : log_event))
     {
       /* NDB_MGM_ALLOCID_CONFIG_MISMATCH is a non retriable error */
@@ -691,15 +692,6 @@
 }
 
 void
-MgmApiSession::getStatPort(Parser_t::Context &, 
-			   const class Properties &) {
-
-  m_output->println("get statport reply");
-  m_output->println("tcpport: %d", 0);
-  m_output->println("");
-}
-
-void
 MgmApiSession::insertError(Parser<MgmApiSession>::Context &,
 			   Properties const &args) {
   Uint32 node = 0, error = 0;
@@ -828,6 +820,32 @@
 }
 
 void
+MgmApiSession::getClusterLogLevel(Parser<MgmApiSession>::Context &			, Properties const &) {
+  const char* names[] = { "startup",
+			  "shutdown", 
+			  "statistics", 
+			  "checkpoint", 
+			  "noderestart", 
+			  "connection", 
+			  "info", 
+			  "warning", 
+			  "error", 
+			  "congestion", 
+			  "debug", 
+			  "backup" };
+
+  int loglevel_count = (CFG_MAX_LOGLEVEL - CFG_MIN_LOGLEVEL + 1) ;
+  LogLevel::EventCategory category;
+
+  m_output->println("get cluster loglevel");
+  for(int i = 0; i < loglevel_count; i++) {
+    category = (LogLevel::EventCategory) i;
+    m_output->println("%s: %d", names[i], m_mgmsrv.m_event_listner[0].m_logLevel.getLogLevel(category));
+  }
+  m_output->println("");
+}
+
+void
 MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
 				  Properties const &args) {
   const char *reply= "set cluster loglevel reply";
@@ -1350,6 +1368,12 @@
     if (ndb_logevent_body[i].index_fn)
       val= (*(ndb_logevent_body[i].index_fn))(val);
     str.appfmt("%s=%d\n",ndb_logevent_body[i].token, val);
+    if(strcmp(ndb_logevent_body[i].token,"error") == 0)
+    {
+      int m_text_len= strlen(m_text);
+      snprintf(m_text+m_text_len, 4 , " - ");
+      ndb_error_string(theData[3], m_text+(m_text_len+3), sizeof(m_text)-m_text_len-3);
+    }
   }
 
   Vector<NDB_SOCKET_TYPE> copy;

--- 1.13.7.1/ndb/src/mgmsrv/Services.hpp	2006-10-05 23:13:38 +10:00
+++ 1.23/storage/ndb/src/mgmsrv/Services.hpp	2006-10-05 23:13:38 +10:00
@@ -61,7 +61,6 @@
   virtual ~MgmApiSession();
   void runSession();
 
-  void getStatPort(Parser_t::Context &ctx, const class Properties &args);
   void getConfig(Parser_t::Context &ctx, const class Properties &args);
 #ifdef MGM_GET_CONFIG_BACKWARDS_COMPAT
   void getConfig_old(Parser_t::Context &ctx);
@@ -94,6 +93,8 @@
   void bye(Parser_t::Context &ctx, const class Properties &args);
   void endSession(Parser_t::Context &ctx, const class Properties &args);
   void setLogLevel(Parser_t::Context &ctx, const class Properties &args);
+  void getClusterLogLevel(Parser_t::Context &ctx, 
+			  const class Properties &args);
   void setClusterLogLevel(Parser_t::Context &ctx, 
 			  const class Properties &args);
   void setLogFilter(Parser_t::Context &ctx, const class Properties &args);

--- 1.41.7.1/ndb/src/mgmsrv/main.cpp	2006-10-05 23:13:38 +10:00
+++ 1.50/storage/ndb/src/mgmsrv/main.cpp	2006-10-05 23:13:38 +10:00
@@ -51,7 +51,7 @@
 
 // copied from mysql.cc to get readline
 extern "C" {
-#if defined( __WIN__) || defined(OS2)
+#if defined( __WIN__)
 #include <conio.h>
 #elif !defined(__NETWARE__)
 #include <readline/readline.h>

--- 1.43.9.1/ndb/src/ndbapi/NdbTransaction.cpp	2006-10-05 23:13:38 +10:00
+++ 1.60/storage/ndb/src/ndbapi/NdbTransaction.cpp	2006-10-05 23:13:38 +10:00
@@ -62,6 +62,7 @@
   theTCConPtr(0),
   theTransactionId(0),
   theGlobalCheckpointId(0),
+  p_latest_trans_gci(0),
   theStatus(NotConnected),
   theCompletionStatus(NotCompleted), 
   theCommitStatus(NotStarted),
@@ -127,6 +128,8 @@
   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;
@@ -434,7 +437,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){
@@ -706,7 +709,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(); 
@@ -812,7 +815,7 @@
  *************************************************************************/
     NdbApiSignal tSignal(tNdb->theMyRef);
     Uint32 tTransId1, tTransId2;
-    TransporterFacade *tp = TransporterFacade::instance();
+    TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
     int	  tReturnCode;
 
     tTransId1 = (Uint32) theTransactionId;
@@ -859,7 +862,7 @@
 {
   NdbApiSignal tSignal(theNdb->theMyRef);
   Uint32 tTransId1, tTransId2;
-  TransporterFacade *tp = TransporterFacade::instance(); 
+  TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
   int	  tReturnCode;
 
   tTransId1 = (Uint32) theTransactionId;
@@ -970,7 +973,7 @@
 }//NdbTransaction::releaseScanOperations()
 
 /*****************************************************************************
-void releaseExecutedScanOperation();
+void releaseScanOperation();
 
 Remark:         Release scan op when hupp'ed trans closed (save memory)
 ******************************************************************************/
@@ -978,27 +981,58 @@
 NdbTransaction::releaseExecutedScanOperation(NdbIndexScanOperation* cursorOp)
 {
   DBUG_ENTER("NdbTransaction::releaseExecutedScanOperation");
-  DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp))
+  DBUG_PRINT("enter", ("this=0x%x op=0x%x", (UintPtr)this, (UintPtr)cursorOp));
+  
+  releaseScanOperation(&m_firstExecutedScanOp, 0, cursorOp);
+  
+  DBUG_VOID_RETURN;
+}//NdbTransaction::releaseExecutedScanOperation()
 
-  // here is one reason to make op lists doubly linked
-  if (m_firstExecutedScanOp == cursorOp) {
-    m_firstExecutedScanOp = (NdbIndexScanOperation*)cursorOp->theNext;
-    cursorOp->release();
-    theNdb->releaseScanOperation(cursorOp);
-  } else if (m_firstExecutedScanOp != NULL) {
-    NdbIndexScanOperation* tOp = m_firstExecutedScanOp;
-    while (tOp->theNext != NULL) {
-      if (tOp->theNext == cursorOp) {
-        tOp->theNext = cursorOp->theNext;
-        cursorOp->release();
-        theNdb->releaseScanOperation(cursorOp);
-        break;
+bool
+NdbTransaction::releaseScanOperation(NdbIndexScanOperation** listhead,
+				     NdbIndexScanOperation** listtail,
+				     NdbIndexScanOperation* op)
+{
+  if (* listhead == op)
+  {
+    * listhead = (NdbIndexScanOperation*)op->theNext;
+    if (listtail && *listtail == op)
+    {
+      assert(* listhead == 0);
+      * listtail = 0;
+    }
+      
+  }
+  else
+  {
+    NdbIndexScanOperation* tmp = * listhead;
+    while (tmp != NULL)
+    {
+      if (tmp->theNext == op)
+      {
+	tmp->theNext = (NdbIndexScanOperation*)op->theNext;
+	if (listtail && *listtail == op)
+	{
+	  assert(op->theNext == 0);
+	  *listtail = tmp;
+	}
+	break;
       }
-      tOp = (NdbIndexScanOperation*)tOp->theNext;
+      tmp = (NdbIndexScanOperation*)tmp->theNext;
     }
+    if (tmp == NULL)
+      op = NULL;
   }
-  DBUG_VOID_RETURN;
-}//NdbTransaction::releaseExecutedScanOperation()
+  
+  if (op != NULL)
+  {
+    op->release();
+    theNdb->releaseScanOperation(op);
+    return true;
+  }
+  
+  return false;
+}
 
 /*****************************************************************************
 NdbOperation* getNdbOperation(const char* aTableName);
@@ -1546,6 +1580,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
@@ -1724,6 +1761,8 @@
     if (tCommitFlag == 1) {
       theCommitStatus = Committed;
       theGlobalCheckpointId = tGCI;
+      assert(tGCI);
+      *p_latest_trans_gci = tGCI;
     } else if ((tNoComp >= tNoSent) &&
                (theLastExecOpInList->theCommitIndicator == 1)){
 
@@ -1900,6 +1939,8 @@
     if (tCommitFlag == 1) {
       theCommitStatus = Committed;
       theGlobalCheckpointId = tGCI;
+      assert(tGCI);
+      *p_latest_trans_gci = tGCI;
     } else if ((tNoComp >= tNoSent) &&
                (theLastExecOpInList->theCommitIndicator == 1)){
       /**********************************************************************/

--- 1.16.3.1/ndb/tools/delete_all.cpp	2006-10-05 23:13:38 +10:00
+++ 1.22/storage/ndb/tools/delete_all.cpp	2006-10-05 23:13:38 +10:00
@@ -31,6 +31,8 @@
 
 static const char* _dbname = "TEST_DB";
 static my_bool _transactional = false;
+static my_bool _tupscan = 0;
+static my_bool _diskscan = 0;
 static struct my_option my_long_options[] =
 {
   NDB_STD_OPTS("ndb_desc"),
@@ -40,6 +42,12 @@
   { "transactional", 't', "Single transaction (may run out of operations)",
     (gptr*) &_transactional, (gptr*) &_transactional, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "tupscan", 999, "Run tupscan",
+    (gptr*) &_tupscan, (gptr*) &_tupscan, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+  { "diskscan", 999, "Run diskcan",
+    (gptr*) &_diskscan, (gptr*) &_diskscan, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 static void usage()
@@ -142,7 +150,11 @@
       goto failed;
     }
     
-    if( pOp->readTuples(NdbOperation::LM_Exclusive,par) ) {
+    int flags = 0;
+    flags |= _tupscan ? NdbScanOperation::SF_TupScan : 0;
+    flags |= _diskscan ? NdbScanOperation::SF_DiskScan : 0;
+    if( pOp->readTuples(NdbOperation::LM_Exclusive, 
+			flags, par) ) {
       goto failed;
     }
     

--- 1.18.2.1/ndb/tools/desc.cpp	2006-10-05 23:13:38 +10:00
+++ 1.26/storage/ndb/tools/desc.cpp	2006-10-05 23:13:38 +10:00
@@ -18,6 +18,14 @@
 #include <ndb_opts.h>
 #include <NDBT.hpp>
 #include <NdbApi.hpp>
+#include <NdbSleep.h>
+
+void desc_AutoGrowSpecification(struct NdbDictionary::AutoGrowSpecification ags);
+int desc_logfilegroup(Ndb *myndb, char* name);
+int desc_undofile(Ndb_cluster_connection &con, Ndb *myndb, char* name);
+int desc_datafile(Ndb_cluster_connection &con, Ndb *myndb, char* name);
+int desc_tablespace(Ndb *myndb,char* name);
+int desc_table(Ndb *myndb,char* name);
 
 NDB_STD_OPTS_VARS;
 
@@ -27,6 +35,7 @@
 
 const char *load_default_groups[]= { "mysql_cluster",0 };
 
+static int _retries = 0;
 static struct my_option my_long_options[] =
 {
   NDB_STD_OPTS("ndb_desc"),
@@ -39,6 +48,9 @@
   { "extra-partition-info", 'p', "Print more info per partition",
     (gptr*) &_partinfo, (gptr*) &_partinfo, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
+  { "retries", 'r', "Retry every second for # retries",
+    (gptr*) &_retries, (gptr*) &_retries, 0,
+    GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, 
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 static void usage()
@@ -84,54 +96,192 @@
     ERR(MyNdb.getNdbError());
     return NDBT_ProgramExit(NDBT_FAILED);
   }
-  
-  const NdbDictionary::Dictionary * dict= MyNdb.getDictionary();
-  for (int i = 0; i < argc; i++) {
-    NDBT_Table* pTab = (NDBT_Table*)dict->getTable(argv[i]);
-    if (pTab != 0){
-      ndbout << (* pTab) << endl;
-
-      NdbDictionary::Dictionary::List list;
-      if (dict->listIndexes(list, argv[i]) != 0){
-	ndbout << argv[i] << ": " << dict->getNdbError() << endl;
-	return NDBT_ProgramExit(NDBT_FAILED);
-      }
-        
-      ndbout << "-- Indexes -- " << endl;
-      ndbout << "PRIMARY KEY(";
-      unsigned j;
-      for (j= 0; (int)j < pTab->getNoOfPrimaryKeys(); j++)
-      {
-	const NdbDictionary::Column * col = pTab->getColumn(pTab->getPrimaryKey(j));
-	ndbout << col->getName();
-	if ((int)j < pTab->getNoOfPrimaryKeys()-1)
-	  ndbout << ", ";       
-      }
-      ndbout << ") - UniqueHashIndex" << endl;
-	
-      for (j= 0; j < list.count; j++) {
-	NdbDictionary::Dictionary::List::Element& elt = list.elements[j];
-	const NdbDictionary::Index *pIdx = dict->getIndex(elt.name, argv[i]);
-	if (!pIdx){
-	  ndbout << argv[i] << ": " << dict->getNdbError() << endl;
-	  return NDBT_ProgramExit(NDBT_FAILED);
-	}
-	  
-	ndbout << (*pIdx) << endl;
-      }
-
-      ndbout << endl;
-      
-      if (_partinfo)
-	print_part_info(&MyNdb, pTab);
-    }
+
+  NdbDictionary::Dictionary * dict= MyNdb.getDictionary();
+  for(int i= 0; i<argc;i++)
+  {
+    if(desc_table(&MyNdb,argv[i]))
+      ;
+    else if(desc_tablespace(&MyNdb,argv[i]))
+      ;
+    else if(desc_logfilegroup(&MyNdb,argv[i]))
+      ;
+    else if(desc_datafile(con, &MyNdb, argv[i]))
+      ;
+    else if(desc_undofile(con, &MyNdb, argv[i]))
+      ;
     else
-      ndbout << argv[i] << ": " << dict->getNdbError() << endl;
+      ndbout << "No such object: " << argv[i] << endl << endl;
   }
-  
+
   return NDBT_ProgramExit(NDBT_OK);
 }
 
+void desc_AutoGrowSpecification(struct NdbDictionary::AutoGrowSpecification ags)
+{
+  ndbout << "AutoGrow.min_free: " << ags.min_free << endl;
+  ndbout << "AutoGrow.max_size: " << ags.max_size << endl;
+  ndbout << "AutoGrow.file_size: " << ags.file_size << endl;
+  ndbout << "AutoGrow.filename_pattern: " << ags.filename_pattern << endl;
+}
+
+int desc_logfilegroup(Ndb *myndb, char* name)
+{
+  NdbDictionary::Dictionary *dict= myndb->getDictionary();
+  assert(dict);
+  NdbDictionary::LogfileGroup lfg= dict->getLogfileGroup(name);
+  NdbError err= dict->getNdbError();
+  if(err.classification!=ndberror_cl_none)
+    return 0;
+
+  ndbout << "Type: LogfileGroup" << endl;
+  ndbout << "Name: " << lfg.getName() << endl;
+  ndbout << "UndoBuffer size: " << lfg.getUndoBufferSize() << endl;
+  ndbout << "Version: " << lfg.getObjectVersion() << endl;
+  ndbout << "Free Words: " << lfg.getUndoFreeWords() << endl;
+
+  desc_AutoGrowSpecification(lfg.getAutoGrowSpecification());
+
+  ndbout << endl;
+
+  return 1;
+}
+
+int desc_tablespace(Ndb *myndb, char* name)
+{
+  NdbDictionary::Dictionary *dict= myndb->getDictionary();
+  assert(dict);
+  NdbDictionary::Tablespace ts= dict->getTablespace(name);
+  NdbError err= dict->getNdbError();
+  if(err.classification!=ndberror_cl_none)
+    return 0;
+
+  ndbout << "Type: Tablespace" << endl;
+  ndbout << "Name: " << ts.getName() << endl;
+  ndbout << "Object Version: " << ts.getObjectVersion() << endl;
+  ndbout << "Extent Size: " << ts.getExtentSize() << endl;
+  ndbout << "Default Logfile Group: " << ts.getDefaultLogfileGroup() << endl;
+  ndbout << endl;
+  return 1;
+}
+
+int desc_undofile(Ndb_cluster_connection &con, Ndb *myndb, char* name)
+{
+  unsigned id;
+  NdbDictionary::Dictionary *dict= myndb->getDictionary();
+  Ndb_cluster_connection_node_iter iter;
+
+  assert(dict);
+
+  con.init_get_next_node(iter);
+
+  while(id= con.get_next_node(iter))
+  {
+    NdbDictionary::Undofile uf= dict->getUndofile(0, name);
+    NdbError err= dict->getNdbError();
+    if(err.classification!=ndberror_cl_none)
+      return 0;
+
+    ndbout << "Type: Undofile" << endl;
+    ndbout << "Name: " << name << endl;
+    ndbout << "Node: " << id << endl;
+    ndbout << "Path: " << uf.getPath() << endl;
+    ndbout << "Size: " << uf.getSize() << endl;
+
+    ndbout << "Logfile Group: " << uf.getLogfileGroup() << endl;
+
+    /** FIXME: are these needed, the functions aren't there
+	but the prototypes are...
+
+	ndbout << "Number: " << uf.getFileNo() << endl;
+    */
+
+    ndbout << endl;
+  }
+
+  return 1;
+}
+
+int desc_datafile(Ndb_cluster_connection &con, Ndb *myndb, char* name)
+{
+  unsigned id;
+  NdbDictionary::Dictionary *dict= myndb->getDictionary();
+  assert(dict);
+  Ndb_cluster_connection_node_iter iter;
+
+  con.init_get_next_node(iter);
+
+  while(id= con.get_next_node(iter))
+  {
+    NdbDictionary::Datafile df= dict->getDatafile(id, name);
+    NdbError err= dict->getNdbError();
+    if(err.classification!=ndberror_cl_none)
+      return 0;
+
+    ndbout << "Type: Datafile" << endl;
+    ndbout << "Name: " << name << endl;
+    ndbout << "Node: " << id << endl;
+    ndbout << "Path: " << df.getPath() << endl;
+    ndbout << "Size: " << df.getSize() << endl;
+    ndbout << "Free: " << df.getFree() << endl;
+
+    ndbout << "Tablespace: " << df.getTablespace() << endl;
+
+    /** We probably don't need to display this ever...
+	ndbout << "Number: " << uf.getFileNo() << endl;
+    */
+
+    ndbout << endl;
+  }
+
+  return 1;
+}
+
+int desc_table(Ndb *myndb, char* name)
+{
+  NdbDictionary::Dictionary * dict= myndb->getDictionary();
+  NDBT_Table* pTab;
+  while ((pTab = (NDBT_Table*)dict->getTable(name)) == NULL && --_retries >= 0) NdbSleep_SecSleep(1);
+  if (!pTab)
+    return 0;
+
+  ndbout << (* pTab) << endl;
+
+  NdbDictionary::Dictionary::List list;
+  if (dict->listIndexes(list, name) != 0){
+    ndbout << name << ": " << dict->getNdbError() << endl;
+    return NDBT_ProgramExit(NDBT_FAILED);
+  }
+
+  ndbout << "-- Indexes -- " << endl;
+  ndbout << "PRIMARY KEY(";
+  unsigned j;
+  for (j= 0; (int)j < pTab->getNoOfPrimaryKeys(); j++)
+  {
+    const NdbDictionary::Column * col= pTab->getColumn(pTab->getPrimaryKey(j));
+    ndbout << col->getName();
+    if ((int)j < pTab->getNoOfPrimaryKeys()-1)
+      ndbout << ", ";
+  }
+  ndbout << ") - UniqueHashIndex" << endl;
+  for (j= 0; j < list.count; j++) {
+    NdbDictionary::Dictionary::List::Element& elt = list.elements[j];
+    const NdbDictionary::Index *pIdx = dict->getIndex(elt.name, name);
+    if (!pIdx){
+      ndbout << name << ": " << dict->getNdbError() << endl;
+      return NDBT_ProgramExit(NDBT_FAILED);
+    }
+
+    ndbout << (*pIdx) << endl;
+  }
+  ndbout << endl;
+
+  if (_partinfo)
+    print_part_info(myndb, pTab);
+	
+  return 1;
+}
+
 struct InfoInfo
 {
   const char * m_title;
@@ -147,7 +297,8 @@
     { "Partition", 0, NdbDictionary::Column::FRAGMENT },
     { "Row count", 0, NdbDictionary::Column::ROW_COUNT },
     { "Commit count", 0, NdbDictionary::Column::COMMIT_COUNT },
-    { "Frag memory", 0, NdbDictionary::Column::FRAGMENT_MEMORY },
+    { "Frag fixed memory", 0, NdbDictionary::Column::FRAGMENT_FIXED_MEMORY },
+    { "Frag varsized memory", 0, NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY },
     { 0, 0, 0 }
   };
 

--- 1.20.3.1/ndb/tools/listTables.cpp	2006-10-05 23:13:38 +10:00
+++ 1.29/storage/ndb/tools/listTables.cpp	2006-10-05 23:13:38 +10:00
@@ -31,6 +31,8 @@
 static Ndb* ndb = 0;
 static const NdbDictionary::Dictionary * dic = 0;
 static int _unqualified = 0;
+static int _parsable = 0;
+static int show_temp_status = 0;
 
 const char *load_default_groups[]= { "mysql_cluster",0 };
 
@@ -78,10 +80,23 @@
 	if (dic->listIndexes(list, tabname) == -1)
 	    fatal_dict("listIndexes");
     }
-    if (ndb->usingFullyQualifiedNames())
-       ndbout_c("%-5s %-20s %-8s %-7s %-12s %-8s %s", "id", "type", "state", "logging", "database", "schema", "name");
-     else
-       ndbout_c("%-5s %-20s %-8s %-7s %s", "id", "type", "state", "logging", "name");
+    if (!_parsable)
+    {
+      if (ndb->usingFullyQualifiedNames())
+      {
+        if (show_temp_status)
+          ndbout_c("%-5s %-20s %-8s %-7s %-4s %-12s %-8s %s", "id", "type", "state", "logging", "temp", "database", "schema", "name");
+        else
+          ndbout_c("%-5s %-20s %-8s %-7s %-12s %-8s %s", "id", "type", "state", "logging", "database", "schema", "name");
+      }
+      else
+      {
+        if (show_temp_status)
+          ndbout_c("%-5s %-20s %-8s %-7s %-4s %s", "id", "type", "state", "logging", "temp", "name");
+        else
+          ndbout_c("%-5s %-20s %-8s %-7s %s", "id", "type", "state", "logging", "name");
+      }
+    }
     for (unsigned i = 0; i < list.count; i++) {
 	NdbDictionary::Dictionary::List::Element& elt = list.elements[i];
         char type[100];
@@ -115,8 +130,20 @@
         case NdbDictionary::Object::ReadOnlyConstraint:
             strcpy(type, "ReadOnlyConstraint");
             break;
+	case NdbDictionary::Object::Tablespace:
+	  strcpy(type, "Tablespace");
+	  break;
+	case NdbDictionary::Object::LogfileGroup:
+	  strcpy(type, "LogfileGroup");
+	  break;
+	case NdbDictionary::Object::Datafile:
+	  strcpy(type, "Datafile");
+	  break;
+	case NdbDictionary::Object::Undofile:
+	  strcpy(type, "Undofile");
+	  break;
         default:
-            sprintf(type, "%d", (int)elt.type);
+	  sprintf(type, "%d", (int)elt.type);
             break;
         }
         char state[100];
@@ -148,22 +175,73 @@
 	    strcpy(store, "-");
 	else {
 	    switch (elt.store) {
-	    case NdbDictionary::Object::StoreTemporary:
+	    case NdbDictionary::Object::StoreNotLogged:
 		strcpy(store, "No");
 		break;
 	    case NdbDictionary::Object::StorePermanent:
 		strcpy(store, "Yes");
 		break;
 	    default:
-		sprintf(state, "%d", (int)elt.store);
+		sprintf(store, "%d", (int)elt.store);
 		break;
 	    }
 	}
+        char temp[100];
+        if (show_temp_status)
+        {
+          if (! isTable)
+              strcpy(temp, "-");
+          else {
+              switch (elt.temp) {
+              case NDB_TEMP_TAB_PERMANENT:
+                  strcpy(temp, "No");
+                  break;
+              case NDB_TEMP_TAB_TEMPORARY:
+                  strcpy(temp, "Yes");
+                  break;
+              default:
+                  sprintf(temp, "%d", (int)elt.temp);
+                  break;
+              }
+          }
+        }
 	if (ndb->usingFullyQualifiedNames())
-	  ndbout_c("%-5d %-20s %-8s %-7s %-12s %-8s %s", elt.id, type, state, store, (elt.database)?elt.database:"", (elt.schema)?elt.schema:"", elt.name);
-       else
-	 ndbout_c("%-5d %-20s %-8s %-7s %s", elt.id, type, state, store, elt.name);
+        {
+          if (_parsable)
+          {
+            if (show_temp_status)
+              ndbout_c("%d\t'%s'\t'%s'\t'%s'\t'%s'\t'%s'\t'%s'\t'%s'", elt.id, type, state, store, temp, (elt.database)?elt.database:"", (elt.schema)?elt.schema:"", elt.name);
+            else
+              ndbout_c("%d\t'%s'\t'%s'\t'%s'\t'%s'\t'%s'\t'%s'", elt.id, type, state, store, (elt.database)?elt.database:"", (elt.schema)?elt.schema:"", elt.name);
+          }
+          else
+          {
+            if (show_temp_status)
+              ndbout_c("%-5d %-20s %-8s %-7s %-4s %-12s %-8s %s", elt.id, type, state, store, temp, (elt.database)?elt.database:"", (elt.schema)?elt.schema:"", elt.name);
+            else
+              ndbout_c("%-5d %-20s %-8s %-7s %-12s %-8s %s", elt.id, type, state, store, (elt.database)?elt.database:"", (elt.schema)?elt.schema:"", elt.name);
+          }
+        }
+        else
+        {
+          if (_parsable)
+          {
+            if (show_temp_status)
+              ndbout_c("%d\t'%s'\t'%s'\t'%s'\t'%s'\t'%s'", elt.id, type, state, store, temp, elt.name);
+            else
+              ndbout_c("%d\t'%s'\t'%s'\t'%s'\t'%s'", elt.id, type, state, store, elt.name);
+          }
+          else
+          {
+            if (show_temp_status)
+              ndbout_c("%-5d %-20s %-8s %-7s %-4s %s", elt.id, type, state, store, temp, elt.name);
+            else
+              ndbout_c("%-5d %-20s %-8s %-7s %s", elt.id, type, state, store, elt.name);
+          }
+        }
     }
+    if (_parsable)
+      exit(0);
 }
 
 NDB_STD_OPTS_VARS;
@@ -171,6 +249,10 @@
 static const char* _dbname = "TEST_DB";
 static int _loops;
 static int _type;
+enum options_ndb_show_tables
+{
+  OPT_SHOW_TMP_STATUS=256
+};
 static struct my_option my_long_options[] =
 {
   NDB_STD_OPTS("ndb_show_tables"),
@@ -186,6 +268,12 @@
   { "unqualified", 'u', "Use unqualified table names",
     (gptr*) &_unqualified, (gptr*) &_unqualified, 0,
     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
+  { "parsable", 'p', "Return output suitable for mysql LOAD DATA INFILE",
+    (gptr*) &_parsable, (gptr*) &_parsable, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
+  { "show-temp-status", OPT_SHOW_TMP_STATUS, "Show table temporary flag",
+    (gptr*) &show_temp_status, (gptr*) &show_temp_status, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 static void usage()

--- 1.22.1.1/ndb/tools/select_all.cpp	2006-10-05 23:13:38 +10:00
+++ 1.26/storage/ndb/tools/select_all.cpp	2006-10-05 23:13:38 +10:00
@@ -45,6 +45,12 @@
 
 const char *load_default_groups[]= { "mysql_cluster",0 };
 
+static int _tup = 0;
+static int _dumpDisk = 0;
+static int use_rowid = 0;
+static int nodata = 0;
+static int use_gci = 0;
+
 static struct my_option my_long_options[] =
 {
   NDB_STD_OPTS("ndb_desc"),
@@ -72,6 +78,21 @@
   { "delimiter", 'D', "Column delimiter",
     (gptr*) &_delimiter, (gptr*) &_delimiter, 0,
     GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+  { "disk", 256, "Dump disk ref",
+    (gptr*) &_dumpDisk, (gptr*) &_dumpDisk, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
+  { "rowid", 256, "Dump rowid",
+    (gptr*) &use_rowid, (gptr*) &use_rowid, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
+  { "gci", 256, "Dump gci",
+    (gptr*) &use_gci, (gptr*) &use_gci, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
+  { "tupscan", 't', "Scan in tup order",
+    (gptr*) &_tup, (gptr*) &_tup, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
+  { "nodata", 256, "Dont print data",
+    (gptr*) &nodata, (gptr*) &nodata, 0,
+    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 }, 
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 static void usage()
@@ -216,12 +237,14 @@
     }
 
     int rs;
+    unsigned scan_flags = 0;
+    if (_tup) scan_flags |= NdbScanOperation::SF_TupScan;
     switch(_lock + (3 * order)){
     case 1:
-      rs = pOp->readTuples(NdbScanOperation::LM_Read, 0, parallel);
+      rs = pOp->readTuples(NdbScanOperation::LM_Read, scan_flags, parallel);
       break;
     case 2:
-      rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, 0, parallel);
+      rs = pOp->readTuples(NdbScanOperation::LM_Exclusive, scan_flags, parallel);
       break;
     case 3:
       rs = pIOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel, 
@@ -235,7 +258,7 @@
       break;
     case 0:
     default:
-      rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, 0, parallel);
+      rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead, scan_flags, parallel);
       break;
     }
     if( rs != 0 ){
@@ -295,15 +318,38 @@
       }
     }
     
-    for(int a = 0; a<pTab->getNoOfColumns(); a++){
-      if((row->attributeStore(a) = 
-	  pOp->getValue(pTab->getColumn(a)->getName())) == 0) {
-	ERR(pTrans->getNdbError());
-	pNdb->closeTransaction(pTrans);
-	return -1;
-      }
+    bool disk= false;
+    for(int a = 0; a<pTab->getNoOfColumns(); a++)
+    {
+      const NdbDictionary::Column* col = pTab->getColumn(a);
+      if(col->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
+	disk= true;
+
+      if (!nodata)
+	if((row->attributeStore(a) = pOp->getValue(col)) == 0)
+	{
+	  ERR(pTrans->getNdbError());
+	  pNdb->closeTransaction(pTrans);
+	  return -1;
+	}
+    }
+    
+    NdbRecAttr * disk_ref= 0;
+    if(_dumpDisk && disk)
+      disk_ref = pOp->getValue(NdbDictionary::Column::DISK_REF);
+
+    NdbRecAttr * rowid= 0, *frag = 0, *gci = 0;
+    if (use_rowid)
+    {
+      frag = pOp->getValue(NdbDictionary::Column::FRAGMENT);
+      rowid = pOp->getValue(NdbDictionary::Column::ROWID);
     }
 
+    if (use_gci)
+    {
+      gci = pOp->getValue(NdbDictionary::Column::ROW_GCI);
+    }
+    
     check = pTrans->execute(NdbTransaction::NoCommit);   
     if( check == -1 ) {
       const NdbError err = pTrans->getNdbError();
@@ -319,8 +365,19 @@
       return -1;
     }
 
-    if (headers)
-      row->header(ndbout) << endl;
+    if (rowid)
+      ndbout << "ROWID\t";
+    
+    if (gci)
+      ndbout << "\tGCI";
+    
+    if (headers && !nodata)
+      row->header(ndbout);
+    
+    if (disk_ref)
+      ndbout << "\tDISK_REF";
+
+    ndbout << endl;
     
     int eof;
     int rows = 0;
@@ -329,17 +386,43 @@
     while(eof == 0){
       rows++;
 
-      if (useHexFormat) {
-	ndbout.setHexFormat(1) << (*row) << endl;
-      } else {
-	ndbout << (*row) << endl;
+      if (useHexFormat)
+	ndbout.setHexFormat(1);
+
+      if (rowid)
+      {
+	ndbout << "[ fragment: " << frag->u_32_value()
+	       << " m_page: " << rowid->u_32_value() 
+	       << " m_page_idx: " << *(Uint32*)(rowid->aRef() + 4) << " ]";
+	ndbout << "\t";
+      }
+      
+      if (gci)
+      {
+	if (gci->isNULL())
+	  ndbout << "NULL\t";
+	else
+	  ndbout << gci->u_64_value() << "\t";
       }
 
+      if (!nodata)
+	ndbout << (*row);
+      
+      if(disk_ref)
+      {
+	ndbout << "\t";
+	ndbout << "[ m_file_no: " << *(Uint16*)(disk_ref->aRef()+6)
+	       << " m_page: " << disk_ref->u_32_value() 
+	       << " m_page_idx: " << *(Uint16*)(disk_ref->aRef() + 4) << " ]";
+      }
+      
+      if (rowid || disk_ref || gci || !nodata)
+	ndbout << endl;
       eof = pOp->nextResult();
     }
     if (eof == -1) {
       const NdbError err = pTrans->getNdbError();
-
+      
       if (err.status == NdbError::TemporaryError){
 	pNdb->closeTransaction(pTrans);
 	NdbSleep_MilliSleep(50);
@@ -350,11 +433,11 @@
       pNdb->closeTransaction(pTrans);
       return -1;
     }
-
+    
     pNdb->closeTransaction(pTrans);
-
+    
     ndbout << rows << " rows returned" << endl;
-
+    
     return 0;
   }
   return -1;

--- 1.23.2.1/ndb/tools/waiter.cpp	2006-10-05 23:13:38 +10:00
+++ 1.27/storage/ndb/tools/waiter.cpp	2006-10-05 23:13:38 +10:00
@@ -96,7 +96,7 @@
     wait_status= NDB_MGM_NODE_STATUS_STARTED;
   }
 
-  if (waitClusterStatus(_hostName, wait_status, _timeout) != 0)
+  if (waitClusterStatus(_hostName, wait_status, _timeout*10) != 0)
     return NDBT_ProgramExit(NDBT_FAILED);
   return NDBT_ProgramExit(NDBT_OK);
 }
@@ -315,7 +315,7 @@
     }
     g_info << "Waiting for cluster enter state " 
 	    << ndb_mgm_get_node_status_string(_status)<< endl;
-    NdbSleep_SecSleep(1);
+    NdbSleep_MilliSleep(100);
     attempts++;
   }
   return 0;
Thread
bk commit into 5.1 tree (stewart:1.2302)Stewart Smith5 Oct