List:Commits« Previous MessageNext Message »
From:Magnus Blåudd Date:July 3 2009 1:14pm
Subject:bzr commit into mysql-5.1-telco-7.1 branch (magnus.blaudd:2929)
View as plain text  
#At file:///home/msvensson/mysql/tmp/7allT58Yj8/7.1-ndbinfo/ based on revid:jonas@stripped0702140305-jj00g6sj0loj0ytz

 2929 Magnus Blåudd	2009-07-03 [merge]
      Merge

    removed:
      storage/ndb/include/ndbinfo.h
      storage/ndb/src/common/util/ndbinfo.cpp
      storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_helpers.cpp
      storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_tableids.h
      storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_tables.h
      storage/ndb/src/mgmsrv/mgm_ndbinfo.cpp
    added:
      storage/ndb/src/kernel/vm/Ndbinfo.cpp
      storage/ndb/src/kernel/vm/Ndbinfo.hpp
    modified:
      mysql-test/suite/ndb/r/ndb_basic.result
      mysql-test/suite/ndb/r/ndbinfo.result
      mysql-test/suite/ndb/t/ndb_basic.test
      mysql-test/suite/ndb/t/ndbinfo.test
      sql/ha_ndbcluster.cc
      sql/ha_ndbinfo.cc
      storage/ndb/include/Makefile.am
      storage/ndb/include/kernel/signaldata/DbinfoScan.hpp
      storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp
      storage/ndb/include/kernel/signaldata/SignalData.hpp
      storage/ndb/src/common/debugger/signaldata/DbinfoScan.cpp
      storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
      storage/ndb/src/common/util/Makefile.am
      storage/ndb/src/kernel/blocks/LocalProxy.cpp
      storage/ndb/src/kernel/blocks/LocalProxy.hpp
      storage/ndb/src/kernel/blocks/Makefile.am
      storage/ndb/src/kernel/blocks/backup/Backup.cpp
      storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
      storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
      storage/ndb/src/kernel/blocks/dbinfo/CMakeLists.txt
      storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp
      storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.hpp
      storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp
      storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
      storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp
      storage/ndb/src/kernel/blocks/suma/Suma.cpp
      storage/ndb/src/kernel/blocks/trix/Trix.cpp
      storage/ndb/src/kernel/vm/Makefile.am
      storage/ndb/src/kernel/vm/SimulatedBlock.cpp
      storage/ndb/src/kernel/vm/SimulatedBlock.hpp
      storage/ndb/src/mgmsrv/Makefile.am
      storage/ndb/src/ndbapi/NdbInfo.cpp
      storage/ndb/src/ndbapi/NdbInfo.hpp
      storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp
      storage/ndb/src/ndbapi/NdbInfoScanOperation.hpp
      storage/ndb/test/ndbapi/testNdbinfo.cpp
=== modified file 'mysql-test/suite/ndb/r/ndb_basic.result'
--- a/mysql-test/suite/ndb/r/ndb_basic.result	2009-06-04 13:14:14 +0000
+++ b/mysql-test/suite/ndb/r/ndb_basic.result	2009-07-03 11:12:33 +0000
@@ -7,7 +7,7 @@ attr2 INT,
 attr3 VARCHAR(10)
 ) ENGINE=ndbcluster;
 drop table t1;
-SHOW GLOBAL STATUS LIKE 'ndb%';
+SHOW GLOBAL STATUS LIKE 'ndb\_%';
 Variable_name	Value
 Ndb_cluster_node_id	#
 Ndb_config_from_host	#
@@ -21,7 +21,7 @@ Ndb_pruned_scan_count	#
 Ndb_cluster_connection_pool	#
 Ndb_conflict_fn_max	#
 Ndb_conflict_fn_old	#
-SHOW GLOBAL VARIABLES LIKE 'ndb%';
+SHOW GLOBAL VARIABLES LIKE 'ndb\_%';
 Variable_name	Value
 ndb_autoincrement_prefetch_sz	#
 ndb_batch_size	#

=== modified file 'mysql-test/suite/ndb/r/ndbinfo.result'
--- a/mysql-test/suite/ndb/r/ndbinfo.result	2009-06-23 14:07:58 +0000
+++ b/mysql-test/suite/ndb/r/ndbinfo.result	2009-07-03 11:12:33 +0000
@@ -73,9 +73,15 @@ TABLE_ID	TABLE_NAME	CREATE_SQL
 	`FREE` INT UNSIGNED,
 	`SIZE` INT UNSIGNED
 ) ENGINE=NDBINFO;
+7	TEST	CREATE TABLE `TEST` (
+	`NODE_ID` INT UNSIGNED,
+	`BLOCK_NUMBER` INT UNSIGNED,
+	`BLOCK_INSTANCE` INT UNSIGNED,
+	`COUNTER` INT UNSIGNED
+) ENGINE=NDBINFO;
 select count(*) from TABLES;
 count(*)
-7
+8
 select * from TABLES where TABLE_ID = 2;
 TABLE_ID	TABLE_NAME	CREATE_SQL
 2	MEMUSAGE	CREATE TABLE `MEMUSAGE` (
@@ -97,6 +103,12 @@ TABLE_ID	TABLE_NAME	CREATE_SQL
 	`FREE` INT UNSIGNED,
 	`SIZE` INT UNSIGNED
 ) ENGINE=NDBINFO;
+7	TEST	CREATE TABLE `TEST` (
+	`NODE_ID` INT UNSIGNED,
+	`BLOCK_NUMBER` INT UNSIGNED,
+	`BLOCK_INSTANCE` INT UNSIGNED,
+	`COUNTER` INT UNSIGNED
+) ENGINE=NDBINFO;
 select * from TABLES where TABLE_NAME = 'LOGDESTINATION';
 TABLE_ID	TABLE_NAME	CREATE_SQL
 3	LOGDESTINATION	CREATE TABLE `LOGDESTINATION` (
@@ -108,7 +120,7 @@ TABLE_ID	TABLE_NAME	CREATE_SQL
 ) ENGINE=NDBINFO;
 select count(*) from TABLES t1, TABLES t2 WHERE t1.TABLE_ID = t1.TABLE_ID;
 count(*)
-49
+64
 update TABLES set TABLE_ID=2 where TABLE_ID=3;
 ERROR HY000: Table storage engine for 'TABLES' doesn't have this option
 FLUSH  TABLES;
@@ -121,5 +133,12 @@ TABLE_ID
 4
 5
 6
+7
+SHOW GLOBAL STATUS LIKE 'ndbinfo\_%';
+Variable_name	Value
+SHOW GLOBAL VARIABLES LIKE 'ndbinfo\_%';
+Variable_name	Value
+ndbinfo_max_bytes	0
+ndbinfo_max_rows	10
 drop table TABLES;
 DROP DATABASE ndb$info;

=== modified file 'mysql-test/suite/ndb/t/ndb_basic.test'
--- a/mysql-test/suite/ndb/t/ndb_basic.test	2008-10-06 11:03:32 +0000
+++ b/mysql-test/suite/ndb/t/ndb_basic.test	2009-07-03 11:12:33 +0000
@@ -25,9 +25,9 @@ drop table t1;
 # Show status and variables
 #
 --replace_column 2 #
-SHOW GLOBAL STATUS LIKE 'ndb%';
+SHOW GLOBAL STATUS LIKE 'ndb\_%';
 --replace_column 2 #
-SHOW GLOBAL VARIABLES LIKE 'ndb%';
+SHOW GLOBAL VARIABLES LIKE 'ndb\_%';
 
 #
 # Create a normal table with primary key

=== modified file 'mysql-test/suite/ndb/t/ndbinfo.test'
--- a/mysql-test/suite/ndb/t/ndbinfo.test	2009-06-24 14:32:19 +0000
+++ b/mysql-test/suite/ndb/t/ndbinfo.test	2009-07-03 11:12:33 +0000
@@ -25,5 +25,9 @@ update TABLES set TABLE_ID=2 where TABLE
 
 FLUSH  TABLES;
 SELECT TABLE_ID from TABLES;
+
+SHOW GLOBAL STATUS LIKE 'ndbinfo\_%';
+SHOW GLOBAL VARIABLES LIKE 'ndbinfo\_%';
+
 drop table TABLES;
 DROP DATABASE ndb$info;

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2009-06-15 14:01:01 +0000
+++ b/sql/ha_ndbcluster.cc	2009-07-03 10:31:30 +0000
@@ -13985,6 +13985,8 @@ struct st_mysql_storage_engine ndbcluste
 
 #include "ha_ndbinfo.h"
 
+extern struct st_mysql_sys_var* ndbinfo_system_variables[];
+
 struct st_mysql_storage_engine ndbinfo_storage_engine=
 { MYSQL_HANDLERTON_INTERFACE_VERSION };
 
@@ -14014,7 +14016,7 @@ mysql_declare_plugin(ndbcluster)
   ndbinfo_deinit,             /* plugin deinit */
   0x0001,                     /* plugin version */
   NULL,                       /* status variables */
-  NULL,                       /* system variables */
+  ndbinfo_system_variables,   /* system variables */
   NULL                        /* config options */
 }
 mysql_declare_plugin_end;

=== modified file 'sql/ha_ndbinfo.cc'
--- a/sql/ha_ndbinfo.cc	2009-06-24 08:39:09 +0000
+++ b/sql/ha_ndbinfo.cc	2009-07-03 10:31:30 +0000
@@ -20,6 +20,32 @@
 #include "ha_ndbinfo.h"
 #include "../storage/ndb/src/ndbapi/NdbInfo.hpp"
 
+
+static MYSQL_THDVAR_UINT(
+  max_rows,                          /* name */
+  PLUGIN_VAR_RQCMDARG,
+  "Specify max number of rows to fetch per roundtrip to cluster",
+  NULL,                              /* check func. */
+  NULL,                              /* update func. */
+  10,                                /* default */
+  1,                                 /* min */
+  256,                               /* max */
+  0                                  /* block */
+);
+
+static MYSQL_THDVAR_UINT(
+  max_bytes,                         /* name */
+  PLUGIN_VAR_RQCMDARG,
+  "Specify approx. max number of bytes to fetch per roundtrip to cluster",
+  NULL,                              /* check func. */
+  NULL,                              /* update func. */
+  0,                                 /* default */
+  0,                                 /* min */
+  65535,                             /* max */
+  0                                  /* block */
+);
+
+
 static NdbInfo* g_ndbinfo;
 
 extern Ndb_cluster_connection* g_ndb_cluster_connection;
@@ -92,6 +118,16 @@ int ha_ndbinfo::open(const char *name, i
 {
   DBUG_ENTER("ha_ndbinfo::open");
   DBUG_PRINT("enter", ("name: %s, mode: %d", name, mode));
+
+  if (!g_ndbinfo)
+  {
+    push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 1,
+                 "Can't open table - 'ndbinfo' has been started "
+                 "in limited mode because the 'ndbcluster' "
+                 "engine is disabled");
+    DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+  }
+
   assert(is_closed());
 
   int err = g_ndbinfo->openTable(name, &m_impl.m_table);
@@ -123,10 +159,14 @@ int ha_ndbinfo::rnd_init(bool scan)
   DBUG_PRINT("info", ("scan: %d", scan));
   assert(is_open());
   assert(m_impl.m_scan_op == NULL); // No scan already ongoing
+  THD* thd = current_thd;
 
   int err;
   NdbInfoScanOperation* scan_op = NULL;
-  if ((err = g_ndbinfo->createScanOperation(m_impl.m_table, &scan_op)) != 0)
+  if ((err = g_ndbinfo->createScanOperation(m_impl.m_table,
+                                            &scan_op,
+                                            THDVAR(thd, max_rows),
+                                            THDVAR(thd, max_bytes))) != 0)
     DBUG_RETURN(err2mysql(err));
 
   if ((err = scan_op->readTuples()) != 0)
@@ -278,12 +318,10 @@ int ndbinfo_init(void *plugin)
   /* Check if 'ndbcluster_init' has been run and connected to cluster */
   if (!g_ndb_cluster_connection)
   {
-    sql_print_warning("Disabling 'ndbinfo' because 'ndbcluster' is "
-                      "not started");
-    // hton->state = SHOW_OPTION_DISABLED;
-    // TODO ^ this does not mark the engine as disabled
-    // Write small patch for MySQL Server allowing an engine to disable itself?
-    DBUG_RETURN(1);
+    sql_print_warning("Starting 'ndbinfo' in limited mode "
+                      "because 'ndbcluster' engine is disabled");
+
+    DBUG_RETURN(0);
   }
 
   bool use_lower_case = (lower_case_table_names != 0);
@@ -326,4 +364,11 @@ int ndbinfo_deinit(void *plugin)
   DBUG_RETURN(0);
 }
 
+struct st_mysql_sys_var* ndbinfo_system_variables[]= {
+  MYSQL_SYSVAR(max_rows),
+  MYSQL_SYSVAR(max_bytes),
+
+  NULL
+};
+
 template class Vector<const NdbInfoRecAttr*>;

=== modified file 'storage/ndb/include/Makefile.am'
--- a/storage/ndb/include/Makefile.am	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/Makefile.am	2009-07-03 10:31:30 +0000
@@ -20,8 +20,7 @@ ndbinclude_HEADERS = \
 ndb_constants.h \
 ndb_init.h \
 ndb_types.h \
-ndb_version.h \
-ndbinfo.h
+ndb_version.h
 
 ndbapiinclude_HEADERS = \
 ndbapi/ndbapi_limits.h \

=== modified file 'storage/ndb/include/kernel/signaldata/DbinfoScan.hpp'
--- a/storage/ndb/include/kernel/signaldata/DbinfoScan.hpp	2009-06-23 11:42:57 +0000
+++ b/storage/ndb/include/kernel/signaldata/DbinfoScan.hpp	2009-07-03 10:31:30 +0000
@@ -20,136 +20,56 @@
 
 struct DbinfoScanCursor
 {
-  Uint32 cur_requestInfo;
-  Uint32 cur_node;
-  Uint32 cur_block;
-  Uint32 cur_item;
+  Uint32 data[11];
 };
 
-struct DbinfoScanReq;
-extern "C" void dbinfo_ratelimit_init(struct dbinfo_ratelimit *rl,
-                                      struct DbinfoScanReq *);
-
-struct DbinfoScanReq
+struct DbinfoScan
 {
-  /* Reciver(s) */
-  friend class Backup;
-  friend class Dbacc;
-  friend class Dbdict;
-  friend class Dbinfo;
-  friend class Dbtc;
-  friend class Dbtup;
-  friend class Dbtux;
-  friend class DbUtil;
-  friend class Qmgr;
-  friend class Suma;
-  friend class Trix;
-
-  friend void dbinfo_ratelimit_init(struct dbinfo_ratelimit *rl,
-                                    struct DbinfoScanReq *r);
-
-  /* Sender(s) */
-  friend class NdbInfoScanOperation;
-
-  friend bool printDBINFO_SCAN_REQ(FILE * output, const Uint32 * theData,
-                                   Uint32 len, Uint16 receiverBlockNo);
-
   STATIC_CONST( SignalLength = 12 );
-  STATIC_CONST( SignalLengthWithCursor = 16 );
 
-  Uint32 tableId;         // DBINFO table ID
-  Uint32 apiRef;          // API doing scan
-  Uint32 apiTxnId;        // ID unique to API.
-  Uint32 senderRef;       // Sender, DBINFO or proxy for multi-threaded block
-  Uint32 instance;        // Block instance for multi-threaded block
-  Uint32 colBitmapLo;     // bitmap of what columns you want. (64bit)
-  Uint32 colBitmapHi;
-  Uint32 requestInfo;     // start, endofdata
-
-  STATIC_CONST( StartScan  = 0x1 );
-  STATIC_CONST( AllColumns = 0x2 );
-
-  Uint32 maxRows;
-  Uint32 maxBytes;
-  Uint32 rows_total;
-  Uint32 word_total;
-
-  union
-  {
-    Uint32 cursordata[1];
-    struct DbinfoScanCursor cursor;
-  };
-};
-
-
-class DbinfoScanConf {
-  /* Reciver(s) */
-  friend class NdbInfoScanOperation;
-
-  /* Sender(s) */
-  friend class Backup;
-  friend class Dbacc;
-  friend class Dbdict;
-  friend class Dbinfo;
-  friend class Dbtc;
-  friend class Dbtup;
-  friend class Dbtux;
-  friend class DbUtil;
-  friend class LocalProxy;
-  friend class Qmgr;
-  friend class Suma;
-  friend class Trix;
-
-  friend bool printDBINFO_SCAN_CONF(FILE * output, const Uint32 * theData,
-                                    Uint32 len, Uint16 receiverBlockNo);
-
-  STATIC_CONST( DoneLength = 3 );
-  STATIC_CONST( SignalLength = 12 );
-  STATIC_CONST( SignalLengthWithCursor = 16 );
+  // API identifiers
+  Uint32 resultData;      // Will be returned in TransIdAI::connectPtr
+  Uint32 transId[2];      // ID unique to API
+  Uint32 resultRef;       // Where to send result rows
 
+  // Parameters for the scan
   Uint32 tableId;         // DBINFO table ID
-  Uint32 apiRef;          // API doing scan
-  Uint32 apiTxnId;        // ID unique to API.
-  Uint32 senderRef;       // Sender of DBINFO_SCANREQ
-  Uint32 instance;        // Block instance for multi-threaded block
-  Uint32 colBitmapLo;     // bitmap of what columns you want. (64bit)
-  Uint32 colBitmapHi;
-  Uint32 requestInfo;     // start, endofdata
-
-  STATIC_CONST( MoreData  = 0x1 );
-  STATIC_CONST( AllColumns = 0x2 );
-
-  Uint32 maxRows;
-  Uint32 maxBytes;
-  Uint32 rows_total;
-  Uint32 word_total;
+  Uint32 colBitmap[2];     // bitmap of what columns you want. (64bit)
+  Uint32 requestInfo;     // flags
+  Uint32 maxRows;         // Max number of rows to return per REQ
+  Uint32 maxBytes;        // Max number of bytes to return per REQ
+
+  // Result from the scan
+  Uint32 returnedRows;    // Number of rows returned for this CONF
+
+  // Cursor that contains data used by the kernel for keeping track
+  // of where it is, how many bytes or rows it has sent etc.
+  // Set to zero in last CONF to indicate that scan is finished
+  Uint32 cursor_sz;
+  // Cursor data of cursor_sz size follows
+  DbinfoScanCursor cursor;
+
+  static const Uint32* getCursorPtr(const DbinfoScan* sig) {
+    return sig->cursor.data;
+  }
+  static Uint32* getCursorPtrSend(DbinfoScan* sig) {
+    return sig->cursor.data;
+  }
 
-  union
-  {
-    Uint32 cursordata[1];
-    struct DbinfoScanCursor cursor;
-  };
 };
 
-/**
- * SENDER:  DBINFO
- * RECIVER: API,MGM
- */
-class DbinfoScanRef {
-  /* Reciver(s) */
-  friend class NdbInfoScanOperation;
-
-  /* Sender(s) */
-  friend class Dbinfo;
-  friend class LocalProxy;
+typedef DbinfoScan DbinfoScanReq;
+typedef DbinfoScan DbinfoScanConf;
 
-  friend bool printDBINFO_SCAN_REF(FILE * output, const Uint32 * theData,
-                                   Uint32 len, Uint16 receiverBlockNo);
+struct DbinfoScanRef
+{
+  STATIC_CONST( SignalLength = 5 );
 
-  STATIC_CONST( SignalLength = 3 );
+  // API identifiers
+  Uint32 resultData;      // Will be returned in TransIdAI::connectPtr
+  Uint32 transId[2];      // ID unique to API
+  Uint32 resultRef;       // Where to send result rows
 
-  Uint32 tableId;         // DBINFO table ID
-  Uint32 apiTxnId;        // ID unique to API.
   Uint32 errorCode;       // Error Code
   enum ErrorCode
   {

=== modified file 'storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp'
--- a/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/include/kernel/signaldata/DumpStateOrd.hpp	2009-06-24 20:56:51 +0000
@@ -176,7 +176,6 @@ public:
     DumpDbinfo = 14000,
     DbinfoListTables = 14001,
     DbinfoListColumns = 14002,
-    DbinfoScanTable = 14003,
 
     SchemaResourceSnapshot = 4000, // Save resource consumption
     SchemaResourceCheckLeak = 4001 // check same as snapshot

=== modified file 'storage/ndb/include/kernel/signaldata/SignalData.hpp'
--- a/storage/ndb/include/kernel/signaldata/SignalData.hpp	2009-06-15 13:12:19 +0000
+++ b/storage/ndb/include/kernel/signaldata/SignalData.hpp	2009-07-03 10:31:30 +0000
@@ -279,8 +279,7 @@ GSN_PRINT_SIGNATURE(printBUILD_INDX_IMPL
 GSN_PRINT_SIGNATURE(printAPI_VERSION_REQ);
 GSN_PRINT_SIGNATURE(printAPI_VERSION_CONF);
 
-GSN_PRINT_SIGNATURE(printDBINFO_SCAN_REQ);
-GSN_PRINT_SIGNATURE(printDBINFO_SCAN_CONF);
+GSN_PRINT_SIGNATURE(printDBINFO_SCAN);
 GSN_PRINT_SIGNATURE(printDBINFO_SCAN_REF);
 
 #endif

=== removed file 'storage/ndb/include/ndbinfo.h'
--- a/storage/ndb/include/ndbinfo.h	2009-06-23 14:07:58 +0000
+++ b/storage/ndb/include/ndbinfo.h	1970-01-01 00:00:00 +0000
@@ -1,139 +0,0 @@
-/* Copyright (C) 2007 MySQL AB
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; version 2 of the License.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
-
-#include <ndb_types.h>
-
-#ifndef __NDBINFO_H__
-#define __NDBINFO_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define NDBINFO_TYPE_STRING 1
-#define NDBINFO_TYPE_NUMBER 2
-
-struct ndbinfo_column {
-  char name[50];
-  int coltype;
-};
-
-#define NDBINFO_TABLE_MEMBERS \
-  char name[50]; \
-  int ncols; \
-  int flags;
-
-struct ndbinfo_table {
-  NDBINFO_TABLE_MEMBERS
-  struct ndbinfo_column col[1];
-};
-
-#define DECLARE_NDBINFO_TABLE(var, num)         \
-struct ndbinfostruct##var {                     \
-  NDBINFO_TABLE_MEMBERS                         \
-  struct ndbinfo_column col[num];               \
-} var
-
-int ndbinfo_create_sql(struct ndbinfo_table *t, char* sql, int len);
-
-static inline const char* ndbinfo_coltype_to_string(int coltype)
-{
-  static const char* ndbinfo_type_string[]= {"NONE",
-                                             "VARCHAR(512)",
-                                             "INT UNSIGNED"
-  };
-
-  if(coltype>3)
-    coltype= 0;
-
-  return ndbinfo_type_string[coltype];
-}
-
-struct dbinfo_row {
-  Uint32* buf;      // Start of row buffer
-  Uint32* curr;     // Current position in row buffer
-  Uint32* end;      // Last position in buffer
-  int col_count;    // Current column counter
-
-  Uint32 size(void) const {
-    return (Uint32)(curr - buf);
-  };
-};
-
-void dbinfo_write_row_init(struct dbinfo_row *r, char* buf, int len);
-
-int dbinfo_write_row_column(struct dbinfo_row *r, const char* col, int clen);
-
-int dbinfo_write_row_column_uint32(struct dbinfo_row *r, Uint32 value);
-
-/*
- * We need to call protected function of SimulatedBlock (sendSignal)
- * so easier to implement as macro...
- */
-#define dbinfo_send_row(signal, r, rl, apiTxnId, senderRef)             \
-  do {                                                                  \
-  TransIdAI *tidai= (TransIdAI*)signal->getDataPtrSend();               \
-  tidai->connectPtr= 0;                                                 \
-  tidai->transId[0]= apiTxnId;                                          \
-  tidai->transId[1]= 0;                                                 \
-  LinearSectionPtr ptr[3];                                              \
-  ptr[0].p = r.buf;                                                     \
-  ptr[0].sz = r.size();                                                 \
-  rl.rows++;                                                            \
-  rl.bytes += r.size();                                                 \
-  sendSignal(senderRef, GSN_DBINFO_TRANSID_AI, signal, 3, JBB, ptr, 1); \
-} while (0)
-
-#define dbinfo_ratelimit_sendconf(signal, req, rl, itemnumber)          \
-  do {                                                                  \
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();      \
-  conf->tableId= (req).tableId;                                         \
-  conf->senderRef= (req).senderRef;                                     \
-  conf->apiTxnId= (req).apiTxnId;                                       \
-  conf->colBitmapLo= (req).colBitmapLo;                                 \
-  conf->colBitmapHi= (req).colBitmapHi;                                 \
-  conf->requestInfo= (req).requestInfo | DbinfoScanConf::MoreData;      \
-  conf->cursor.cur_requestInfo= 0;                                      \
-  conf->cursor.cur_node= getOwnNodeId();                                \
-  conf->cursor.cur_block= number();                                     \
-  conf->cursor.cur_item= (itemnumber);                                  \
-  conf->maxRows= (rl).maxRows;                                          \
-  conf->maxBytes= (rl).maxBytes;                                        \
-  conf->rows_total= (rl).rows_total + (rl).rows;                        \
-  conf->word_total= (rl).bytes_total+ (rl).bytes;                       \
-  sendSignal((req).senderRef, GSN_DBINFO_SCANCONF, signal,              \
-             DbinfoScanConf::SignalLengthWithCursor, JBB);              \
-} while (0)
-
-
-struct dbinfo_ratelimit {
-  Uint32 maxRows;
-  Uint32 maxBytes;
-  Uint32 rows_total;
-  Uint32 bytes_total;
-  Uint32 rows;
-  Uint32 bytes;
-};
-
-struct DbinfoScanReq;
-void dbinfo_ratelimit_init(struct dbinfo_ratelimit *rl, struct DbinfoScanReq *);
-
-int dbinfo_ratelimit_continue(struct dbinfo_ratelimit *rl);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

=== modified file 'storage/ndb/src/common/debugger/signaldata/DbinfoScan.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/DbinfoScan.cpp	2009-06-15 13:12:19 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/DbinfoScan.cpp	2009-07-03 10:31:30 +0000
@@ -19,52 +19,43 @@
 #include <signaldata/DbinfoScan.hpp>
 
 bool
-printDBINFO_SCAN_REQ(FILE* output, const Uint32* theData, Uint32 len, Uint16)
+printDBINFO_SCAN(FILE* output, const Uint32* theData, Uint32 len, Uint16)
 {
-  const DbinfoScanReq* sig = (const DbinfoScanReq*)theData;
-  fprintf(output, " tableId: %u", sig->tableId);
-  fprintf(output, " apiRef: 0x%x", sig->apiRef);
-  fprintf(output, " apiTxnId: %u", sig->apiTxnId);
-  fprintf(output, " senderRef: 0x%x", sig->senderRef);
-  fprintf(output, " instance: %u", sig->instance);
-  fprintf(output, " colBitmapLo: 0x%x", sig->colBitmapLo);
-  fprintf(output, " colBitmapHi: 0x%x", sig->colBitmapHi);
-  fprintf(output, " requestInfo: %u", sig->requestInfo);
-  fprintf(output, "\n");
-  fprintf(output, " maxRows: %u", sig->maxRows);
-  fprintf(output, " maxBytes: %u", sig->maxBytes);
-  fprintf(output, " rows_total: %u", sig->rows_total);
-  fprintf(output, " word_total: %u", sig->word_total);
+  const DbinfoScan* sig = (const DbinfoScan*)theData;
+  fprintf(output, " resultData: 0x%x", sig->resultData);
+  fprintf(output, " transid: { 0x%x, 0x%x}", sig->transId[0], sig->transId[1]);
+  fprintf(output, " resultRef: 0x%x", sig->resultRef);
   fprintf(output, "\n");
-  return true;
-}
-
-bool
-printDBINFO_SCAN_CONF(FILE* output, const Uint32* theData, Uint32 len, Uint16)
-{
-  const DbinfoScanConf* sig = (const DbinfoScanConf*)theData;
   fprintf(output, " tableId: %u", sig->tableId);
-  fprintf(output, " apiRef: 0x%x", sig->apiRef);
-  fprintf(output, " apiTxnId: %u", sig->apiTxnId);
-  fprintf(output, " senderRef: 0x%x", sig->senderRef);
-  fprintf(output, " instance: %u", sig->instance);
-  fprintf(output, " colBitmapLo: 0x%x", sig->colBitmapLo);
-  fprintf(output, " colBitmapHi: 0x%x", sig->colBitmapHi);
-  fprintf(output, " requestInfo: %u", sig->requestInfo);
+  fprintf(output, " colBitmap: { 0x%x, 0x%x }",
+          sig->colBitmap[0], sig->colBitmap[1]);
+  fprintf(output, " requestInfo: 0x%x", sig->requestInfo);
   fprintf(output, "\n");
   fprintf(output, " maxRows: %u", sig->maxRows);
   fprintf(output, " maxBytes: %u", sig->maxBytes);
-  fprintf(output, " rows_total: %u", sig->rows_total);
-  fprintf(output, " word_total: %u", sig->word_total);
   fprintf(output, "\n");
+  fprintf(output, " returnedRows: %u", sig->returnedRows);
+  fprintf(output, "\n");
+  fprintf(output, " cursor_sz: %u\n", sig->cursor_sz);
+  const Uint32* cursor_data = DbinfoScan::getCursorPtr(sig);
+  fprintf(output, " senderRef: 0x%x saveSenderRef: 0x%x\n",
+          cursor_data[0], cursor_data[1]);
+  fprintf(output, " currRef: 0x%x saveCurrRef: 0x%x flags: 0x%x\n",
+          cursor_data[2], cursor_data[3], cursor_data[4]);
+  fprintf(output, " data: [ 0x%x, 0x%x, 0x%x, 0x%x ]\n",
+          cursor_data[5], cursor_data[6], cursor_data[7], cursor_data[8]);
+  fprintf(output, " totalRows: %u totalBytes: %u\n",
+          cursor_data[9], cursor_data[10]);
   return true;
 }
 
 bool printDBINFO_SCAN_REF(FILE* output, const Uint32* theData, Uint32 len, Uint16)
 {
   const DbinfoScanRef* sig = (const DbinfoScanRef*)theData;
-  fprintf(output, " tableId: %u", sig->tableId);
-  fprintf(output, " apiTxnId: %u", sig->apiTxnId);
+  fprintf(output, " resultData: 0x%x", sig->resultData);
+  fprintf(output, " transid: { 0x%x, 0x%x}", sig->transId[0], sig->transId[1]);
+  fprintf(output, " resultRef: 0x%x", sig->resultRef);
+  fprintf(output, "\n");
   fprintf(output, " errorCode: %u", sig->errorCode);
   fprintf(output, "\n");
   return true;

=== modified file 'storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp	2009-06-15 13:12:19 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp	2009-07-03 10:31:30 +0000
@@ -251,8 +251,8 @@ SignalDataPrintFunctions[] = {
   ,{ GSN_API_VERSION_REQ, printAPI_VERSION_REQ }
   ,{ GSN_API_VERSION_CONF, printAPI_VERSION_CONF }
 
-  ,{ GSN_DBINFO_SCANREQ, printDBINFO_SCAN_REQ }
-  ,{ GSN_DBINFO_SCANCONF, printDBINFO_SCAN_CONF }
+  ,{ GSN_DBINFO_SCANREQ, printDBINFO_SCAN }
+  ,{ GSN_DBINFO_SCANCONF, printDBINFO_SCAN }
   ,{ GSN_DBINFO_SCANREF, printDBINFO_SCAN_REF }
 
   ,{ 0, 0 }

=== modified file 'storage/ndb/src/common/util/Makefile.am'
--- a/storage/ndb/src/common/util/Makefile.am	2009-06-23 11:55:41 +0000
+++ b/storage/ndb/src/common/util/Makefile.am	2009-07-03 10:31:30 +0000
@@ -28,8 +28,7 @@ libgeneral_la_SOURCES = \
             strdup.c \
             ConfigValues.cpp ndb_init.cpp basestring_vsnprintf.c \
             Bitmask.cpp \
-	    ndb_rand.c \
-	    ndbinfo.cpp
+	    ndb_rand.c 
 
 INCLUDES_LOC = @ZLIB_INCLUDES@
 

=== removed file 'storage/ndb/src/common/util/ndbinfo.cpp'
--- a/storage/ndb/src/common/util/ndbinfo.cpp	2009-06-23 11:55:41 +0000
+++ b/storage/ndb/src/common/util/ndbinfo.cpp	1970-01-01 00:00:00 +0000
@@ -1,54 +0,0 @@
-/* Copyright (C) 2007 MySQL AB
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; version 2 of the License.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include <ndb_global.h>
-#include <my_base.h>
-#include <m_string.h> /* for my_snprintf */
-
-#include <ndbinfo.h>
-
-int ndbinfo_create_sql(struct ndbinfo_table *t, char* sql, int len)
-{
-  int i;
-
-  my_snprintf(sql,len,"CREATE TABLE `%s` (", t->name);
-
-  len-=strlen(sql);
-  sql+=strlen(sql);
-  if(len<0)
-    return ENOMEM;
-
-  for(i=0;i<t->ncols;i++)
-  {
-    my_snprintf(sql,len,"\n\t`%s` %s,",
-             t->col[i].name, ndbinfo_coltype_to_string(t->col[i].coltype));
-    len-=strlen(sql);
-    sql+=strlen(sql);
-    if(len<0)
-      return ENOMEM;
-  }
-  *(--sql)='\0';
-  my_snprintf(sql,len,"\n) ENGINE=NDBINFO;");
-  len-=strlen(sql);
-  sql+=strlen(sql);
-  if(len<0)
-    return ENOMEM;
-
-  return 0;
-}

=== modified file 'storage/ndb/src/kernel/blocks/LocalProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/LocalProxy.cpp	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/LocalProxy.cpp	2009-07-03 10:31:30 +0000
@@ -977,68 +977,141 @@ LocalProxy::sendDROP_TRIG_IMPL_CONF(Sign
 
 // GSN_DBINFO_SCANREQ
 
-void
-LocalProxy::execDBINFO_SCANREQ(Signal* signal)
+bool
+LocalProxy::find_next(Ndbinfo::ScanCursor* cursor) const
 {
-  Ss_DBINFO_SCANREQ& ss = ssSeize<Ss_DBINFO_SCANREQ>(1);
+  jam();
+  const Uint32 node = refToNode(cursor->currRef);
+  const Uint32 block = refToMain(cursor->currRef);
+  Uint32 instance = refToInstance(cursor->currRef);
 
-  const DbinfoScanReq* req = (const DbinfoScanReq*)signal->getDataPtr();
-  ss.m_req = *req;
-  ndbrequire(signal->getLength() == DbinfoScanReq::SignalLength ||
-             signal->getLength() == DbinfoScanReq::SignalLengthWithCursor);
-  ss.m_len = signal->getLength();
-  sendREQ(signal, ss);
-}
+  ndbrequire(node == getOwnNodeId());
+  ndbrequire(block == number());
 
-void
-LocalProxy::execDBINFO_SCANCONF(Signal* signal)
-{
-  Ss_DBINFO_SCANREQ& ss = ssFind<Ss_DBINFO_SCANREQ>(1);
-  recvCONF(signal, ss);
+  if (instance++ < c_workers)
+  {
+    cursor->currRef = numberToRef(block, instance, node);
+    return true;
+  }
+
+  cursor->currRef = numberToRef(block, node);
+  return false;
 }
 
+
+
 void
-LocalProxy::sendDBINFO_SCANREQ(Signal* signal, Uint32 ssId)
+LocalProxy::execDBINFO_SCANREQ(Signal* signal)
 {
-  Ss_DBINFO_SCANREQ& ss = ssFind<Ss_DBINFO_SCANREQ>(ssId);
+  jamEntry();
+  const DbinfoScanReq* req = (const DbinfoScanReq*) signal->getDataPtr();
+  Uint32 signal_length = signal->getLength();
+  ndbrequire(signal_length == DbinfoScanReq::SignalLength+req->cursor_sz);
+
+  Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(req);
+
+  if (Ndbinfo::ScanCursor::getHasMoreData(cursor->flags) &&
+      cursor->saveCurrRef)
+  {
+    /* Continue in the saved block ref */
+    cursor->currRef = cursor->saveCurrRef;
+    cursor->saveCurrRef = 0;
+
+    // Set this block as sender and remember original sender
+    cursor->saveSenderRef = cursor->senderRef;
+    cursor->senderRef = reference();
+
+    sendSignal(cursor->currRef, GSN_DBINFO_SCANREQ,
+               signal, signal_length, JBB);
+    return;
+  }
+
+  Ndbinfo::ScanCursor::setHasMoreData(cursor->flags, false);
 
-  DbinfoScanReq* req = (DbinfoScanReq*)signal->getDataPtrSend();
-  *req = ss.m_req;
-  req->senderRef = reference();
-  req->instance = ss.m_worker;
-  sendSignal(workerRef(ss.m_worker), GSN_DBINFO_SCANREQ,
-             signal, ss.m_len, JBB);
+  if (find_next(cursor))
+  {
+    jam();
+    ndbrequire(cursor->currRef);
+    ndbrequire(cursor->saveCurrRef == 0);
+
+    // Set this block as sender and remember original sender
+    cursor->saveSenderRef = cursor->senderRef;
+    cursor->senderRef = reference();
+
+    sendSignal(cursor->currRef, GSN_DBINFO_SCANREQ,
+               signal, signal_length, JBB);
+    return;
+  }
+
+  /* Scan is done, send SCANCONF back to caller  */
+
+  /* Swap back saved senderRef */
+  const Uint32 senderRef = cursor->senderRef = cursor->saveSenderRef;
+  cursor->saveSenderRef = 0;
+
+  ndbrequire(cursor->currRef);
+  ndbrequire(cursor->saveCurrRef == 0);
+
+  ndbrequire(refToInstance(cursor->currRef) == 0);
+  sendSignal(cursor->senderRef, GSN_DBINFO_SCANCONF, signal, signal_length, JBB);
+  return;
 }
 
 void
-LocalProxy::sendDBINFO_SCANCONF(Signal* signal, Uint32 ssId)
+LocalProxy::execDBINFO_SCANCONF(Signal* signal)
 {
-  Ss_DBINFO_SCANREQ& ss = ssFind<Ss_DBINFO_SCANREQ>(ssId);
+  jamEntry();
   const DbinfoScanConf* conf = (const DbinfoScanConf*)signal->getDataPtr();
-  const Uint32 reqlength = signal->getLength();
-  if (!lastReply(ss))
-    return;
+  Uint32 signal_length = signal->getLength();
+  ndbrequire(signal_length == DbinfoScanConf::SignalLength+conf->cursor_sz);
 
-  if (ss.m_error == 0)
+  Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(conf);
+
+  if (Ndbinfo::ScanCursor::getHasMoreData(cursor->flags))
   {
+    /* The underlying block want to continue */
     jam();
-    DbinfoScanConf *conf = (DbinfoScanConf*)signal->getDataPtrSend();
-    memcpy(conf,&ss.m_req, reqlength * sizeof(Uint32));
-    conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-    sendSignal(ss.m_req.senderRef, GSN_DBINFO_SCANCONF,
-               signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
-  }
-  else
+    
+    /* Swap back saved senderRef */
+    const Uint32 senderRef = cursor->senderRef = cursor->saveSenderRef;
+    cursor->saveSenderRef = 0;
+
+    /* Save currRef to continue with same instance again */
+    cursor->saveCurrRef = cursor->currRef;
+    cursor->currRef = reference();
+
+    sendSignal(senderRef, GSN_DBINFO_SCANCONF, signal, signal_length, JBB);
+    return;
+  } 
+  
+  /* The underlying block reported completed, find next if any */
+  if (find_next(cursor))
   {
     jam();
-    DbinfoScanRef *ref = (DbinfoScanRef*)signal->getDataPtrSend();
-    ref->tableId = conf->tableId;
-    ref->apiTxnId = conf->apiTxnId;
-    ref->errorCode = ss.m_error;
-    sendSignal(ss.m_req.senderRef, GSN_DBINFO_SCANREF, signal,
-               DbinfoScanRef::SignalLength, JBB);
+
+    ndbrequire(cursor->senderRef == reference());
+    ndbrequire(cursor->saveSenderRef); // Should already be set
+
+    ndbrequire(cursor->saveCurrRef == 0);
+
+    sendSignal(cursor->currRef, GSN_DBINFO_SCANREQ,
+               signal, signal_length, JBB);
+    return;
   }
-  ssRelease<Ss_DBINFO_SCANREQ>(ssId);
+
+  /* Scan in this block and its instances are completed */
+
+  /* Swap back saved senderRef */
+  const Uint32 senderRef = cursor->senderRef = cursor->saveSenderRef;
+  cursor->saveSenderRef = 0;
+
+  ndbrequire(cursor->currRef);
+  ndbrequire(cursor->saveCurrRef == 0);
+
+  sendSignal(senderRef, GSN_DBINFO_SCANCONF, signal, signal_length, JBB);
+  return;
 }
 
 BLOCK_FUNCTIONS(LocalProxy)

=== modified file 'storage/ndb/src/kernel/blocks/LocalProxy.hpp'
--- a/storage/ndb/src/kernel/blocks/LocalProxy.hpp	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/LocalProxy.hpp	2009-07-03 10:31:30 +0000
@@ -556,23 +556,9 @@ protected:
   void sendDROP_TRIG_IMPL_CONF(Signal*, Uint32 ssId);
 
   // GSN_DBINFO_SCANREQ
-  struct Ss_DBINFO_SCANREQ : SsSequential {
-    DbinfoScanReq m_req;
-    Uint32 m_len;
-    Ss_DBINFO_SCANREQ() {
-      m_sendREQ = &LocalProxy::sendDBINFO_SCANREQ;
-      m_sendCONF = &LocalProxy::sendDBINFO_SCANCONF;
-    }
-    enum { poolSize = 3 };
-    static SsPool<Ss_DBINFO_SCANREQ>& pool(LocalProxy* proxy) {
-      return proxy->c_ss_DBINFO_SCANREQ;
-    }
-  };
-  SsPool<Ss_DBINFO_SCANREQ> c_ss_DBINFO_SCANREQ;
+  bool find_next(Ndbinfo::ScanCursor* cursor) const;
   void execDBINFO_SCANREQ(Signal*);
-  void sendDBINFO_SCANREQ(Signal*, Uint32 ssId);
   void execDBINFO_SCANCONF(Signal*);
-  void sendDBINFO_SCANCONF(Signal*, Uint32 ssId);
 };
 
 #endif

=== modified file 'storage/ndb/src/kernel/blocks/Makefile.am'
--- a/storage/ndb/src/kernel/blocks/Makefile.am	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/kernel/blocks/Makefile.am	2009-07-03 10:31:30 +0000
@@ -65,7 +65,6 @@ libblocks_a_SOURCES = tsman.cpp lgman.cp
   backup/BackupProxy.cpp \
   RestoreProxy.cpp \
   dbinfo/Dbinfo.cpp \
-  dbinfo/ndbinfo_helpers.cpp \
   dblqh/DblqhCommon.cpp \
   PgmanProxy.cpp \
   dbtup/DbtupClient.cpp

=== modified file 'storage/ndb/src/kernel/blocks/backup/Backup.cpp'
--- a/storage/ndb/src/kernel/blocks/backup/Backup.cpp	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/backup/Backup.cpp	2009-07-03 10:31:30 +0000
@@ -63,8 +63,6 @@
 
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
 
 #include <NdbTick.h>
 #include <dbtup/Dbtup.hpp>
@@ -660,53 +658,62 @@ void Backup::execDBINFO_SCANREQ(Signal *
 {
   jamEntry();
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
+  const Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
 
-  char buf[512];
-  struct dbinfo_ratelimit rl;
-  struct dbinfo_row r;
+  Ndbinfo::Ratelimit rl;
 
-  dbinfo_ratelimit_init(&rl, &req);
-
-  if(req.tableId == NDBINFO_BACKUP_RECORDS_TABLEID)
+  if(req.tableId == Ndbinfo::BACKUP_RECORDS_TABLEID)
   {
+#if 0
+// TODO
     BackupRecordPtr ptr LINT_SET_PTR;
-    for(c_backups.first(ptr); ptr.i != RNIL; c_backups.next(ptr))
+    ptr.i = cursor->data[0];
+    while(c_backups.get(ptr))
     {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, ptr.i);
-      dbinfo_write_row_column_uint32(&r, ptr.p->backupId);
-      dbinfo_write_row_column_uint32(&r, ptr.p->masterRef);
-      dbinfo_write_row_column_uint32(&r, ptr.p->clientRef);
-      dbinfo_write_row_column_uint32(&r, ptr.p->slaveState.getState());
-      dbinfo_write_row_column_uint32(&r, (Uint32)ptr.p->noOfBytes); // TODO
-      dbinfo_write_row_column_uint32(&r, (Uint32)ptr.p->noOfRecords); // TODO
-      dbinfo_write_row_column_uint32(&r, (Uint32)ptr.p->noOfLogBytes); // TODO
-      dbinfo_write_row_column_uint32(&r, (Uint32)ptr.p->noOfLogRecords); //TODO
-      dbinfo_write_row_column_uint32(&r, ptr.p->errorCode);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
-    }
-  }
-  else if( req.tableId == NDBINFO_BACKUP_PARAMETERS_TABLEID )
-  {
-    dbinfo_write_row_init(&r, buf, sizeof(buf));
-    dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-    dbinfo_write_row_column_uint32(&r, m_curr_disk_write_speed);
-    dbinfo_write_row_column_uint32(&r, 4*m_words_written_this_period);
-    dbinfo_write_row_column_uint32(&r, m_overflow_disk_write);
-    dbinfo_write_row_column_uint32(&r, m_reset_delay_used);
-    dbinfo_write_row_column_uint32(&r, 0); // Uninteresting m_reset_disk_speed_time);
-    dbinfo_write_row_column_uint32(&r, c_backupPool.getSize());
-    dbinfo_write_row_column_uint32(&r, c_backupFilePool.getSize());
-    dbinfo_write_row_column_uint32(&r, c_tablePool.getSize());
-    dbinfo_write_row_column_uint32(&r, c_triggerPool.getSize());
-    dbinfo_write_row_column_uint32(&r, c_fragmentPool.getSize());
-    dbinfo_write_row_column_uint32(&r, c_pagePool.getSize());
-    dbinfo_write_row_column_uint32(&r, c_defaults.m_compressed_backup);
-    dbinfo_write_row_column_uint32(&r, c_defaults.m_compressed_lcp);
-    dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(ptr.i);
+      row.write_uint32(ptr.p->backupId);
+      row.write_uint32(ptr.p->masterRef);
+      row.write_uint32(ptr.p->clientRef);
+      row.write_uint32(ptr.p->slaveState.getState());
+      row.write_uint32((Uint32)ptr.p->noOfBytes); // TODO
+      row.write_uint32((Uint32)ptr.p->noOfRecords); // TODO
+      row.write_uint32((Uint32)ptr.p->noOfLogBytes); // TODO
+      row.write_uint32((Uint32)ptr.p->noOfLogRecords); //TODO
+      row.write_uint32(ptr.p->errorCode);
+      ndbinfo_send_row(signal, req, row, rl);
+      c_backups.next(ptr);
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
+    }
+#endif
+  }
+  else if(req.tableId == Ndbinfo::BACKUP_PARAMETERS_TABLEID)
+  {
+    Ndbinfo::Row row(signal, req);
+    row.write_uint32(getOwnNodeId());
+    row.write_uint32(m_curr_disk_write_speed);
+    row.write_uint32(4*m_words_written_this_period);
+    row.write_uint32(m_overflow_disk_write);
+    row.write_uint32(m_reset_delay_used);
+    row.write_uint32(0); // Uninteresting m_reset_disk_speed_time);
+    row.write_uint32(c_backupPool.getSize());
+    row.write_uint32(c_backupFilePool.getSize());
+    row.write_uint32(c_tablePool.getSize());
+    row.write_uint32(c_triggerPool.getSize());
+    row.write_uint32(c_fragmentPool.getSize());
+    row.write_uint32(c_pagePool.getSize());
+    row.write_uint32(c_defaults.m_compressed_backup);
+    row.write_uint32(c_defaults.m_compressed_lcp);
+    ndbinfo_send_row(signal, req, row, rl);
   }
-  else if( req.tableId == NDBINFO_POOLS_TABLEID )
+  else if(req.tableId == Ndbinfo::POOLS_TABLEID)
   {
     struct {
       const char* poolname;
@@ -735,25 +742,30 @@ void Backup::execDBINFO_SCANREQ(Signal *
           { NULL, 0, 0}
         };
 
+    Uint32 pool = cursor->data[0];
     BlockNumber bn = blockToMain(number());
-    for(int i=0; pools[i].poolname; i++)
+    while(pools[pool].poolname)
     {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, bn);           // block number
-      dbinfo_write_row_column_uint32(&r, req.instance); // block instance
-      dbinfo_write_row_column(&r, pools[i].poolname, strlen(pools[i].poolname));
-      dbinfo_write_row_column_uint32(&r, pools[i].free);
-      dbinfo_write_row_column_uint32(&r, pools[i].size);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
+      jam();
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_string(pools[pool].poolname);
+      row.write_uint32(pools[pool].free);
+      row.write_uint32(pools[pool].size);
+      ndbinfo_send_row(signal, req, row, rl);
+      pool++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
     }
   }
 
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, DbinfoScanReq::SignalLengthWithCursor * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 
 bool

=== modified file 'storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp	2009-07-03 10:31:30 +0000
@@ -36,12 +36,6 @@
 #include <signaldata/TransIdAI.hpp>
 #include <KeyDescriptor.hpp>
 
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
-
-// TO_DO_RONM is a label for comments on what needs to be improved in future versions
-// when more time is given.
-
 #ifdef VM_TRACE
 #define DEBUG(x) ndbout << "DBACC: "<< x << endl;
 #else
@@ -8226,32 +8220,23 @@ void Dbacc::execDBINFO_SCANREQ(Signal *s
   jamEntry();
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
 
-  char buf[512];
-  struct dbinfo_ratelimit rl;
-  struct dbinfo_row r;
-
-  dbinfo_ratelimit_init(&rl, &req);
-
-  if(req.tableId == NDBINFO_MEMUSAGE_TABLEID)
-  {
-    jam();
-    dbinfo_write_row_init(&r, buf, sizeof(buf));
-    dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-    dbinfo_write_row_column_uint32(&r, blockToMain(number()));// block number
-    dbinfo_write_row_column_uint32(&r, req.instance);         // block instance
-    dbinfo_write_row_column(&r, "IndexMemory", 11);
-    Uint32 page_size_kb= sizeof(*rpPageptr.p);;
-    dbinfo_write_row_column(&r, (char*)&page_size_kb, 4); // 8kb
-    dbinfo_write_row_column_uint32(&r, cnoOfAllocatedPages); // alloced pages
-    dbinfo_write_row_column_uint32(&r, cpagesize); // number of pages
-    dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
-  }
-
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, DbinfoScanReq::SignalLengthWithCursor * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  Ndbinfo::Ratelimit rl;
+
+  if(req.tableId == Ndbinfo::MEMUSAGE_TABLEID)
+  {
+    jam();
+    Ndbinfo::Row row(signal, req);
+    row.write_uint32(getOwnNodeId());
+    row.write_uint32(blockToMain(number())); // block number
+    row.write_uint32(instance());            // block instance
+    row.write_string("IndexMemory");
+    row.write_uint32(sizeof(*rpPageptr.p));
+    row.write_uint32(cnoOfAllocatedPages);   // alloced pages
+    row.write_uint32(cpagesize);             // number of pages
+    ndbinfo_send_row(signal, req, row, rl);
+  }
+
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 
 void

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2009-06-16 12:25:18 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2009-07-03 11:13:59 +0000
@@ -99,8 +99,6 @@ extern EventLogger * g_eventLogger;
 
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
 
 #define ZNOT_FOUND 626
 #define ZALREADYEXIST 630
@@ -277,15 +275,13 @@ Dbdict::execDUMP_STATE_ORD(Signal* signa
 void Dbdict::execDBINFO_SCANREQ(Signal *signal)
 {
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
-  char buf[512];
-  struct dbinfo_row r;
-  struct dbinfo_ratelimit rl;
-
-  dbinfo_ratelimit_init(&rl, &req);
+  const Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
+  Ndbinfo::Ratelimit rl;
 
   jamEntry();
 
-  if(req.tableId == NDBINFO_POOLS_TABLEID)
+  if(req.tableId == Ndbinfo::POOLS_TABLEID)
   {
     struct {
       const char* poolname;
@@ -368,25 +364,30 @@ void Dbdict::execDBINFO_SCANREQ(Signal *
           { NULL, 0, 0}
         };
 
+    Uint32 pool = cursor->data[0];
     BlockNumber bn = blockToMain(number());
-    for(int i=0; pools[i].poolname; i++)
+    while(pools[pool].poolname)
     {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, bn);           // block number
-      dbinfo_write_row_column_uint32(&r, req.instance); // block instance
-      dbinfo_write_row_column(&r, pools[i].poolname, strlen(pools[i].poolname));
-      dbinfo_write_row_column_uint32(&r, pools[i].free);
-      dbinfo_write_row_column_uint32(&r, pools[i].size);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
+      jam();
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_string(pools[pool].poolname);
+      row.write_uint32(pools[pool].free);
+      row.write_uint32(pools[pool].size);
+      ndbinfo_send_row(signal, req, row, rl);
+      pool++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
     }
   }
 
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, DbinfoScanReq::SignalLengthWithCursor * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 
 

=== modified file 'storage/ndb/src/kernel/blocks/dbinfo/CMakeLists.txt'
--- a/storage/ndb/src/kernel/blocks/dbinfo/CMakeLists.txt	2008-10-08 08:12:18 +0000
+++ b/storage/ndb/src/kernel/blocks/dbinfo/CMakeLists.txt	2009-07-03 10:31:30 +0000
@@ -18,7 +18,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/
 INCLUDE(${CMAKE_SOURCE_DIR}/storage/ndb/config/type_kernel.cmake)
 
 ADD_LIBRARY(ndbdbinfo STATIC
-		      Dbinfo.cpp
-		      ndbinfo_helpers.cpp
+	Dbinfo.cpp
 )
 

=== modified file 'storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp'
--- a/storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp	2009-06-23 14:07:58 +0000
+++ b/storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp	2009-07-03 10:31:30 +0000
@@ -1,4 +1,5 @@
-/* Copyright (C) 2007 MySQL AB
+/* Copyright (C) 2007-2008 MySQL AB, 2009 Sun Microsystems Inc.
+   All rights reserved. Use is subject to license terms.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -14,7 +15,6 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #include "Dbinfo.hpp"
-#include <ndbinfo.h>
 
 #include <signaldata/NodeFailRep.hpp>
 #include <signaldata/ReadNodesConf.hpp>
@@ -22,9 +22,6 @@
 #include <signaldata/DumpStateOrd.hpp>
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include "ndbinfo_tables.h"
-#include "ndbinfo_tableids.h"
-#include <AttributeHeader.hpp>
 
 Uint32 dbinfo_blocks[] = { DBACC, DBTUP, BACKUP, DBTC, SUMA, DBUTIL, TRIX, DBTUX, DBDICT, 0};
 
@@ -34,6 +31,8 @@ Dbinfo::Dbinfo(Block_context& ctx) :
 {
   BLOCK_CONSTRUCTOR(Dbinfo);
 
+  STATIC_ASSERT(sizeof(DbinfoScanCursor) == sizeof(Ndbinfo::ScanCursor));
+
   c_nodePool.setSize(MAX_NDB_NODES);
 
   /* Add Received Signals */
@@ -44,8 +43,6 @@ Dbinfo::Dbinfo(Block_context& ctx) :
   addRecSignal(GSN_DBINFO_SCANREQ, &Dbinfo::execDBINFO_SCANREQ);
   addRecSignal(GSN_DBINFO_SCANCONF, &Dbinfo::execDBINFO_SCANCONF);
 
-  addRecSignal(GSN_DBINFO_TRANSID_AI, &Dbinfo::execDBINFO_TRANSID_AI);
-
   addRecSignal(GSN_READ_NODESCONF, &Dbinfo::execREAD_NODESCONF);
   addRecSignal(GSN_NODE_FAILREP, &Dbinfo::execNODE_FAILREP);
   addRecSignal(GSN_INCL_NODEREQ, &Dbinfo::execINCL_NODEREQ);
@@ -102,68 +99,6 @@ void Dbinfo::sendSTTORRY(Signal* signal)
   sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
 }
 
-/*
- * Executing DBINFO_TRANSID_AI is only for debugging
- * We use this as part of the DUMP interface
- * and during debugging.
- */
-void Dbinfo::execDBINFO_TRANSID_AI(Signal* signal)
-{
-  jamEntry();
-  TransIdAI *tidai= (TransIdAI*)signal->theData;
-
-  if(!assembleFragments(signal)){
-    return;
-  }
-
-  const Uint32 tableId= tidai->transId[0];
-  const int ncols = ndbinfo_tables[tableId]->ncols;
-
-  SectionHandle handle(this, signal);
-  SegmentedSectionPtr ptr;
-  handle.getSection(ptr, 0);
-
-  char rowbuf[1024];
-  char *row= rowbuf;
-  copy((Uint32*)rowbuf, ptr);
-
-  //Uint32 rowsz= ptr.sz;
-  int len;
-
-  for(int i=0; i<ncols; i++)
-  {
-    jam();
-    AttributeHeader ah(*(Uint32*)row);
-    row+=ah.getHeaderSize()*sizeof(Uint32);
-
-    ndbout << "AI " << ah.getAttributeId() << " ";
-    len= ah.getByteSize();
-    ndbout << "||" << len << "||" << " ";
-    ndbout << "Table " << tableId << " ::: ";
-    switch(ndbinfo_tables[tableId]->col[i].coltype)
-    {
-    case NDBINFO_TYPE_NUMBER:
-      jam();
-      ndbout << *(Uint32*)row;
-      row+= len;
-      break;
-    case NDBINFO_TYPE_STRING:
-      jam();
-      char b[512];
-      memcpy(b,row,len);
-      b[len]=0;
-      ndbout << b;
-      row+= len;
-      break;
-    default:
-      ndbassert(false);
-      break;
-    };
-    ndbout << endl;
-  }
-  releaseSections(handle);
-}
-
 void Dbinfo::execDUMP_STATE_ORD(Signal* signal)
 {
   jamEntry();
@@ -174,11 +109,11 @@ void Dbinfo::execDUMP_STATE_ORD(Signal* 
     jam();
     ndbout_c("--- BEGIN NDB$INFO.TABLES ---");
     char create_sql[512];
-    for(Uint32 i=0;i<number_ndbinfo_tables;i++)
+    for(int i = 0; i < Ndbinfo::getNumTables(); i++)
     {
-      ndbinfo_create_sql(ndbinfo_tables[i],
-                         create_sql, sizeof(create_sql));
-      ndbout_c("%d,%s,%s",i,ndbinfo_tables[i]->name,create_sql);
+      const Ndbinfo::Table& tab = Ndbinfo::getTable(i);
+      Ndbinfo::create_sql(tab, create_sql, sizeof(create_sql));
+      ndbout_c("%d,%s,%s", i, tab.m.name, create_sql);
     }
     ndbout_c("--- END NDB$INFO.TABLES ---");
     break;
@@ -186,339 +121,335 @@ void Dbinfo::execDUMP_STATE_ORD(Signal* 
   case DumpStateOrd::DbinfoListColumns:
     jam();
     ndbout_c("--- BEGIN NDB$INFO.COLUMNS ---");
-    for(Uint32 i=0;i<number_ndbinfo_tables;i++)
+    for(int i = 0; i < Ndbinfo::getNumTables(); i++)
     {
-      struct ndbinfo_table *t= ndbinfo_tables[i];
+      const Ndbinfo::Table& tab = Ndbinfo::getTable(i);
 
-      for(int j=0;j<t->ncols;j++)
-        ndbout_c("%d,%d,%s,%d",i,j,t->col[j].name,t->col[j].coltype);
+      for(int j = 0; j < tab.m.ncols; j++)
+        ndbout_c("%d,%d,%s,%d", i, j,
+                 tab.col[j].name, tab.col[j].coltype);
     }
     ndbout_c("--- END NDB$INFO.COLUMNS ---");
     break;
 
-  case DumpStateOrd::DbinfoScanTable:
-    jam();
-    const Uint32 tableId= signal->theData[1];
-
-    DbinfoScanReq *req = (DbinfoScanReq*)signal->theData;
-    req->tableId= tableId;
-    req->senderRef= reference();
-    req->apiRef= reference();
-    req->apiTxnId= tableId;
-    req->requestInfo= DbinfoScanReq::AllColumns | DbinfoScanReq::StartScan;
-    req->colBitmapLo= ~0;
-    req->colBitmapHi= ~0;
-    req->maxRows= 2;
-    req->maxBytes= 0;
-    req->rows_total= 0;
-    req->word_total= 0;
-
-    ndbout_c("BEGIN DBINFO DUMP SCAN on %u",tableId);
-
-    sendSignal(reference(), GSN_DBINFO_SCANREQ,
-               signal, DbinfoScanReq::SignalLength, JBB);
-    break;
   };
 }
 
-void Dbinfo::execDBINFO_SCANREQ(Signal *signal)
+Uint32 Dbinfo::find_next_node(Uint32 node) const
 {
-  jamEntry();
-  DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
+  node++;
+  while(!c_aliveNodes.get(node) &&
+        node < MAX_NDB_NODES)
+     node++;
 
-  const Uint32 tableId= req.tableId;
-  const Uint32 apiRef= req.apiRef;
-  const Uint32 senderRef= req.senderRef;
-  const Uint32 apiTxnId= req.apiTxnId;
-  //const Uint32 colBitmapLo= req.colBitmapLo;
-  //const Uint32 colBitmapHi= req.colBitmapHi;
-  //const Uint32 requestInfo= req.requestInfo;
+  if (node == MAX_NDB_NODES)
+    return 0;
+  return node;
+}
 
-  Uint32 i;
-  int j;
-  int startid= 0;
+Uint32 Dbinfo::find_next_block(Uint32 block) const
+{
+  int i = 0;
+  // Find current blocks position
+  while (dbinfo_blocks[i] != block &&
+         dbinfo_blocks[i] != 0)
+    i++;
 
-  int startTableId, startColumnId;
+  // Make sure current block was found
+  ndbrequire(dbinfo_blocks[i]);
 
-  int continue_sending;
+  // Return the next block(which might be 0)
+  return dbinfo_blocks[++i];
+}
 
-  char buf[1024];
-  struct dbinfo_row r;
-  struct dbinfo_ratelimit rl;
+bool Dbinfo::find_next(Ndbinfo::ScanCursor* cursor) const
+{
+  Uint32 node = refToNode(cursor->currRef);
+  Uint32 block = refToBlock(cursor->currRef);
+  const Uint32 instance = refToInstance(cursor->currRef);
+  ndbrequire(instance == 0);
 
-  switch(req.tableId)
+  if (block)
   {
-  case NDBINFO_TABLES_TABLEID:
     jam();
-
-    char create_sql[512];
-
-    dbinfo_ratelimit_init(&rl, &req);
-
-    if(!(req.requestInfo & DbinfoScanReq::StartScan))
+    if (block == DBINFO)
     {
       jam();
-      startid= req.cursor.cur_item;
-    }
 
-    for(i=startid;dbinfo_ratelimit_continue(&rl) && i<number_ndbinfo_tables;i++)
-    {
-      jam();
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      ndbinfo_create_sql(ndbinfo_tables[i],
-                         create_sql, sizeof(create_sql));
-
-      dbinfo_write_row_column_uint32(&r, i);
-      dbinfo_write_row_column(&r, ndbinfo_tables[i]->name,
-                              strlen(ndbinfo_tables[i]->name)+1);
-      dbinfo_write_row_column(&r, create_sql, strlen(create_sql)+1);
+      // Starting scan on this node
+      ndbrequire(node == getOwnNodeId());
 
-      dbinfo_send_row(signal,r,rl,apiTxnId,apiRef);
+      // Start on first block
+      cursor->currRef = numberToRef(dbinfo_blocks[0], node);

+      return true;
     }
 
-    if(!dbinfo_ratelimit_continue(&rl) && i < number_ndbinfo_tables)
+    // Find next block
+    block = find_next_block(block);
+    if (block)
     {
       jam();
-      dbinfo_ratelimit_sendconf(signal,req,rl,i);
-    }
-    else
-    {
-      jam();
-      DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-      conf->tableId= req.tableId;
-      conf->senderRef= req.senderRef;
-      conf->apiTxnId= req.apiTxnId;
-      conf->requestInfo= 0;
-      sendSignal(req.senderRef, GSN_DBINFO_SCANCONF, signal,
-                 DbinfoScanConf::SignalLength, JBB);
+      cursor->currRef = numberToRef(block, node);
+      return true;
     }
+  }
 
-    break;
+  node = find_next_node(node);
+  if (node)
+  {
+    jam();
+    block = DBINFO;
+    cursor->currRef = numberToRef(block, node);
+    return true;
+  }
 
-  case NDBINFO_COLUMNS_TABLEID:
+  // No more nodes -> done
+  cursor->currRef = 0;
+  return false;
+}
+
+void Dbinfo::execDBINFO_SCANREQ(Signal *signal)
+{
+  jamEntry();
+  DbinfoScanReq* req_ptr = (DbinfoScanReq*)signal->getDataPtrSend();
+  const Uint32 senderRef = signal->header.theSendersBlockRef;
+
+  // Copy signal on stack
+  DbinfoScanReq req = *req_ptr;
+
+  const Uint32 resultData = req.resultData;
+  const Uint32 transId0 = req.transId[0];
+  const Uint32 transId1 = req.transId[1];
+  const Uint32 resultRef = req.resultRef;
+
+  // Validate tableId
+  const Uint32 tableId = req.tableId;
+  if (tableId >= Ndbinfo::getNumTables())
+  {
+    jam();
+    DbinfoScanRef *ref= (DbinfoScanRef*)signal->getDataPtrSend();
+    ref->resultData = resultData;
+    ref->transId[0] = transId0;
+    ref->transId[1] = transId1;
+    ref->resultRef = resultRef;
+    ref->errorCode= DbinfoScanRef::NoTable;
+    sendSignal(senderRef, GSN_DBINFO_SCANREF, signal,
+               DbinfoScanRef::SignalLength, JBB);
+    return;
+  }
+
+  // TODO Check all scan parameters
+
+  Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
+  Uint32 signal_length = signal->getLength();
+  if (signal_length == DbinfoScanReq::SignalLength)
+  {
+    // Initialize cursor
     jam();
+    cursor->senderRef = senderRef;
+    cursor->saveSenderRef = 0;
+    cursor->currRef = 0;
+    cursor->saveCurrRef = 0;
+    // Reset all data holders
+    memset(cursor->data, 0, sizeof(cursor->data));
+    cursor->flags = 0;
+    cursor->totalRows = 0;
+    cursor->totalBytes = 0;
+    req.cursor_sz = Ndbinfo::ScanCursor::Length;
+    signal_length += req.cursor_sz;
+  }
+  ndbrequire(signal_length ==
+             DbinfoScanReq::SignalLength + Ndbinfo::ScanCursor::Length);
+  ndbrequire(req.cursor_sz == Ndbinfo::ScanCursor::Length);
 
-    startTableId= 0;
-    startColumnId= 0;
+  switch(tableId)
+  {
+  case Ndbinfo::TABLES_TABLEID:
+  {
+    jam();
 
-    if(!(req.requestInfo & DbinfoScanReq::StartScan))
+    Ndbinfo::Ratelimit rl;
+    char create_sql[512];
+    Uint32 tableId = cursor->data[0];
+
+    while(tableId < Ndbinfo::getNumTables())
     {
       jam();
-      startTableId= req.cursor.cur_item >> 8;
-      startColumnId= req.cursor.cur_item & 0xFF;
+      const Ndbinfo::Table& tab = Ndbinfo::getTable(tableId);
+      Ndbinfo::Row row(signal, req);
+      Ndbinfo::create_sql(tab, create_sql, sizeof(create_sql));
+      row.write_uint32(tableId);
+      row.write_string(tab.m.name);
+      row.write_string(create_sql);
+      ndbinfo_send_row(signal, req, row, rl);
+
+      tableId++;
+
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, tableId);
+        return;
+      }
     }
 
-    struct ndbinfo_table *t;
+    // All tables sent
+    req.cursor_sz = 0; // Close cursor
+    ndbinfo_send_scan_conf(signal, req, rl);
+    return;
+
+    break;
+  }
 
-    dbinfo_ratelimit_init(&rl, &req);
+  case Ndbinfo::COLUMNS_TABLEID:
+  {
+    jam();
 
-    continue_sending= 1;
+    Ndbinfo::Ratelimit rl;
+    Uint32 tableId = cursor->data[0];
+    Uint32 columnId = cursor->data[1];
 
-    for(i=startTableId; continue_sending && i<number_ndbinfo_tables; i++)
+    while(tableId < Ndbinfo::getNumTables())
     {
       jam();
-      t= ndbinfo_tables[i];
-
-      for(j=startColumnId; continue_sending && j<t->ncols;j++)
+      const Ndbinfo::Table& tab = Ndbinfo::getTable(tableId);
+      while(columnId < tab.m.ncols)
       {
         jam();
-        dbinfo_write_row_init(&r, buf, sizeof(buf));
-        dbinfo_write_row_column_uint32(&r, i);
-        dbinfo_write_row_column_uint32(&r, j);
-        dbinfo_write_row_column(&r, t->col[j].name, strlen(t->col[j].name)+1);
-        const char* coltype_name= ndbinfo_coltype_to_string(t->col[j].coltype);
-        dbinfo_write_row_column(&r, coltype_name, strlen(coltype_name)+1);
-        dbinfo_send_row(signal,r,rl, apiTxnId,apiRef);
+        Ndbinfo::Row row(signal, req);
+        row.write_uint32(tableId);
+        row.write_uint32(columnId);
+        row.write_string(tab.col[columnId].name);
+        row.write_string(Ndbinfo::coltype_to_string(tab.col[columnId].coltype));
+        ndbinfo_send_row(signal, req, row, rl);
 
-        continue_sending= dbinfo_ratelimit_continue(&rl);
+        assert(columnId < 256);
+        columnId++;
+
+        if(rl.need_break(req))
+        {
+          jam();
+          ndbinfo_send_scan_break(signal, req, rl, tableId, columnId);
+          return;
+        }
       }
-      startColumnId= 0;
+      columnId = 0;
+      tableId++;
     }
 
-    if((i < number_ndbinfo_tables || j < t->ncols))
-    {
-      jam();
-      i--;
-      dbinfo_ratelimit_sendconf(signal, req, rl, (i << 8) | j);
-    }
-    else
-    {
-      jam();
-      DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-      conf->tableId= req.tableId;
-      conf->senderRef= req.senderRef;
-      conf->apiTxnId= req.apiTxnId;
-      conf->requestInfo= 0;
-      sendSignal(req.senderRef, GSN_DBINFO_SCANCONF, signal,
-                 DbinfoScanConf::SignalLength, JBB);
-    }
+    // All tables and columns sent
+    req.cursor_sz = 0; // Close cursor
+    ndbinfo_send_scan_conf(signal, req, rl);
 
     break;
+  }
 
   default:
+  {
     jam();
 
-    if(tableId > number_ndbinfo_tables)
-    {
-      jam();
-      DbinfoScanRef *ref= (DbinfoScanRef*)signal->getDataPtrSend();
-      ref->tableId= tableId;
-      ref->apiTxnId= apiTxnId;
-      ref->errorCode= DbinfoScanRef::NoTable;
-      sendSignal(senderRef, GSN_DBINFO_SCANREF, signal,
-                 DbinfoScanRef::SignalLength, JBB);
-      break;
-    }
-
     ndbassert(tableId > 1);
 
-    if(signal->getLength() == DbinfoScanReq::SignalLength)
-    {
-      /*
-       * We've gotten a request from application, first
-       * ScanReq signal. start from beginning
-       */
+    //printSignalHeader(stdout, signal->header, 99, 98, true);
+    //printDBINFO_SCAN(stdout, signal->theData, signal->getLength(), 0);
 
+    if (Ndbinfo::ScanCursor::getHasMoreData(cursor->flags) ||
+        find_next(cursor))
+    {
       jam();
+      ndbrequire(cursor->currRef);
 
-      DbinfoScanReq ireq= *(DbinfoScanReq*)signal->theData;
-      DbinfoScanReq *oreq= (DbinfoScanReq*)signal->getDataPtrSend();
+      // CONF or REF should be sent back here
+      cursor->senderRef = reference();
 
-      memcpy(signal->getDataPtrSend(),&ireq,DbinfoScanReq::SignalLength*sizeof(Uint32));
-      oreq->senderRef= reference();
-      oreq->cursor.cur_requestInfo= 0;
-      oreq->cursor.cur_node= 0;
-      oreq->cursor.cur_block= DBINFO;
-      oreq->cursor.cur_item= 0;
-
-      for(oreq->cursor.cur_node= 0;
-          !c_aliveNodes.get(oreq->cursor.cur_node);
-          oreq->cursor.cur_node++)
-        ;
-
-      sendSignal(numberToRef(DBINFO,oreq->cursor.cur_node), GSN_DBINFO_SCANREQ,
-                 signal, DbinfoScanReq::SignalLengthWithCursor, JBB);
+      // Send SCANREQ
+      MEMCOPY_NO_WORDS(req_ptr,
+                       &req, signal_length);
+      sendSignal(cursor->currRef,
+                 GSN_DBINFO_SCANREQ,
+                 signal, signal_length, JBB);
     }
     else
     {
-      /**
-       * We have a cursor, so we need to continue scanning.
-       */
+      // Scan is done, send SCANCONF back to caller
       jam();
-      int next_dbinfo_block= 0;
-      if(req.cursor.cur_block != DBINFO)
-      {
-        while(dbinfo_blocks[next_dbinfo_block] != req.cursor.cur_block
-            && dbinfo_blocks[next_dbinfo_block] != 0)
-        {
-          jam();
-          next_dbinfo_block++;
-        }
-      }
-
-      DbinfoScanReq ireq= *(DbinfoScanReq*)signal->theData;
-      DbinfoScanReq *oreq= (DbinfoScanReq*)signal->getDataPtrSend();
-
-      memcpy(signal->getDataPtrSend(),&ireq,signal->getLength()*sizeof(Uint32));
-      oreq->senderRef= reference(); //marty
-      oreq->cursor.cur_block= dbinfo_blocks[next_dbinfo_block];
-
-      sendSignal(numberToRef(oreq->cursor.cur_block, oreq->cursor.cur_node),
-                 GSN_DBINFO_SCANREQ,
-                 signal, signal->getLength(), JBB);
+      DbinfoScanConf *apiconf= (DbinfoScanConf*)signal->getDataPtrSend();
+      MEMCOPY_NO_WORDS(apiconf, &req, DbinfoScanConf::SignalLength);
+      // Set cursor_sz back to 0 to indicate end of scan
+      apiconf->cursor_sz = 0;
+      sendSignal(resultRef, GSN_DBINFO_SCANCONF, signal,
+                 DbinfoScanConf::SignalLength, JBB);
     }
     break;
-  };
+  }
+  }
 }
 
 void Dbinfo::execDBINFO_SCANCONF(Signal *signal)
 {
-  DbinfoScanConf conf= *(DbinfoScanConf*)signal->theData;
+  const DbinfoScanConf* conf_ptr= (const DbinfoScanConf*)signal->getDataPtr();
+  // Copy signal on stack
+  const DbinfoScanConf conf= *conf_ptr;
 
   jamEntry();
 
-  const Uint32 tableId= conf.tableId;
-  const Uint32 senderRef= conf.senderRef;
-  const Uint32 apiRef= conf.apiRef;
-  const Uint32 apiTxnId= conf.apiTxnId;
-  //const Uint32 colBitmapLo= conf.colBitmapLo;
-  //const Uint32 colBitmapHi= conf.colBitmapHi;
+  //printDBINFO_SCAN(stdout, signal->theData, signal->getLength(), 0);
 
-  DbinfoScanReq *oreq= (DbinfoScanReq*)signal->getDataPtrSend();
+  Uint32 signal_length = signal->getLength();
+  ndbrequire(signal_length ==
+             DbinfoScanReq::SignalLength+Ndbinfo::ScanCursor::Length);
+  ndbrequire(conf.cursor_sz == Ndbinfo::ScanCursor::Length);
 
-  memcpy(signal->getDataPtrSend(),&conf,signal->getLength()*sizeof(Uint32));
+  // Validate tableId
+  const Uint32 tableId= conf.tableId;
+  ndbassert(tableId < Ndbinfo::getNumTables());
 
-  if(conf.requestInfo & DbinfoScanConf::MoreData)
-  {
-    /*
-     * Continue a DUMP scan of DBINFO table (hit maxrows/maxbytes)
-     */
-    jam();
-    oreq->requestInfo &= ~(DbinfoScanReq::StartScan);
-    sendSignal(numberToRef(oreq->cursor.cur_block, oreq->cursor.cur_node),
-               GSN_DBINFO_SCANREQ,
-               signal, signal->getLength(), JBB);
-    return;
-  }
+  const Uint32 resultRef = conf.resultRef;
 
-  int next_dbinfo_block= 0;
+  // Copy cursor on stack
+  ndbrequire(conf.cursor_sz);
+  Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&conf);
 
-  if(signal->getLength() == DbinfoScanConf::DoneLength) // we have the ACK from a DUMP initiated scan
+  if (Ndbinfo::ScanCursor::getHasMoreData(cursor->flags) || conf.returnedRows)
   {
+    // Rate limit break, pass through to API
     jam();
-    ndbout_c("FINISHED DBINFO DUMP Scan on %u",signal->theData[0]);
+    ndbrequire(cursor->currRef);
+    DbinfoScanConf *apiconf = (DbinfoScanConf*) signal->getDataPtrSend();
+    MEMCOPY_NO_WORDS(apiconf, &conf, signal_length);
+    sendSignal(resultRef, GSN_DBINFO_SCANCONF, signal, signal_length, JBB);
     return;
   }
 
-  if(conf.cursor.cur_block != DBINFO)
+  if (find_next(cursor))
   {
     jam();
-    while(dbinfo_blocks[next_dbinfo_block] != conf.cursor.cur_block
-          && dbinfo_blocks[next_dbinfo_block] != 0)
-    {
-      jam();
-      next_dbinfo_block++;
-    }
-  }
+    ndbrequire(cursor->currRef);
 
-  next_dbinfo_block++;
+    // CONF or REF should be sent back here
+    cursor->senderRef = reference();
 
-  if(dbinfo_blocks[next_dbinfo_block]!=0)
-  {
-    jam();
-    oreq->cursor.cur_block= dbinfo_blocks[next_dbinfo_block];
-  }
-  else
-  {
-    for(oreq->cursor.cur_node++;
-        !c_aliveNodes.get(oreq->cursor.cur_node)
-          && oreq->cursor.cur_node < MAX_NDB_NODES;
-        oreq->cursor.cur_node++)
-      ;
-
-    if(oreq->cursor.cur_node < MAX_NDB_NODES)
-    {
-      jam();
-      oreq->cursor.cur_requestInfo= 0;
-      oreq->cursor.cur_block= DBINFO;
-      oreq->cursor.cur_item= 0;
-    }
-    else
-    {
-      jam();
-      DbinfoScanConf *apiconf= (DbinfoScanConf*)signal->getDataPtrSend();
-      apiconf->tableId= tableId;
-      apiconf->senderRef= senderRef;
-      apiconf->apiTxnId= apiTxnId;
-      sendSignal(apiRef, GSN_DBINFO_SCANCONF, signal,
-                 DbinfoScanConf::DoneLength, JBB);
-      return;
-    }
+    // Send SCANREQ
+    MEMCOPY_NO_WORDS(signal->getDataPtrSend(),
+                     &conf, signal_length);
+    sendSignal(cursor->currRef,
+               GSN_DBINFO_SCANREQ,
+               signal, signal_length, JBB);
+    return;
   }
 
-  sendSignal(numberToRef(oreq->cursor.cur_block, oreq->cursor.cur_node),
-             GSN_DBINFO_SCANREQ,
-             signal, signal->getLength(), JBB);
+  // Scan is done, send SCANCONF back to caller
+  jam();
+  DbinfoScanConf *apiconf = (DbinfoScanConf*) signal->getDataPtrSend();
+  MEMCOPY_NO_WORDS(apiconf, &conf, DbinfoScanConf::SignalLength);
+
+  // Set cursor_sz back to 0 to indicate end of scan
+  apiconf->cursor_sz = 0;
+  sendSignal(resultRef, GSN_DBINFO_SCANCONF, signal,
+             DbinfoScanConf::SignalLength, JBB);
+  return;
 }
 
 

=== modified file 'storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.hpp'
--- a/storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.hpp	2008-10-05 07:14:37 +0000
+++ b/storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.hpp	2009-07-03 10:31:30 +0000
@@ -1,4 +1,5 @@
-/* Copyright (C) 2007 MySQL AB
+/* Copyright (C) 2007-2008 MySQL AB, 2009 Sun Microsystems Inc.
+   All rights reserved. Use is subject to license terms.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -49,8 +50,10 @@ protected:
   void execREAD_CONFIG_REQ(Signal*);
   void execDUMP_STATE_ORD(Signal* signal);
 
+  Uint32 find_next_node(Uint32 node) const;
+  Uint32 find_next_block(Uint32 block) const;
+  bool find_next(Ndbinfo::ScanCursor* cursor) const;
   void execDBINFO_SCANREQ(Signal *signal);
-  void execDBINFO_TRANSID_AI(Signal* signal);
   void execDBINFO_SCANCONF(Signal *signal);
 
   /* for maintaining c_aliveNodes */

=== removed file 'storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_helpers.cpp'
--- a/storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_helpers.cpp	2009-06-23 15:39:55 +0000
+++ b/storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_helpers.cpp	1970-01-01 00:00:00 +0000
@@ -1,61 +0,0 @@
-#include "Dbinfo.hpp"
-#include <ndbinfo.h>
-#include <AttributeHeader.hpp>
-#include <signaldata/DbinfoScan.hpp>
-
-void dbinfo_write_row_init(struct dbinfo_row *r, char* buf, int len)
-{
-  r->buf = r->curr = (Uint32*)buf;
-  r->end = r->buf + len;
-  r->col_count = 0;
-}
-
-int dbinfo_write_row_column(struct dbinfo_row *r, const char* col, int clen)
-{
-  // Create AttributeHeader
-  AttributeHeader ah(r->col_count++, clen);
-  const Uint32 header_sz = ah.getHeaderSize();
-  const Uint32 data_sz = ah.getDataSize();
-
-  // Check row buffer space
-  if((header_sz + data_sz) > (Uint32)(r->end - r->curr))
-  {
-    ndbout_c("Warning, too small ndbinfo row buffer");
-    assert(false);
-    return -1; // Not enough room.
-  }
-
-  // Write AttributeHeader to buffer
-  ah.insertHeader(r->curr);
-  r->curr += header_sz;
-
-  // Write data to buffer
-  memcpy(r->curr, col, clen);
-  r->curr += data_sz;
-
-  assert(r->curr <= r->end);
-  return 0;
-}
-
-int dbinfo_write_row_column_uint32(struct dbinfo_row *r, Uint32 value)
-{
-  return dbinfo_write_row_column(r, (char*)&value, sizeof(Uint32));
-}
-
-void dbinfo_ratelimit_init(struct dbinfo_ratelimit *rl, struct DbinfoScanReq *r)
-{
-  rl->maxRows= r->maxRows;
-  rl->maxBytes= r->maxBytes;
-  rl->rows_total= r->rows_total;
-  rl->bytes_total= r->word_total;
-  rl->rows= 0;
-  rl->bytes= 0;
-}
-
-int dbinfo_ratelimit_continue(struct dbinfo_ratelimit *rl)
-{
-  if(((rl->maxRows==0) || (rl->maxRows > rl->rows))
-     && ((rl->maxBytes==0) || (rl->maxBytes > rl->bytes)) )
-    return 1;
-  return 0;
-}

=== removed file 'storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_tableids.h'
--- a/storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_tableids.h	2008-10-05 07:14:21 +0000
+++ b/storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_tableids.h	1970-01-01 00:00:00 +0000
@@ -1,21 +0,0 @@
-
-#ifndef NDBINFO_TABLEIDS_H
-#define NDBINFO_TABLEIDS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define NDBINFO_TABLES_TABLEID    0
-#define NDBINFO_COLUMNS_TABLEID   1
-#define NDBINFO_MEMUSAGE_TABLEID  2
-#define NDBINFO_LOGDESTINATION_TABLEID  3
-#define NDBINFO_BACKUP_RECORDS_TABLEID 4
-#define NDBINFO_BACKUP_PARAMETERS_TABLEID 5
-#define NDBINFO_POOLS_TABLEID                     6
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

=== removed file 'storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_tables.h'
--- a/storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_tables.h	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/dbinfo/ndbinfo_tables.h	1970-01-01 00:00:00 +0000
@@ -1,133 +0,0 @@
-/* Copyright (C) 2007 MySQL AB
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; version 2 of the License.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
-#ifndef NDBINFO_TABLES_H
-#define NDBINFO_TABLES_H
-
-#include <ndbinfo.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** Reserved for DBINFO only */
-DECLARE_NDBINFO_TABLE(ndbinfo_TABLES,3)
-     = { "TABLES", 3, 0,
-        {
-          {"TABLE_ID",  NDBINFO_TYPE_NUMBER},
-          {"TABLE_NAME",NDBINFO_TYPE_STRING},
-          {"CREATE_SQL",NDBINFO_TYPE_STRING},
-        }};
-
-/** Reserved for DBINFO only */
-DECLARE_NDBINFO_TABLE(ndbinfo_COLUMNS,4)
-     = { "COLUMNS", 4, 0,
-        {
-          {"TABLE_ID",    NDBINFO_TYPE_NUMBER},
-          {"COLUMN_ID",   NDBINFO_TYPE_NUMBER},
-          {"COLUMN_NAME", NDBINFO_TYPE_STRING},
-          {"COLUMN_TYPE", NDBINFO_TYPE_STRING},
-        }};
-
-DECLARE_NDBINFO_TABLE(ndbinfo_MEMUSAGE,7)
-     = { "MEMUSAGE", 7, 0,
-        {
-          {"NODE_ID",          NDBINFO_TYPE_NUMBER},
-          {"BLOCK_NUMBER",     NDBINFO_TYPE_NUMBER},
-          {"BLOCK_INSTANCE",   NDBINFO_TYPE_NUMBER},
-          {"RESOURCE_NAME",    NDBINFO_TYPE_STRING},
-          {"PAGE_SIZE",        NDBINFO_TYPE_NUMBER},
-          {"PAGES_USED",       NDBINFO_TYPE_NUMBER},
-          {"PAGES_TOTAL",      NDBINFO_TYPE_NUMBER},
-        }};
-
-DECLARE_NDBINFO_TABLE(ndbinfo_LOGDESTINATION,5) =
-{ "LOGDESTINATION", 5, 0,
- {
-   {"NODE_ID",NDBINFO_TYPE_NUMBER},
-   {"TYPE",NDBINFO_TYPE_STRING},
-   {"PARAMS",NDBINFO_TYPE_STRING},
-   {"CURRENT_SIZE",NDBINFO_TYPE_NUMBER},
-   {"MAX_SIZE",NDBINFO_TYPE_NUMBER},
- }
-};
-
-DECLARE_NDBINFO_TABLE(ndbinfo_BACKUP_RECORDS,11)
-= { "BACKUP_RECORDS", 11, 0,
-   {
-     {"NODE_ID",          NDBINFO_TYPE_NUMBER},
-     {"BACKUP_RECORD",    NDBINFO_TYPE_NUMBER},
-     {"BACKUP_ID",        NDBINFO_TYPE_NUMBER},
-     {"MASTER_REF",       NDBINFO_TYPE_NUMBER},
-     {"CLIENT_REF",       NDBINFO_TYPE_NUMBER},
-     {"STATE",            NDBINFO_TYPE_NUMBER},
-     {"BYTES",            NDBINFO_TYPE_NUMBER},
-     {"RECORDS",          NDBINFO_TYPE_NUMBER},
-     {"LOG_BYTES",        NDBINFO_TYPE_NUMBER},
-     {"LOG_RECORDS",      NDBINFO_TYPE_NUMBER},
-     {"ERROR_CODE",       NDBINFO_TYPE_NUMBER},
-   }
-};
-
-DECLARE_NDBINFO_TABLE(ndbinfo_BACKUP_PARAMETERS,14)
-= { "BACKUP_PARAMETERS", 14, 0,
-   {
-     {"NODE_ID",                  NDBINFO_TYPE_NUMBER},
-     {"CURRENT_DISK_WRITE_SPEED", NDBINFO_TYPE_NUMBER},
-     {"BYTES_WRITTEN_THIS_PERIOD",NDBINFO_TYPE_NUMBER},
-     {"OVERFLOW_DISK_WRITE",      NDBINFO_TYPE_NUMBER},
-     {"RESET_DELAY_USED",         NDBINFO_TYPE_NUMBER},
-     {"RESET_DISK_SPEED_TIME",    NDBINFO_TYPE_NUMBER},
-     {"BACKUP_POOL_SIZE",         NDBINFO_TYPE_NUMBER},
-     {"BACKUP_FILE_POOL_SIZE",    NDBINFO_TYPE_NUMBER},
-     {"TABLE_POOL_SIZE",          NDBINFO_TYPE_NUMBER},
-     {"TRIGGER_POOL_SIZE",        NDBINFO_TYPE_NUMBER},
-     {"FRAGMENT_POOL_SIZE",       NDBINFO_TYPE_NUMBER},
-     {"PAGE_POOL_SIZE",           NDBINFO_TYPE_NUMBER},
-     {"COMPRESSED_BACKUP",        NDBINFO_TYPE_NUMBER},
-     {"COMPRESSED_LCP",           NDBINFO_TYPE_NUMBER},
-   }
-};
-
-DECLARE_NDBINFO_TABLE(ndbinfo_POOLS,6)
-= { "POOLS", 6, 0,
-   {
-     {"NODE_ID",                  NDBINFO_TYPE_NUMBER},
-     {"BLOCK_NUMBER",             NDBINFO_TYPE_NUMBER},
-     {"BLOCK_INSTANCE",           NDBINFO_TYPE_NUMBER},
-     {"POOL_NAME",                NDBINFO_TYPE_STRING},
-     {"FREE",                     NDBINFO_TYPE_NUMBER},
-     {"SIZE",                     NDBINFO_TYPE_NUMBER},
-   }
-};
-
-static Uint32 number_ndbinfo_tables= 7;
-
-#define DBINFOTBL(x) (struct ndbinfo_table*)&x
-
-struct ndbinfo_table *ndbinfo_tables[] = {
-  DBINFOTBL(ndbinfo_TABLES),
-  DBINFOTBL(ndbinfo_COLUMNS),
-  DBINFOTBL(ndbinfo_MEMUSAGE),
-  DBINFOTBL(ndbinfo_LOGDESTINATION),
-  DBINFOTBL(ndbinfo_BACKUP_RECORDS),
-  DBINFOTBL(ndbinfo_BACKUP_PARAMETERS),
-  DBINFOTBL(ndbinfo_POOLS),
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2009-06-30 18:49:53 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2009-07-03 11:13:59 +0000
@@ -88,8 +88,6 @@
 
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
 
 
 // Use DEBUG to print messages that should be
@@ -11786,14 +11784,13 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
 void Dbtc::execDBINFO_SCANREQ(Signal *signal)
 {
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
-  char buf[512];
-  struct dbinfo_row r;
-  struct dbinfo_ratelimit rl;
-  dbinfo_ratelimit_init(&rl, &req);
+  const Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
+  Ndbinfo::Ratelimit rl;
 
   jamEntry();
 
-  if(req.tableId == NDBINFO_POOLS_TABLEID)
+  if(req.tableId == Ndbinfo::POOLS_TABLEID)
   {
     struct {
       const char* poolname;
@@ -11822,63 +11819,30 @@ void Dbtc::execDBINFO_SCANREQ(Signal *si
           { NULL, 0, 0}
         };
 
+    Uint32 pool = cursor->data[0];
     BlockNumber bn = blockToMain(number());
-    for(int i=0; pools[i].poolname; i++)
-    {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, bn);           // block number
-      dbinfo_write_row_column_uint32(&r, req.instance); // block instance
-      dbinfo_write_row_column(&r, pools[i].poolname, strlen(pools[i].poolname));
-      dbinfo_write_row_column_uint32(&r, pools[i].free);
-      dbinfo_write_row_column_uint32(&r, pools[i].size);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
-    }
-  }
-
-  /*  if(req->tableId ==
-  dbinfo_ratelimit_init(&rl, &req);
-
-    if(!(req.requestInfo & DbinfoScanReq::StartScan))
-      startid= req.cur_item;
-
-    for(i=startid;dbinfo_ratelimit_continue(&rl) && i<number_ndbinfo_tables;i++)
+    while(pools[pool].poolname)
     {
       jam();
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      ndbinfo_create_sql(ndbinfo_tables[i],
-                         create_sql, sizeof(create_sql));
-
-      dbinfo_write_row_column(&r, (char*)&i, sizeof(i));
-      dbinfo_write_row_column(&r, ndbinfo_tables[i]->name,
-                              strlen(ndbinfo_tables[i]->name));
-      dbinfo_write_row_column(&r, create_sql, strlen(create_sql));
-
-      dbinfo_send_row(signal,r,rl,apiTxnId,apiRef);
-    }
-
-    if(!dbinfo_ratelimit_continue(&rl) && i < number_ndbinfo_tables)
-    {
-      jam();
-      dbinfo_ratelimit_sendconf(signal,req,rl,i);
-    }
-    else
-    {
-      DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-      conf->tableId= req.tableId;
-      conf->senderRef= req.senderRef;
-      conf->apiTxnId= req.apiTxnId;
-      conf->requestInfo= 0;
-      sendSignal(req.senderRef, GSN_DBINFO_SCANCONF, signal,
-                 DbinfoScanConf::SignalLength, JBB);
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_string(pools[pool].poolname);
+      row.write_uint32(pools[pool].free);
+      row.write_uint32(pools[pool].size);
+      ndbinfo_send_row(signal, req, row, rl);
+      pool++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
     }
-  */
+  }
 
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, DbinfoScanReq::SignalLengthWithCursor * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 
 bool

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp	2009-06-30 18:22:56 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp	2009-07-03 11:13:59 +0000
@@ -30,8 +30,6 @@
 
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
 
 
 /* **************************************************************** */
@@ -76,33 +74,28 @@ void Dbtup::execDBINFO_SCANREQ(Signal* s
 {
   jamEntry();
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
-  const Uint32 reqlength= signal->getLength();
+  const Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
 
-  const Uint32 tableId= req.tableId;
-  const Uint32 instance= req.instance;
+  Ndbinfo::Ratelimit rl;
 
-  char buf[1024];
-  struct dbinfo_row r;
-  struct dbinfo_ratelimit rl;
-
-  dbinfo_ratelimit_init(&rl, &req);
-
-  if(tableId == NDBINFO_MEMUSAGE_TABLEID)
+  if(req.tableId == Ndbinfo::MEMUSAGE_TABLEID)
   {
     jam();
-    dbinfo_write_row_init(&r, buf, sizeof(buf));
-    dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-    dbinfo_write_row_column_uint32(&r, blockToMain(number()));// block number
-    dbinfo_write_row_column_uint32(&r, instance);             // block instance
-    dbinfo_write_row_column(&r, "DataMemory", 10);
-    Uint32 page_size_kb= sizeof(Page);;
-    dbinfo_write_row_column(&r, (char*)&page_size_kb, 4); // 8kb
-    dbinfo_write_row_column_uint32(&r, cTotNoFragPages); // alloced pages
-    dbinfo_write_row_column_uint32(&r, cTotPages); // number of pages
-    dbinfo_send_row(signal,r,rl,req.apiTxnId,req.apiRef);
+    Ndbinfo::Row row(signal, req);
+    row.write_uint32(getOwnNodeId());
+    row.write_uint32(blockToMain(number())); // block number
+    row.write_uint32(instance());            // block instance
+    row.write_string("DataMemory");
+    row.write_uint32(sizeof(Page));
+    row.write_uint32(cTotNoFragPages);       // alloced pages
+    row.write_uint32(cTotPages);             // number of pages
+    ndbinfo_send_row(signal, req, row, rl);
+
   }
-  if(req.tableId == NDBINFO_POOLS_TABLEID)
+  if(req.tableId == Ndbinfo::POOLS_TABLEID)
   {
+    jam();
     struct {
       const char* poolname;
       Uint32 free;
@@ -133,25 +126,52 @@ void Dbtup::execDBINFO_SCANREQ(Signal* s
           { NULL, 0, 0}
         };
 
+    Uint32 pool = cursor->data[0];
     BlockNumber bn = blockToMain(number());
-    for(int i=0; pools[i].poolname; i++)
+    while(pools[pool].poolname)
     {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, bn);       // block number
-      dbinfo_write_row_column_uint32(&r, instance); // block instance
-      dbinfo_write_row_column(&r, pools[i].poolname, strlen(pools[i].poolname));
-      dbinfo_write_row_column_uint32(&r, pools[i].free);
-      dbinfo_write_row_column_uint32(&r, pools[i].size);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
+      jam();
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_string(pools[pool].poolname);
+      row.write_uint32(pools[pool].free);
+      row.write_uint32(pools[pool].size);
+      ndbinfo_send_row(signal, req, row, rl);
+      pool++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
+    }
+  }
+  if(req.tableId == Ndbinfo::TEST_TABLEID)
+  {
+    Uint32 counter = cursor->data[0];
+    BlockNumber bn = blockToMain(number());
+    while(counter < 1000)
+    {
+      jam();
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_uint32(counter);
+      ndbinfo_send_row(signal, req, row, rl);
+      counter++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, counter);
+        return;
+      }
     }
   }
 
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, reqlength * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 
 #ifdef VM_TRACE

=== modified file 'storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp	2009-07-03 10:31:30 +0000
@@ -21,20 +21,18 @@
 
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
+
 
 void Dbtux::execDBINFO_SCANREQ(Signal *signal)
 {
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
-  char buf[512];
-  struct dbinfo_row r;
-  struct dbinfo_ratelimit rl;
-  dbinfo_ratelimit_init(&rl, &req);
+  const Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
+  Ndbinfo::Ratelimit rl;
 
   jamEntry();
 
-  if(req.tableId == NDBINFO_POOLS_TABLEID)
+  if(req.tableId == Ndbinfo::POOLS_TABLEID)
   {
     struct {
       const char* poolname;
@@ -66,25 +64,30 @@ void Dbtux::execDBINFO_SCANREQ(Signal *s
           { NULL, 0, 0}
         };
 
+    Uint32 pool = cursor->data[0];
     BlockNumber bn = blockToMain(number());
-    for(int i=0; pools[i].poolname; i++)
+    while(pools[pool].poolname)
     {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, bn);           // block number
-      dbinfo_write_row_column_uint32(&r, req.instance); // block instance
-      dbinfo_write_row_column(&r, pools[i].poolname, strlen(pools[i].poolname));
-      dbinfo_write_row_column_uint32(&r, pools[i].free);
-      dbinfo_write_row_column_uint32(&r, pools[i].size);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
+      jam();
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_string(pools[pool].poolname);
+      row.write_uint32(pools[pool].free);
+      row.write_uint32(pools[pool].size);
+      ndbinfo_send_row(signal, req, row, rl);
+      pool++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
     }
   }
 
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, DbinfoScanReq::SignalLengthWithCursor * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 
 /*

=== modified file 'storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp'
--- a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/dbutil/DbUtil.cpp	2009-07-03 10:31:30 +0000
@@ -44,8 +44,6 @@
 
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
 
 /**************************************************************************
  * ------------------------------------------------------------------------
@@ -686,15 +684,13 @@ DbUtil::execDUMP_STATE_ORD(Signal* signa
 void DbUtil::execDBINFO_SCANREQ(Signal *signal)
 {
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
-  char buf[512];
-  struct dbinfo_row r;
-  struct dbinfo_ratelimit rl;
-
-  dbinfo_ratelimit_init(&rl, &req);
+  const Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
+  Ndbinfo::Ratelimit rl;
 
   jamEntry();
 
-  if(req.tableId == NDBINFO_POOLS_TABLEID)
+  if(req.tableId == Ndbinfo::POOLS_TABLEID)
   {
     struct {
       const char* poolname;
@@ -726,25 +722,30 @@ void DbUtil::execDBINFO_SCANREQ(Signal *
           { NULL, 0, 0}
         };
 
+    Uint32 pool = cursor->data[0];
     BlockNumber bn = blockToMain(number());
-    for(int i=0; pools[i].poolname; i++)
+    while(pools[pool].poolname)
     {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, bn);           // block number
-      dbinfo_write_row_column_uint32(&r, req.instance); // block instance
-      dbinfo_write_row_column(&r, pools[i].poolname, strlen(pools[i].poolname));
-      dbinfo_write_row_column_uint32(&r, pools[i].free);
-      dbinfo_write_row_column_uint32(&r, pools[i].size);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
+      jam();
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_string(pools[pool].poolname);
+      row.write_uint32(pools[pool].free);
+      row.write_uint32(pools[pool].size);
+      ndbinfo_send_row(signal, req, row, rl);
+      pool++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
     }
   }
 
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, DbinfoScanReq::SignalLengthWithCursor * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 void
 DbUtil::mutex_created(Signal* signal, Uint32 ptrI, Uint32 retVal){

=== modified file 'storage/ndb/src/kernel/blocks/suma/Suma.cpp'
--- a/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/suma/Suma.cpp	2009-07-03 10:31:30 +0000
@@ -63,8 +63,6 @@
 
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
 
 #include <EventLogger.hpp>
 extern EventLogger * g_eventLogger;
@@ -1496,15 +1494,13 @@ Suma::execDUMP_STATE_ORD(Signal* signal)
 void Suma::execDBINFO_SCANREQ(Signal *signal)
 {
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
-  char buf[512];
-  struct dbinfo_row r;
-  struct dbinfo_ratelimit rl;
-
-  dbinfo_ratelimit_init(&rl, &req);
+  const Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
+  Ndbinfo::Ratelimit rl;
 
   jamEntry();
 
-  if(req.tableId == NDBINFO_POOLS_TABLEID)
+  if(req.tableId == Ndbinfo::POOLS_TABLEID)
   {
     struct {
       const char* poolname;
@@ -1539,25 +1535,30 @@ void Suma::execDBINFO_SCANREQ(Signal *si
           { NULL, 0, 0}
         };
 
+    Uint32 pool = cursor->data[0];
     BlockNumber bn = blockToMain(number());
-    for(int i=0; pools[i].poolname; i++)
+    while(pools[pool].poolname)
     {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, bn);           // block number
-      dbinfo_write_row_column_uint32(&r, req.instance); // block instance
-      dbinfo_write_row_column(&r, pools[i].poolname, strlen(pools[i].poolname));
-      dbinfo_write_row_column_uint32(&r, pools[i].free);
-      dbinfo_write_row_column_uint32(&r, pools[i].size);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
+      jam();
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_string(pools[pool].poolname);
+      row.write_uint32(pools[pool].free);
+      row.write_uint32(pools[pool].size);
+      ndbinfo_send_row(signal, req, row, rl);
+      pool++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
     }
   }
 
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, DbinfoScanReq::SignalLengthWithCursor * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 
 /*************************************************************

=== modified file 'storage/ndb/src/kernel/blocks/trix/Trix.cpp'
--- a/storage/ndb/src/kernel/blocks/trix/Trix.cpp	2009-06-15 13:31:37 +0000
+++ b/storage/ndb/src/kernel/blocks/trix/Trix.cpp	2009-07-03 10:31:30 +0000
@@ -39,9 +39,6 @@
 
 #include <signaldata/DbinfoScan.hpp>
 #include <signaldata/TransIdAI.hpp>
-#include <ndbinfo.h>
-#include <dbinfo/ndbinfo_tableids.h>
-
 #include <signaldata/WaitGCP.hpp>
 
 #define CONSTRAINT_VIOLATION 893
@@ -495,15 +492,13 @@ Trix::execDUMP_STATE_ORD(Signal* signal)
 void Trix::execDBINFO_SCANREQ(Signal *signal)
 {
   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
-  char buf[512];
-  struct dbinfo_row r;
-  struct dbinfo_ratelimit rl;
-
-  dbinfo_ratelimit_init(&rl, &req);
+  const Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtr(&req);
+  Ndbinfo::Ratelimit rl;
 
   jamEntry();
 
-  if(req.tableId == NDBINFO_POOLS_TABLEID)
+  if(req.tableId == Ndbinfo::POOLS_TABLEID)
   {
     struct {
       const char* poolname;
@@ -520,25 +515,30 @@ void Trix::execDBINFO_SCANREQ(Signal *si
           { NULL, 0, 0}
         };
 
+    Uint32 pool = cursor->data[0];
     BlockNumber bn = blockToMain(number());
-    for(int i=0; pools[i].poolname; i++)
+    while(pools[pool].poolname)
     {
-      dbinfo_write_row_init(&r, buf, sizeof(buf));
-      dbinfo_write_row_column_uint32(&r, getOwnNodeId());
-      dbinfo_write_row_column_uint32(&r, bn);           // block number
-      dbinfo_write_row_column_uint32(&r, req.instance); // block instance
-      dbinfo_write_row_column(&r, pools[i].poolname, strlen(pools[i].poolname));
-      dbinfo_write_row_column_uint32(&r, pools[i].free);
-      dbinfo_write_row_column_uint32(&r, pools[i].size);
-      dbinfo_send_row(signal, r, rl, req.apiTxnId, req.apiRef);
+      jam();
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(bn);           // block number
+      row.write_uint32(instance()); // block instance
+      row.write_string(pools[pool].poolname);
+      row.write_uint32(pools[pool].free);
+      row.write_uint32(pools[pool].size);
+      ndbinfo_send_row(signal, req, row, rl);
+      pool++;
+      if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pool);
+        return;
+      }
     }
   }
 
-  DbinfoScanConf *conf= (DbinfoScanConf*)signal->getDataPtrSend();
-  memcpy(conf,&req, DbinfoScanReq::SignalLengthWithCursor * sizeof(Uint32));
-  conf->requestInfo &= ~(DbinfoScanConf::MoreData);
-  sendSignal(req.senderRef, GSN_DBINFO_SCANCONF,
-             signal, DbinfoScanConf::SignalLengthWithCursor, JBB);
+  ndbinfo_send_scan_conf(signal, req, rl);
 }
 
 // Build index

=== modified file 'storage/ndb/src/kernel/vm/Makefile.am'
--- a/storage/ndb/src/kernel/vm/Makefile.am	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/kernel/vm/Makefile.am	2009-07-03 10:31:30 +0000
@@ -38,7 +38,8 @@ libkernel_a_SOURCES = \
 	ndbd_malloc_impl.cpp \
 	Pool.cpp WOPool.cpp RWPool.cpp DynArr256.cpp LockQueue.cpp \
 	GlobalData.cpp \
-	SafeMutex.cpp
+	SafeMutex.cpp \
+	Ndbinfo.cpp
 
 libsched_a_SOURCES = TimeQueue.cpp		\
                      ThreadConfig.cpp \
@@ -120,4 +121,3 @@ testSafeMutex_LDFLAGS = @ndb_bin_am_ldfl
   $(top_builddir)/strings/libmystringslt.la \
   @readline_link@ @TERMCAP_LIB@
 
-

=== added file 'storage/ndb/src/kernel/vm/Ndbinfo.cpp'
--- a/storage/ndb/src/kernel/vm/Ndbinfo.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/vm/Ndbinfo.cpp	2009-07-03 10:31:30 +0000
@@ -0,0 +1,291 @@
+/*
+   Copyright (C) 2009 Sun Microsystems Inc.
+   All rights reserved. Use is subject to license terms.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#include "Ndbinfo.hpp"
+#include "SimulatedBlock.hpp"
+#include <AttributeHeader.hpp>
+#include <signaldata/TransIdAI.hpp>
+
+Ndbinfo::Row::Row(Signal* signal, DbinfoScanReq& req) :
+  col_counter(0),
+  m_req(req)
+{
+  // Use the "temporary" part of signal->theData as row buffer
+  start = signal->getDataPtrSend() + DbinfoScanReq::SignalLength;
+  const Uint32 data_sz = sizeof(signal->theData)/sizeof(signal->theData[0]);
+  end = signal->getDataPtrSend() + data_sz;
+  assert(start < end);
+
+  curr = start;
+}
+
+bool
+Ndbinfo::Row::check_buffer_space(AttributeHeader& ah) const
+{
+  const Uint32 needed =  ah.getHeaderSize() + ah.getDataSize();
+  const Uint32 avail = (Uint32)(end - curr);
+
+  if(needed > avail)
+  {
+    ndbout_c("Warning, too small row buffer for attribute: %d, "
+             "needed: %d, avail: %d", ah.getAttributeId(), needed, avail);
+    assert(false);
+    return false; // Not enough room in row buffer
+  }
+  return true;
+}
+
+void
+Ndbinfo::Row::check_attribute_type(AttributeHeader& ah, ColumnType type) const
+{
+  const Table& tab = getTable(m_req.tableId);
+  const Uint32 colid = ah.getAttributeId();
+  assert(colid < tab.m.ncols);
+  assert(tab.col[colid].coltype == type);
+}
+
+void
+Ndbinfo::Row::write_string(const char* str)
+{
+  const size_t clen = strlen(str) + 1;
+  // Create AttributeHeader
+  AttributeHeader ah(col_counter++, clen);
+  check_attribute_type(ah, Ndbinfo::String);
+  if (!check_buffer_space(ah))
+    return;
+
+  // Write AttributeHeader to buffer
+  ah.insertHeader(curr);
+  curr += ah.getHeaderSize();
+
+  // Write data to buffer
+  memcpy(curr, str, clen);
+  curr += ah.getDataSize();
+
+  assert(curr <= end);
+  return;
+}
+
+void
+Ndbinfo::Row::write_uint32(Uint32 value)
+{
+  // Create AttributeHeader
+  AttributeHeader ah(col_counter++, sizeof(Uint32));
+  check_attribute_type(ah, Ndbinfo::Number);
+  if (!check_buffer_space(ah))
+    return;
+
+  // Write AttributeHeader to buffer
+  ah.insertHeader(curr);
+  curr += ah.getHeaderSize();
+
+  // Write data to buffer
+  memcpy(curr, &value, sizeof(Uint32));
+  curr += ah.getDataSize();
+
+  assert(curr <= end);
+  return;
+}
+
+
+#define DECLARE_NDBINFO_TABLE(var, num)  \
+static const struct  {                   \
+  Ndbinfo::Table::Members m;             \
+  Ndbinfo::Column col[num];              \
+} var
+
+
+/** Reserved for DBINFO only */
+DECLARE_NDBINFO_TABLE(ndbinfo_TABLES,3) =
+{ "TABLES", 3, 0,
+  {
+    {"TABLE_ID",  Ndbinfo::Number},
+    {"TABLE_NAME",Ndbinfo::String},
+    {"CREATE_SQL",Ndbinfo::String},
+  }};
+
+/** Reserved for DBINFO only */
+DECLARE_NDBINFO_TABLE(ndbinfo_COLUMNS,4) =
+{ "COLUMNS", 4, 0,
+  {
+    {"TABLE_ID",    Ndbinfo::Number},
+    {"COLUMN_ID",   Ndbinfo::Number},
+    {"COLUMN_NAME", Ndbinfo::String},
+    {"COLUMN_TYPE", Ndbinfo::String},
+  }};
+
+DECLARE_NDBINFO_TABLE(ndbinfo_MEMUSAGE,7) =
+{ "MEMUSAGE", 7, 0,
+  {
+    {"NODE_ID",          Ndbinfo::Number},
+    {"BLOCK_NUMBER",     Ndbinfo::Number},
+    {"BLOCK_INSTANCE",   Ndbinfo::Number},
+    {"RESOURCE_NAME",    Ndbinfo::String},
+    {"PAGE_SIZE",        Ndbinfo::Number},
+    {"PAGES_USED",       Ndbinfo::Number},
+    {"PAGES_TOTAL",      Ndbinfo::Number},
+  }};
+
+DECLARE_NDBINFO_TABLE(ndbinfo_LOGDESTINATION,5) =
+{ "LOGDESTINATION", 5, 0,
+  {
+    {"NODE_ID",Ndbinfo::Number},
+    {"TYPE",Ndbinfo::String},
+    {"PARAMS",Ndbinfo::String},
+    {"CURRENT_SIZE",Ndbinfo::Number},
+    {"MAX_SIZE",Ndbinfo::Number},
+  }
+};
+
+DECLARE_NDBINFO_TABLE(ndbinfo_BACKUP_RECORDS,11) =
+{ "BACKUP_RECORDS", 11, 0,
+  {
+    {"NODE_ID",          Ndbinfo::Number},
+    {"BACKUP_RECORD",    Ndbinfo::Number},
+    {"BACKUP_ID",        Ndbinfo::Number},
+    {"MASTER_REF",       Ndbinfo::Number},
+    {"CLIENT_REF",       Ndbinfo::Number},
+    {"STATE",            Ndbinfo::Number},
+    {"BYTES",            Ndbinfo::Number},
+    {"RECORDS",          Ndbinfo::Number},
+    {"LOG_BYTES",        Ndbinfo::Number},
+    {"LOG_RECORDS",      Ndbinfo::Number},
+    {"ERROR_CODE",       Ndbinfo::Number},
+  }
+};
+
+DECLARE_NDBINFO_TABLE(ndbinfo_BACKUP_PARAMETERS,14) =
+{ "BACKUP_PARAMETERS", 14, 0,
+  {
+    {"NODE_ID",                  Ndbinfo::Number},
+    {"CURRENT_DISK_WRITE_SPEED", Ndbinfo::Number},
+    {"BYTES_WRITTEN_THIS_PERIOD",Ndbinfo::Number},
+    {"OVERFLOW_DISK_WRITE",      Ndbinfo::Number},
+    {"RESET_DELAY_USED",         Ndbinfo::Number},
+    {"RESET_DISK_SPEED_TIME",    Ndbinfo::Number},
+    {"BACKUP_POOL_SIZE",         Ndbinfo::Number},
+    {"BACKUP_FILE_POOL_SIZE",    Ndbinfo::Number},
+    {"TABLE_POOL_SIZE",          Ndbinfo::Number},
+    {"TRIGGER_POOL_SIZE",        Ndbinfo::Number},
+    {"FRAGMENT_POOL_SIZE",       Ndbinfo::Number},
+    {"PAGE_POOL_SIZE",           Ndbinfo::Number},
+    {"COMPRESSED_BACKUP",        Ndbinfo::Number},
+    {"COMPRESSED_LCP",           Ndbinfo::Number},
+  }
+};
+
+DECLARE_NDBINFO_TABLE(ndbinfo_POOLS,6) =
+{ "POOLS", 6, 0,
+  {
+    {"NODE_ID",                  Ndbinfo::Number},
+    {"BLOCK_NUMBER",             Ndbinfo::Number},
+    {"BLOCK_INSTANCE",           Ndbinfo::Number},
+    {"POOL_NAME",                Ndbinfo::String},
+    {"FREE",                     Ndbinfo::Number},
+    {"SIZE",                     Ndbinfo::Number},
+  }
+};
+
+DECLARE_NDBINFO_TABLE(ndbinfo_TEST,4) =
+{ "TEST", 4, 0,
+  {
+    {"NODE_ID",                 Ndbinfo::Number},
+    {"BLOCK_NUMBER",            Ndbinfo::Number},
+    {"BLOCK_INSTANCE",          Ndbinfo::Number},
+    {"COUNTER",                 Ndbinfo::Number},
+  }
+};
+
+#define DBINFOTBL(x) (Ndbinfo::Table*)&x
+
+static Ndbinfo::Table *ndbinfo_tables[] = {
+  DBINFOTBL(ndbinfo_TABLES),
+  DBINFOTBL(ndbinfo_COLUMNS),
+  DBINFOTBL(ndbinfo_MEMUSAGE),
+  DBINFOTBL(ndbinfo_LOGDESTINATION),
+  DBINFOTBL(ndbinfo_BACKUP_RECORDS),
+  DBINFOTBL(ndbinfo_BACKUP_PARAMETERS),
+  DBINFOTBL(ndbinfo_POOLS),
+  DBINFOTBL(ndbinfo_TEST),
+};
+
+static int number_ndbinfo_tables =
+  sizeof(ndbinfo_tables) / sizeof(ndbinfo_tables[0]);
+
+
+int Ndbinfo::getNumTables(){
+  return number_ndbinfo_tables;
+}
+
+const Ndbinfo::Table& Ndbinfo::getTable(int i)
+{
+  assert(i >= 0 && i < number_ndbinfo_tables);
+  return *ndbinfo_tables[i];
+}
+
+const Ndbinfo::Table& Ndbinfo::getTable(Uint32 i)
+{
+  return getTable((int)i);
+}
+
+int
+Ndbinfo::create_sql(const Ndbinfo::Table& tab,
+                    char* sql, int len,
+                    const char* line_separator)
+{
+  my_snprintf(sql,len,"CREATE TABLE `%s` (", tab.m.name);
+
+  len-=strlen(sql);
+  sql+=strlen(sql);
+  if(len<0)
+    return ENOMEM;
+
+  for(int i = 0; i < tab.m.ncols; i++)
+  {
+    my_snprintf(sql, len, "%s\t`%s` %s,",
+                line_separator, tab.col[i].name,
+                coltype_to_string(tab.col[i].coltype));
+    len-=strlen(sql);
+    sql+=strlen(sql);
+    if(len<0)
+      return ENOMEM;
+  }
+  *(--sql)='\0';
+  my_snprintf(sql,len,"%s) ENGINE=NDBINFO;", line_separator);
+  len-=strlen(sql);
+  sql+=strlen(sql);
+  if(len<0)
+    return ENOMEM;
+
+  return 0;
+}
+
+const char*
+Ndbinfo::coltype_to_string(ColumnType coltype) {
+  static const char* type_string[]= {"NONE",
+                                     "VARCHAR(512)",
+                                     "INT UNSIGNED"
+  };
+
+  if(coltype>3)
+    coltype= (ColumnType)0;
+
+  return type_string[coltype];
+}
+
+

=== added file 'storage/ndb/src/kernel/vm/Ndbinfo.hpp'
--- a/storage/ndb/src/kernel/vm/Ndbinfo.hpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/vm/Ndbinfo.hpp	2009-07-03 10:31:30 +0000
@@ -0,0 +1,159 @@
+/*
+   Copyright (C) 2009 Sun Microsystems Inc.
+   All rights reserved. Use is subject to license terms.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#ifndef KERNEL_NDBINFO_HPP
+#define KERNEL_NDBINFO_HPP
+
+#include <signaldata/DbinfoScan.hpp>
+
+class Ndbinfo {
+public:
+
+  enum ColumnType {
+    String = 1,
+    Number = 2
+  };
+
+  struct Column {
+    char name[50];
+    ColumnType coltype;
+  };
+
+  static const char* coltype_to_string(ColumnType coltype);
+
+  enum TableId {
+    TABLES_TABLEID =             0,
+    COLUMNS_TABLEID =            1,
+    MEMUSAGE_TABLEID =           2,
+    LOGDESTINATION_TABLEID =     3,
+    BACKUP_RECORDS_TABLEID =     4,
+    BACKUP_PARAMETERS_TABLEID =  5,
+    POOLS_TABLEID =              6,
+    TEST_TABLEID =               7
+  };
+
+  struct Table {
+    struct Members {
+      char name[50];
+      int ncols;
+      int flags;
+    } m;
+    Column col[1];
+
+    int columns(void) const {
+      return m.ncols;
+    }
+  };
+  static int getNumTables();
+  static const Table& getTable(int i);
+  static const Table& getTable(Uint32 i);
+  static int create_sql(const Table& t, char* sql, int len,
+                        const char* line_separator = "\n");
+
+  class Row {
+    friend class SimulatedBlock;
+    Uint32* start;      // Start of row buffer
+    Uint32* curr;       // Current position in row buffer
+    Uint32* end;        // End of buffer
+    int col_counter;    // Current column counter
+    DbinfoScan& m_req;  // The scan parameters
+    Row();              // Not impl
+    Row(const Row&);    // Not impl
+  public:
+
+    Row(class Signal* signal, DbinfoScanReq& req);
+
+    Uint32 getLength(void) const {
+      return (Uint32)(curr - start);
+    }
+
+    Uint32* getDataPtr() const {
+      return start;
+    }
+
+    void write_string(const char* col);
+    void write_uint32(Uint32 value);
+
+    int columns(void) const {
+      return col_counter;
+    }
+
+  private:
+    bool check_buffer_space(class AttributeHeader& ah) const;
+    void check_attribute_type(class AttributeHeader& ah, ColumnType) const;
+  };
+
+  struct ScanCursor
+  {
+    Uint32 senderRef;
+    Uint32 saveSenderRef;
+    Uint32 currRef; // The current node, block and instance
+    Uint32 saveCurrRef;
+    /**
+     * Flags
+     *
+     m = More data         - 1  Bit 1
+
+               1111111111222222222233
+     01234567890123456789012345678901
+     m
+    */
+    Uint32 flags;
+    Uint32 data[4];  // Cursor data
+
+    Uint32 totalRows; // MASV hmm? Is it really used...
+    Uint32 totalBytes;
+    STATIC_CONST( Length = 10 );
+    
+    STATIC_CONST( MOREDATA_SHIFT = 0 );
+    STATIC_CONST( MOREDATA_MASK = 1 );
+
+    static bool getHasMoreData(const UintR & flags){
+      return (bool)((flags >> MOREDATA_SHIFT) & MOREDATA_MASK);
+    }
+    static void setHasMoreData(UintR & flags, bool value){
+      flags = (flags & ~(MOREDATA_MASK << MOREDATA_SHIFT)) |
+              ((value & MOREDATA_MASK) << MOREDATA_SHIFT);
+    }
+  };
+
+  class Ratelimit {
+    friend class SimulatedBlock;
+    Uint32 rows;
+    Uint32 bytes;
+    Ratelimit(const Ratelimit&);// Not impl
+  public:
+    Ratelimit() :
+      rows(0),
+      bytes(0){
+    }
+
+    bool need_break(const DbinfoScan& scan) const {
+      // Automatically limit the maxRows value
+      Uint32 maxRows = min(scan.maxRows ? scan.maxRows : 256, 256);
+
+      if (maxRows != 0 && rows >= maxRows)
+        return true; // More than max rows already sent
+      if (scan.maxBytes != 0 &&  bytes >= scan.maxBytes)
+        return true; // More than max bytes already sent
+      return false;
+    }
+  };
+};
+
+#endif

=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.cpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.cpp	2009-06-30 18:49:53 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.cpp	2009-07-03 11:13:59 +0000
@@ -54,6 +54,8 @@
 #include <signaldata/CallbackSignal.hpp>
 #include "LongSignalImpl.hpp"
 
+#include <signaldata/TransIdAI.hpp>
+
 #include <EventLogger.hpp>
 extern EventLogger * g_eventLogger;
 
@@ -3663,3 +3665,96 @@ SimulatedBlock::debugOutTag(char *buf, i
   return buf;
 }
 #endif
+
+void
+SimulatedBlock::ndbinfo_send_row(Signal* signal,
+                                 const DbinfoScanReq& req,
+                                 const Ndbinfo::Row& row,
+                                 Ndbinfo::Ratelimit& rl) const
+{
+  // Check correct number of columns against table
+  assert(row.columns() == Ndbinfo::getTable(req.tableId).columns());
+
+  TransIdAI *tidai= (TransIdAI*)signal->getDataPtrSend();
+  tidai->connectPtr= req.resultData;
+  tidai->transId[0]= req.transId[0];
+  tidai->transId[1]= req.transId[1];
+
+  LinearSectionPtr ptr[3];
+  ptr[0].p = row.getDataPtr();
+  ptr[0].sz = row.getLength();
+
+  rl.rows++;
+  rl.bytes += row.getLength();
+
+  sendSignal(req.resultRef, GSN_DBINFO_TRANSID_AI,
+             signal, TransIdAI::HeaderLength, JBB, ptr, 1);
+}
+
+void
+SimulatedBlock::ndbinfo_send_scan_break(Signal* signal,
+                                       DbinfoScanReq& req,
+                                       const Ndbinfo::Ratelimit& rl,
+                                       Uint32 data1, Uint32 data2,
+                                       Uint32 data3, Uint32 data4) const
+{
+  DbinfoScanConf* conf= (DbinfoScanConf*)signal->getDataPtrSend();
+  const Uint32 signal_length = DbinfoScanReq::SignalLength + req.cursor_sz;
+  MEMCOPY_NO_WORDS(conf, &req, signal_length);
+
+  conf->returnedRows = rl.rows;
+
+  // Update the cursor with current item number
+  Ndbinfo::ScanCursor* cursor =
+    (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtrSend(conf);
+
+  cursor->data[0] = data1;
+  cursor->data[1] = data2;
+  cursor->data[2] = data3;
+  cursor->data[3] = data4;
+
+  // Increase number of rows and bytes sent to far
+  cursor->totalRows += rl.rows;
+  cursor->totalBytes += rl.bytes;
+
+  Ndbinfo::ScanCursor::setHasMoreData(cursor->flags, true);
+
+  sendSignal(cursor->senderRef, GSN_DBINFO_SCANCONF, signal,
+             signal_length, JBB);
+}
+
+void
+SimulatedBlock::ndbinfo_send_scan_conf(Signal* signal,
+                                       DbinfoScanReq& req,
+                                       const Ndbinfo::Ratelimit& rl) const
+{
+  DbinfoScanConf* conf= (DbinfoScanConf*)signal->getDataPtrSend();
+  const Uint32 signal_length = DbinfoScanReq::SignalLength + req.cursor_sz;
+  Uint32 sender_ref = req.resultRef;
+  MEMCOPY_NO_WORDS(conf, &req, signal_length);
+
+  conf->returnedRows = rl.rows;
+
+  if (req.cursor_sz)
+  {
+    jam();
+    // Update the cursor with current item number
+    Ndbinfo::ScanCursor* cursor =
+      (Ndbinfo::ScanCursor*)DbinfoScan::getCursorPtrSend(conf);
+
+    // Reset all data holders
+    memset(cursor->data, 0, sizeof(cursor->data));
+
+    // Increase number of rows and bytes sent to far
+    cursor->totalRows += rl.rows;
+    cursor->totalBytes += rl.bytes;
+
+    Ndbinfo::ScanCursor::setHasMoreData(cursor->flags, false);
+
+    sender_ref = cursor->senderRef;
+
+  }
+  sendSignal(sender_ref, GSN_DBINFO_SCANCONF, signal,
+             signal_length, JBB);
+}
+

=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.hpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2009-06-30 18:49:53 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2009-07-03 11:13:59 +0000
@@ -58,6 +58,8 @@
 #include "ndbd_malloc_impl.hpp"
 #include <blocks/record_types.hpp>
 
+#include "Ndbinfo.hpp"
+
 #ifdef VM_TRACE
 #define D(x) \
   do { \
@@ -1006,6 +1008,21 @@ public:
   void debugOutUnlock() { globalSignalLoggers.unlock(); }
   const char* debugOutTag(char* buf, int line);
 #endif
+
+  void ndbinfo_send_row(Signal* signal,
+                        const DbinfoScanReq& req,
+                        const Ndbinfo::Row& row,
+                        Ndbinfo::Ratelimit& rl) const;
+
+  void ndbinfo_send_scan_break(Signal* signal,
+                               DbinfoScanReq& req,
+                               const Ndbinfo::Ratelimit& rl,
+                               Uint32 data1, Uint32 data2 = 0,
+                               Uint32 data3 = 0, Uint32 data4 = 0) const;
+
+  void ndbinfo_send_scan_conf(Signal* signal,
+                              DbinfoScanReq& req,
+                              const Ndbinfo::Ratelimit& rl) const;
 };
 
 // outside blocks e.g. within a struct

=== modified file 'storage/ndb/src/mgmsrv/Makefile.am'
--- a/storage/ndb/src/mgmsrv/Makefile.am	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/mgmsrv/Makefile.am	2009-07-03 10:31:30 +0000
@@ -30,7 +30,6 @@ ndb_mgmd_SOURCES = \
 	ConfigInfo.cpp \
 	InitConfigFileParser.cpp \
 	Config.cpp \
-	mgm_ndbinfo.cpp \
 	ConfigManager.cpp \
 	DirIterator.cpp
 

=== removed file 'storage/ndb/src/mgmsrv/mgm_ndbinfo.cpp'
--- a/storage/ndb/src/mgmsrv/mgm_ndbinfo.cpp	2008-10-06 06:53:04 +0000
+++ b/storage/ndb/src/mgmsrv/mgm_ndbinfo.cpp	1970-01-01 00:00:00 +0000
@@ -1,14 +0,0 @@
-
-#include <BaseString.hpp>
-#include <ndbinfo.h>
-
-int print_ndbinfo_table_mgm(struct ndbinfo_table* t, BaseString &out)
-{
-  int i;
-  out.appfmt("%d\n",t->ncols);
-
-  for(i=0;i<t->ncols;i++)
-    out.appfmt("%s\n",t->col[i].name);
-
-  return 0;
-}

=== modified file 'storage/ndb/src/ndbapi/NdbInfo.cpp'
--- a/storage/ndb/src/ndbapi/NdbInfo.cpp	2009-06-24 08:39:09 +0000
+++ b/storage/ndb/src/ndbapi/NdbInfo.cpp	2009-07-03 10:31:30 +0000
@@ -267,13 +267,17 @@ bool NdbInfo::load_tables()
 }
 
 int NdbInfo::createScanOperation(const InfoTable* table,
-                                 NdbInfoScanOperation** ret_scan_op)
+                                 NdbInfoScanOperation** ret_scan_op,
+                                 Uint32 max_rows, Uint32 max_bytes)
 {
-  NdbInfoScanOperation* scan_op = new NdbInfoScanOperation(m_connection, table);
+  NdbInfoScanOperation* scan_op = new NdbInfoScanOperation(m_connection,
+                                                           table, max_rows,
+                                                           max_bytes);
   if (!scan_op)
     return ERR_OutOfMemory;
-
-  if (!scan_op->init())
+  // Global id counter, not critical if you get same id on two instances
+  // since reference is also part of the unique identifier.
+  if (!scan_op->init(m_id_counter++))
   {
     delete scan_op;
     return ERR_ClusterFailure;
@@ -284,7 +288,7 @@ int NdbInfo::createScanOperation(const I
   return 0;
 }
 
-void NdbInfo::releaseScanOperation(NdbInfoScanOperation* scan_op)
+void NdbInfo::releaseScanOperation(NdbInfoScanOperation* scan_op) const
 {
   delete scan_op;
 }
@@ -297,11 +301,9 @@ void NdbInfo::flush_tables()
   assert(m_tables.entries() == NUM_HARDCODED_TABLES);
 }
 
-int
-NdbInfo::openTable(const char* table_name,
-                   const NdbInfo::InfoTable** table_copy)
+bool
+NdbInfo::check_tables()
 {
-  pthread_mutex_lock(&m_mutex);
   if (m_connection->get_connect_count() != m_connect_count)
   {
     // Connect count has changed -> flush the cached table definitions
@@ -313,12 +315,25 @@ NdbInfo::openTable(const char* table_nam
     // flushed, try to load it
     if (!load_tables())
     {
-      pthread_mutex_unlock(&m_mutex);
-      return ERR_ClusterFailure;
+      return false;
     }
   }
   // Make sure that some dynamic tables have been loaded
   assert(m_tables.entries() > NUM_HARDCODED_TABLES);
+  return true;
+}
+
+
+int
+NdbInfo::openTable(const char* table_name,
+                   const NdbInfo::InfoTable** table_copy)
+{
+  pthread_mutex_lock(&m_mutex);
+
+  if (!check_tables()){
+    pthread_mutex_unlock(&m_mutex);
+    return ERR_ClusterFailure;
+  }
 
   InfoTable* tab;
   if (!m_tables.search(table_name, &tab))
@@ -335,6 +350,42 @@ NdbInfo::openTable(const char* table_nam
   return 0;
 }
 
+int
+NdbInfo::openTable(Uint32 tableId,
+                   const NdbInfo::InfoTable** table_copy)
+{
+  pthread_mutex_lock(&m_mutex);
+
+  if (!check_tables()){
+    pthread_mutex_unlock(&m_mutex);
+    return ERR_ClusterFailure;
+  }
+
+  // Find the table with correct id
+  const InfoTable* table = NULL;
+  for (size_t i = 0; i < m_tables.entries(); i++)
+  {
+    const InfoTable* tmp = m_tables.value(i);
+    if (tmp->m_table_id == tableId)
+    {
+      table = tmp;
+      break;
+    }
+  }
+  if (table == NULL)
+  {
+    // No such table existed
+    pthread_mutex_unlock(&m_mutex);
+    return ERR_NoSuchTable;
+  }
+
+  // Return a _copy_ of the table
+  *table_copy = new InfoTable(*table);
+
+  pthread_mutex_unlock(&m_mutex);
+  return 0;
+}
+
 void NdbInfo::closeTable(const InfoTable* table) {
   delete table;
 }

=== modified file 'storage/ndb/src/ndbapi/NdbInfo.hpp'
--- a/storage/ndb/src/ndbapi/NdbInfo.hpp	2009-06-24 08:39:09 +0000
+++ b/storage/ndb/src/ndbapi/NdbInfo.hpp	2009-07-03 10:31:30 +0000
@@ -93,11 +93,13 @@ public:
   void flush_tables();
 
   int openTable(const char* table_name, const InfoTable**);
+  int openTable(Uint32 tableId, const InfoTable**);
   void closeTable(const InfoTable* table);
 
   int createScanOperation(const InfoTable*,
-                          class NdbInfoScanOperation**);
-  void releaseScanOperation(class NdbInfoScanOperation*);
+                          class NdbInfoScanOperation**,
+                          Uint32 max_rows = 256, Uint32 max_bytes = 0);
+  void releaseScanOperation(class NdbInfoScanOperation*) const;
 
 private:
   static const size_t NUM_HARDCODED_TABLES = 2;
@@ -109,12 +111,14 @@ private:
   InfoTable* m_columns_table;
   BaseString m_prefix;
   bool m_use_lower_case;
+  Uint32 m_id_counter;
 
   bool addColumn(Uint32 tableId, const InfoColumn aCol);
 
   bool load_ndbinfo_tables();
   bool load_hardcoded_tables(void);
   bool load_tables();
+  bool check_tables();
 
   BaseString mysql_table_name(const char* table_name) const;
 

=== modified file 'storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp'
--- a/storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp	2009-06-29 20:56:37 +0000
+++ b/storage/ndb/src/ndbapi/NdbInfoScanOperation.cpp	2009-07-03 11:13:59 +0000
@@ -28,17 +28,22 @@
 #include "NdbApiSignal.hpp"
 
 NdbInfoScanOperation::NdbInfoScanOperation(Ndb_cluster_connection* connection,
-                                           const NdbInfo::InfoTable* table) :
+                                           const NdbInfo::InfoTable* table,
+                                           Uint32 max_rows, Uint32 max_bytes) :
   m_state(Undefined),
   m_connection(connection),
   m_signal_sender(NULL),
   m_table(table),
-  m_node_id(0)
+  m_node_id(0),
+  m_max_rows(max_rows),
+  m_max_bytes(max_bytes),
+  m_result_data(0x37),
+  m_received_rows(0)
 {
 }
 
 bool
-NdbInfoScanOperation::init(void)
+NdbInfoScanOperation::init(Uint32 id)
 {
   DBUG_ENTER("NdbInfoScanoperation::init");
   if (m_state != Undefined)
@@ -48,6 +53,10 @@ NdbInfoScanOperation::init(void)
   if (!m_signal_sender)
     DBUG_RETURN(false);
 
+  m_transid0 = id;
+  m_transid1 = m_table->getTableId();
+  m_result_ref = m_signal_sender->getOwnRef();
+
   for (unsigned i = 0; i < m_table->columns(); i++)
     m_recAttrs.push_back(NULL);
 
@@ -107,32 +116,19 @@ int NdbInfoScanOperation::execute()
   if (m_state != Prepared)
     DBUG_RETURN(-1);
 
-  SimpleSignal ss;
-  DbinfoScanReq * req = CAST_PTR(DbinfoScanReq, ss.getDataPtrSend());
-  req->requestInfo = DbinfoScanReq::AllColumns | DbinfoScanReq::StartScan;
-  req->tableId = m_table->getTableId();
-  req->apiRef = m_signal_sender->getOwnRef();
-  req->apiTxnId = 37; //m_id; // MASV Can be removed
-  req->senderRef = m_signal_sender->getOwnRef();
-  req->instance = 0;
-  req->colBitmapLo = ~0;
-  req->colBitmapHi = ~0;
-  req->maxRows = 2;
-  req->maxBytes = 0;
-  req->rows_total = 0;
-  req->word_total = 0;
+  assert(m_cursor.size() == 0);
 
   m_signal_sender->lock();
-  int ret = sendDBINFO_SCANREQ(ss, DbinfoScanReq::SignalLength);
+  int ret = sendDBINFO_SCANREQ();
   m_signal_sender->unlock();
 
-  m_state = Started;
+  m_state = MoreData;
 
   DBUG_RETURN(ret);
 }
 
 int
-NdbInfoScanOperation::sendDBINFO_SCANREQ(SimpleSignal &ss, Uint32 signal_len)
+NdbInfoScanOperation::sendDBINFO_SCANREQ(void)
 {
   DBUG_ENTER("NdbInfoScanOperation::sendDBINFO_SCANREQ");
 
@@ -143,13 +139,43 @@ NdbInfoScanOperation::sendDBINFO_SCANREQ
       DBUG_RETURN(NdbInfo::ERR_ClusterFailure);
   }
 
+  SimpleSignal ss;
+  DbinfoScanReq * req = CAST_PTR(DbinfoScanReq, ss.getDataPtrSend());
+
+  // API Identifiers
+  req->resultData = m_result_data;
+  req->transId[0] = m_transid0;
+  req->transId[1] = m_transid1;
+  req->resultRef = m_result_ref;
+
+  // Scan parameters
+  req->tableId = m_table->getTableId();
+  req->colBitmap[0] = ~0;
+  req->colBitmap[1] = ~0;
+  req->requestInfo = 0;
+  req->maxRows = m_max_rows;
+  req->maxBytes = m_max_bytes;
+
+  // Scan result
+  req->returnedRows = 0;
+
+  // Cursor data
+  Uint32* cursor_ptr = DbinfoScan::getCursorPtrSend(req);
+  for (unsigned i = 0; i < m_cursor.size(); i++)
+  {
+    *cursor_ptr = m_cursor[i];
+    DBUG_PRINT("info", ("cursor[%u]: 0x%x", i, m_cursor[i]));
+    cursor_ptr++;
+  }
+  req->cursor_sz = m_cursor.size();
+  m_cursor.clear();
+
   assert(m_node_id);
+  Uint32 len = DbinfoScanReq::SignalLength + req->cursor_sz;
   if (m_signal_sender->sendSignal(m_node_id, ss, DBINFO,
-                                  GSN_DBINFO_SCANREQ,
-                                  signal_len) != SEND_OK)
+                                  GSN_DBINFO_SCANREQ, len) != SEND_OK)
     DBUG_RETURN(NdbInfo::ERR_ClusterFailure);
 
-
   DBUG_RETURN(0);
 }
 
@@ -161,14 +187,19 @@ int NdbInfoScanOperation::receive(void)
     const SimpleSignal* sig = m_signal_sender->waitFor();
     if (!sig)
       DBUG_RETURN(-1);
+    //sig->print();
 
     int sig_number = sig->readSignalNumber();
     switch (sig_number) {
 
     case GSN_DBINFO_TRANSID_AI:
-      execDBINFO_TRANSID_AI(sig);
-      DBUG_RETURN(1); // More data
+    {
+      int ret = execDBINFO_TRANSID_AI(sig);
+      if (ret == 0)
+        continue;
+      DBUG_RETURN(ret); // More data
       break;
+    }
 
     case GSN_DBINFO_SCANCONF:
     {
@@ -180,22 +211,21 @@ int NdbInfoScanOperation::receive(void)
     }
 
     case GSN_DBINFO_SCANREF:
-      DBUG_RETURN(execDBINFO_SCANREF(sig));
+    {
+      int ret = execDBINFO_SCANREF(sig);
+      if (ret == 0)
+        continue;
+      DBUG_RETURN(ret);
       break;
+    }
 
     case GSN_NODE_FAILREP:
       // Ignore and wait for NF_COMPLETEREP
       break;
 
     case GSN_NF_COMPLETEREP:
-    {
-      const NFCompleteRep * const rep =
-        CAST_CONSTPTR(NFCompleteRep, sig->getDataPtr());
-      NodeId nodeId= rep->failedNodeId;
-      if (nodeId == m_node_id)
-        DBUG_RETURN(-3);
+      DBUG_RETURN(-3);
       break;
-    }
 
     case GSN_SUB_GCP_COMPLETE_REP:
     case GSN_API_REGCONF:
@@ -220,7 +250,6 @@ NdbInfoScanOperation::nextResult()
 
   switch(m_state)
   {
-  case Started:
   case MoreData:
   {
     m_signal_sender->lock();
@@ -230,7 +259,6 @@ NdbInfoScanOperation::nextResult()
     break;
   }
   case End:
-    assert(false);
     DBUG_RETURN(0); // EOF
     break;
   default:
@@ -256,10 +284,21 @@ NdbInfoScanOperation::close()
   DBUG_VOID_RETURN;
 }
 
-void
+int
 NdbInfoScanOperation::execDBINFO_TRANSID_AI(const SimpleSignal * signal)
 {
   DBUG_ENTER("NdbInfoScanOperation::execDBINFO_TRANSID_AI");
+  const TransIdAI* transid =
+          CAST_CONSTPTR(TransIdAI, signal->getDataPtr());
+  if (transid->connectPtr != m_result_data ||
+      transid->transId[0] != m_transid0 ||
+      transid->transId[1] != m_transid1)
+  {
+    // Drop signal that belongs to previous scan
+    DBUG_RETURN(0);
+  }
+  m_received_rows++;
+
   const Uint32* start = signal->ptr[0].p;
   const Uint32* end = start + signal->ptr[0].sz;
 
@@ -288,8 +327,7 @@ NdbInfoScanOperation::execDBINFO_TRANSID
     // No reading beyond end of signal size
     assert(start <= end);
   }
-
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(1);
 }
 
 int
@@ -299,18 +337,39 @@ NdbInfoScanOperation::execDBINFO_SCANCON
   const DbinfoScanConf* conf =
           CAST_CONSTPTR(DbinfoScanConf, sig->getDataPtr());
 
-  if (conf->requestInfo & DbinfoScanConf::MoreData)
+  if (conf->resultData != m_result_data ||
+      conf->transId[0] != m_transid0 ||
+      conf->transId[1] != m_transid1 ||
+      conf->resultRef != m_result_ref)
   {
-    DBUG_PRINT("info", ("Request more data"));
-    SimpleSignal ss;
-    DbinfoScanReq * req = CAST_PTR(DbinfoScanReq,
-                                   ss.getDataPtrSend());
-    memcpy(req, conf, DbinfoScanReq::SignalLengthWithCursor*sizeof(Uint32));
-    req->requestInfo &= ~(DbinfoScanReq::StartScan);
-    req->apiRef = m_signal_sender->getOwnRef(); // MASV somehow becomes invalid
+    // Drop signal that belongs to previous scan
+    DBUG_RETURN(1); // Continue waiting
+  }
+  const Uint32 tableId = conf->tableId;
+  assert(tableId == m_table->getTableId());
 
-    int err = sendDBINFO_SCANREQ(ss,
-                                 DbinfoScanReq::SignalLengthWithCursor);
+  // Assert all scan settings is unchanged
+  assert(conf->colBitmap[0] == ~0);
+  assert(conf->colBitmap[1] == ~0);
+  assert(conf->requestInfo == 0);
+  assert(conf->maxRows == m_max_rows);
+  assert(conf->maxBytes == m_max_bytes);
+
+  // Save cursor data
+  assert(m_cursor.size() == 0);
+  const Uint32* cursor_ptr = DbinfoScan::getCursorPtr(conf);
+  for (unsigned i = 0; i < conf->cursor_sz; i++)
+  {
+    m_cursor.push_back(*cursor_ptr);
+    DBUG_PRINT("info", ("cursor[%u]: 0x%x", i, m_cursor[i]));
+    cursor_ptr++;
+  }
+  assert(conf->cursor_sz == m_cursor.size());
+
+  if (conf->cursor_sz)
+  {
+    DBUG_PRINT("info", ("Request more data"));
+    int err = sendDBINFO_SCANREQ();
     if (err != 0)
     {
       DBUG_PRINT("info", ("Failed to reuqest more data"));
@@ -333,6 +392,15 @@ NdbInfoScanOperation::execDBINFO_SCANREF
   const DbinfoScanRef* ref =
           CAST_CONSTPTR(DbinfoScanRef, signal->getDataPtr());
 
+  if (ref->resultData != m_result_data ||
+      ref->transId[0] != m_transid0 ||
+      ref->transId[1] != m_transid1 ||
+      ref->resultRef != m_result_ref);
+  {
+    // Drop signal that belongs to previous scan
+    DBUG_RETURN(0); // Continue waiting
+  }
+
   m_state = Error;
   DBUG_RETURN(ref->errorCode);
 }

=== modified file 'storage/ndb/src/ndbapi/NdbInfoScanOperation.hpp'
--- a/storage/ndb/src/ndbapi/NdbInfoScanOperation.hpp	2009-06-24 08:04:33 +0000
+++ b/storage/ndb/src/ndbapi/NdbInfoScanOperation.hpp	2009-07-03 10:31:30 +0000
@@ -29,25 +29,34 @@ public:
 protected:
   friend class NdbInfo;
   NdbInfoScanOperation(class Ndb_cluster_connection*,
-                       const NdbInfo::InfoTable*);
-  bool init(void);
+                       const NdbInfo::InfoTable*,
+                       Uint32 max_rows, Uint32 max_bytes);
+  bool init(Uint32 id);
   ~NdbInfoScanOperation();
   void close();
 private:
-  void execDBINFO_TRANSID_AI(const struct SimpleSignal * signal);
+  int execDBINFO_TRANSID_AI(const struct SimpleSignal * signal);
   int execDBINFO_SCANCONF(const struct SimpleSignal * signal);
   int execDBINFO_SCANREF(const struct SimpleSignal * signal);
-  int sendDBINFO_SCANREQ(struct SimpleSignal& ss, Uint32 signal_len);
+  int sendDBINFO_SCANREQ();
 
   int receive(void);
 
   enum State { Undefined, Initial, Prepared,
-               Started, MoreData, End, Error } m_state;
+               MoreData, End, Error } m_state;
   class Ndb_cluster_connection* m_connection;
   class SignalSender*           m_signal_sender;
   const NdbInfo::InfoTable*     m_table;
   Vector<NdbInfoRecAttr*>       m_recAttrs;
+  Vector<Uint32>                m_cursor;
   Uint32 m_node_id;
+  Uint32 m_transid0;
+  Uint32 m_transid1;
+  Uint32 m_result_ref;
+  Uint32 m_max_rows;
+  Uint32 m_max_bytes;
+  Uint32 m_result_data;
+  Uint32 m_received_rows;
 };
 
 

=== modified file 'storage/ndb/test/ndbapi/testNdbinfo.cpp'
--- a/storage/ndb/test/ndbapi/testNdbinfo.cpp	2009-06-24 08:04:33 +0000
+++ b/storage/ndb/test/ndbapi/testNdbinfo.cpp	2009-07-03 10:31:30 +0000
@@ -23,7 +23,7 @@
 
 int runTestNdbInfo(NDBT_Context* ctx, NDBT_Step* step)
 {
-  NdbInfo ndbinfo(&ctx->m_cluster_connection, "ndbinfo");
+  NdbInfo ndbinfo(&ctx->m_cluster_connection, "ndbinfo/");
   if (!ndbinfo.init())
   {
     g_err << "ndbinfo.init failed" << endl;
@@ -31,9 +31,9 @@ int runTestNdbInfo(NDBT_Context* ctx, ND
   }
 
   const NdbInfo::InfoTable* table;
-  if (ndbinfo.openTable("./ndbinfo/TABLES", &table) != 0)
+  if (ndbinfo.openTable("ndbinfo/TABLES", &table) != 0)
   {
-    g_err << "Failed to getTable(TABLES)" << endl;
+    g_err << "Failed to openTable(TABLES)" << endl;
     return NDBT_FAILED;
   }
 
@@ -62,7 +62,7 @@ int runTestNdbInfo(NDBT_Context* ctx, ND
       return NDBT_FAILED;
     }
 
-    while(scanOp->nextResult())
+    while(scanOp->nextResult() == 1)
     {
       g_info << "NAME: " << tableName->c_str() << endl;
       g_info << "SQL: " << createSQL->c_str() << endl;
@@ -74,6 +74,306 @@ int runTestNdbInfo(NDBT_Context* ctx, ND
   return NDBT_OK;
 }
 
+
+int runScanAll(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbInfo ndbinfo(&ctx->m_cluster_connection, "ndbinfo/");
+  if (!ndbinfo.init())
+  {
+    g_err << "ndbinfo.init failed" << endl;
+    return NDBT_FAILED;
+  }
+
+  Uint32 tableId = 0;
+  while(true) {
+    const NdbInfo::InfoTable* table;
+
+    int err = ndbinfo.openTable(tableId, &table);
+    if (err == NdbInfo::ERR_NoSuchTable)
+    {
+      // No more tables -> return
+      return NDBT_OK;
+    }
+    else if (err != 0)
+    {
+      // Unexpected return code
+      g_err << "Failed to openTable(" << tableId << "), err: " << err << endl;
+      return NDBT_FAILED;
+    }
+    ndbout << "table("<<tableId<<"): " << table->getName() << endl;
+
+    for (int l = 0; l < ctx->getNumLoops(); l++)
+    {
+      NdbInfoScanOperation* scanOp = NULL;
+      if (ndbinfo.createScanOperation(table, &scanOp))
+      {
+        g_err << "No NdbInfoScanOperation" << endl;
+        return NDBT_FAILED;
+      }
+
+      if (scanOp->readTuples() != 0)
+      {
+        g_err << "scanOp->readTuples failed" << endl;
+        return NDBT_FAILED;
+      }
+
+      int columnId = 0;
+      while (scanOp->getValue(columnId))
+        columnId++;
+      // At least one column
+      assert(columnId >= 1);
+
+      if(scanOp->execute() != 0)
+      {
+        g_err << "scanOp->execute failed" << endl;
+        return NDBT_FAILED;
+      }
+
+      int row = 0;
+      while(scanOp->nextResult() == 1)
+        row++;
+      ndbout << "rows: " << row << endl;
+      ndbinfo.releaseScanOperation(scanOp);
+    }
+    ndbinfo.closeTable(table);
+    tableId++;
+  }
+
+  // Should never come here
+  assert(false);
+  return NDBT_FAILED;
+}
+
+int runScanStop(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbInfo ndbinfo(&ctx->m_cluster_connection, "ndbinfo/");
+  if (!ndbinfo.init())
+  {
+    g_err << "ndbinfo.init failed" << endl;
+    return NDBT_FAILED;
+  }
+
+  Uint32 tableId = 0;
+  while(true) {
+    const NdbInfo::InfoTable* table;
+
+    int err = ndbinfo.openTable(tableId, &table);
+    if (err == NdbInfo::ERR_NoSuchTable)
+    {
+      // No more tables -> return
+      return NDBT_OK;
+    }
+    else if (err != 0)
+    {
+      // Unexpected return code
+      g_err << "Failed to openTable(" << tableId << "), err: " << err << endl;
+      return NDBT_FAILED;
+    }
+    ndbout << "table: " << table->getName() << endl;
+
+    for (int l = 0; l < ctx->getNumLoops()*10; l++)
+    {
+      NdbInfoScanOperation* scanOp = NULL;
+      if (ndbinfo.createScanOperation(table, &scanOp))
+      {
+        g_err << "No NdbInfoScanOperation" << endl;
+        return NDBT_FAILED;
+      }
+
+      if (scanOp->readTuples() != 0)
+      {
+        g_err << "scanOp->readTuples failed" << endl;
+        return NDBT_FAILED;
+      }
+
+      int columnId = 0;
+      while (scanOp->getValue(columnId))
+        columnId++;
+      // At least one column
+      assert(columnId >= 1);
+
+      if(scanOp->execute() != 0)
+      {
+        g_err << "scanOp->execute failed" << endl;
+        return NDBT_FAILED;
+      }
+
+      int stopRow = rand() % 100;
+      int row = 0;
+      while(scanOp->nextResult() == 1)
+      {
+        row++;
+        if (row == stopRow)
+        {
+          ndbout_c("Aborting scan at row %d", stopRow);
+          break;
+        }
+      }
+      ndbinfo.releaseScanOperation(scanOp);
+    }
+    ndbinfo.closeTable(table);
+    tableId++;
+  }
+
+  // Should never come here
+  assert(false);
+  return NDBT_FAILED;
+}
+
+
+int runRatelimit(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbInfo ndbinfo(&ctx->m_cluster_connection, "ndbinfo/");
+  if (!ndbinfo.init())
+  {
+    g_err << "ndbinfo.init failed" << endl;
+    return NDBT_FAILED;
+  }
+
+  Uint32 tableId = 6; // MASV 0
+  while(true) {
+
+    const NdbInfo::InfoTable* table;
+
+    int err = ndbinfo.openTable(tableId, &table);
+    if (err == NdbInfo::ERR_NoSuchTable)
+    {
+      // No more tables -> return
+      return NDBT_OK;
+    }
+    else if (err != 0)
+    {
+      // Unexpected return code
+      g_err << "Failed to openTable(" << tableId << "), err: " << err << endl;
+      return NDBT_FAILED;
+    }
+    ndbout << "table: " << table->getName() << endl;
+    
+
+    struct { Uint32 rows; Uint32 bytes; } limits[] = {
+      { 0, 0 },
+      { 1, 0 }, { 2, 0 }, { 10, 0 }, { 37, 0 }, { 1000, 0 },
+      { 0, 1 }, { 0, 2 }, { 0, 10 }, { 0, 37 }, { 0, 1000 },
+      { 1, 1 }, { 2, 2 }, { 10, 10 }, { 37, 37 }, { 1000, 1000 }
+    };
+
+    int lastRows = 0;
+    for (int l = 0; l < sizeof(limits)/sizeof(limits[0]); l++)
+    {
+
+      Uint32 maxRows = limits[l].rows;
+      Uint32 maxBytes = limits[l].bytes;
+
+      NdbInfoScanOperation* scanOp = NULL;
+      if (ndbinfo.createScanOperation(table, &scanOp, maxRows, maxBytes))
+      {
+        g_err << "No NdbInfoScanOperation" << endl;
+        return NDBT_FAILED;
+      }
+
+      if (scanOp->readTuples() != 0)
+      {
+        g_err << "scanOp->readTuples failed" << endl;
+        return NDBT_FAILED;
+      }
+
+      int columnId = 0;
+      while (scanOp->getValue(columnId))
+        columnId++;
+      // At least one column
+      assert(columnId >= 1);
+
+      if(scanOp->execute() != 0)
+      {
+        g_err << "scanOp->execute failed" << endl;
+        return NDBT_FAILED;
+      }
+
+      int row = 0;
+      while(scanOp->nextResult() == 1)
+        row++;
+      ndbinfo.releaseScanOperation(scanOp);
+
+      ndbout_c("[%u,%u] rows: %d", maxRows, maxBytes, row);
+      if (lastRows != 0)
+      {
+        // Check that the number of rows is same as last round on same table
+        if (lastRows != row)
+        {
+          g_err << "Got different number of rows this round, expected: "
+                << lastRows << ", got: " << row << endl;
+          ndbinfo.closeTable(table);
+          return NDBT_FAILED;
+        }
+      }
+      lastRows = row;
+    }
+    ndbinfo.closeTable(table);
+    tableId++;
+  }
+
+  // Should never come here
+  assert(false);
+  return NDBT_FAILED;
+}
+
+int runTestTable(NDBT_Context* ctx, NDBT_Step* step)
+{
+  NdbInfo ndbinfo(&ctx->m_cluster_connection, "ndbinfo/");
+  if (!ndbinfo.init())
+  {
+    g_err << "ndbinfo.init failed" << endl;
+    return NDBT_FAILED;
+  }
+
+  const NdbInfo::InfoTable* table;
+  if (ndbinfo.openTable("ndbinfo/TEST", &table) != 0)
+  {
+    g_err << "Failed to openTable(TEST)" << endl;
+    return NDBT_FAILED;
+  }
+
+  for (int l = 0; l < ctx->getNumLoops(); l++)
+  {
+
+    NdbInfoScanOperation* scanOp = NULL;
+    if (ndbinfo.createScanOperation(table, &scanOp))
+    {
+      g_err << "No NdbInfoScanOperation" << endl;
+      return NDBT_FAILED;
+    }
+
+    if (scanOp->readTuples() != 0)
+    {
+      g_err << "scanOp->readTuples failed" << endl;
+      return NDBT_FAILED;
+    }
+
+    const NdbInfoRecAttr* nodeId= scanOp->getValue("NODE_ID");
+    const NdbInfoRecAttr* blockNumber= scanOp->getValue("BLOCK_NUMBER");
+    const NdbInfoRecAttr* blockInstance= scanOp->getValue("BLOCK_INSTANCE");
+    const NdbInfoRecAttr* counter= scanOp->getValue("COUNTER");
+
+    if(scanOp->execute() != 0)
+    {
+      g_err << "scanOp->execute failed" << endl;
+      return NDBT_FAILED;
+    }
+
+    int rows = 0;
+    while(scanOp->nextResult() == 1)
+    {
+      rows++;//
+    }
+    ndbout << "rows: " << rows << endl;
+    ndbinfo.releaseScanOperation(scanOp);
+  }
+
+  ndbinfo.closeTable(table);
+  return NDBT_OK;
+}
+
+
 NDBT_TESTSUITE(testNdbinfo);
 TESTCASE("Ndbinfo",
          "Test ndbapi interface to NDB$INFO"){
@@ -83,6 +383,23 @@ TESTCASE("Ndbinfo10",
          "Test ndbapi interface to NDB$INFO"){
   STEPS(runTestNdbInfo, 10);
 }
+TESTCASE("ScanAll",
+         "Scan all colums of all table known to NdbInfo"){
+  STEPS(runScanAll, 1);
+}
+TESTCASE("ScanStop",
+         "Randomly stop the scan"){
+  STEPS(runScanStop, 1);
+}
+TESTCASE("Ratelimit",
+         "Scan wit different combinations of ratelimit"){
+  STEPS(runRatelimit, 1);
+}
+TESTCASE("TestTable",
+         "Scan the test table and make sure it returns correct number "
+          "of rows which will depend on how many TUP blocks are configured"){
+  STEP(runTestTable);
+}
 NDBT_TESTSUITE_END(testNdbinfo);
 
 

Attachment: [text/bzr-bundle] bzr/magnus.blaudd@sun.com-20090703111359-37c0l83ogewtd1lw.bundle
Thread
bzr commit into mysql-5.1-telco-7.1 branch (magnus.blaudd:2929)Magnus Blåudd3 Jul 2009