List:Internals« Previous MessageNext Message »
From:jonas.oreland Date:May 4 2004 9:20am
Subject:bk commit into 4.1 tree (joreland:1.1806)
View as plain text  
Below is the list of changes that have just been committed into a local
4.1 repository of jonas. When jonas does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://www.mysql.com/doc/I/n/Installing_source_tree.html

ChangeSet
  1.1806 04/05/04 11:19:19 joreland@stripped +55 -0
  Merge NDB patches into 4.1-clone, below is list of changesets
  
  # --------------------------------------------
  # 04/04/13      joreland@stripped      1.1858.1.1
  # Removal of NDBT_Table
  # --------------------------------------------
  # 04/04/13      joreland@stripped      1.1858.1.2
  # Removal of NDBT_Table
  # --------------------------------------------
  # 04/04/13      joreland@stripped      1.1858.1.3
  # Fix for crashing AT
  # --------------------------------------------
  # 04/04/13      joreland@stripped      1.1858.1.4
  # Bug fixes in testIndex
  # --------------------------------------------
  # 04/04/13      joreland@stripped      1.1866.1.5
  # Merge joreland@stripped:/home/bk/mysql-4.1-ndb
  # into mysql.com:/home/jonas/src/tmp
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1858.1.5
  # Fix for takeover when accessing indexes.
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1866.1.6
  # Merge joreland@stripped:/home/bk/mysql-4.1-ndb
  # into mysql.com:/home/jonas/src/tmp
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1858.2.1
  # Fixed error handling of fire_trigger_ord + lqhkeyref w.r.t indexes
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1858.2.2
  # Simple retry mechanism in UTIL
  # Helps testIndex -n BuildDuring _a lot_
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1858.2.3
  # Misc fixes to test prg.
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1858.2.4
  # Allow more retires on application errors
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1858.2.5
  # Pass no of rows fetched in SUB_SYNC_CONTINUE_REQ
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1869
  # wl1714
  # Improve parallellism
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1870
  # Merge joreland@stripped:/home/bk/mysql-4.1-ndb
  # into mysql.com:/home/jonas/src/wl1714
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1866.1.7
  # Merge
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1871
  # Merge mysql.com:/home/jonas/src/wl1714
  # into mysql.com:/home/jonas/src/mysql-4.1-ndb
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1872
  # Fix for testScan -n ScanReadError5030
  # --------------------------------------------
  # 04/04/14      joreland@stripped      1.1873
  # fix testDict -n FragmentType*
  # --------------------------------------------
  # 04/04/14      johan@stingray.(none)   1.1866.2.1
  # small fixes
  # --------------------------------------------
  # 04/04/14      johan@stingray.(none)   1.1874
  # Merge jandersson@stripped:/home/bk/mysql-4.1-ndb
  # into stingray.(none):/space/bk/rep/mysql-4.1-ndb
  # --------------------------------------------
  # 04/04/14      johan@stingray.(none)   1.1875
  # handle rep node as an api node
  # --------------------------------------------
  # 04/04/14      pekka@stripped 1.1873.1.1
  # Fix for NDBT_Table removal
  # --------------------------------------------
  # 04/04/15      joreland@stripped      1.1873.1.2
  # Uninitialized var.
  # --------------------------------------------
  # 04/04/15      johan@stingray.(none)   1.1876
  # Merge jandersson@stripped:/home/bk/mysql-4.1-ndb
  # into stingray.(none):/space/bk/rep/mysql-4.1-ndb
  # --------------------------------------------
  # 04/04/15      joreland@stripped      1.1873.1.3
  # Write pid before changing user
  # (as runas user probably doesn't have permissions on pid-dir)
  # --------------------------------------------
  # --------------------------------------------
  # 04/04/15      ndb@stripped  1.1862.1.3
  # Fix printout of varchars
  # --------------------------------------------
  # 04/04/15      ndb@stripped  1.1877
  # Merge joreland@stripped:/home/bk/mysql-4.1-ndb
  # into mc03.ndb.mysql.com:/space/ndb/tmp
  # --------------------------------------------
  # 04/04/15      ndb@stripped  1.1862.1.4
  # Hmm.. don't print attr as many times as length of array
  # --------------------------------------------
  # 04/04/15      ndb@stripped  1.1878
  # Merge mc03.ndb.mysql.com:/space/ndb/mysql-4.1-ndb
  # into mc03.ndb.mysql.com:/space/ndb/tmp
  # --------------------------------------------
  # 04/04/15      joreland@stripped      1.1876.1.1
  # Merge joreland@stripped:/home/bk/mysql-4.1-ndb
  # into mysql.com:/home/jonas/src/mysql-4.1-ndb
  # --------------------------------------------
  # 04/04/15      joreland@stripped      1.1877.1.1
  # Merge joreland@stripped:/home/bk/mysql-4.1-ndb
  # into mysql.com:/home/jonas/src/mysql-4.1-ndb
  # --------------------------------------------
  # 04/04/15      ndb@stripped  1.1879
  # Merge joreland@stripped:/home/bk/mysql-4.1-ndb
  # into mc03.ndb.mysql.com:/space/ndb/tmp
  # --------------------------------------------
  # 04/04/17      joreland@stripped      1.1880
  # LCP bug when restarting ops take's longer than DIH sending a new lcp ord
  # Solution:
  # Send LCP_FRAG_REP after restarting all ops
  # --------------------------------------------
  # 04/04/18      joreland@stripped      1.1881
  # Missspelled ERROR_INSERT
  # --------------------------------------------
  # 04/04/18      joreland@stripped      1.1882
  # Added possibility to log only distributed signals
  # --------------------------------------------
  # 04/04/22      joreland@stripped      1.1883
  # Removed dependancy to libstdc++
  # * pure virtual functions "__cxa_pure_virtual" is defined in libstd++ ->
  #   remove all pure virtual functions
  # --------------------------------------------
  # 04/04/23      joreland@stripped      1.1884
  # Various minor bug fixes for problems found while compiling
  # with icc
  # --------------------------------------------
  # --------------------------------------------
  # 04/04/25      joreland@stripped      1.1885
  # Removed debug code (joreland:1.1875)
  # --------------------------------------------
  # 04/04/26      ejonore@stripped      1.1862.1.5
  # Lock pages in memory _after_ daemon-mode (exec/fork)
  # --------------------------------------------
  # 04/04/27      ejonore@stripped      1.1862.1.6
  # 1) Trap abort()
  # 2) StopStart/StopAborted events
  # 3) warning if memlock fails
  # 4) use g_logger more often (instead of ndbout)
  # 
  # --------------------------------------------
  # 04/04/27      joreland@stripped      1.1886
  # bug fix for a bug in wl1714 + software upgrade
  # --------------------------------------------
  # 04/04/27      joreland@stripped      1.1887
  # Cset exclude: joreland@stripped|ChangeSet|20040422160720|05374
  # --------------------------------------------
  # 04/04/27      joreland@stripped      1.1888
  # removed libstc++ second try...
  # --------------------------------------------
  # 04/04/28      ejonore@stripped      1.1862.1.7
  # 1) Don't lock FUTURE pages but only current
  # 2) Do this when SIZEALT has completed
  # --------------------------------------------
  # 04/04/30      joreland@stripped      1.1889
  # Merge jonas@orca:/home/ndb/releases/mysql-4.1-ndb-3.4.x
  # into mysql.com:/home/jonas/src/mysql-4.1-ndb
  # --------------------------------------------
  # 04/05/03      ndb@stripped  1.1862.1.8
  # Version update
  # --------------------------------------------
  # 04/05/03      joreland@stripped      1.1862.3.1
  # Changed restart behavior.
  # Use "angel" process which monitor "real" process
  # --------------------------------------------
  # 04/05/03      joreland@stripped      1.1862.1.9
  # Merge jonas@orca:/home/ndb/releases/mysql-4.1-ndb-3.4.x
  # into mysql.com:/home/jonas/src/mysql-4.1-ndb-3.4.x
  # --------------------------------------------
  # 04/05/03      joreland@stripped      1.1890
  # Merge B2 fixes
  # --------------------------------------------
  # --------------------------------------------
  # 04/05/03      joreland@stripped      1.1862.1.10
  # Better handling of children terminations
  # --------------------------------------------
  # 04/05/03      joreland@stripped      1.1862.1.11
  # Fixes for angel-restarting
  # --------------------------------------------
  # 04/05/03      joreland@stripped      1.1891
  # Merge mysql.com:/home/jonas/src/mysql-4.1-ndb-3.4.x
  # into mysql.com:/home/jonas/src/mysql-4.1-ndb
  # --------------------------------------------
  #

  BitKeeper/etc/logging_ok
    1.293 04/05/04 11:19:19 joreland@stripped +1 -0
    Logging to logging@stripped accepted

  ndb/src/common/util/new.cpp
    1.1 04/05/04 11:18:53 joreland@stripped +46 -0

  ndb/test/src/UtilTransactions.cpp
    1.2 04/05/04 11:18:53 joreland@stripped +15 -2
    Merge ndb fixes

  ndb/test/src/NDBT_Test.cpp
    1.2 04/05/04 11:18:53 joreland@stripped +2 -0
    Merge ndb fixes

  ndb/test/src/NDBT_Tables.cpp
    1.2 04/05/04 11:18:53 joreland@stripped +2 -1
    Merge ndb fixes

  ndb/test/src/HugoTransactions.cpp
    1.2 04/05/04 11:18:53 joreland@stripped +12 -0
    Merge ndb fixes

  ndb/test/ndbapi/testScan/testScan.cpp
    1.2 04/05/04 11:18:53 joreland@stripped +32 -14
    Merge ndb fixes

  ndb/test/ndbapi/testMgm/testMgm.cpp
    1.2 04/05/04 11:18:53 joreland@stripped +0 -1
    Merge ndb fixes

  ndb/test/ndbapi/testIndex/testIndex.cpp
    1.2 04/05/04 11:18:53 joreland@stripped +9 -8
    Merge ndb fixes

  ndb/test/ndbapi/testDict/testDict.cpp
    1.2 04/05/04 11:18:53 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/src/common/util/new.cpp
    1.0 04/05/04 11:18:53 joreland@stripped +0 -0
    BitKeeper file /home/jonas/src/mysql-4.1/ndb/src/common/util/new.cpp

  ndb/src/rep/rep_version.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +3 -1
    Merge ndb fixes

  ndb/src/ndbapi/Ndberror.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/src/ndbapi/ClusterMgr.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +3 -2
    Merge ndb fixes

  ndb/src/mgmsrv/NodeLogLevel.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +2 -0
    Merge ndb fixes

  ndb/src/mgmsrv/MgmtSrvr.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +2 -0
    Merge ndb fixes

  ndb/src/kernel/vm/SimulatedBlock.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +0 -1
    Merge ndb fixes

  ndb/src/kernel/vm/SignalCounter.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/src/kernel/vm/Emulator.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +26 -116
    Merge ndb fixes

  ndb/src/kernel/vm/DLFifoList.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +17 -5
    Merge ndb fixes

  ndb/src/kernel/vm/Configuration.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -0
    Merge ndb fixes

  ndb/src/kernel/vm/Configuration.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +8 -4
    Merge ndb fixes

  ndb/src/kernel/ndb-main/Main.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +81 -126
    Merge ndb fixes

  ndb/src/kernel/error/Error.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/src/kernel/blocks/suma/Suma.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +5 -2
    Merge ndb fixes

  ndb/src/kernel/blocks/ndbfs/Filename.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +9 -0
    Merge ndb fixes

  ndb/src/kernel/blocks/dbutil/DbUtil.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +2 -1
    Merge ndb fixes

  ndb/src/kernel/blocks/dbutil/DbUtil.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +16 -0
    Merge ndb fixes

  ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +234 -323
    Merge ndb fixes

  ndb/src/kernel/blocks/dbtc/DbtcInit.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +3 -1
    Merge ndb fixes

  ndb/src/kernel/blocks/dbtc/Dbtc.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +25 -11
    Merge ndb fixes

  ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +237 -135
    Merge ndb fixes

  ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +5 -9
    Merge ndb fixes

  ndb/src/kernel/blocks/dblqh/Dblqh.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +84 -69
    Merge ndb fixes

  ndb/src/kernel/blocks/dbdict/Dbdict.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +47 -9
    Merge ndb fixes

  ndb/src/kernel/blocks/backup/restore/main.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +10 -6
    Merge ndb fixes

  ndb/src/kernel/blocks/backup/restore/Restore.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +2 -1
    Merge ndb fixes

  ndb/src/kernel/blocks/backup/restore/Restore.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -0
    Merge ndb fixes

  ndb/src/kernel/blocks/ERROR_codes.txt
    1.2 04/05/04 11:18:52 joreland@stripped +6 -1
    Merge ndb fixes

  ndb/src/cw/cpcd/Process.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +4 -5
    Merge ndb fixes

  ndb/src/common/util/version.c
    1.2 04/05/04 11:18:52 joreland@stripped +0 -1
    Merge ndb fixes

  ndb/src/common/util/Makefile
    1.2 04/05/04 11:18:52 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/src/common/portlib/unix/NdbMem.c
    1.2 04/05/04 11:18:52 joreland@stripped +2 -1
    Merge ndb fixes

  ndb/src/common/logger/ConsoleLogHandler.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/src/common/debugger/SignalLoggerManager.cpp
    1.2 04/05/04 11:18:52 joreland@stripped +22 -4
    Merge ndb fixes

  ndb/include/util/SocketServer.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -2
    Merge ndb fixes

  ndb/include/ndbapi/NdbScanOperation.hpp
    1.2 04/05/04 11:18:52 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/include/ndb_version.h
    1.2 04/05/04 11:18:51 joreland@stripped +2 -2
    Merge ndb fixes

  ndb/include/kernel/signaldata/ScanFrag.hpp
    1.2 04/05/04 11:18:51 joreland@stripped +24 -5
    Merge ndb fixes

  ndb/include/debugger/SignalLoggerManager.hpp
    1.2 04/05/04 11:18:51 joreland@stripped +6 -0
    Merge ndb fixes

  ndb/examples/ndbapi_scan_example/Makefile
    1.2 04/05/04 11:18:51 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/examples/ndbapi_async_example/ndbapi_async.cpp
    1.2 04/05/04 11:18:51 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/examples/ndbapi_async_example/Makefile
    1.2 04/05/04 11:18:51 joreland@stripped +1 -1
    Merge ndb fixes

  ndb/config/Defs.LINUX.x86.GCC.mk
    1.2 04/05/04 11:18:51 joreland@stripped +3 -3
    Merge ndb fixes

  BitKeeper/etc/logging_ok
    1.292 04/05/04 11:18:51 joreland@stripped +1 -0
    Merge ndb fixes

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	joreland
# Host:	eel.ndb.mysql.com
# Root:	/home/jonas/src/mysql-4.1

--- 1.291/BitKeeper/etc/logging_ok	Tue Apr 27 14:48:38 2004
+++ 1.293/BitKeeper/etc/logging_ok	Tue May  4 11:19:19 2004
@@ -31,6 +31,7 @@
 dlenev@stripped
 dlenev@stripped
 dlenev@stripped
+ejonore@stripped
 gerberb@stripped
 gluh@gluh.(none)
 gluh@stripped
@@ -71,6 +72,7 @@
 jcole@stripped
 jcole@stripped
 jcole@stripped
+joreland@stripped
 jorge@stripped
 kaj@stripped
 konstantin@stripped
--- New file ---
+++ ndb/src/common/util/new.cpp	04/05/04 11:18:53

#include <malloc.h>
#include <stdlib.h>

extern "C" {
  void (* ndb_new_handler)() = 0;
}

void *operator new (size_t sz)
{
  void * p = malloc (sz ? sz : 1);
  if(p)
    return p;
  if(ndb_new_handler)
    (* ndb_new_handler)();
  abort();
}

void *operator new[] (size_t sz)
{
  void * p = (void *) malloc (sz ? sz : 1);
  if(p)
    return p;
  if(ndb_new_handler)
    (* ndb_new_handler)();
  abort();
}

void operator delete (void *ptr)
{
  if (ptr)
    free(ptr);
}

void operator delete[] (void *ptr) throw ()
{
  if (ptr)
    free(ptr);
}

/**
 * GCC linking problem...
 */
#if ( __GNUC__ == 3 )
extern "C" { int __cxa_pure_virtual() {return 0;} }
#endif


--- 1.1/ndb/config/Defs.LINUX.x86.GCC.mk	Wed Apr 14 10:23:50 2004
+++ 1.2/ndb/config/Defs.LINUX.x86.GCC.mk	Tue May  4 11:18:51 2004
@@ -3,12 +3,12 @@
 # Defines
 SHELL       := /bin/sh
 
-C++         := g++$(GCC_VERSION)
+C++         := gcc$(GCC_VERSION)
 CC          := gcc$(GCC_VERSION)
 AR_RCS      := $(PURE) ar rcs 
 SO          := gcc$(GCC_VERSION) -shared -lpthread -o
 
-MAKEDEPEND  := g++$(GCC_VERSION) -M
+MAKEDEPEND  := gcc$(GCC_VERSION) -M
 PIC         := -fPIC
 
 RPCGENFLAGS := -M -C -N
@@ -53,4 +53,4 @@
 
 LINK.c = $(PURE) $(CC) $(CFLAGS) $(LDFLAGS)
 
-LDFLAGS_LAST = -lpthread -lrt -Wl,-Bstatic -lstdc++ -Wl,-Bdynamic
+LDFLAGS_LAST = -lpthread -lrt

--- 1.1/ndb/examples/ndbapi_async_example/Makefile	Wed Apr 14 10:44:35 2004
+++ 1.2/ndb/examples/ndbapi_async_example/Makefile	Tue May  4 11:18:51 2004
@@ -1,4 +1,4 @@
--include ../../Defs.mk
+-include .defs.mk
 #NDB_OS = OS_YOU_ARE_RUNNING_ON
 #NDB_OS = LINUX
 #You need to set the NDB_OS variable here (LINUX, SOLARIS, MACOSX)

--- 1.1/ndb/examples/ndbapi_async_example/ndbapi_async.cpp	Wed Apr 14 10:23:51 2004
+++ 1.2/ndb/examples/ndbapi_async_example/ndbapi_async.cpp	Tue May  4 11:18:51 2004
@@ -349,7 +349,7 @@
   NdbOperation*   myNdbOperation;       // For operations
 
   async_callback_t * cb;
-  int retries;
+  int retries = 0;
   int current = 0;
   for(int i=0; i<1024; i++)
   {

--- 1.1/ndb/examples/ndbapi_scan_example/Makefile	Wed Apr 14 10:44:35 2004
+++ 1.2/ndb/examples/ndbapi_scan_example/Makefile	Tue May  4 11:18:51 2004
@@ -1,4 +1,4 @@
--include ../../Defs.mk
+-include .defs.mk
 #NDB_OS = OS_YOU_ARE_RUNNING_ON
 #You need to set the NDB_OS variable here  (LINUX, SOLARIS, MACOSX)
 #NDB_OS = LINUX

--- 1.1/ndb/include/debugger/SignalLoggerManager.hpp	Wed Apr 14 10:23:52 2004
+++ 1.2/ndb/include/debugger/SignalLoggerManager.hpp	Tue May  4 11:18:51 2004
@@ -111,6 +111,9 @@
   void setTrace(unsigned long trace);   
   unsigned long getTrace() const;
 
+  void setOwnNodeId(int nodeId);
+  void setLogDistributed(bool val);
+
   /**
    * Print header
    */
@@ -149,6 +152,9 @@
   static void printDataWord(FILE * output, Uint32 & pos, const Uint32 data);
 
 private:
+  bool m_logDistributed;
+  int m_ownNodeId;
+
   FILE * outputStream;
   int log(int cmd, BlockNumber bno, LogMode logMode);
   

--- 1.1/ndb/include/kernel/signaldata/ScanFrag.hpp	Wed Apr 14 10:23:55 2004
+++ 1.2/ndb/include/kernel/signaldata/ScanFrag.hpp	Tue May  4 11:18:51 2004
@@ -54,6 +54,7 @@
   static Uint32 getReadCommittedFlag(const Uint32 & requestInfo);
   static Uint32 getRangeScanFlag(const Uint32 & requestInfo);
   static Uint32 getAttrLen(const Uint32 & requestInfo);
+  static Uint32 getScanPrio(const Uint32 & requestInfo);
   
   static void setConcurrency(Uint32 & requestInfo, Uint32 concurrency);
   static void setLockMode(Uint32 & requestInfo, Uint32 lockMode);
@@ -62,6 +63,7 @@
   static void setReadCommittedFlag(Uint32 & requestInfo, Uint32 readCommitted);
   static void setRangeScanFlag(Uint32 & requestInfo, Uint32 rangeScan);
   static void setAttrLen(Uint32 & requestInfo, Uint32 attrLen);
+  static void setScanPrio(Uint32& requestInfo, Uint32 prio);
 };
 
 class KeyInfo20 {
@@ -192,10 +194,11 @@
  * k = Keyinfo               - 1  Bit 8
  * r = read committed        - 1  Bit 9
  * x = range scan            - 1  Bit 6
+ * p = Scan prio             - 4  Bits (12-15) -> max 15
  *
  *           1111111111222222222233
  * 01234567890123456789012345678901
- * ccccclxhkr      aaaaaaaaaaaaaaaa 
+ * ccccclxhkr  ppppaaaaaaaaaaaaaaaa 
  */
 #define SF_CONCURRENCY_SHIFT (0)
 #define SF_CONCURRENCY_MASK  (31)
@@ -211,6 +214,9 @@
 #define SF_ATTR_LEN_SHIFT    (16)
 #define SF_ATTR_LEN_MASK     (65535)
 
+#define SF_PRIO_SHIFT 12
+#define SF_PRIO_MASK 15
+
 inline 
 Uint32
 ScanFragReq::getConcurrency(const Uint32 & requestInfo){
@@ -237,20 +243,33 @@
 
 inline
 Uint32
-ScanFragReq::getReadCommittedFlag(const Uint32 & requestInfo){
-  return (requestInfo >> SF_READ_COMMITTED_SHIFT) & 1;
+ScanFragReq::getRangeScanFlag(const Uint32 & requestInfo){
+  return (requestInfo >> SF_RANGE_SCAN_SHIFT) & 1;
 }
 
 inline
 Uint32
-ScanFragReq::getRangeScanFlag(const Uint32 & requestInfo){
-  return (requestInfo >> SF_RANGE_SCAN_SHIFT) & 1;
+ScanFragReq::getReadCommittedFlag(const Uint32 & requestInfo){
+  return (requestInfo >> SF_READ_COMMITTED_SHIFT) & 1;
 }
 
 inline 
 Uint32
 ScanFragReq::getAttrLen(const Uint32 & requestInfo){
   return (requestInfo >> SF_ATTR_LEN_SHIFT) & SF_ATTR_LEN_MASK;
+}
+
+inline
+Uint32
+ScanFragReq::getScanPrio(const Uint32 & requestInfo){
+  return (requestInfo >> SF_PRIO_SHIFT) & SF_PRIO_MASK;
+}
+
+inline
+void
+ScanFragReq::setScanPrio(UintR & requestInfo, UintR val){
+  ASSERT_MAX(val, SF_PRIO_MASK, "ScanFragReq::setScanPrio");
+  requestInfo |= (val << SF_PRIO_SHIFT);
 }
 
 inline

--- 1.1/ndb/include/ndb_version.h	Wed Apr 14 10:23:52 2004
+++ 1.2/ndb/include/ndb_version.h	Tue May  4 11:18:51 2004
@@ -29,8 +29,8 @@
  */
 
 #define NDB_VERSION_MAJOR 3
-#define NDB_VERSION_MINOR 4
-#define NDB_VERSION_BUILD 5
+#define NDB_VERSION_MINOR 5
+#define NDB_VERSION_BUILD 0
 #define NDB_VERSION_STATUS "alpha"
 
 #define NDB_VERSION_D MAKE_VERSION(NDB_VERSION_MAJOR, NDB_VERSION_MINOR, NDB_VERSION_BUILD)

--- 1.1/ndb/include/ndbapi/NdbScanOperation.hpp	Wed Apr 14 10:23:57 2004
+++ 1.2/ndb/include/ndbapi/NdbScanOperation.hpp	Tue May  4 11:18:52 2004
@@ -149,7 +149,7 @@
     char* anAttrName;
     Uint32 anAttrId;
   };
-  typedef struct String {
+  struct String {
     char* aStringValue;
     Uint32 len;
   };

--- 1.1/ndb/include/util/SocketServer.hpp	Wed Apr 14 10:23:58 2004
+++ 1.2/ndb/include/util/SocketServer.hpp	Tue May  4 11:18:52 2004
@@ -62,8 +62,7 @@
      * To manage threads self, just return NULL
      */
     virtual Session * newSession(NDB_SOCKET_TYPE theSock) = 0;
-
-    virtual void stopSessions() {}
+    virtual void stopSessions(){}
   };
   
   /**

--- 1.1/ndb/src/common/debugger/SignalLoggerManager.cpp	Wed Apr 14 10:24:07 2004
+++ 1.2/ndb/src/common/debugger/SignalLoggerManager.cpp	Tue May  4 11:18:52 2004
@@ -31,6 +31,8 @@
       logModes[i] = 0;
   }
   outputStream = 0;
+  m_ownNodeId = 0;
+  m_logDistributed = false;
 }
 
 SignalLoggerManager::~SignalLoggerManager()
@@ -78,7 +80,17 @@
 {
   return traceId;
 }
+
+void
+SignalLoggerManager::setOwnNodeId(int nodeId){
+  m_ownNodeId = nodeId;
+}
   
+void
+SignalLoggerManager::setLogDistributed(bool val){
+  m_logDistributed = val;
+}
+
 int
 getParameter(char *blocks[NO_OF_BLOCKS], const char * par, const char * line)
 {
@@ -236,10 +248,12 @@
   Uint32 trace = sh.theTrace;
   //Uint32 senderBlockNo = refToBlock(sh.theSendersBlockRef);
   Uint32 receiverBlockNo = sh.theReceiversBlockNumber;
+  Uint32 senderNode = refToNode(sh.theSendersBlockRef);
 
   if(outputStream != 0 && 
      (traceId == 0 || traceId == trace) &&
-     logMatch(receiverBlockNo, LogIn)){
+     (logMatch(receiverBlockNo, LogOut) ||
+      (m_logDistributed && m_ownNodeId != senderNode))){
 #ifdef VM_TRACE_TIME
     fprintf(outputStream, "---- Received - Signal - %d ----\n", time(0));
 #else
@@ -261,10 +275,12 @@
   Uint32 trace = sh.theTrace;
   //Uint32 senderBlockNo = refToBlock(sh.theSendersBlockRef);
   Uint32 receiverBlockNo = sh.theReceiversBlockNumber;
+  Uint32 senderNode = refToNode(sh.theSendersBlockRef);
 
   if(outputStream != 0 && 
      (traceId == 0 || traceId == trace) &&
-     logMatch(receiverBlockNo, LogIn)){
+     (logMatch(receiverBlockNo, LogOut) ||
+      (m_logDistributed && m_ownNodeId != senderNode))){
 #ifdef VM_TRACE_TIME
     fprintf(outputStream, "---- Received - Signal - %d ----\n", time(0));
 #else
@@ -293,7 +309,8 @@
 
   if(outputStream != 0 && 
      (traceId == 0 || traceId == trace) &&
-     logMatch(senderBlockNo, LogOut)){
+     (logMatch(senderBlockNo, LogOut) ||
+      (m_logDistributed && m_ownNodeId != node))){
 #ifdef VM_TRACE_TIME
     fprintf(outputStream, "---- Send ----- Signal - %d ----\n", time(0));
 #else
@@ -321,7 +338,8 @@
 
   if(outputStream != 0 && 
      (traceId == 0 || traceId == trace) &&
-     logMatch(senderBlockNo, LogOut)){
+     (logMatch(senderBlockNo, LogOut) ||
+      (m_logDistributed && m_ownNodeId != node))){
 #ifdef VM_TRACE_TIME
     fprintf(outputStream, "---- Send ----- Signal - %d ----\n", time(0));
 #else

--- 1.1/ndb/src/common/logger/ConsoleLogHandler.cpp	Wed Apr 14 10:24:09 2004
+++ 1.2/ndb/src/common/logger/ConsoleLogHandler.cpp	Tue May  4 11:18:52 2004
@@ -58,7 +58,7 @@
 void 
 ConsoleLogHandler::writeFooter()
 {
-  ndbout << getDefaultFooter();
+  ndbout << getDefaultFooter() << flush;
 }
 
   

--- 1.1/ndb/src/common/portlib/unix/NdbMem.c	Wed Apr 14 10:24:10 2004
+++ 1.2/ndb/src/common/portlib/unix/NdbMem.c	Tue May  4 11:18:52 2004
@@ -62,7 +62,8 @@
 #if defined NDB_MACOSX
   return 0;
 #else
-  return mlockall(MCL_CURRENT | MCL_FUTURE);
+  //return mlockall(MCL_CURRENT | MCL_FUTURE);
+  return mlockall(MCL_CURRENT);
 #endif
 }
 

--- 1.1/ndb/src/common/util/Makefile	Wed Apr 14 10:44:36 2004
+++ 1.2/ndb/src/common/util/Makefile	Tue May  4 11:18:52 2004
@@ -8,7 +8,7 @@
 SOURCES   = File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \
             SimpleProperties.cpp Parser.cpp InputStream.cpp SocketServer.cpp \
 	    OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \
-	    NdbSqlUtil.cpp
+	    NdbSqlUtil.cpp new.cpp
 
 SOURCES.c = uucode.c random.c getarg.c version.c
 

--- 1.1/ndb/src/common/util/version.c	Wed Apr 14 10:24:13 2004
+++ 1.2/ndb/src/common/util/version.c	Tue May  4 11:18:52 2004
@@ -65,7 +65,6 @@
 
 #ifndef TEST_VERSION
 struct NdbUpGradeCompatible ndbCompatibleTable_full[] = {
-  { NDB_VERSION_D      , MAKE_VERSION(NDB_VERSION_MAJOR,NDB_VERSION_MINOR,2), UG_Range },
   { 0, 0, UG_Null }
 };
 

--- 1.1/ndb/src/cw/cpcd/Process.cpp	Wed Apr 14 10:24:16 2004
+++ 1.2/ndb/src/cw/cpcd/Process.cpp	Tue May  4 11:18:52 2004
@@ -361,8 +361,8 @@
     switch(pid = fork()) {
     case 0: /* Child */
       
+      writePid(getpid());
       if(runas(m_runas.c_str()) == 0){
-	writePid(getpid());
 	do_exec();
       }
       _exit(1);
@@ -385,15 +385,14 @@
      */
     switch(fork()) {
     case 0: /* Child */
-      if(runas(m_runas.c_str()) != 0){
-	writePid(-1);
-	_exit(1);
-      }
       signal(SIGCHLD, SIG_IGN);
       pid_t pid;
       switch(pid = fork()) {
       case 0: /* Child */
 	writePid(getpid());
+	if(runas(m_runas.c_str()) != 0){
+	  _exit(1);
+	}
 	setsid();
 	do_exec();
 	_exit(1);

--- 1.1/ndb/src/kernel/blocks/ERROR_codes.txt	Wed Apr 14 10:24:17 2004
+++ 1.2/ndb/src/kernel/blocks/ERROR_codes.txt	Tue May  4 11:18:52 2004
@@ -3,7 +3,7 @@
 Next NDBFS 2000
 Next DBACC 3001
 Next DBTUP 4007
-Next DBLQH 5031
+Next DBLQH 5036
 Next DBDICT 6003
 Next DBDIH 7173
 Next DBTC 8035
@@ -187,6 +187,10 @@
 5032: lqhKeyRef, ZTEMPORARY_REDO_LOG_FAILURE
 5033: lqhKeyRef, ZTAIL_PROBLEM_IN_LOG_ERROR
 
+5034: Don't pop scan queue
+
+5035: Delay ACC_CONTOPCONT
+
 ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC
 -------------------------------------------------
 8040:
@@ -262,6 +266,7 @@
 CMVMI
 -----
 9000 Set RestartOnErrorInsert to restart -n
+9998 Enter endless loop (trigger watchdog)
 9999 Crash system immediatly
 
 Test Crashes in handling node restarts

--- 1.1/ndb/src/kernel/blocks/backup/restore/Restore.cpp	Wed Apr 14 10:24:18 2004
+++ 1.2/ndb/src/kernel/blocks/backup/restore/Restore.cpp	Tue May  4 11:18:52 2004
@@ -938,6 +938,7 @@
     ndbout_c("Restore: Failed to allocate memory");
     abort();
   }
+  d->m_table = this;
   allAttributesDesc.push_back(d);
 
   if(desc.key != NoKey /* && not variable */){

--- 1.1/ndb/src/kernel/blocks/backup/restore/Restore.hpp	Wed Apr 14 10:24:18 2004
+++ 1.2/ndb/src/kernel/blocks/backup/restore/Restore.hpp	Tue May  4 11:18:52 2004
@@ -89,9 +89,10 @@
 public:
   
   AttributeDesc() {
-    name[0] = 0; 
+    name[0] = 0;
   } 
 
+  const TableS * m_table;
   Uint32 getSizeInWords() const { return (size * arraySize + 31)/ 32;}
 }; // AttributeDesc
 

--- 1.1/ndb/src/kernel/blocks/backup/restore/main.cpp	Wed Apr 14 10:24:18 2004
+++ 1.2/ndb/src/kernel/blocks/backup/restore/main.cpp	Tue May  4 11:18:52 2004
@@ -20,6 +20,7 @@
 #include <NdbSleep.h>
 #include <Vector.hpp>
 #include <ndb_limits.h>
+#include <NdbTCP.h>
 #ifdef USE_MYSQL
 #include <mysql.h>
 #endif
@@ -607,15 +608,20 @@
       } // switch size
       break;
     case (String):
-      if (desc.size == 8) 
-      {
-	ndbout << data.string_value;
-	j = desc.arraySize;
+      if (desc.size == 8){ 
+	NdbDictionary::Column::Type type = desc.m_table->m_dictTable->getColumn(desc.attrId)->getType();
+	if(type == NdbDictionary::Column::Varchar){
+    	  short len = ntohs(data.u_int16_value[0]);
+  	  ndbout.print("%.*s", len, (data.string_value+2));
+  	} else {
+    	  ndbout << data.string_value;
+	}
       } // if
       else 
       {
 	ndbout << "String sz != 8 - this is something wrong??" << endl;
       }
+      j = desc.arraySize;
       break;
     case (Float):
       // Not yet supported to print float
@@ -642,7 +648,6 @@
   {
     const AttributeS * attr = tuple[i];
     debug << i << " " << attr->Desc->name;
-    
     ndbout << (* attr);
     
     if (i != (tuple.getNoOfAttributes() - 1))
@@ -792,7 +797,6 @@
   
 } // restoreCallback
 #endif
-
 
 
 

--- 1.1/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp	Wed Apr 14 10:24:18 2004
+++ 1.2/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp	Tue May  4 11:18:52 2004
@@ -46,10 +46,11 @@
 #include <TimeQueue.hpp>
 #include <new>
 
+#include <NdbSleep.h>
 #include <SafeCounter.hpp>
 
 // Used here only to print event reports on stdout/console.
-static EventLogger eventLogger;
+EventLogger g_eventLogger;
 
 Cmvmi::Cmvmi(const Configuration & conf) :
   SimulatedBlock(CMVMI, conf)
@@ -92,11 +93,6 @@
   
   subscriberPool.setSize(5);
 
-  // Print to stdout/console
-  eventLogger.createConsoleHandler();
-  eventLogger.setCategory("NDB");
-  eventLogger.enable(Logger::LL_INFO, Logger::LL_ALERT); // Log INFO to ALERT
-
   const ClusterConfiguration::ClusterData & clData = 
     theConfig.clusterConfigurationData() ;
   
@@ -130,6 +126,10 @@
   if(ERROR_INSERTED(9999)){
     CRASH_INSERTION(9999);
   }
+
+  if(ERROR_INSERTED(9998)){
+    while(true) NdbSleep_SecSleep(1);
+  }
 }//execNDB_TAMPER()
 
 void Cmvmi::execSET_LOGLEVELORD(Signal* signal) 
@@ -194,7 +194,7 @@
   }
 
   // Print the event info
-  eventLogger.log(eventReport->getEventType(), signal->theData);
+  g_eventLogger.log(eventReport->getEventType(), signal->theData);
 
 }//execEVENT_REP()
 
@@ -395,6 +395,15 @@
     sendSignal(numberToRef(blockNo, 0), GSN_SIZEALT_REP, signal,21, JBB);
   } else {
     jam();
+
+    if(theConfig.lockPagesInMainMemory()){
+      int res = NdbMem_MemLockAll();
+      if(res != 0){
+	g_eventLogger.warning("Failed to memlock pages");
+	warningEvent("Failed to memlock pages");
+      }
+    }
+    
     sendSTTORRY(signal);
   }
 }
@@ -404,7 +413,7 @@
   int id = signal->theData[1];
   const BlockReference userRef = signal->theData[0];
   const ClusterConfiguration::ClusterData & clusterConf = 
-        theConfig.clusterConfigurationData();
+    theConfig.clusterConfigurationData();
   const int myNodeId = globalData.ownId;
   
   jamEntry();
@@ -1116,6 +1125,24 @@
 };
 #endif
 
+
+static int iii;
+
+static
+int
+recurse(char * buf, int loops, int arg){
+  char * tmp = (char*)alloca(arg);
+  printf("tmp = %p\n", tmp);
+  for(iii = 0; iii<arg; iii += 1024){
+    tmp[iii] = (iii % 23 + (arg & iii));
+  }
+  
+  if(loops == 0)
+    return tmp[345];
+  else
+    return tmp[arg/loops] + recurse(tmp, loops - 1, arg);
+}
+
 void
 Cmvmi::execDUMP_STATE_ORD(Signal* signal)
 {
@@ -1141,7 +1168,18 @@
    * Here I can dump CMVMI state if needed
    */
   if(signal->theData[0] == 13){
-    infoEvent("Cmvmi: signalCount = %d", signalCount);
+#if 0
+    int loop = 100;
+    int len = (10*1024*1024);
+    if(signal->getLength() > 1)
+      loop = signal->theData[1];
+    if(signal->getLength() > 2)
+      len = signal->theData[2];
+    
+    ndbout_c("recurse(%d loop, %dkb per recurse)", loop, len/1024);
+    int a = recurse(0, loop, len);
+    ndbout_c("after...%d", a);
+#endif
   }
 
   DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];

--- 1.1/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	Wed Apr 14 10:24:18 2004
+++ 1.2/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	Tue May  4 11:18:52 2004
@@ -2635,7 +2635,7 @@
   c_noNodesFailed--;
 
   c_nodes.getPtr(nodePtr);
-  ndbrequire(nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD);
+  ndbrequire(nodePtr.p->nodeState == NodeRecord::NDB_NODE_DEAD);
   nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
   signal->theData[0] = reference();
   sendSignal(retRef, GSN_INCL_NODECONF, signal, 1, JBB);

--- 1.1/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	Wed Apr 14 10:24:19 2004
+++ 1.2/ndb/src/kernel/blocks/dblqh/Dblqh.hpp	Tue May  4 11:18:52 2004
@@ -20,6 +20,8 @@
 #include <pc.hpp>
 #include <ndb_limits.h>
 #include <SimulatedBlock.hpp>
+#include <DLList.hpp>
+#include <DLFifoList.hpp>
 #include <DLHashTable.hpp>
 
 #include <NodeBitmask.hpp>
@@ -505,6 +507,79 @@
   }; // size 20 bytes
   typedef Ptr<Databuf> DatabufPtr;
 
+  struct ScanRecord {
+    enum ScanState {
+      SCAN_FREE = 0,
+      WAIT_STORED_PROC_COPY = 1,
+      WAIT_STORED_PROC_SCAN = 2,
+      WAIT_NEXT_SCAN_COPY = 3,
+      WAIT_NEXT_SCAN = 4,
+      WAIT_DELETE_STORED_PROC_ID_SCAN = 5,
+      WAIT_DELETE_STORED_PROC_ID_COPY = 6,
+      WAIT_ACC_COPY = 7,
+      WAIT_ACC_SCAN = 8,
+      WAIT_SCAN_KEYINFO = 9,
+      WAIT_SCAN_NEXTREQ = 10,
+      WAIT_COPY_KEYINFO = 11,
+      WAIT_CLOSE_SCAN = 12,
+      WAIT_CLOSE_COPY = 13,
+      WAIT_RELEASE_LOCK = 14,
+      WAIT_TUPKEY_COPY = 15,
+      WAIT_LQHKEY_COPY = 16,
+      IN_QUEUE = 17
+    };
+    enum ScanType {
+      ST_IDLE = 0,
+      SCAN = 1,
+      COPY = 2
+    };
+    UintR scanAccOpPtr[MAX_PARALLEL_OP_PER_SCAN];
+    UintR scanApiOpPtr[MAX_PARALLEL_OP_PER_SCAN];
+    UintR scanOpLength[MAX_PARALLEL_OP_PER_SCAN];
+    UintR scanLocalref[2];
+    UintR copyPtr;
+    union {
+      Uint32 nextPool;
+      Uint32 nextList;
+    };
+    Uint32 prevList;
+    Uint32 nextHash;
+    Uint32 prevHash;
+    bool equal(const ScanRecord & key) const {
+      return scanNumber == key.scanNumber && fragPtrI == key.fragPtrI;
+    }
+    Uint32 hashValue() const {
+      return fragPtrI ^ scanNumber;
+    }
+    
+    UintR scanAccPtr;
+    UintR scanAiLength;
+    UintR scanCompletedOperations;
+    UintR scanConcurrentOperations;
+    UintR scanErrorCounter;
+    UintR scanLocalFragid;
+    UintR scanSchemaVersion;
+    Uint32 fragPtrI;
+    UintR scanSearchCondFalseCount;
+    UintR scanStoredProcId;
+    ScanState scanState;
+    UintR scanTcrec;
+    ScanType scanType;
+    BlockReference scanApiBlockref;
+    NodeId scanNodeId;
+    Uint8 scanCompletedStatus;
+    Uint8 scanFlag;
+    Uint8 scanLockHold;
+    Uint8 scanLockMode;
+    Uint8 readCommitted;
+    Uint8 rangeScan;
+    Uint8 scanNumber;
+    Uint8 scanReleaseCounter;
+    Uint8 scanTcWaiting;
+    Uint8 scanKeyinfoFlag;
+  }; // Size 272 bytes
+  typedef Ptr<ScanRecord> ScanRecordPtr;
+
   struct Fragrecord {
     enum ExecSrStatus {
       IDLE = 0,
@@ -627,7 +702,11 @@
      *       fragment operations on the fragment. 
      *       A maximum of four concurrently active is allowed.
      */
-    Uint16 fragScanRec[MAX_PARALLEL_SCANS_PER_FRAG + MAX_PARALLEL_INDEX_SCANS_PER_FRAG];
+    typedef Bitmask<4> ScanNumberMask;
+    ScanNumberMask m_scanNumberMask;
+    DLList<ScanRecord>::Head m_activeScans;
+    DLFifoList<ScanRecord>::Head m_queuedScans;
+
     Uint16 srLqhLognode[4];
     /**
      *       The fragment pointers in TUP and TUX
@@ -799,12 +878,7 @@
      *       should perform.
      */
     Uint8 nextLcp;
-    /**
-     *       The number of active scans currently in the fragment
-     *       replica.
-     */
-    Uint8 noActiveScan;
-    /**
+   /**
      *       How many local checkpoints does the fragment contain
      */
     Uint8 srChkpnr;
@@ -1774,64 +1848,6 @@
   }; // size 44 bytes
   typedef Ptr<PageRefRecord> PageRefRecordPtr;
 
-  struct ScanRecord {
-    enum ScanState {
-      SCAN_FREE = 0,
-      WAIT_STORED_PROC_COPY = 1,
-      WAIT_STORED_PROC_SCAN = 2,
-      WAIT_NEXT_SCAN_COPY = 3,
-      WAIT_NEXT_SCAN = 4,
-      WAIT_DELETE_STORED_PROC_ID_SCAN = 5,
-      WAIT_DELETE_STORED_PROC_ID_COPY = 6,
-      WAIT_ACC_COPY = 7,
-      WAIT_ACC_SCAN = 8,
-      WAIT_SCAN_KEYINFO = 9,
-      WAIT_SCAN_NEXTREQ = 10,
-      WAIT_COPY_KEYINFO = 11,
-      WAIT_CLOSE_SCAN = 12,
-      WAIT_CLOSE_COPY = 13,
-      WAIT_RELEASE_LOCK = 14,
-      WAIT_TUPKEY_COPY = 15,
-      WAIT_LQHKEY_COPY = 16
-    };
-    enum ScanType {
-      ST_IDLE = 0,
-      SCAN = 1,
-      COPY = 2
-    };
-    UintR scanAccOpPtr[MAX_PARALLEL_OP_PER_SCAN];
-    UintR scanApiOpPtr[MAX_PARALLEL_OP_PER_SCAN];
-    UintR scanOpLength[MAX_PARALLEL_OP_PER_SCAN];
-    UintR scanLocalref[2];
-    UintR copyPtr;
-    UintR nextScanrec;
-    UintR scanAccPtr;
-    UintR scanAiLength;
-    UintR scanCompletedOperations;
-    UintR scanConcurrentOperations;
-    UintR scanErrorCounter;
-    UintR scanLocalFragid;
-    UintR scanSchemaVersion;
-    UintR scanSearchCondFalseCount;
-    UintR scanStoredProcId;
-    ScanState scanState;
-    UintR scanTcrec;
-    ScanType scanType;
-    BlockReference scanApiBlockref;
-    NodeId scanNodeId;
-    Uint8 scanCompletedStatus;
-    Uint8 scanFlag;
-    Uint8 scanLockHold;
-    Uint8 scanLockMode;
-    Uint8 readCommitted;
-    Uint8 rangeScan;
-    Uint8 scanNumber;
-    Uint8 scanReleaseCounter;
-    Uint8 scanTcWaiting;
-    Uint8 scanKeyinfoFlag;
-  }; // Size 272 bytes
-  typedef Ptr<ScanRecord> ScanRecordPtr;
-
   struct Tablerec {
     enum TableStatus {
       TABLE_DEFINED = 0,
@@ -2644,11 +2660,10 @@
   UintR cpageRefFileSize;
 
 #define ZSCANREC_FILE_SIZE 100
-  ScanRecord *scanRecord;
+  ArrayPool<ScanRecord> c_scanRecordPool;
   ScanRecordPtr scanptr;
-  UintR cfirstfreeScanrec;
-  UintR cscanrecFileSize;
   UintR cscanNoFreeRec;
+  Uint32 cscanrecFileSize;
 
 // Configurable
   Tablerec *tablerec;
@@ -2893,7 +2908,7 @@
     return getNodeState().startLevel < NodeState::SL_STOPPING_3;
   }
 
-
+  DLHashTable<ScanRecord> c_scanTakeOverHash;
 };
 
 #endif

--- 1.1/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp	Wed Apr 14 10:24:19 2004
+++ 1.2/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp	Tue May  4 11:18:52 2004
@@ -56,7 +56,6 @@
   logFileOperationRecord = 0;
   logPageRecord = 0;
   pageRefRecord = 0;
-  scanRecord = 0;
   tablerec = 0;
   tcConnectionrec = 0;
   tcNodeFailRecord = 0;
@@ -127,9 +126,9 @@
 					      sizeof(PageRefRecord),
 					      cpageRefFileSize);
 
-  scanRecord = (ScanRecord*)allocRecord("ScanRecord",
-					sizeof(ScanRecord),
-					cscanrecFileSize);
+  cscanNoFreeRec = cscanrecFileSize;
+  c_scanRecordPool.setSize(cscanrecFileSize);
+  c_scanTakeOverHash.setSize(64);
 
   tablerec = (Tablerec*)allocRecord("Tablerec",
 				    sizeof(Tablerec), 
@@ -172,7 +171,8 @@
 
 Dblqh::Dblqh(const class Configuration & conf):
   SimulatedBlock(DBLQH, conf),
-  m_commitAckMarkerHash(m_commitAckMarkerPool)
+  m_commitAckMarkerHash(m_commitAckMarkerPool),
+  c_scanTakeOverHash(c_scanRecordPool)
 {
   BLOCK_CONSTRUCTOR(Dblqh);
 
@@ -391,10 +391,6 @@
 		sizeof(PageRefRecord),
 		cpageRefFileSize);
   
-  deallocRecord((void**)&scanRecord,
-		"ScanRecord",
-		sizeof(ScanRecord),
-		cscanrecFileSize);
 
   deallocRecord((void**)&tablerec,
 		"Tablerec",

--- 1.1/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	Wed Apr 14 10:24:19 2004
+++ 1.2/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	Tue May  4 11:18:52 2004
@@ -66,9 +66,7 @@
 #define DEBUG(x)
 #endif
 
-const Uint32 NR_ScanNo = MAX_PARALLEL_SCANS_PER_FRAG - 1;
-const Uint32 NR_MinRangeScanNo = MAX_PARALLEL_SCANS_PER_FRAG;
-const Uint32 NR_MaxRangeScanNo = NR_MinRangeScanNo + MAX_PARALLEL_INDEX_SCANS_PER_FRAG;
+const Uint32 NR_ScanNo = 0;
 
 void Dblqh::execACC_COM_BLOCK(Signal* signal)
 {
@@ -360,8 +358,7 @@
     break;
   case ZCHECK_LCP_STOP_BLOCKED:
     jam();
-    scanptr.i = data0;
-    ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+    c_scanRecordPool.getPtr(scanptr, data0);
     tcConnectptr.i = scanptr.p->scanTcrec;
     ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
     fragptr.i = tcConnectptr.p->fragmentptr;
@@ -964,8 +961,10 @@
     ndbrequire(tFragPtr.i != RNIL);
     // store it
     fragptr.p->tableFragptr = tFragPtr.i;
+  } else {
+    fragptr.p->tableFragptr = fragptr.i;
   }
-
+  
   if (tempTable) {
 //--------------------------------------------
 // reqinfo bit 3-4 = 2 means temporary table
@@ -2047,15 +2046,13 @@
       case TcConnectionrec::SCAN_STATE_USED:
 	if (tTcConptr.p->tcScanRec < cscanrecFileSize){
 	  ScanRecordPtr TscanPtr;
-	  TscanPtr.i = tTcConptr.p->tcScanRec;
-	  ptrCheckGuard(TscanPtr, cscanrecFileSize, scanRecord);	  
+	  c_scanRecordPool.getPtr(TscanPtr, tTcConptr.p->tcScanRec);
 	  ndbout << " scanState = " << TscanPtr.p->scanState << endl;
 	  //TscanPtr.p->scanAccOpPtr[16];
 	  //TscanPtr.p->scanApiOpPtr[16];
 	  //TscanPtr.p->scanOpLength[16];
 	  //TscanPtr.p->scanLocalref[2];
 	  ndbout << " copyPtr="<<TscanPtr.p->copyPtr
-		 << " nextScanrec="<<TscanPtr.p->nextScanrec
 		 << " scanAccPtr="<<TscanPtr.p->scanAccPtr
 		 << " scanAiLength="<<TscanPtr.p->scanAiLength
 		 << endl;
@@ -3499,7 +3496,6 @@
 void Dblqh::prepareContinueAfterBlockedLab(Signal* signal) 
 {
   UintR ttcScanOp;
-  UintR ttcScanNumber;
   UintR taccreq;
 
 /* -------------------------------------------------------------------------- */
@@ -3515,20 +3511,20 @@
   if (regTcPtr->indTakeOver == ZTRUE) {
     jam();
     ttcScanOp = KeyInfo20::getScanOp(regTcPtr->tcScanInfo);
-    ttcScanNumber = KeyInfo20::getScanNo(regTcPtr->tcScanInfo);
-    scanptr.i = ZNIL;
-    if (ttcScanNumber < NR_MaxRangeScanNo && ttcScanNumber != NR_ScanNo) {
-      jam();
-      // table fragment also when index scan
-      scanptr.i = fragptr.p->fragScanRec[ttcScanNumber];
+    scanptr.i = RNIL;
+    {
+      ScanRecord key;
+      key.scanNumber = KeyInfo20::getScanNo(regTcPtr->tcScanInfo);
+      key.fragPtrI = fragptr.i;
+      c_scanTakeOverHash.find(scanptr, key);
+      ndbassert(scanptr.i != RNIL);
     }
-    if (scanptr.i == ZNIL) {
+    if (scanptr.i == RNIL) {
       jam();
       releaseActiveFrag(signal);
       takeOverErrorLab(signal);
       return;
     }//if
-    ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
     Uint32 accOpPtr = scanptr.p->scanAccOpPtr[ttcScanOp];
     if (accOpPtr == RNIL) {
       jam();
@@ -6455,7 +6451,7 @@
           }//if
         } else {
           scanptr.i = tcConnectptr.p->tcScanRec;
-          ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+	  c_scanRecordPool.getPtr(scanptr);
           if (scanptr.p->scanType == ScanRecord::COPY) {
             jam();
             if (scanptr.p->scanNodeId == tcNodeFailptr.p->oldNodeId) {
@@ -6593,7 +6589,7 @@
 {
   jamEntry();
   scanptr.i = signal->theData[0];
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   Uint32 length = signal->theData[3];
   ndbrequire(length <= 4);
   accScanInfoEnterLab(signal, &signal->theData[4], length);
@@ -6604,7 +6600,7 @@
 {
   jamEntry();
   scanptr.i = signal->theData[0];
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   Uint32 length = signal->theData[3];
   ndbrequire(length <= 20);
   accScanInfoEnterLab(signal, &signal->theData[4], length);
@@ -6639,7 +6635,7 @@
   AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
   jamEntry();
   scanptr.i = accScanConf->scanPtr;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   if (scanptr.p->scanState == ScanRecord::WAIT_ACC_SCAN) {
     accScanConfScanLab(signal);
   } else {
@@ -6665,7 +6661,7 @@
   NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
   jamEntry();
   scanptr.i = nextScanConf->scanPtr;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   if (nextScanConf->localKeyLength == 1) {
     jam();
     nextScanConf->localKey[1] = 
@@ -6719,7 +6715,7 @@
   Uint32 storedProcId = signal->theData[1];
   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   switch (scanptr.p->scanState) {
   case ScanRecord::WAIT_STORED_PROC_SCAN:
     jam();
@@ -6756,7 +6752,7 @@
   Uint32 errorCode  = signal->theData[1];
   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   switch (scanptr.p->scanState) {
   case ScanRecord::WAIT_STORED_PROC_SCAN:
     jam();
@@ -6829,13 +6825,14 @@
   }//if
   if (ERROR_INSERTED(5030)){
     ndbout << "ERROR 5030" << endl;
+    CLEAR_ERROR_INSERT_VALUE;
     // Drop signal
     return;
   }//if
 
   scanptr.i = tcConnectptr.p->tcScanRec;
   ndbrequire(scanptr.i != RNIL);
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   scanptr.p->scanTcWaiting = ZTRUE;
 
   /* ------------------------------------------------------------------
@@ -6846,6 +6843,9 @@
    * ------------------------------------------------------------------ */
   if (nextReq->closeFlag == ZTRUE){
     jam();
+    if(ERROR_INSERTED(5034)){
+      CLEAR_ERROR_INSERT_VALUE;
+    }
     closeScanRequestLab(signal);
     return;
   }//if
@@ -6929,7 +6929,7 @@
 void Dblqh::continueScanReleaseAfterBlockedLab(Signal* signal) 
 {
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   scanptr.p->scanState = ScanRecord::WAIT_RELEASE_LOCK;
   signal->theData[0] = scanptr.p->scanAccPtr;
   ndbrequire((scanptr.p->scanReleaseCounter -1) < MAX_PARALLEL_OP_PER_SCAN);
@@ -6963,6 +6963,10 @@
   case TcConnectionrec::SCAN_STATE_USED:
     DEBUG("scanState = " << scanptr.p->scanState);
     switch (scanptr.p->scanState) {
+    case ScanRecord::IN_QUEUE:
+      jam();
+      tupScanCloseConfLab(signal);
+      break;
     case ScanRecord::WAIT_SCAN_KEYINFO:
     case ScanRecord::WAIT_NEXT_SCAN:
       jam();
@@ -7167,30 +7171,21 @@
     goto error_handler;
   }//if
   
-  // 1 table scan is reserved for node recovery
-  if (! rangeScan && fragptr.p->noActiveScan >= NR_ScanNo){
-    jam();
-    errorCode = ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
-    goto error_handler;
-  }
-  // count is actually not used in range scans
-  fragptr.p->noActiveScan++;
-
   // 1 scan record is reserved for node recovery
   if (cscanNoFreeRec < 2) {
     jam();
     errorCode = ScanFragRef::ZNO_FREE_SCANREC_ERROR;
-    goto error_handler1;
+    goto error_handler;
   }
 
   // XXX adjust cmaxAccOps for range scans and remove this comment
   if ((cbookedAccOps + scanConcurrentOperations) > cmaxAccOps) {
     jam();
     errorCode = ScanFragRef::ZSCAN_BOOK_ACC_OP_ERROR;
-    goto error_handler1;
+    goto error_handler;
   }//if
 
-  seizeScanrec(signal);
+  ndbrequire(c_scanRecordPool.seize(scanptr));
   initScanTc(signal,
              transid1,
              transid2,
@@ -7201,6 +7196,7 @@
     jam();
     goto error_handler2;
   }//if
+  cscanNoFreeRec--;
   cbookedAccOps += scanConcurrentOperations;
 
   hashIndex = (tcConnectptr.p->transid[0] ^ tcConnectptr.p->tcOprec) & 1023;
@@ -7227,9 +7223,7 @@
 
 error_handler2:
   // no scan number allocated
-  releaseScanrec(signal);
-error_handler1:
-  fragptr.p->noActiveScan--;
+  c_scanRecordPool.release(scanptr);
 error_handler:
   ref = (ScanFragRef*)&signal->theData[0];
   tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
@@ -7267,6 +7261,12 @@
 void Dblqh::continueAfterReceivingAllAiLab(Signal* signal) 
 {
   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
+
+  if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
+    jam();
+    return;
+  }
+  
   scanptr.p->scanState = ScanRecord::WAIT_ACC_SCAN;
   AccScanReq * req = (AccScanReq*)&signal->theData[0];
   req->senderData = scanptr.i;
@@ -7293,7 +7293,7 @@
 {
   if (saveTupattrbuf(signal, dataPtr, length) == ZOK) {
     scanptr.i = tcConnectptr.p->tcScanRec;
-    ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+    c_scanRecordPool.getPtr(scanptr);
     if (tcConnectptr.p->currTupAiLen < scanptr.p->scanAiLength) {
       jam();
     } else {
@@ -7304,13 +7304,21 @@
     return;
   }//if
   terrorCode = ZGET_ATTRINBUF_ERROR;
-  fragptr.i = tcConnectptr.p->fragmentptr;
-  ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
   finishScanrec(signal);
   releaseScanrec(signal);
-  fragptr.p->noActiveScan--;
   tcConnectptr.p->transactionState = TcConnectionrec::IDLE;
-  sendScanFragRefLateLab(signal);
+  tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
+
+  ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
+  ref->senderData = tcConnectptr.p->clientConnectrec;
+  ref->transId1 = tcConnectptr.p->transid[0];
+  ref->transId2 = tcConnectptr.p->transid[1];
+  ref->errorCode = terrorCode;
+  sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal, 
+	     ScanFragRef::SignalLength, JBB);
+  deleteTransidHash(signal);
+  releaseOprec(signal);
+  releaseTcrec(signal, tcConnectptr);
 }//Dblqh::scanAttrinfoLab()
 
 /*---------------------------------------------------------------------*/
@@ -7322,7 +7330,7 @@
 {
   jamEntry();
   scanptr.i = signal->theData[0];
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   switch(scanptr.p->scanType){
   case ScanRecord::SCAN:
     if (scanptr.p->scanTcWaiting == ZTRUE) {
@@ -7361,17 +7369,6 @@
 
 void Dblqh::sendScanFragRefLateLab(Signal* signal) 
 {
-  tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
-  ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
-  ref->senderData = tcConnectptr.p->clientConnectrec;
-  ref->transId1 = tcConnectptr.p->transid[0];
-  ref->transId2 = tcConnectptr.p->transid[1];
-  ref->errorCode = terrorCode;
-  sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal, 
-	     ScanFragRef::SignalLength, JBB);
-  deleteTransidHash(signal);
-  releaseOprec(signal);
-  releaseTcrec(signal, tcConnectptr);
 }//Dblqh::sendScanFragRefLateLab()
 
 
@@ -7506,7 +7503,7 @@
 void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal) 
 {
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
   initScanAccOp(signal);
   signal->theData[0] = scanptr.p->scanAccPtr;
@@ -7527,7 +7524,7 @@
 {
   jamEntry();
   scanptr.i = signal->theData[0];
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   tcConnectptr.i = scanptr.p->scanTcrec;
   ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
   fragptr.i = tcConnectptr.p->fragmentptr;
@@ -7582,7 +7579,7 @@
 void Dblqh::continueAfterCheckLcpStopBlocked(Signal* signal)
 {
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   signal->theData[0] = scanptr.p->scanAccPtr;
   signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
   if (! scanptr.p->rangeScan)
@@ -7831,7 +7828,7 @@
   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
   scanptr.i = tcConnectptr.p->tcScanRec;
   releaseActiveFrag(signal);
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   if (scanptr.p->scanCompletedStatus == ZTRUE) {
     /* ---------------------------------------------------------------------
      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
@@ -7930,7 +7927,7 @@
 void Dblqh::continueScanAfterBlockedLab(Signal* signal) 
 {
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   Uint32 accOpPtr;
   if (scanptr.p->scanFlag == NextScanReq::ZSCAN_NEXT_ABORT) {
     jam();
@@ -7966,7 +7963,7 @@
   scanptr.i = tcConnectptr.p->tcScanRec;
   releaseActiveFrag(signal);
   releaseOprec(signal);
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   if (scanptr.p->scanCompletedStatus == ZTRUE) {
     /* ---------------------------------------------------------------------
      *       STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
@@ -8068,7 +8065,7 @@
 {
   tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   scanptr.p->scanState = ScanRecord::WAIT_CLOSE_SCAN;
   signal->theData[0] = scanptr.p->scanAccPtr;
   signal->theData[1] = RNIL;
@@ -8132,7 +8129,6 @@
   finishScanrec(signal);
   releaseScanrec(signal);
   tcConnectptr.p->tcScanRec = RNIL;
-  fragptr.p->noActiveScan = fragptr.p->noActiveScan - 1;
   deleteTransidHash(signal);
   releaseOprec(signal);
   releaseTcrec(signal, tcConnectptr);
@@ -8165,8 +8161,9 @@
   const Uint32 scanLockHold = ScanFragReq::getHoldLockFlag(reqinfo);
   const Uint32 keyinfo = ScanFragReq::getKeyinfoFlag(reqinfo);
   const Uint32 readCommitted = ScanFragReq::getReadCommittedFlag(reqinfo);
-  const Uint32 rangeScan = ScanFragReq::getRangeScanFlag(reqinfo);
+  const Uint32 idx = ScanFragReq::getRangeScanFlag(reqinfo);
   const Uint32 attrLen = ScanFragReq::getAttrLen(reqinfo);
+  const Uint32 scanPrio = ScanFragReq::getScanPrio(reqinfo);
 
   scanptr.p->scanKeyinfoFlag = keyinfo;
   scanptr.p->scanLockHold = scanLockHold;
@@ -8181,7 +8178,7 @@
   scanptr.p->scanErrorCounter = 0;
   scanptr.p->scanLockMode = scanLockMode;
   scanptr.p->readCommitted = readCommitted;
-  scanptr.p->rangeScan = rangeScan;
+  scanptr.p->rangeScan = idx;
   scanptr.p->scanSearchCondFalseCount = 0;
   scanptr.p->scanState = ScanRecord::SCAN_FREE;
   scanptr.p->scanFlag = ZFALSE;
@@ -8189,6 +8186,7 @@
   scanptr.p->scanLocalref[1] = 0;
   scanptr.p->scanLocalFragid = 0;
   scanptr.p->scanTcWaiting = ZTRUE;
+  scanptr.p->scanNumber = ZNIL;
 
   for (Uint32 i = 0; i < scanConcurrentOperations; i++) {
     jam();
@@ -8196,6 +8194,59 @@
     scanptr.p->scanOpLength[i] = 0;
     scanptr.p->scanAccOpPtr[i] = 0;
   }//for
+
+  /**
+   * Used for scan take over
+   */
+  FragrecordPtr tFragPtr;
+  tFragPtr.i = fragptr.p->tableFragptr;
+  ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+  scanptr.p->fragPtrI = fragptr.p->tableFragptr;
+
+  /**
+   * !idx uses 1 - (MAX_PARALLEL_SCANS_PER_FRAG - 1)  =  1-11
+   *  idx uses from MAX_PARALLEL_SCANS_PER_FRAG - MAX = 12-42)
+   */
+  Uint32 start = (idx ? MAX_PARALLEL_SCANS_PER_FRAG : 1 );
+  Uint32 stop = (idx ? MAX_PARALLEL_INDEX_SCANS_PER_FRAG : MAX_PARALLEL_SCANS_PER_FRAG - 1);
+  stop += start;
+  Uint32 free = tFragPtr.p->m_scanNumberMask.find(start);
+
+  if(free == Fragrecord::ScanNumberMask::NotFound || free >= stop){
+    jam();
+
+    if(scanPrio == 0){
+      jam();
+      return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
+    }
+    
+    /**
+     * Put on queue
+     */
+    scanptr.p->scanState = ScanRecord::IN_QUEUE;
+    LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
+				      tFragPtr.p->m_queuedScans);
+    queue.add(scanptr);
+    return ZOK;
+  }
+  
+
+  scanptr.p->scanNumber = free;
+  tFragPtr.p->m_scanNumberMask.clear(free);// Update mask  
+
+  LocalDLList<ScanRecord> active(c_scanRecordPool, tFragPtr.p->m_activeScans);
+  active.add(scanptr);
+  if(scanptr.p->scanKeyinfoFlag){
+    jam();
+#ifdef VM_TRACE
+    ScanRecordPtr tmp;
+    ndbrequire(!c_scanTakeOverHash.find(tmp, * scanptr.p));
+#endif
+    c_scanTakeOverHash.add(scanptr);
+  }
+  return ZOK;
+
+#if 0
   if (! rangeScan) {
     jam();
     for (Int32 i = NR_ScanNo - 1; i >= 0; i--) {
@@ -8223,6 +8274,7 @@
     }
   }
   return ZNO_FREE_FRAG_SCAN_REC_ERROR;
+#endif
 }//Dblqh::initScanrec()
 
 /* =========================================================================
@@ -8263,17 +8315,72 @@
  * ========================================================================= */
 void Dblqh::finishScanrec(Signal* signal)
 {
-  if (! scanptr.p->rangeScan) {
-    ndbrequire(scanptr.p->scanNumber < NR_ScanNo);
-    fragptr.p->fragScanRec[scanptr.p->scanNumber] = ZNIL;
-  } else {
+  FragrecordPtr tFragPtr;
+  tFragPtr.i = scanptr.p->fragPtrI;
+  ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+  
+  LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
+				    tFragPtr.p->m_queuedScans);
+  
+  if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
     jam();
-    ndbrequire(NR_MinRangeScanNo <= scanptr.p->scanNumber && scanptr.p->scanNumber < NR_MaxRangeScanNo);
-    FragrecordPtr tFragPtr;
-    tFragPtr.i = fragptr.p->tableFragptr;
-    ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
-    tFragPtr.p->fragScanRec[scanptr.p->scanNumber] = ZNIL;
+    queue.release(scanptr);
+    return;
   }
+
+  if(scanptr.p->scanKeyinfoFlag){
+    jam();
+    ScanRecordPtr tmp;
+    c_scanTakeOverHash.remove(tmp, * scanptr.p);
+    ndbrequire(tmp.p == scanptr.p);
+  }
+  
+  LocalDLList<ScanRecord> scans(c_scanRecordPool, tFragPtr.p->m_activeScans);
+  scans.release(scanptr);
+  
+  const Uint32 scanNumber = scanptr.p->scanNumber;
+  ndbrequire(!tFragPtr.p->m_scanNumberMask.get(scanNumber));
+  ScanRecordPtr restart;
+
+  /**
+   * Start on of queued scans
+   */
+  if(scanNumber == NR_ScanNo || !queue.first(restart)){
+    jam();
+    tFragPtr.p->m_scanNumberMask.set(scanNumber);
+    return;
+  }
+
+  if(ERROR_INSERTED(5034)){
+    jam();
+    tFragPtr.p->m_scanNumberMask.set(scanNumber);
+    return;
+  }
+
+  ScanRecordPtr tmpScan = scanptr;
+  TcConnectionrecPtr tmpTc = tcConnectptr;
+  
+  tcConnectptr.i = restart.p->scanTcrec;
+  ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
+  restart.p->scanNumber = scanNumber;
+  restart.p->scanState = ScanRecord::WAIT_ACC_SCAN;
+  
+  queue.remove(restart);
+  scans.add(restart);
+  if(restart.p->scanKeyinfoFlag){
+    jam();
+#ifdef VM_TRACE
+    ScanRecordPtr tmp;
+    ndbrequire(!c_scanTakeOverHash.find(tmp, * restart.p));
+#endif
+    c_scanTakeOverHash.add(restart);
+  }
+  
+  scanptr = restart;
+  continueAfterReceivingAllAiLab(signal);  
+  
+  scanptr = tmpScan;
+  tcConnectptr = tmpTc;
 }//Dblqh::finishScanrec()
 
 /* ========================================================================= 
@@ -8283,8 +8390,6 @@
  * ========================================================================= */
 void Dblqh::releaseScanrec(Signal* signal) 
 {
-  scanptr.p->nextScanrec = cfirstfreeScanrec;
-  cfirstfreeScanrec = scanptr.i;
   scanptr.p->scanState = ScanRecord::SCAN_FREE;
   scanptr.p->scanType = ScanRecord::ST_IDLE;
   scanptr.p->scanTcWaiting = ZFALSE;
@@ -8292,20 +8397,6 @@
   cscanNoFreeRec++;
 }//Dblqh::releaseScanrec()
 
-/* =========================================================================
- * =======                       SEIZE SCAN RECORD                   ======= 
- *
- *       GETS A NEW SCAN RECORD FROM FREELIST.
- * ========================================================================= */
-void Dblqh::seizeScanrec(Signal* signal) 
-{
-  scanptr.i = cfirstfreeScanrec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
-  cfirstfreeScanrec = scanptr.p->nextScanrec;
-  scanptr.p->nextScanrec = RNIL;
-  cscanNoFreeRec--;
-}//Dblqh::seizeScanrec()
-
 /* ------------------------------------------------------------------------
  * -------              SEND KEYINFO20 TO API                       ------- 
  *
@@ -8471,10 +8562,8 @@
   ndbrequire(cnoActiveCopy < 3);
   ndbrequire(getFragmentrec(signal, fragId));
   ndbrequire(fragptr.p->copyFragState == ZIDLE);
-  ndbrequire(fragptr.p->noActiveScan < MAX_PARALLEL_SCANS_PER_FRAG);
-  ndbrequire(cfirstfreeScanrec != RNIL);
   ndbrequire(cfirstfreeTcConrec != RNIL);
-  ndbrequire(fragptr.p->fragScanRec[NR_ScanNo] == ZNIL);
+  ndbrequire(fragptr.p->m_scanNumberMask.get(NR_ScanNo));
 
   fragptr.p->fragDistributionKey = copyFragReq->distributionKey;
 
@@ -8494,7 +8583,8 @@
     return;
   }//if
   
-  seizeScanrec(signal);
+  LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
+  ndbrequire(scans.seize(scanptr));
 /* ------------------------------------------------------------------------- */
 // We keep track of how many operation records in ACC that has been booked.
 // Copy fragment has records always booked and thus need not book any. The
@@ -8519,8 +8609,9 @@
   scanptr.p->scanCompletedStatus = ZFALSE;
   scanptr.p->scanErrorCounter = 0;
   scanptr.p->scanNumber = NR_ScanNo;
-  fragptr.p->fragScanRec[NR_ScanNo] = scanptr.i;
-  fragptr.p->noActiveScan++;
+  scanptr.p->scanKeyinfoFlag = 0; // Don't put into hash
+  scanptr.p->fragPtrI = fragptr.i;
+  fragptr.p->m_scanNumberMask.clear(NR_ScanNo);
 
   initScanTc(signal,
              0,
@@ -8600,7 +8691,7 @@
     return;
   }//if
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN_COPY;
   switch (fragptr.p->fragStatus) {
   case Fragrecord::FSACTIVE:
@@ -8636,7 +8727,7 @@
 void Dblqh::continueFirstCopyAfterBlockedLab(Signal* signal) 
 {
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   signal->theData[0] = scanptr.p->scanAccPtr;
   signal->theData[1] = RNIL;
   signal->theData[2] = NextScanReq::ZSCAN_NEXT;
@@ -8798,7 +8889,7 @@
   UintR readLength = tupKeyConf->readLength;
 
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   releaseActiveFrag(signal);
   if (tcConnectptr.p->errorCode != 0) {
     jam();
@@ -8867,7 +8958,7 @@
 
   ndbrequire(tcConnectptr.p->transid[1] == lqhKeyConf->transId2);
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   if (tcConnectptr.p->copyCountWords >= cmaxWordsAtNodeRec) {
     tcConnectptr.p->copyCountWords -= lqhKeyConf->transId1; // Data overload, see note!
     if (scanptr.p->scanCompletedStatus == ZTRUE) {
@@ -8918,7 +9009,7 @@
   fragptr.i = tcConnectptr.p->fragmentptr;
   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   if (scanptr.p->scanState != ScanRecord::WAIT_LQHKEY_COPY) {
     jam();
 /*---------------------------------------------------------------------------*/
@@ -8964,7 +9055,7 @@
 void Dblqh::continueCopyAfterBlockedLab(Signal* signal) 
 {
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   tcConnectptr.p->errorCode = 0;
   signal->theData[0] = scanptr.p->scanAccPtr;
   signal->theData[1] = scanptr.p->scanAccOpPtr[0];
@@ -8978,7 +9069,7 @@
   ndbrequire(tcConnectptr.p->transid[1] == signal->theData[4]);
   tcConnectptr.p->copyCountWords -= signal->theData[3];
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   scanptr.p->scanErrorCounter++;
   tcConnectptr.p->errorCode = terrorCode;
   closeCopyLab(signal);
@@ -9001,7 +9092,7 @@
   fragptr.i = tcConnectptr.p->fragmentptr;
   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   scanptr.p->scanState = ScanRecord::WAIT_CLOSE_COPY;
   switch (fragptr.p->fragStatus) {
   case Fragrecord::FSACTIVE:
@@ -9037,7 +9128,7 @@
 void Dblqh::continueCloseCopyAfterBlockedLab(Signal* signal) 
 {
   scanptr.i = tcConnectptr.p->tcScanRec;
-  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+  c_scanRecordPool.getPtr(scanptr);
   signal->theData[0] = scanptr.p->scanAccPtr;
   signal->theData[1] = RNIL;
   signal->theData[2] = ZCOPY_CLOSE;
@@ -9085,6 +9176,8 @@
 {
   fragptr.i = tcConnectptr.p->fragmentptr;
   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+  fragptr.p->copyFragState = ZIDLE;
+
   if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
     jam();
     tcNodeFailptr.i = tcConnectptr.p->tcNodeFailrec;
@@ -9129,11 +9222,7 @@
   }//if
   releaseActiveCopy(signal);
   tcConnectptr.p->tcScanRec = RNIL;
-  ndbrequire(scanptr.p->scanNumber < MAX_PARALLEL_SCANS_PER_FRAG);
-  fragptr.p->fragScanRec[scanptr.p->scanNumber] = ZNIL;
-  ndbrequire(fragptr.p->noActiveScan > 0);
-  fragptr.p->noActiveScan--;
-  fragptr.p->copyFragState = ZIDLE;
+  finishScanrec(signal);
   releaseOprec(signal);
   releaseTcrec(signal, tcConnectptr);
   releaseScanrec(signal);
@@ -9321,8 +9410,10 @@
 /* ***************>> */
 void Dblqh::execCOPY_STATEREQ(Signal* signal) 
 {
-  Uint32* dataPtr = &signal->theData[2];
   jamEntry();
+  ndbrequire(0)
+#if 0
+  Uint32* dataPtr = &signal->theData[2];
   BlockReference tmasterBlockref = signal->theData[0];
   Uint32 tnoCopy = 0;
   do {
@@ -9340,7 +9431,7 @@
 /*   THIS FRAGMENT IS CURRENTLY ACTIVE IN COPYING THE FRAGMENT.              */
 /*---------------------------------------------------------------------------*/
       scanptr.i = fragptr.p->fragScanRec[NR_ScanNo];
-      ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+      c_scanRecordPool.getPtr(scanptr);
       if (scanptr.p->scanCompletedStatus == ZTRUE) {
         jam();
         dataPtr[3 + (tnoCopy << 2)] = ZCOPY_CLOSING;
@@ -9366,6 +9457,7 @@
   signal->theData[0] = cownNodeid;
   signal->theData[1] = tnoCopy;
   sendSignal(tmasterBlockref, GSN_COPY_STATECONF, signal, 18, JBB);
+#endif
   return;
 }//Dblqh::execCOPY_STATEREQ()
 
@@ -9857,6 +9949,12 @@
  *-------------------------------------------------------------------------- */
 void Dblqh::execACC_CONTOPCONF(Signal* signal) 
 {
+  if(ERROR_INSERTED(5035) && signal->getSendersBlockRef() != reference()){
+    sendSignalWithDelay(reference(), GSN_ACC_CONTOPCONF, signal, 1000, 
+			signal->length());
+    return;
+  }
+
   jamEntry();
   lcpLocptr.i = signal->theData[0];
   ptrCheckGuard(lcpLocptr, clcpLocrecFileSize, lcpLocRecord);
@@ -10142,8 +10240,6 @@
    *   WE START BY SENDING LCP_REPORT TO DIH TO REPORT THE COMPLETED LCP.
    *   TO CATER FOR NODE CRASHES WE SEND IT IN PARALLEL TO ALL NODES.
    * ----------------------------------------------------------------------- */
-  sendLCP_FRAG_REP(signal, lcpPtr.p->currentFragment);
-
   fragptr.i = lcpPtr.p->currentFragment.fragPtrI;
   ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
   fragptr.p->fragActiveStatus = ZFALSE;
@@ -10194,6 +10290,12 @@
     lcpPtr.p->lcpState = LcpRecord::LCP_BLOCKED_COMP;
     return;
   }//if
+
+  /**
+   * Send rep when fragment is done + unblocked
+   */
+  sendLCP_FRAG_REP(signal, lcpPtr.p->currentFragment);
+  
   /* ------------------------------------------------------------------------
    *       WE ALSO RELEASE THE LOCAL LCP RECORDS.
    * ----------------------------------------------------------------------- */
@@ -11782,6 +11884,12 @@
 /* WRITE.                                                                    */
 /*---------------------------------------------------------------------------*/
   switch (logFilePtr.p->fileChangeState) {
+#if 0
+  case LogFileRecord::BOTH_WRITES_ONGOING:
+    jam();
+    ndbout_c("not crashing!!");
+    // Fall-through
+#endif
   case LogFileRecord::NOT_ONGOING:
     jam();
     checkGcpCompleted(signal,
@@ -16046,18 +16154,16 @@
 void Dblqh::initialiseScanrec(Signal* signal) 
 {
   ndbrequire(cscanrecFileSize > 1);
-  for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
-    ptrAss(scanptr, scanRecord);
-    scanptr.p->nextScanrec = scanptr.i + 1;
+  DLList<ScanRecord> tmp(c_scanRecordPool);
+  while (tmp.seize(scanptr)){
+    //new (scanptr.p) ScanRecord();
     scanptr.p->scanType = ScanRecord::ST_IDLE;
     scanptr.p->scanState = ScanRecord::SCAN_FREE;
     scanptr.p->scanTcWaiting = ZFALSE;
-  }//for
-  scanptr.i = cscanrecFileSize - 1;
-  ptrAss(scanptr, scanRecord);
-  scanptr.p->nextScanrec = RNIL;
-  cfirstfreeScanrec = 0;
-  cscanNoFreeRec = cscanrecFileSize;
+    scanptr.p->nextHash = RNIL;
+    scanptr.p->prevHash = RNIL;
+  }
+  tmp.release();
 }//Dblqh::initialiseScanrec()
 
 /* ========================================================================== 
@@ -16136,6 +16242,8 @@
                         Uint32 fragId,
                         Uint32 copyType) 
 {
+  new (fragptr.p) Fragrecord();
+  fragptr.p->m_scanNumberMask.set(); // All is free
   fragptr.p->accBlockref = caccBlockref;
   fragptr.p->accBlockedList = RNIL;
   fragptr.p->activeList = RNIL;
@@ -16151,12 +16259,8 @@
   for (Uint32 i = 0; i < MAX_LCP_STORED; i++) {
     fragptr.p->lcpId[i] = 0;
   }//for
-  for (Uint32 i = 0; i < NR_MaxRangeScanNo; i++) {
-    fragptr.p->fragScanRec[i] = ZNIL;
-  }//for
   fragptr.p->maxGciCompletedInLcp = 0;
   fragptr.p->maxGciInLcp = 0;
-  fragptr.p->noActiveScan = 0;
   fragptr.p->copyFragState = ZIDLE;
   fragptr.p->nextFrag = RNIL;
   fragptr.p->newestGci = cnewestGci;
@@ -17809,7 +17913,7 @@
 
     ScanRecordPtr sp;
     sp.i = recordNo;
-    ptrAss(sp, scanRecord);
+    c_scanRecordPool.getPtr(scanptr);
     if (sp.p->scanState != ScanRecord::SCAN_FREE){
       dumpState->args[0] = DumpStateOrd::LqhDumpOneScanRec;
       dumpState->args[1] = recordNo;
@@ -17836,7 +17940,7 @@
 
     ScanRecordPtr sp;
     sp.i = recordNo;
-    ptrAss(sp, scanRecord);
+    c_scanRecordPool.getPtr(sp);
     infoEvent("Dblqh::ScanRecord[%d]: state=%d, type=%d, "
 	      "complStatus=%d, scanNodeId=%d",
 	      sp.i,
@@ -17868,8 +17972,6 @@
 	      sp.p->scanTcWaiting,
 	      sp.p->scanTcrec,
 	      sp.p->scanKeyinfoFlag);
-    infoEvent(" next=%d",
-	      sp.p->nextScanrec);
     return;
   }
   if(dumpState->args[0] == DumpStateOrd::LqhDumpLcpState){

--- 1.1/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	Wed Apr 14 10:24:19 2004
+++ 1.2/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	Tue May  4 11:18:52 2004
@@ -380,11 +380,8 @@
   /* WHEN THE TRIGGER IS DEACTIVATED.         */
   /* **************************************** */
   struct TcFiredTriggerData {
-    TcFiredTriggerData(AttributeBuffer::DataBufferPool & abp):
-      keyValues(abp),
-      beforeValues(abp),
-      afterValues(abp)
-    {}
+    TcFiredTriggerData() {}
+
     /**
      * Trigger id, used to identify the trigger
      **/
@@ -396,19 +393,24 @@
     Uint32 fireingOperation;
 
     /**
+     * Used for scrapping in case of node failure
+     */
+    Uint32 nodeId;
+
+    /**
      * Trigger attribute info, primary key value(s)
      */
-    AttributeBuffer keyValues;
+    AttributeBuffer::Head keyValues;
     
     /**
      * Trigger attribute info, attribute value(s) before operation
      */
-    AttributeBuffer beforeValues;
+    AttributeBuffer::Head beforeValues;
     
     /**
      * Trigger attribute info, attribute value(s) after operation
      */
-    AttributeBuffer afterValues;
+    AttributeBuffer::Head afterValues;
 
     /**
      * Next ptr (used in pool/list)
@@ -416,16 +418,28 @@
     union {
       Uint32 nextPool;
       Uint32 nextList;
+      Uint32 nextHash;
     };
     
     /**
      * Prev pointer (used in list)
      */
-    Uint32 prevList;
-
+    union {
+      Uint32 prevList;
+      Uint32 prevHash;
+    };
+    
     inline void print(NdbOut & s) const { 
       s << "[FiredTriggerData = " << triggerId << "]"; 
     }
+
+    inline Uint32 hashValue() const {
+      return fireingOperation ^ nodeId;
+    }
+
+    inline bool equal(const TcFiredTriggerData & rec) const {
+      return fireingOperation == rec.fireingOperation && nodeId == rec.nodeId;
+    }
   };
   typedef Ptr<TcFiredTriggerData> FiredTriggerPtr;
   
@@ -433,6 +447,7 @@
    * Pool of trigger data record
    */
   ArrayPool<TcFiredTriggerData> c_theFiredTriggerPool;
+  DLHashTable<TcFiredTriggerData> c_firedTriggerHash;
   AttributeBuffer::DataBufferPool c_theTriggerAttrInfoPool;
 
   Uint32 c_maxNumberOfDefinedTriggers;
@@ -822,7 +837,6 @@
     UintR triggerExecutionCount;
     UintR triggeringOperation;
     UintR savedState[LqhKeyConf::SignalLength];
-    UintR triggerError;
     
     // Index data
     bool isIndexOp; // Used to mark on-going TcKeyReq as index table access

--- 1.1/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp	Wed Apr 14 10:24:19 2004
+++ 1.2/ndb/src/kernel/blocks/dbtc/DbtcInit.cpp	Tue May  4 11:18:52 2004
@@ -71,6 +71,7 @@
   c_theIndexOperationPool.setSize(c_maxNumberOfIndexOperations);
   c_theSeizedIndexOperationPool.setSize(c_maxNumberOfIndexOperations);
   c_theAttributeBufferPool.setSize(c_transactionBufferSpace);
+  c_firedTriggerHash.setSize((c_maxNumberOfFiredTriggers+10)/10);
 }//Dbtc::initData()
 
 void Dbtc::initRecords() 
@@ -93,7 +94,7 @@
   DLFifoList<TcFiredTriggerData> triggers(c_theFiredTriggerPool);
   FiredTriggerPtr tptr;
   while(triggers.seize(tptr) == true) {
-    new (tptr.p) TcFiredTriggerData(c_theAttributeBufferPool);
+    new (tptr.p) TcFiredTriggerData();
   }
   triggers.release();
 
@@ -169,6 +170,7 @@
 Dbtc::Dbtc(const class Configuration & conf):
   SimulatedBlock(DBTC, conf),
   c_theDefinedTriggers(c_theDefinedTriggerPool),
+  c_firedTriggerHash(c_theFiredTriggerPool),
   c_maxNumberOfDefinedTriggers(0),
   c_maxNumberOfFiredTriggers(0),
   c_theIndexes(c_theIndexPool),

--- 1.1/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	Wed Apr 14 10:24:19 2004
+++ 1.2/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	Tue May  4 11:18:52 2004
@@ -2314,7 +2314,6 @@
   regTcPtr->noReceivedTriggers = 0;
   regTcPtr->triggerExecutionCount = 0;
   regTcPtr->triggeringOperation = RNIL;
-  regTcPtr->triggerError = 0;
   regTcPtr->isIndexOp = false;
   regTcPtr->indexOp = RNIL;
   regTcPtr->currentIndexId = RNIL;
@@ -3500,7 +3499,7 @@
   UintR TapiConnectFilesize = capiConnectFilesize;
   UintR Ttrans1 = lqhKeyConf->transId1;
   UintR Ttrans2 = lqhKeyConf->transId2;
-  regTcPtr->noFiredTriggers = lqhKeyConf->noFiredTriggers;
+  Uint32 noFired = lqhKeyConf->noFiredTriggers;
 
   if (TapiConnectptrIndex >= TapiConnectFilesize) {
     TCKEY_abort(signal, 29);
@@ -3554,6 +3553,7 @@
   UintR TtcTimer = ctcTimer;
   regTcPtr->lastLqhCon = tlastLqhConnect;
   regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
+  regTcPtr->noFiredTriggers = noFired;
 
   UintR Ttckeyrec = (UintR)regApiPtr->tckeyrec;
   UintR TclientData = regTcPtr->clientData;
@@ -3576,18 +3576,16 @@
     // will be returned unpacked
     regTcPtr->attrInfoLen = treadlenAi;
   } else {
-    jam();
-    regApiPtr->tcSendArray[Ttckeyrec] = TclientData;
-    regApiPtr->tcSendArray[Ttckeyrec + 1] = treadlenAi;
-    if ((regTcPtr->noFiredTriggers == 0) &&
-        (regTcPtr->triggeringOperation == RNIL)) {
+    if (noFired == 0 && regTcPtr->triggeringOperation == RNIL) {
       jam();
       /*
-      Skip counting triggering operations the first round
-      since they will enter execLQHKEYCONF a second time
-      Skip counting internally generated TcKeyReq
-      */
-      regApiPtr->tckeyrec += 2;
+       * Skip counting triggering operations the first round
+       * since they will enter execLQHKEYCONF a second time
+       * Skip counting internally generated TcKeyReq
+       */
+      regApiPtr->tcSendArray[Ttckeyrec] = TclientData;
+      regApiPtr->tcSendArray[Ttckeyrec + 1] = treadlenAi;
+      regApiPtr->tckeyrec = Ttckeyrec + 2;
     }//if
   }//if
   if (TdirtyOp == ZTRUE) {
@@ -3597,7 +3595,7 @@
     regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec - 1;
   } else {
     jam();
-    if (regTcPtr->noFiredTriggers == 0) {
+    if (noFired == 0) {
       jam();
       // No triggers to execute
       UintR Tlqhkeyconfrec = regApiPtr->lqhkeyconfrec;
@@ -3624,10 +3622,9 @@
       Continue triggering operation
       */
       jam();
-      regTcPtr->triggeringOperation = RNIL;
       continueTriggeringOp(signal, opPtr.p);
     }
-  } else if (regTcPtr->noFiredTriggers == 0) {
+  } else if (noFired == 0) {
     // This operation did not fire any triggers, finish operation
     jam();
     if (regTcPtr->isIndexOp) {
@@ -3639,20 +3636,19 @@
     // We have fired triggers
     jam();
     saveTriggeringOpState(signal, regTcPtr);
-    if (regTcPtr->noReceivedTriggers == regTcPtr->noFiredTriggers) {
+    if (regTcPtr->noReceivedTriggers == noFired) {
       ApiConnectRecordPtr transPtr;
-    
+      
       // We have received all data
       jam();
       transPtr.i = TapiConnectptrIndex;
       transPtr.p = regApiPtr;
       executeTriggers(signal, &transPtr);
     }
-  // else wait for more trigger data
+    // else wait for more trigger data
   }
 }//Dbtc::execLQHKEYCONF()
-
-
+ 
 void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
 			      TcConnectRecord* regTcPtr) 
 {
@@ -4863,16 +4859,8 @@
 {
   const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
   jamEntry();
-
-  handleFailedOperation(signal, lqhKeyRef, true);
-}
-
-void Dbtc::handleFailedOperation(Signal* signal,
-				 const LqhKeyRef * const lqhKeyRef, 
-				 bool gotLqhKeyRef)
-{
+  
   UintR compare_transid1, compare_transid2;
-
   UintR TtcConnectFilesize = ctcConnectFilesize;
   /*-------------------------------------------------------------------------
    *                                                                         
@@ -4891,7 +4879,7 @@
      * ALREADY COMPLETED (ABORTED).
      *-----------------------------------------------------------------------*/
     tcConnectptr.i = lqhKeyRef->connectPtr;
-    terrorCode = lqhKeyRef->errorCode;
+    Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
     ptrAss(tcConnectptr, tcConnectRecord);
     TcConnectRecord * const regTcPtr = tcConnectptr.p;
     if (regTcPtr->tcConnectstate == OS_OPERATING) {
@@ -4906,98 +4894,58 @@
 	return;
       }//if
 
-      if (regTcPtr->triggeringOperation != RNIL) {
+      const ConnectionState state = regApiPtr->apiConnectstate;
+      const Uint32 triggeringOp = regTcPtr->triggeringOperation;
+      if (triggeringOp != RNIL) {
         jam();
 	// This operation was created by a trigger execting operation
 	TcConnectRecordPtr opPtr;
 	TcConnectRecord *localTcConnectRecord = tcConnectRecord;
        
 	const Uint32 currentIndexId = regTcPtr->currentIndexId;
+	ndbassert(currentIndexId != 0); // Only index triggers so far
 	
-	opPtr.i = regTcPtr->triggeringOperation;
+	opPtr.i = triggeringOp;
 	ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
-	if (currentIndexId != RNIL)
-        {
-          jam();
-	  // The operation executed an index trigger
-	  TcIndexData* indexData = NULL;
-	  indexData = c_theIndexes.getPtr(currentIndexId);
-          if (regTcPtr->operation == ZDELETE) {
-            if (lqhKeyRef->errorCode == ZNOT_FOUND) {
-              if (indexData->indexState == IS_BUILDING) {
-                jam();
-                /*
-	        If an index trigger fail with delete during index
-	        build phase it just means that the index build has not
-	        yet inserted that tuple
-	        Check if operation was a delete and part of trigger execution
-                */
-              } else {
-                jam();
-                ndbassert(false);
-                terrorCode = ZINDEX_CORRUPT_ERROR;
-                abortErrorLab(signal);
-                return;
-              }//if
-            } else {
-              terrorCode = lqhKeyRef->errorCode;
-              abortErrorLab(signal);
-              return;
-            }
-          } else if (regTcPtr->operation == ZINSERT) {
-            if (lqhKeyRef->errorCode == ZALREADYEXIST) {
-              terrorCode = 893; //Constraint violation
-              abortErrorLab(signal);
-              return;
-            } else {
-              terrorCode = lqhKeyRef->errorCode;
-              abortErrorLab(signal);
-            }
-          } else {
-            ndbrequire(false);
-            return;
-          }
-	  markOperationAborted(regApiPtr, regTcPtr);
-          if (regApiPtr->apiConnectstate == CS_ABORTING) {
-            jam();
-            return;
-          }
-	  unlinkReadyTcCon(signal);
-	  releaseTcCon(signal);
-	  // Decrease counter as if NOOP
-	  regApiPtr->lqhkeyreqrec--;
-          opPtr.p->triggerExecutionCount--;
-          if (opPtr.p->triggerExecutionCount == 0) {
-            jam();
-            /*
-	    We have completed current trigger execution
-            continue triggering operation
-            */
-            continueTriggeringOp(signal, opPtr.p);
-	  }//if
-	  if (!regApiPtr->theFiredTriggers.isEmpty()) {
-	    jam();
-            /*
-	    There are more triggers
-	    Continue with next trigger
-            */
-	    executeTriggers(signal, &apiConnectptr);
-	  }//if
-	  return;
+	
+	// The operation executed an index trigger
+	const Uint32 opType = regTcPtr->operation;
+	if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
+	  jam();
+	  /**
+	   * "Normal path"
+	   */
+	  // fall-through
 	} else {
-          /**
-           * Currently the index id is always set for triggering operations
-             since we only support them for unique hash indexes at the moment.
-           */
-          ndbrequire(false);
-          return;
-        }
+	  jam();
+	  /** ZDELETE && NOT_FOUND */
+	  TcIndexData* indexData = c_theIndexes.getPtr(currentIndexId);
+	  if(indexData->indexState == IS_BUILDING && state != CS_ABORTING){
+	    jam();
+	    /**
+	     * Ignore error
+	     */
+	    regApiPtr->lqhkeyconfrec++;
+	    
+	    unlinkReadyTcCon(signal);
+	    releaseTcCon(signal);
+	    
+	    opPtr.p->triggerExecutionCount--;
+	    if (opPtr.p->triggerExecutionCount == 0) {
+	      /**
+	       * We have completed current trigger execution
+	       * Continue triggering operation
+	       */
+	      jam();
+	      continueTriggeringOp(signal, opPtr.p);
+	    }
+	    return;
+	  }
+	}
       }
-      if (gotLqhKeyRef) {
-        jam();
-	markOperationAborted(regApiPtr, regTcPtr);
-      }//if
-
+      
+      markOperationAborted(regApiPtr, regTcPtr);
+      
       if(regApiPtr->apiConnectstate == CS_ABORTING){
 	/**
 	 * We're already aborting' so don't send an "extra" TCKEYREF
@@ -5006,8 +4954,8 @@
 	return;
       }
       
-      const Uint32 abortOption = regTcPtr->m_execAbortOption;
-      if (abortOption == TcKeyReq::AbortOnError) {
+      const Uint32 abort = regTcPtr->m_execAbortOption;
+      if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
 	/**
 	 * No error is allowed on this operation
 	 */
@@ -5035,10 +4983,8 @@
       bool isIndexOp = regTcPtr->isIndexOp;
       Uint32 indexOp = tcConnectptr.p->indexOp;
       Uint32 clientData = regTcPtr->clientData;
-      if (gotLqhKeyRef) {
-	unlinkReadyTcCon(signal);   /* LINK TC CONNECT RECORD OUT OF  */
-	releaseTcCon(signal);       /* RELEASE THE TC CONNECT RECORD  */
-      }
+      unlinkReadyTcCon(signal);   /* LINK TC CONNECT RECORD OUT OF  */
+      releaseTcCon(signal);       /* RELEASE THE TC CONNECT RECORD  */
       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
       if (isIndexOp) {
         jam();
@@ -5057,18 +5003,12 @@
        * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO 
        * TCKEYCONF (IF THERE IS ANYTHING TO SEND).          
        *---------------------------------------------------------------------*/
-      if (gotLqhKeyRef) {
-        jam();
-	regApiPtr->lqhkeyreqrec = regApiPtr->lqhkeyreqrec - 1;
-      } else {
-        jam();
-	regApiPtr->lqhkeyconfrec = regApiPtr->lqhkeyconfrec + 1;
-      }//if 
+      regApiPtr->lqhkeyreqrec--;
       if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
 	if ((regApiPtr->lqhkeyconfrec == 0) &&
 	    (regApiPtr->apiConnectstate == CS_START_COMMITTING)) {
-
-	  if(abortOption == TcKeyReq::IgnoreError){
+	  
+	  if(abort == TcKeyReq::IgnoreError){
 	    jam();
 	    regApiPtr->returnsignal = RS_NO_RETURN;
 	    abort010Lab(signal);
@@ -6289,12 +6229,21 @@
 		 transP->firstTcConnect,
 		 c_apiConTimer[apiConnectptr.i]
 		 );
+    ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d", 
+	     __LINE__,
+	     apiConnectptr.i, 
+	     transP->apiConnectstate,
+	     c_apiConTimer_line[apiConnectptr.i],
+	     transP->firstTcConnect,
+	     c_apiConTimer[apiConnectptr.i]
+	     );
+    ndbrequire(false);
     setApiConTimer(apiConnectptr.i, 0, __LINE__);
     return;
   }
   
   OperationState tmp[16];
-
+  
   Uint32 TloopCount = 0;
   do {
     jam();
@@ -6316,6 +6265,8 @@
 	  snprintf(buf, sizeof(buf), buf2);
 	}
 	warningEvent(buf);
+	ndbout_c(buf);
+	ndbrequire(false);
 	releaseAbortResources(signal);
         return;
       }//if
@@ -7919,8 +7870,8 @@
   tblockref = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
 
   apiConnectptr.p->tcBlockref = tblockref;
-  apiConnectptr.p->ndbapiBlockref = tapplRef;
-  apiConnectptr.p->ndbapiConnect = tapplOprec;
+  apiConnectptr.p->ndbapiBlockref = 0;
+  apiConnectptr.p->ndbapiConnect = 0;
   apiConnectptr.p->buddyPtr = RNIL;
   setApiConTimer(apiConnectptr.i, 0, __LINE__);
   switch(ttransStatus){
@@ -9821,6 +9772,7 @@
   ScanFragReq::setReadCommittedFlag(requestInfo, scanptr.p->readCommitted);
   ScanFragReq::setRangeScanFlag(requestInfo, scanptr.p->rangeScan);
   ScanFragReq::setAttrLen(requestInfo, scanptr.p->scanAiLength);
+  ScanFragReq::setScanPrio(requestInfo, 1);
   apiConnectptr.i = scanptr.p->scanApiRec;
   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
   ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
@@ -11195,34 +11147,52 @@
 void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
 {
   jamEntry();
-  FireTrigOrd * const fireTrigOrd =  (FireTrigOrd *)signal->getDataPtr();
+  FireTrigOrd * const fireOrd =  (FireTrigOrd *)signal->getDataPtr();
   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
   ApiConnectRecordPtr transPtr;
   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
   TcConnectRecordPtr opPtr;
-  
-  opPtr.i = fireTrigOrd->getConnectionPtr();
-  ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
-  transPtr.i = opPtr.p->apiConnect;
-  transPtr.p = &localApiConnectRecord[transPtr.i];
-  if(opPtr.p->triggerError == 0){
-    scheduleFiredTrigger(&transPtr, &opPtr);
-  }
-  
-  // If we have received complete info of all fired triggers
-  // then execute the triggers
-  if (++(opPtr.p->noReceivedTriggers) == opPtr.p->noFiredTriggers) {
-    jam();
-    if (opPtr.p->triggerError != 0) {
-      jam();
-      // Abort transaction
-      apiConnectptr.i = transPtr.i;
-      terrorCode = opPtr.p->triggerError;
-      abortErrorLab(signal);
-      return;    
-    }//if
-    executeTriggers(signal, &transPtr);
-  }//if
+
+  /**
+   * TODO
+   * Check transid,
+   * Fix overload i.e invalid word count
+   */
+  TcFiredTriggerData key;
+  key.fireingOperation = fireOrd->getConnectionPtr();
+  key.nodeId = refToNode(signal->getSendersBlockRef());
+  FiredTriggerPtr trigPtr;
+  if(c_firedTriggerHash.find(trigPtr, key)){
+    
+    c_firedTriggerHash.remove(trigPtr);
+
+    bool ok = trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
+    ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
+    ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
+    if(ok){
+      opPtr.i = key.fireingOperation;
+      ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
+      transPtr.i = opPtr.p->apiConnect;
+      transPtr.p = &localApiConnectRecord[transPtr.i];
+      
+      opPtr.p->noReceivedTriggers++;
+      opPtr.p->triggerExecutionCount++;
+    
+      // Insert fired trigger in execution queue
+      transPtr.p->theFiredTriggers.add(trigPtr);
+      if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
+	executeTriggers(signal, &transPtr);
+      }
+      return;
+    }
+    jam();
+    c_theFiredTriggerPool.release(trigPtr);
+  }
+  jam();
+  /**
+   * Failed to find record or invalid word counts
+   */
+  ndbrequire(false);
 }
 
 void Dbtc::execTRIG_ATTRINFO(Signal* signal)
@@ -11231,91 +11201,57 @@
   TrigAttrInfo * const trigAttrInfo =  (TrigAttrInfo *)signal->getDataPtr();
   Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
   const Uint32 *src = trigAttrInfo->getData();
-  TcFiredTriggerData* currentTrigger;
   FiredTriggerPtr firedTrigPtr;
-  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
-  TcConnectRecordPtr opPtr;
   
-  opPtr.i = trigAttrInfo->getConnectionPtr();
-  ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
-
-  if (opPtr.p->accumulatingTriggerData.p) {
+  TcFiredTriggerData key;
+  key.fireingOperation = trigAttrInfo->getConnectionPtr();
+  key.nodeId = refToNode(signal->getSendersBlockRef());
+  if(!c_firedTriggerHash.find(firedTrigPtr, key)){
     jam();
-    // We are already accumulating
-  } else {
-    jam();
-    // Allocate new trigger record
-    ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
-    ApiConnectRecordPtr transPtr;
-
-    transPtr.i = opPtr.p->apiConnect;
-    //transPtr.p = &localApiConnectRecord[transPtr.i];
-    ptrCheckGuard(transPtr, capiConnectFilesize, localApiConnectRecord);
-    if (!c_theFiredTriggerPool.seize(firedTrigPtr)) {
+    if(!c_firedTriggerHash.seize(firedTrigPtr)){
       jam();
-      // Resource shortage, abort transaction
-      // Mark transaction for abortion
-#ifdef VM_TRACE
-      ndbout_c("Dbtc::execTRIG_ATTRINFO: Failed to seize fired triggers\n");
-      ndbout_c("%u: Trigger error = %u\n", __LINE__, 4000);
-#endif
-      opPtr.p->triggerError = 4000;
-      return;    
-    }//if
-    ndbrequire(firedTrigPtr.p->keyValues.isEmpty() &&
-	       firedTrigPtr.p->beforeValues.isEmpty() &&
-	       firedTrigPtr.p->afterValues.isEmpty());
+      /**
+       * Will be handled when FIRE_TRIG_ORD arrives
+       */
+      ndbout_c("op: %d node: %d failed to seize",
+	       key.fireingOperation, key.nodeId);
+      return;
+    }
+    ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
+	       firedTrigPtr.p->beforeValues.getSize() == 0 &&
+	       firedTrigPtr.p->afterValues.getSize() == 0);
+    
+    firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
+    firedTrigPtr.p->fireingOperation = key.fireingOperation;
     firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
-    opPtr.p->accumulatingTriggerData = firedTrigPtr;
-    firedTrigPtr.p->fireingOperation = opPtr.i;
-  }//if
-  currentTrigger = opPtr.p->accumulatingTriggerData.p;
+    c_firedTriggerHash.add(firedTrigPtr);
+  }
+  
+  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
   switch (trigAttrInfo->getAttrInfoType()) {
   case(TrigAttrInfo::PRIMARY_KEY):
     jam();
-    if (currentTrigger->keyValues.append(src, attrInfoLength) == false) {
-      jam();
-      // Mark transaction for abortion
-#ifdef VM_TRACE
-      ndbout_c("Dbtc::execTRIG_ATTRINFO: Failed to seize keyValues\n");
-      ndbout_c("%u: Trigger error = %u\n", __LINE__, 4000);
-#endif
-      opPtr.p->triggerError = 4000;
-      // Return trigger to pool
-      c_theFiredTriggerPool.release(opPtr.p->accumulatingTriggerData.i);
-      return;    
+    {
+      LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
+      buf.append(src, attrInfoLength);
     }
     break;
   case(TrigAttrInfo::BEFORE_VALUES):
     jam();
-    if (currentTrigger->beforeValues.append(src, attrInfoLength) == false) {
-      jam();
-      // Mark transaction for abortion
-#ifdef VM_TRACE
-      ndbout_c("Dbtc::execTRIG_ATTRINFO: Failed to seize beforeValues\n");
-      ndbout_c("%u: Trigger error = %u\n", __LINE__, 4000);
-#endif
-      opPtr.p->triggerError = 4000;
-      // Return trigger to pool
-      c_theFiredTriggerPool.release(opPtr.p->accumulatingTriggerData.i);
-      return;    
+    {
+      LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
+      buf.append(src, attrInfoLength);
     }
     break;
   case(TrigAttrInfo::AFTER_VALUES):
     jam();
-    if (currentTrigger->afterValues.append(src, attrInfoLength) == false) {
-      jam();
-      // Mark transaction for abortion
-#ifdef VM_TRACE
-      ndbout_c("Dbtc::execTRIG_ATTRINFO: Failed to seize afterValues\n");
-      ndbout_c("%u: Trigger error = %u\n", __LINE__, 4000);
-#endif
-      opPtr.p->triggerError = 4000;
-      // Return trigger to pool
-      c_theFiredTriggerPool.release(opPtr.p->accumulatingTriggerData.i);
-      return;    
+    {
+      LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
+      buf.append(src, attrInfoLength);
     }
     break;
+  default:
+    ndbrequire(false);
   }
 }
 
@@ -12342,46 +12278,18 @@
                 LqhKeyConf::SignalLength);  
 }
 
-void Dbtc::restoreTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
+void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
 {
   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
   copyFromToLen(&trigOp->savedState[0],
                 (UintR*)lqhKeyConf,
 		LqhKeyConf::SignalLength);
-  lqhKeyConf->noFiredTriggers = 0;
-}
 
-void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
-{
-  restoreTriggeringOpState(signal, trigOp);
+  lqhKeyConf->noFiredTriggers = 0;
   trigOp->noReceivedTriggers = 0;
-  if (trigOp->triggerError != 0) {
-    // A trigger operation has failed
-    LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
-    LqhKeyRef * lqhKeyRef = (LqhKeyRef *)signal->getDataPtrSend();
-    // Copy fields to avoid overwrite
-    Uint32 opPtr = lqhKeyConf->opPtr;
-    Uint32 userRef = lqhKeyConf->userRef;
-    Uint32 transId1 = lqhKeyConf->transId1;
-    Uint32 transId2 = lqhKeyConf->transId2;
-
-    lqhKeyRef->connectPtr = opPtr;
-    lqhKeyRef->userRef = userRef;
-    if (trigOp->triggerError == 630) { // Tuple already existed
-      jam();
-      lqhKeyRef->errorCode = 893;    // Constraint violation
-    } else {
-      jam();
-      lqhKeyRef->errorCode = trigOp->triggerError;
-    }//if
-    lqhKeyRef->transId1 = transId1;
-    lqhKeyRef->transId2 = transId2;
-    handleFailedOperation(signal, lqhKeyRef, false);
-  } else {
-    jam();
-    // All triggers executed successfully, continue operation
-    execLQHKEYCONF(signal);
-  }//if
+
+  // All triggers executed successfully, continue operation
+  execLQHKEYCONF(signal);
 }
 
 void Dbtc::scheduleFiredTrigger(ApiConnectRecordPtr* transPtr,
@@ -12389,7 +12297,7 @@
 {
   // Set initial values for trigger fireing operation
   opPtr->p->triggerExecutionCount++;
-  opPtr->p->triggerError = 0;
+
   // Insert fired trigger in execution queue
   transPtr->p->theFiredTriggers.add(opPtr->p->accumulatingTriggerData);
   opPtr->p->accumulatingTriggerData.i = RNIL;
@@ -12414,9 +12322,7 @@
         // Execute all ready triggers in parallel
         opPtr.i = trigPtr.p->fireingOperation;
         ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
-	FiredTriggerPtr nextTrigPtr;
-	nextTrigPtr.i = trigPtr.i;
-	nextTrigPtr.p = trigPtr.p;
+	FiredTriggerPtr nextTrigPtr = trigPtr;
 	regApiPtr->theFiredTriggers.next(nextTrigPtr);
         if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
           jam();
@@ -12425,9 +12331,13 @@
           // Should allow for interleaving here by sending a CONTINUEB and 
 	  // return
           // Release trigger records
-          trigPtr.p->keyValues.release();
-          trigPtr.p->beforeValues.release();
-          trigPtr.p->afterValues.release();
+	  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
+	  LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
+	  tmp1.release();
+	  LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
+	  tmp2.release();
+	  LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
+	  tmp3.release();
           regApiPtr->theFiredTriggers.release(trigPtr.i);
         }
 	trigPtr = nextTrigPtr;
@@ -12515,9 +12425,15 @@
   while (trigPtr.i != RNIL) {
     jam();
     // Release trigger records
-    trigPtr.p->keyValues.release();
-    trigPtr.p->beforeValues.release();
-    trigPtr.p->afterValues.release();  
+
+    AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
+    LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
+    tmp1.release();
+    LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
+    tmp2.release();
+    LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
+    tmp3.release();
+    
     triggers->next(trigPtr);
   }
   triggers->release();
@@ -12551,30 +12467,30 @@
     opRecord->triggerExecutionCount++;
   }//if
   // Calculate key length and renumber attribute id:s
-  for(bool moreKeyAttrs = firedTriggerData->afterValues.first(iter);
-      moreKeyAttrs;
-      attrId++) {
+  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
+  LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
+  for(bool moreKeyAttrs = afterValues.first(iter); moreKeyAttrs; attrId++) {
     jam();
     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
 
     attrHeader->setAttributeId(attrId);      
     keyLength += attrHeader->getDataSize();
     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
-    moreKeyAttrs = firedTriggerData->afterValues.next(iter, hops);
+    moreKeyAttrs = afterValues.next(iter, hops);
   }
 
   // Filter out single NULL attributes
   if (attrId == 1) {
     jam();
-    firedTriggerData->afterValues.first(iter);
+    afterValues.first(iter);
     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-    if (attrHeader->isNULL() && !firedTriggerData->afterValues.next(iter)) {
+    if (attrHeader->isNULL() && !afterValues.next(iter)) {
       jam();
       opRecord->triggerExecutionCount--;
       if (opRecord->triggerExecutionCount == 0) {
         /*
-        We have completed current trigger execution
-	Continue triggering operation
+	  We have completed current trigger execution
+	  Continue triggering operation
         */
 	jam();
 	continueTriggeringOp(signal, opRecord);	
@@ -12584,20 +12500,19 @@
   }//if
 
   // Calculate total length of primary key to be stored in index table
-  for(bool moreAttrData = firedTriggerData->keyValues.first(iter);
-      (moreAttrData);
-      moreAttrData = firedTriggerData->keyValues.next(iter, hops)) {
+  LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
+  for(bool moreAttrData = keyValues.first(iter); moreAttrData; ) {
     jam();
     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
     
     totalPrimaryKeyLength += attrHeader->getDataSize();
     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
+    moreAttrData = keyValues.next(iter, hops);
   }
   AttributeHeader pkAttrHeader(attrId, totalPrimaryKeyLength);
-
+  
   TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
-  tcKeyReq->attrLen = 
-    firedTriggerData->afterValues.getSize() + 
+  tcKeyReq->attrLen = afterValues.getSize() + 
     pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
   tcKeyReq->tableId = indexData->indexId;
   TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
@@ -12611,15 +12526,14 @@
   Uint32 attrBufSize = 5; // Maximum for key in TCKEYREQ
   Uint32 dataPos = 0;
   // Filter out AttributeHeader:s since this should no be in key
-  bool moreKeyData = firedTriggerData->afterValues.first(iter);
+  bool moreKeyData = afterValues.first(iter);
   Uint32 headerSize = 0, keyAttrSize = 0, dataSize = 0, headAndData = 0;
 
-  while (moreKeyData && 
-         (dataPos < keyBufSize)) {
+  while (moreKeyData && (dataPos < keyBufSize)) {
     /*
-    If we have not read complete key
-    and it fits in the signal
-    */
+     * If we have not read complete key
+     * and it fits in the signal
+     */
     jam();
     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
     
@@ -12629,19 +12543,18 @@
     // Skip header
     if (headerSize == 1) {
       jam();
-      moreKeyData = firedTriggerData->afterValues.next(iter);
+      moreKeyData = afterValues.next(iter);
     } else {
       jam();
-      moreKeyData = firedTriggerData->afterValues.next(iter, headerSize - 1);
+      moreKeyData = afterValues.next(iter, headerSize - 1);
     }//if
-    while((keyAttrSize != 0) && 
-          (dataPos < keyBufSize)) {
+    while((keyAttrSize != 0) && (dataPos < keyBufSize)) {
       // If we have not read complete key
       jam();
       *dataPtr++ = *iter.data;
       dataPos++;
       keyAttrSize--;
-      moreKeyData = firedTriggerData->afterValues.next(iter);
+      moreKeyData = afterValues.next(iter);
     }
     if (keyAttrSize != 0) {
       jam();
@@ -12650,8 +12563,7 @@
   }
 
   tcKeyLength += dataPos;
-  Uint32 attributesLength = 
-    firedTriggerData->afterValues.getSize() + 
+  Uint32 attributesLength = afterValues.getSize() + 
     pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
   if (attributesLength <= attrBufSize) {
     jam();
@@ -12660,16 +12572,16 @@
     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, attributesLength);
     bool moreAttrData;
     // Insert primary key attributes (insert after values of primary table)
-    for(moreAttrData = firedTriggerData->afterValues.first(iter);
+    for(moreAttrData = afterValues.first(iter);
 	moreAttrData;
-	moreAttrData = firedTriggerData->afterValues.next(iter)) {      
+	moreAttrData = afterValues.next(iter)) {      
       *dataPtr++ = *iter.data;
     }
     // Insert attribute values (insert key values of primary table)
     // as one attribute
     pkAttrHeader.insertHeader(dataPtr);
     dataPtr += pkAttrHeader.getHeaderSize();
-    moreAttrData = firedTriggerData->keyValues.first(iter);
+    moreAttrData = keyValues.first(iter);
     while(moreAttrData) {
       jam();
       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
@@ -12679,15 +12591,15 @@
       // Skip header
       if (headerSize == 1) {
         jam();
-        moreAttrData = firedTriggerData->keyValues.next(iter);
+        moreAttrData = keyValues.next(iter);
       } else {
         jam();
-        moreAttrData = firedTriggerData->keyValues.next(iter, headerSize - 1);
+        moreAttrData = keyValues.next(iter, headerSize - 1);
       }//if
       // Copy attribute data
       while(dataSize-- != 0) {
 	*dataPtr++ = *iter.data;
-	moreAttrData = firedTriggerData->keyValues.next(iter);
+	moreAttrData = keyValues.next(iter);
       }
     }
     tcKeyLength += attributesLength;
@@ -12721,8 +12633,7 @@
     dataPtr = (Uint32 *) &keyInfo->keyData;
     dataPos = 0;
     // Pack any part of a key attribute that did no fit TCKEYREQ
-    while((keyAttrSize != 0) &&
-	  (dataPos < KeyInfo::DataLength)) {
+    while((keyAttrSize != 0) && (dataPos < KeyInfo::DataLength)) {
       // If we have not read complete key
       *dataPtr++ = *iter.data;
       dataPos++;
@@ -12741,7 +12652,7 @@
 	dataPtr = (Uint32 *) &keyInfo->keyData;
 	dataPos = 0;
       }
-      moreKeyData = firedTriggerData->afterValues.next(iter);
+      moreKeyData = afterValues.next(iter);
     }
     
     while(moreKeyData) {
@@ -12754,11 +12665,10 @@
       // Skip header
       if (headerSize == 1) {
         jam();
-        moreKeyData = firedTriggerData->afterValues.next(iter);
+        moreKeyData = afterValues.next(iter);
       } else {
         jam();
-        moreKeyData = firedTriggerData->afterValues.next(iter,
-                                                         headerSize - 1);
+        moreKeyData = afterValues.next(iter, headerSize - 1);
       }//if
       while (keyAttrSize-- != 0) {
         *dataPtr++ = *iter.data;
@@ -12777,7 +12687,7 @@
 	  dataPtr = (Uint32 *) &keyInfo->keyData;	  
           dataPos = 0;
         }       
-        moreKeyData = firedTriggerData->afterValues.next(iter);
+        moreKeyData = afterValues.next(iter);
       }
     }
     if (dataPos != 0) {
@@ -12810,9 +12720,9 @@
     
     bool moreAttrData;
     // Insert primary key attributes (insert after values of primary table)
-    for(moreAttrData = firedTriggerData->afterValues.first(iter);
+    for(moreAttrData = afterValues.first(iter);
 	moreAttrData;
-	moreAttrData = firedTriggerData->afterValues.next(iter)) {      
+	moreAttrData = afterValues.next(iter)) {      
       *dataPtr++ = *iter.data;
       attrInfoPos++;
       if (attrInfoPos == AttrInfo::DataLength) {
@@ -12835,7 +12745,7 @@
     pkAttrHeader.insertHeader(dataPtr);
     dataPtr += pkAttrHeader.getHeaderSize();
     attrInfoPos += pkAttrHeader.getHeaderSize();
-    moreAttrData = firedTriggerData->keyValues.first(iter);
+    moreAttrData = keyValues.first(iter);
     while(moreAttrData) {
       jam();
       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
@@ -12845,11 +12755,10 @@
       // Skip header
       if (headerSize == 1) {
         jam();
-        moreAttrData = firedTriggerData->keyValues.next(iter);
+        moreAttrData = keyValues.next(iter);
       } else {
         jam();
-        moreAttrData = firedTriggerData->keyValues.next(iter,
-                                                        headerSize - 1);
+        moreAttrData = keyValues.next(iter, headerSize - 1);
       }//if
       while(dataSize-- != 0) { // If we have not read complete key
         if (attrInfoPos == AttrInfo::DataLength) {
@@ -12868,7 +12777,7 @@
         }       
         *dataPtr++ = *iter.data;
         attrInfoPos++;
-        moreAttrData = firedTriggerData->keyValues.next(iter);
+        moreAttrData = keyValues.next(iter);
       }
     }
     if (attrInfoPos != 0) {
@@ -12913,7 +12822,9 @@
     opRecord->triggerExecutionCount++;
   }//if
   // Calculate key length and renumber attribute id:s
-  for(bool moreKeyAttrs = firedTriggerData->beforeValues.first(iter);
+  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
+  LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
+  for(bool moreKeyAttrs = beforeValues.first(iter);
       (moreKeyAttrs);
       attrId++) {
     jam();
@@ -12922,15 +12833,15 @@
     attrHeader->setAttributeId(attrId);      
     keyLength += attrHeader->getDataSize();
     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
-    moreKeyAttrs = firedTriggerData->beforeValues.next(iter, hops);
+    moreKeyAttrs = beforeValues.next(iter, hops);
   }
 
   // Filter out single NULL attributes
   if (attrId == 1) {
     jam();
-    firedTriggerData->beforeValues.first(iter);
+    beforeValues.first(iter);
     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
-    if (attrHeader->isNULL() && !firedTriggerData->beforeValues.next(iter)) {
+    if (attrHeader->isNULL() && !beforeValues.next(iter)) {
       jam();
       opRecord->triggerExecutionCount--;
       if (opRecord->triggerExecutionCount == 0) {
@@ -12958,7 +12869,7 @@
   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
   Uint32 dataPos = 0;
   // Filter out AttributeHeader:s since this should no be in key
-  bool moreKeyData = firedTriggerData->beforeValues.first(iter);
+  bool moreKeyData = beforeValues.first(iter);
   Uint32 headerSize = 0, keyAttrSize = 0, headAndData = 0;
 
   while (moreKeyData && 
@@ -12976,10 +12887,10 @@
     // Skip header
     if (headerSize == 1) {
       jam();
-      moreKeyData = firedTriggerData->beforeValues.next(iter);
+      moreKeyData = beforeValues.next(iter);
     } else {
       jam();
-      moreKeyData = firedTriggerData->beforeValues.next(iter, headerSize - 1);
+      moreKeyData = beforeValues.next(iter, headerSize - 1);
     }//if
     while((keyAttrSize != 0) && 
           (dataPos < keyBufSize)) {
@@ -12988,7 +12899,7 @@
       *dataPtr++ = *iter.data;
       dataPos++;
       keyAttrSize--;
-      moreKeyData = firedTriggerData->beforeValues.next(iter);
+      moreKeyData = beforeValues.next(iter);
     }
     if (keyAttrSize != 0) {
       jam();
@@ -13042,7 +12953,7 @@
 	dataPtr = (Uint32 *) &keyInfo->keyData;
 	dataPos = 0;
       }
-      moreKeyData = firedTriggerData->beforeValues.next(iter);
+      moreKeyData = beforeValues.next(iter);
     }
     
     while(moreKeyData) {
@@ -13055,10 +12966,10 @@
       // Skip header
       if (headerSize == 1) {
         jam();
-        moreKeyData = firedTriggerData->beforeValues.next(iter);
+        moreKeyData = beforeValues.next(iter);
       } else {
         jam();
-        moreKeyData = firedTriggerData->beforeValues.next(iter, 
+        moreKeyData = beforeValues.next(iter, 
 							  headerSize - 1);
       }//if
       while (keyAttrSize-- != 0) {
@@ -13078,7 +12989,7 @@
 	  dataPtr = (Uint32 *) &keyInfo->keyData;	  
           dataPos = 0;
         }       
-        moreKeyData = firedTriggerData->beforeValues.next(iter);
+        moreKeyData = beforeValues.next(iter);
       }
     }
     if (dataPos != 0) {

--- 1.1/ndb/src/kernel/blocks/dbutil/DbUtil.cpp	Wed Apr 14 10:24:20 2004
+++ 1.2/ndb/src/kernel/blocks/dbutil/DbUtil.cpp	Tue May  4 11:18:52 2004
@@ -1870,6 +1870,7 @@
   }
 
   releaseSections(signal);
+  transPtr.p->noOfRetries = 3;
   runTransaction(signal, transPtr);
 }
 
@@ -2287,6 +2288,21 @@
   ndbout << "Transaction error (code: " << errCode << ")" << endl;
 #endif
  
+  if(transPtr.p->noOfRetries > 0){
+    transPtr.p->noOfRetries--;
+    switch(errCode){
+    case 266:
+    case 410:
+    case 1204:
+#if 0
+      ndbout_c("errCode: %d noOfRetries: %d -> retry", 
+	       errCode, transPtr.p->noOfRetries);
+#endif
+      runTransaction(signal, transPtr);
+      return;
+    }
+  }
+
   transPtr.p->errorCode = errCode;
   finishTransaction(signal, transPtr);
 }

--- 1.1/ndb/src/kernel/blocks/dbutil/DbUtil.hpp	Wed Apr 14 10:24:20 2004
+++ 1.2/ndb/src/kernel/blocks/dbutil/DbUtil.hpp	Tue May  4 11:18:52 2004
@@ -341,6 +341,7 @@
     SLList<Operation> operations;
 
     Uint32 errorCode;
+    Uint32 noOfRetries;
     Uint32 sent;        // No of operations sent
     Uint32 recv;        // No of completed operations received
     inline bool complete() const { return sent == recv; };
@@ -401,7 +402,7 @@
 		   KeyInfoIterator & kit);
   void sendAttrInfo(Signal*, 
 		    AttrInfo* attrInfo, 
-		    const AttrInfoBuffer & attrInfo,
+		    const AttrInfoBuffer &,
 		    AttrInfoIterator & ait);
   int getResultSet(Signal* signal, const Transaction * transP,
 		   struct LinearSectionPtr sectionsPtr[]);

--- 1.1/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp	Wed Apr 14 10:24:20 2004
+++ 1.2/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp	Tue May  4 11:18:52 2004
@@ -2933,6 +2933,11 @@
       return;
     }
   }
+  
+  signal->theData[0] = EventReport::NDBStopStarted;
+  signal->theData[1] = StopReq::getSystemStop(c_stopRec.stopReq.requestInfo) ? 1 : 0;
+  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
+  
   NodeState newState(NodeState::SL_STOPPING_1, 
 		     StopReq::getSystemStop(c_stopRec.stopReq.requestInfo));
   
@@ -3022,6 +3027,10 @@
   NodeState newState(NodeState::SL_STARTED); 
 
   cntr.updateNodeState(signal, newState);
+
+  signal->theData[0] = EventReport::NDBStopAborted;
+  cntr.sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 1, JBB);
+  
   return false;
 }
 

--- 1.1/ndb/src/kernel/blocks/ndbfs/Filename.cpp	Wed Apr 14 10:24:21 2004
+++ 1.2/ndb/src/kernel/blocks/ndbfs/Filename.cpp	Tue May  4 11:18:52 2004
@@ -184,7 +184,7 @@
   strcat(theName, fileExtension[type]);
   
   if(dir == true){
-    for(Uint32 l = strlen(theName) - 1; l >= 0; l--){
+    for(int l = strlen(theName) - 1; l >= 0; l--){
       if(theName[l] == DIR_SEPARATOR[0]){
 	theName[l] = 0;
 	break;

--- 1.1/ndb/src/kernel/blocks/suma/Suma.cpp	Wed Apr 14 10:24:21 2004
+++ 1.2/ndb/src/kernel/blocks/suma/Suma.cpp	Tue May  4 11:18:52 2004
@@ -1906,7 +1906,8 @@
   
   const Uint32 completed = conf->fragmentCompleted;
   const Uint32 senderData = conf->senderData;
-  
+  const Uint32 completedOps = conf->completedOps;
+
   SubscriptionPtr subPtr;
   c_subscriptions.getPtr(subPtr, senderData);
   
@@ -1922,12 +1923,14 @@
 #else
     SubSyncContinueReq * const req = (SubSyncContinueReq*)signal->getDataPtrSend();
     req->subscriberData = subPtr.p->m_subscriberData;
-    req->noOfRowsSent = 0; //rowCount;
+    req->noOfRowsSent = completedOps;
     sendSignal(subPtr.p->m_subscriberRef, GSN_SUB_SYNC_CONTINUE_REQ, signal,
 	       SubSyncContinueReq::SignalLength, JBB);
 #endif
     return;
   }
+
+  ndbrequire(completedOps == 0);
   
   SyncRecord* tmp = c_syncPool.getPtr(subPtr.p->m_syncPtrI);
   

--- 1.1/ndb/src/kernel/error/Error.hpp	Wed Apr 14 10:24:21 2004
+++ 1.2/ndb/src/kernel/error/Error.hpp	Tue May  4 11:18:52 2004
@@ -34,7 +34,7 @@
  *
  */
 
-typedef enum ErrorCategory
+enum ErrorCategory
 {
    warning,
    ecError,

--- 1.1/ndb/src/kernel/ndb-main/Main.cpp	Wed Apr 14 10:24:22 2004
+++ 1.2/ndb/src/kernel/ndb-main/Main.cpp	Tue May  4 11:18:52 2004
@@ -28,6 +28,7 @@
 #include <WatchDog.hpp>
 
 #include <LogLevel.hpp>
+#include <EventLogger.hpp>
 #include <NodeState.hpp>
 
 #if defined NDB_SOLARIS
@@ -37,16 +38,17 @@
 
 #if !defined NDB_SOFTOSE && !defined NDB_OSE
 #include <signal.h>        // For process signals
+#endif
 
-extern "C" {
-  void ndbSignal(int signo, void (*func) (int));
-  void handler(int signo);                  // for process signal handling
-};
-
-void catchsigs();                         // for process signal handling
-
+extern EventLogger g_eventLogger;
+#if defined (NDB_LINUX) || defined (NDB_SOLARIS)
+#include <sys/types.h>
+#include <sys/wait.h>
 #endif
 
+void catchsigs(bool ignore); // for process signal handling
+extern "C" void handler(int signo);  // for process signal handling
+
 // Shows system information
 void systemInfo(const Configuration & conf,
 		const LogLevel & ll); 
@@ -55,11 +57,16 @@
 
 extern int global_ndb_check;
 NDB_MAIN(ndb_kernel){
-
+  
   global_ndb_check = 1;
 
+  // Print to stdout/console
+  g_eventLogger.createConsoleHandler();
+  g_eventLogger.setCategory("NDB");
+  g_eventLogger.enable(Logger::LL_INFO, Logger::LL_ALERT); // Log INFO to ALERT
+
   globalEmulatorData.create();
-  
+
   // Parse command line options
   Configuration* theConfig = globalEmulatorData.theConfiguration;
   if(!theConfig->init(argc, argv)){
@@ -75,6 +82,9 @@
   NdbConfig_HomePath(homePath, 255);
 
 #if defined (NDB_LINUX) || defined (NDB_SOLARIS)
+  /**
+   * This has only been tested with linux & solaris
+   */
   if (theConfig->getDaemonMode()) {
     // Become a daemon
     char lockfile[255], logfile[255];
@@ -85,12 +95,54 @@
       return 1;
     }
   }
-#endif
+  
+  for(pid_t child = fork(); child != 0; child = fork()){
+    /**
+     * Parent
+     */
+    catchsigs(true);
+    int status = 0;
+    while(waitpid(child, &status, 0) != child);
+    if(WIFEXITED(status) || !theConfig->stopOnError()){
+      switch(WEXITSTATUS(status)){
+      case NRT_Default:
+	g_eventLogger.info("Angel shutting down");
+	exit(0);
+	break;
+      case NRT_NoStart_Restart:
+	theConfig->setInitialStart(false);
+	globalData.theRestartFlag = initial_state;
+	break;
+      case NRT_NoStart_InitialStart:
+	theConfig->setInitialStart(true);
+	globalData.theRestartFlag = initial_state;
+	break;
+      case NRT_DoStart_InitialStart:
+	theConfig->setInitialStart(true);
+	globalData.theRestartFlag = perform_start;
+	break;
+      default:
+      case NRT_DoStart_Restart:
+	theConfig->setInitialStart(false);
+	globalData.theRestartFlag = perform_start;
+	break;
+      }
+      g_eventLogger.info("Ndb has terminated (pid %d) restarting", child);
+    } else {
+      /**
+       * Error shutdown && stopOnError()
+       */
+      exit(0);
+    }
+  }
 
+  g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
+#endif
+  
   systemInfo(* theConfig,
 	     theConfig->clusterConfigurationData().SizeAltData.logLevel);
-  
-  // Load blocks
+
+    // Load blocks
   globalEmulatorData.theSimBlockList->load(* theConfig);
     
   // Set thread concurrency for Solaris' light weight processes
@@ -106,9 +158,7 @@
   globalSignalLoggers.setOutputStream(signalLog);
 #endif
   
-#if !defined NDB_SOFTOSE && !defined NDB_OSE
-  catchsigs();
-#endif
+  catchsigs(false);
    
   /**
    * Do startup
@@ -132,7 +182,7 @@
   globalEmulatorData.theThreadConfig->ipControlLoop();
   
   NdbShutdown(NST_Normal);
-  return 0;
+  return NRT_Default;
 }
 
 
@@ -169,131 +219,39 @@
 #endif
   
   if(logLevel.getLogLevel(LogLevel::llStartUp) > 0){
-    ndbout << "-- NDB Cluster -- DB node " << globalData.ownId
-	   << " -- " << NDB_VERSION_STRING << " -- " << endl;
+    g_eventLogger.info("NDB Cluster -- DB node %d", globalData.ownId);
+    g_eventLogger.info("%s --", NDB_VERSION_STRING);
 #ifdef NDB_SOLARIS
-    ndbout << "NDB is running "  
-	   << " on a machine with " << processors
-	   << " processor(s) at "   <<  speed <<" MHz" 
-	   << endl;
+    g_eventLogger.info("NDB is running on a machine with %d processor(s) at %d MHz",
+		       processor, speed);
 #endif
   }
   if(logLevel.getLogLevel(LogLevel::llStartUp) > 3){
     Uint32 t = config.timeBetweenWatchDogCheck();
-    ndbout << "WatchDog timer is set to " << t << " ms" << endl;
+    g_eventLogger.info("WatchDog timer is set to %d ms", t);
   }
 
 }
 
-#if !defined NDB_SOFTOSE && !defined NDB_OSE
-
-#ifdef NDB_WIN32
-
-void 
-catchsigs()
-{
-  ndbSignal(SIGINT,  handler);    // 2
-  ndbSignal(SIGILL,  handler);    // 4
-  ndbSignal(SIGFPE, handler);     // 8
-#ifndef VM_TRACE
-  ndbSignal(SIGSEGV, handler);    // 11
-#endif
-  ndbSignal(SIGTERM, handler);    // 15
-  ndbSignal(SIGBREAK, handler);   // 21
-  ndbSignal(SIGABRT, handler);    // 22
-}
-
-#else
-
 void 
-catchsigs(){
+catchsigs(bool ignore){
+#if ! defined NDB_SOFTOSE && !defined NDB_OSE 
   // Makes the main process catch process signals, eg installs a 
   // handler named "handler". "handler" will then be called is instead 
   // of the defualt process signal handler)
-  ndbSignal(SIGHUP,  handler);    // 1
-  ndbSignal(SIGINT,  handler);    // 2
-  ndbSignal(SIGQUIT, handler);    // 3
-  ndbSignal(SIGILL,  handler);    // 4
-  ndbSignal(SIGTRAP, handler);    // 5
-#ifdef NDB_LINUX
-  ndbSignal(7, handler);
-#elif NDB_SOLARIS
-  ndbSignal(SIGEMT, handler);     // 7
-#elif NDB_MACOSX
-  ndbSignal(SIGEMT, handler);     // 7
-#endif
-  ndbSignal(SIGFPE, handler);     // 8
-  // SIGKILL cannot be caught,    9
-  ndbSignal(SIGBUS, handler);     // 10
-  ndbSignal(SIGSEGV, handler);    // 11
-  ndbSignal(SIGSYS, handler);     // 12 
-  ndbSignal(SIGPIPE, handler);    // 13
-  ndbSignal(SIGALRM, handler);    // 14
-  ndbSignal(SIGTERM, handler);    // 15
-  ndbSignal(SIGUSR1, handler);    // 16
-  ndbSignal(SIGUSR2, handler);    // 17
-#ifndef NDB_MACOSX
-  ndbSignal(SIGPWR, handler);     // 19
-  ndbSignal(SIGPOLL, handler);    // 22
-#endif
-  // SIGSTOP cannot be caught     23
-  ndbSignal(SIGTSTP, handler);    // 24
-  ndbSignal(SIGTTIN, handler);    // 26
-  ndbSignal(SIGTTOU, handler);    // 27
-  ndbSignal(SIGVTALRM, handler);  // 28
-  ndbSignal(SIGPROF, handler);    // 29
-  ndbSignal(SIGXCPU, handler);    // 30
-  ndbSignal(SIGXFSZ, handler);    // 31
-}
-#endif
-
-extern "C"
-void ndbSignal(int signo, void (*func) (int)) {
-#ifdef NDB_WIN32
-  signal(signo, func);
-#else
-  struct sigaction act, oact;
-  act.sa_handler = func;
-  sigemptyset(&act.sa_mask);
-  act.sa_flags = 0;
-  if(signo == SIGALRM) {
-#ifdef SA_INTERRUPT
-    act.sa_flags |= SA_INTERRUPT;
-#endif
+  if(ignore){
+    for(int i = 1; i<100; i++){
+      if(i != SIGCHLD)
+	signal(i, SIG_IGN);
+    } 
   } else {
-#ifdef SA_RESTART
-    act.sa_flags |= SA_RESTART;
-#endif
+    for(int i = 1; i<100; i++){
+      signal(i, handler);
+    }
   }
-  sigaction(signo, &act, &oact);
 #endif
 }
 
-
-#ifdef NDB_WIN32
-
-extern "C"
-void 
-handler(int sig)
-{
-  switch(sig){
-  case SIGINT:   /*  2 - Interrupt  */
-  case SIGTERM:  /* 15 - Terminate  */
-  case SIGBREAK:  /* 21 - Ctrl-Break sequence */
-  case SIGABRT:   /* 22 - abnormal termination triggered by abort call */
-    globalData.theRestartFlag = perform_stop;
-    break;
-  default:
-    // restart the system
-    char errorData[40];
-    snprintf(errorData, 40, "Signal %d received", sig);
-    ERROR_SET(fatal, 0, errorData, __FILE__);
-    break;
-  }
-}
-
-#else
-
 extern "C"
 void 
 handler(int sig){
@@ -327,9 +285,6 @@
     break;
   }
 }
-
-#endif
-#endif
 
 	
 

--- 1.1/ndb/src/kernel/vm/Configuration.cpp	Wed Apr 14 10:24:22 2004
+++ 1.2/ndb/src/kernel/vm/Configuration.cpp	Tue May  4 11:18:52 2004
@@ -32,6 +32,9 @@
   void ndbSetOwnVersion();
 }
 
+#include <EventLogger.hpp>
+extern EventLogger g_eventLogger;
+
 bool
 Configuration::init(int argc, const char** argv){
 
@@ -259,10 +262,6 @@
 
   delete p;
 
-  if (_lockPagesInMainMemory) {
-    NdbMem_MemLockAll();
-  }
-  
   /**
    * Create the watch dog thread
    */
@@ -335,4 +334,9 @@
   if(_connectString != 0)
     return strdup(_connectString);
   return 0;
+}
+
+void
+Configuration::setInitialStart(bool val){
+  _initialStart = val;
 }

--- 1.1/ndb/src/kernel/vm/Configuration.hpp	Wed Apr 14 10:24:22 2004
+++ 1.2/ndb/src/kernel/vm/Configuration.hpp	Tue May  4 11:18:52 2004
@@ -62,6 +62,7 @@
    * 
    */
   bool getInitialStart() const;
+  void setInitialStart(bool val);
   bool getDaemonMode() const;
   
 private:

--- 1.1/ndb/src/kernel/vm/DLFifoList.hpp	Wed Apr 14 10:24:22 2004
+++ 1.2/ndb/src/kernel/vm/DLFifoList.hpp	Tue May  4 11:18:52 2004
@@ -60,6 +60,11 @@
   void add(Ptr<T> &);
 
   /**
+   * Remove from list 
+   */
+  void remove(Ptr<T> &);
+
+  /**
    * Return an object to pool
    */
   void release(Uint32 i);
@@ -241,14 +246,11 @@
   p.p = thePool.getPtr(i);
   release(p);
 }
-  
-/**
- * Return an object to pool
- */
+
 template <class T>
 inline
 void 
-DLFifoList<T>::release(Ptr<T> & p){
+DLFifoList<T>::remove(Ptr<T> & p){
   T * t = p.p;
   Uint32 ni = t->nextList;
   Uint32 pi = t->prevList;
@@ -268,6 +270,16 @@
     // We are releasing first
     head.firstItem = ni;
   }
+}
+  
+/**
+ * Return an object to pool
+ */
+template <class T>
+inline
+void 
+DLFifoList<T>::release(Ptr<T> & p){
+  remove(p);
   thePool.release(p.i);
 }  
 

--- 1.1/ndb/src/kernel/vm/Emulator.cpp	Wed Apr 14 10:24:22 2004
+++ 1.2/ndb/src/kernel/vm/Emulator.cpp	Tue May  4 11:18:52 2004
@@ -34,11 +34,14 @@
 #include <stdlib.h>
 #include <new>
 
-#ifdef NDB_WIN32
-#include <new.h>
-#include <process.h>
-#define execvp _execvp
-#define set_new_handler _set_new_handler
+extern "C" {
+  extern void (* ndb_new_handler)();
+}
+
+
+#if defined (NDB_LINUX) || defined (NDB_SOLARIS)
+#include <sys/types.h>
+#include <sys/wait.h>
 #endif
 
 /**
@@ -73,7 +76,7 @@
 }
 
 void
-ndb_new_handler(){
+ndb_new_handler_impl(){
   ERROR_SET(fatal, ERR_MEMALLOC, "New handler", "");
 }
 
@@ -88,11 +91,7 @@
 
   theShutdownMutex = NdbMutex_Create();
 
-#ifdef NDB_WIN32
-  set_new_handler((_PNH)ndb_new_handler);
-#else
-  std::set_new_handler(ndb_new_handler);
-#endif
+  ndb_new_handler = ndb_new_handler_impl;
 }
 
 void
@@ -110,60 +109,6 @@
 }
 
 void
-NdbRestart(char * programName,
-	   NdbRestartType type, char * connString){
-#if ! ( defined NDB_OSE || defined NDB_SOFTOSE) 
-  int argc = 2;
-  switch(type){
-  case NRT_NoStart_Restart:
-  case NRT_DoStart_InitialStart:
-    argc = 3;
-    break;
-  case NRT_NoStart_InitialStart:
-    argc = 4;
-    break;
-  case NRT_DoStart_Restart:
-  case NRT_Default:
-  default:
-    argc = 2;
-    break;
-  }
-
-  if(connString != 0){
-    argc += 2;
-  }
-  
-  char ** argv = new char * [argc];
-  argv[0] = programName;
-  argv[argc - 1] = 0;
-
-  switch(type){
-  case NRT_NoStart_Restart:
-    argv[1] = "-n";
-    break;
-  case NRT_DoStart_InitialStart:
-    argv[1] = "-i";
-    break;
-  case NRT_NoStart_InitialStart:
-    argv[1] = "-n";
-    argv[2] = "-i";
-    break;
-  case NRT_DoStart_Restart:
-  case NRT_Default:
-  default:
-    break;
-  }
-
-  if(connString != 0){
-    argv[argc-3] = "-c";
-    argv[argc-2] = connString;
-  }
-  
-  execvp(programName, argv);
-#endif
-}
-
-void
 NdbShutdown(NdbShutdownType type,
 	    NdbRestartType restartType){
   
@@ -181,27 +126,12 @@
     globalData.theRestartFlag = perform_stop;
 
     bool restart = false;
-    char * progName = 0;
-    char * connString = 0;
 #if ! ( defined NDB_OSE || defined NDB_SOFTOSE) 
     if((type != NST_Normal && 
 	globalEmulatorData.theConfiguration->stopOnError() == false) ||
        type == NST_Restart) {
       
       restart  = true;
-      progName = strdup(globalEmulatorData.theConfiguration->programName());
-      connString = globalEmulatorData.theConfiguration->getConnectStringCopy();
-      if(type != NST_Restart){
-	/**
-	 * If we crash before we started
-	 *
-	 * Do restart -n
-	 */
-	if(globalData.theStartLevel == NodeState::SL_STARTED)
-	  restartType = NRT_Default;
-	else
-	  restartType = NRT_NoStart_Restart;
-      }
     }
 #endif
     
@@ -238,21 +168,18 @@
 #endif
     
     if(type == NST_Watchdog){
-      if(restart){
-	NdbRestart(progName, restartType, connString);
-      }
-      
       /**
-       * Very serious
+       * Very serious, don't attempt to free, just die!!
        */
       ndbout << "Watchdog shutdown completed - " << exitAbort << endl;
 #if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
+      signal(6, SIG_DFL);
       abort();
 #else
-      exit(1);
+      exit(-1);
 #endif
     }
-
+    
     globalEmulatorData.theWatchDog->doStop();
     
 #ifdef VM_TRACE
@@ -265,7 +192,7 @@
     globalTransporterRegistry.stopReceiving();
     
     globalTransporterRegistry.removeAll();
-
+    
 #ifdef VM_TRACE
 #define UNLOAD (type != NST_ErrorHandler && type != NST_Watchdog)
 #else
@@ -274,61 +201,44 @@
     if(UNLOAD){
       globalEmulatorData.theSimBlockList->unload();    
       globalEmulatorData.destroy();
-
     }
-
-    if(type != NST_Normal &&
-       type != NST_Restart){
-      if(restart){
-	NdbRestart(progName, restartType, connString);
-      }
-      
+    
+    if(type != NST_Normal && type != NST_Restart){
       ndbout << "Error handler shutdown completed - " << exitAbort << endl;
 #if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
+      signal(6, SIG_DFL);
       abort();
 #else
-      exit(1);
+      exit(-1);
 #endif
     }
     
     /**
-     * This is a normal restart
+     * This is a normal restart, depend on angel
      */
     if(type == NST_Restart){
-      if(restart){
-	NdbRestart(progName, restartType, connString);
-      }
-      /**
-       * What to do if in restart mode, but being unable to do it...
-       */
-#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
-      abort();
-#else
-      exit(1);
-#endif
+      exit(restartType);
     }
-
-    /**
-     * This is normal shutdown
-     */
+    
     ndbout << "Shutdown completed - exiting" << endl;
   } else {
     /**
      * Shutdown is already in progress
      */
-
+    
     /** 
      * If this is the watchdog, kill system the hard way
      */
     if (type== NST_Watchdog){
       ndbout << "Watchdog is killing system the hard way" << endl;
 #if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
+      signal(6, SIG_DFL);
       abort();
 #else
-      exit(1);
+      exit(-1);
 #endif
     }
-      
+    
     while(true)
       NdbSleep_MilliSleep(10);
   }

--- 1.1/ndb/src/kernel/vm/SignalCounter.hpp	Wed Apr 14 10:24:23 2004
+++ 1.2/ndb/src/kernel/vm/SignalCounter.hpp	Tue May  4 11:18:52 2004
@@ -148,7 +148,7 @@
 const char *
 SignalCounter::getText() const {
   static char buf[255];
-  static char nodes[m_nodes.TextLength+1];
+  static char nodes[NodeBitmask::TextLength+1];
   snprintf(buf, sizeof(buf), "[SignalCounter: m_count=%d %s]", m_count, m_nodes.getText(nodes));
   return buf;
 }

--- 1.1/ndb/src/kernel/vm/SimulatedBlock.cpp	Wed Apr 14 10:24:23 2004
+++ 1.2/ndb/src/kernel/vm/SimulatedBlock.cpp	Tue May  4 11:18:52 2004
@@ -948,7 +948,6 @@
   m_sectionPtrI[0] = RNIL; 
   m_sectionPtrI[1] = RNIL;
   m_sectionPtrI[2] = RNIL;
-  m_sectionPtrI[3] = RNIL;
 }
 
 SimulatedBlock::FragmentSendInfo::FragmentSendInfo()

--- 1.1/ndb/src/mgmsrv/MgmtSrvr.cpp	Wed Apr 14 10:24:24 2004
+++ 1.2/ndb/src/mgmsrv/MgmtSrvr.cpp	Tue May  4 11:18:52 2004
@@ -450,6 +450,8 @@
 	nodeTypes[nodeId] = NDB_MGM_NODE_TYPE_API;
       if(type == "DB")
 	nodeTypes[nodeId] = NDB_MGM_NODE_TYPE_NDB;
+      if(type == "REP")
+	nodeTypes[nodeId] = NDB_MGM_NODE_TYPE_API;
     }
   }
   

--- 1.1/ndb/src/mgmsrv/NodeLogLevel.cpp	Wed Apr 14 10:24:24 2004
+++ 1.2/ndb/src/mgmsrv/NodeLogLevel.cpp	Tue May  4 11:18:52 2004
@@ -40,6 +40,7 @@
   {
     return m_logLevel.theCategories[i];
   }
+  return 0;
 }
 
 int 
@@ -49,6 +50,7 @@
   {
     return m_logLevel.theLevels[i];
   }
+  return 0;
 }
 
 void

--- 1.1/ndb/src/ndbapi/ClusterMgr.cpp	Wed Apr 14 10:24:24 2004
+++ 1.2/ndb/src/ndbapi/ClusterMgr.cpp	Tue May  4 11:18:52 2004
@@ -409,9 +409,10 @@
   const bool report = (theNode.m_state.startLevel != NodeState::SL_NOTHING);  
   theNode.m_state.startLevel = NodeState::SL_NOTHING;
   
-  if(report)
+  if(report){
     theFacade.ReportNodeDead(nodeId);
-  
+  }  
+
   theNode.nfCompleteRep = false;
 
   if(noOfConnectedNodes == 0){

--- 1.1/ndb/src/ndbapi/Ndberror.cpp	Wed Apr 14 10:24:25 2004
+++ 1.2/ndb/src/ndbapi/Ndberror.cpp	Tue May  4 11:18:52 2004
@@ -266,7 +266,6 @@
   { 707,  SE, "No more table metadata records" },  
   { 708,  SE, "No more attribute metadata records" },
   { 709,  SE, "No such table existed" },
-  { 720,  SE, "Attribute name reused in table definition" },
   { 721,  SE, "Table or index with given name already exists" },
   { 723,  SE, "No such table existed" },
   { 736,  SE, "Wrong attribute size" },
@@ -293,6 +292,7 @@
   /**
    * Still uncategorized
    */
+  { 720,  AE, "Attribute name reused in table definition" },
   { 4004, AE, "Attribute name not found in the Table" },
   
   { 4100, AE, "Status Error in NDB" },

--- 1.1/ndb/src/rep/rep_version.hpp	Wed Apr 14 10:24:32 2004
+++ 1.2/ndb/src/rep/rep_version.hpp	Tue May  4 11:18:52 2004
@@ -25,6 +25,8 @@
 
 #define DBUG
 
+#include <ndb_version.h>
+
 extern "C"
 void 
 DBUG_PRINT(const char * fmt, ...);
@@ -52,7 +54,7 @@
 /**
  * Used for config id
  */
-#define REP_VERSION_ID 0
+#define REP_VERSION_ID NDB_VERSION
 
 #define MAX_NODE_GROUPS 6
 

--- 1.1/ndb/test/ndbapi/testDict/testDict.cpp	Wed Apr 14 10:24:37 2004
+++ 1.2/ndb/test/ndbapi/testDict/testDict.cpp	Tue May  4 11:18:53 2004
@@ -564,7 +564,7 @@
     goto drop_the_tab;
   }
   
-  if (pTab->equal(*pTab3) == false){
+  if (newTab.equal(*pTab3) == false){
     ndbout << "It was not equal" << endl;
     result = NDBT_FAILED;
     goto drop_the_tab;

--- 1.1/ndb/test/ndbapi/testIndex/testIndex.cpp	Wed Apr 14 10:24:37 2004
+++ 1.2/ndb/test/ndbapi/testIndex/testIndex.cpp	Tue May  4 11:18:53 2004
@@ -256,17 +256,18 @@
   AttribList attrList;
   attrList.buildAttribList(pTab);
 
-  int retries = 10;
+  int retries = 100;
   while(retries > 0){
     const Uint32 i = rand() % attrList.attriblist.size();
     int res = create_index(ctx, i, pTab, pNdb, attrList.attriblist[i], 
 			   logged);
-    if (res == SKIP_INDEX)
+    if (res == SKIP_INDEX){
+      retries--;
       continue;
+    }
 
     if (res == NDBT_FAILED){
-      retries--;
-      continue;
+      return NDBT_FAILED;
     }
     
     ctx->setProperty("createRandomIndex", i);
@@ -1452,22 +1453,22 @@
 	 "Test that index build when running transactions work"){ 
   TC_PROPERTY("OrderedIndex", (unsigned)0);
   TC_PROPERTY("LoggedIndexes", (unsigned)0);
-  TC_PROPERTY("Threads", 2); // # runTransactions4
+  TC_PROPERTY("Threads", 1); // # runTransactions4
   INITIALIZER(runClearTable);
   STEP(runBuildDuring);
   STEP(runTransactions4);
-  STEP(runTransactions4);
+  //STEP(runTransactions4);
   FINALIZER(runClearTable);
 }
 TESTCASE("BuildDuring_O", 
 	 "Test that index build when running transactions work"){ 
   TC_PROPERTY("OrderedIndex", (unsigned)1);
   TC_PROPERTY("LoggedIndexes", (unsigned)0);
-  TC_PROPERTY("Threads", 2); // # runTransactions4
+  TC_PROPERTY("Threads", 1); // # runTransactions4
   INITIALIZER(runClearTable);
   STEP(runBuildDuring);
   STEP(runTransactions4);
-  STEP(runTransactions4);
+  //STEP(runTransactions4);
   FINALIZER(runClearTable);
 }
 TESTCASE("UniqueNull", 

--- 1.1/ndb/test/ndbapi/testMgm/testMgm.cpp	Wed Apr 14 10:24:37 2004
+++ 1.2/ndb/test/ndbapi/testMgm/testMgm.cpp	Tue May  4 11:18:53 2004
@@ -69,7 +69,6 @@
   } else {
     ndbout << "OK!" << endl;
   }
-  delete tab;
   return result;
 }
 

--- 1.1/ndb/test/ndbapi/testScan/testScan.cpp	Wed Apr 14 10:24:37 2004
+++ 1.2/ndb/test/ndbapi/testScan/testScan.cpp	Tue May  4 11:18:53 2004
@@ -23,9 +23,18 @@
 #include "ScanFunctions.hpp"
 #include <random.h>
 
+const NdbDictionary::Table *
+getTable(Ndb* pNdb, int i){
+  const NdbDictionary::Table* t = NDBT_Tables::getTable(i);
+  if (t == NULL){
+    return 0;
+  }
+  return pNdb->getDictionary()->getTable(t->getName());
+}
 
-int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
 
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
+  
   int records = ctx->getNumRecords();
   HugoTransactions hugoTrans(*ctx->getTab());
   if (hugoTrans.loadTable(GETNDB(step), records) != 0){
@@ -37,7 +46,8 @@
 
 int runCreateAllTables(NDBT_Context* ctx, NDBT_Step* step){
 
-  return NDBT_Tables::createAllTables(GETNDB(step), false, true);
+  int a = NDBT_Tables::createAllTables(GETNDB(step), false, true); 
+  return a;
 }
 
 int runDropAllTablesExceptTestTable(NDBT_Context* ctx, NDBT_Step* step){
@@ -64,12 +74,12 @@
 
 
 int runLoadAllTables(NDBT_Context* ctx, NDBT_Step* step){
-
+  
   int records = ctx->getNumRecords();
   for (int i=0; i < NDBT_Tables::getNumTables(); i++){
 
-    const NdbDictionary::Table* tab = NDBT_Tables::getTable(i);
-    if (tab == NULL){
+    const NdbDictionary::Table* tab = getTable(GETNDB(step), i);
+    if (tab == NULL){ 
       return NDBT_FAILED;
     }
     HugoTransactions hugoTrans(*tab);
@@ -85,20 +95,20 @@
   int records = ctx->getNumRecords();
   int parallelism = ctx->getProperty("Parallelism", 240);
   int abort = ctx->getProperty("AbortProb");
-
+  
   int i = 0;
   while (i<loops) {
     
     int tabNum = myRandom48(NDBT_Tables::getNumTables());
-    const NdbDictionary::Table* tab = NDBT_Tables::getTable(tabNum);
+    const NdbDictionary::Table* tab = getTable(GETNDB(step), tabNum);
     if (tab == NULL){
       g_info << "tab == NULL" << endl;
       return NDBT_FAILED;
     }
-
+    
     g_info << "Scan reading from table " << tab->getName() << endl;
     HugoTransactions hugoTrans(*tab);
-
+    
     g_info << i << ": ";
     if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism) != 0){
       return NDBT_FAILED;
@@ -212,7 +222,7 @@
 
   int i = 0;
   HugoTransactions hugoTrans(*ctx->getTab());
-  while (i<loops) {
+  while (i<loops && !ctx->isTestStopped()) {
     g_info << i << ": ";
     if (hugoTrans.scanReadRecords(GETNDB(step), records, abort, parallelism) != 0){
       return NDBT_FAILED;
@@ -230,10 +240,10 @@
 
   int i = 0;
   HugoTransactions hugoTrans(*ctx->getTab());
-  while (i<loops) {
+  while (i<loops && !ctx->isTestStopped()) {
     g_info << i << ": ";
     if (hugoTrans.scanReadCommittedRecords(GETNDB(step), records, 
-					  abort, parallelism) != 0){
+					   abort, parallelism) != 0){
       return NDBT_FAILED;
     }
     i++;
@@ -251,7 +261,7 @@
   
   int i = 0;
   HugoTransactions hugoTrans(*ctx->getTab());
-  while (i<loops) {
+  while (i<loops && !ctx->isTestStopped()) {
     g_info << i << ": ";
     
     ndbout << "insertErrorInAllNodes("<<error<<")"<<endl;
@@ -988,7 +998,15 @@
 	 "When this limit is exceeded the scan will be aborted with errorcode "\
 	 "488."){
   INITIALIZER(runLoadTable);
-  STEPS(runScanRead, 15);
+  STEPS(runScanRead, 70);
+  FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead488Timeout", 
+	 ""){
+  INITIALIZER(runLoadTable);
+  TC_PROPERTY("ErrorCode", 5034);
+  STEPS(runScanRead, 30);
+  STEP(runScanReadError);
   FINALIZER(runClearTable);
 }
 TESTCASE("ScanRead40", 

--- 1.1/ndb/test/src/HugoTransactions.cpp	Wed Apr 14 10:24:41 2004
+++ 1.2/ndb/test/src/HugoTransactions.cpp	Tue May  4 11:18:53 2004
@@ -794,6 +794,18 @@
 	return NDBT_FAILED;
       }
     }
+
+    const NdbError err = pTrans->getNdbError();    
+    if( check == -1 ) {
+      pNdb->closeTransaction(pTrans);
+      ERR(err);
+      if (err.status == NdbError::TemporaryError){
+	NdbSleep_MilliSleep(50);
+	goto restart;
+      }
+      return NDBT_FAILED;
+    }
+    
     pNdb->closeTransaction(pTrans);
     
     g_info << rows << " rows have been updated" << endl;

--- 1.1/ndb/test/src/NDBT_Tables.cpp	Wed Apr 14 10:24:41 2004
+++ 1.2/ndb/test/src/NDBT_Tables.cpp	Tue May  4 11:18:53 2004
@@ -760,8 +760,9 @@
     tmpTab.setStoredTable(_temp? 0 : 1);
     
     int r = pNdb->getDictionary()->createTable(tmpTab);
+    int err = pNdb->getDictionary()->getNdbError().code;
     if(r == -1){
-      if (existsOk && pNdb->getNdbError().code == 721)
+      if (existsOk && err == 721)
 	;
       else {
 	return NDBT_FAILED;

--- 1.1/ndb/test/src/NDBT_Test.cpp	Wed Apr 14 10:24:41 2004
+++ 1.2/ndb/test/src/NDBT_Test.cpp	Tue May  4 11:18:53 2004
@@ -824,6 +824,8 @@
 	continue;
       }
       pTab2 = pDict->getTable(pTab->getName());
+    } else {
+      pTab2 = pTab;
     }
     
     ctx = new NDBT_Context();

--- 1.1/ndb/test/src/UtilTransactions.cpp	Wed Apr 14 10:24:41 2004
+++ 1.2/ndb/test/src/UtilTransactions.cpp	Tue May  4 11:18:53 2004
@@ -352,6 +352,7 @@
   NdbScanOperation *pOp;
   NdbError err;
 
+  int par = parallelism;
   while (true){
   restart:
     if (retryAttempt++ >= retryMax){
@@ -376,7 +377,7 @@
       goto failed;
     }
     
-    NdbResultSet * rs = pOp->readTuplesExclusive(parallelism);
+    NdbResultSet * rs = pOp->readTuplesExclusive(par);
     if( rs == 0 ) {
       goto failed;
     }
@@ -411,16 +412,28 @@
 	  ERR(err);
 	  pNdb->closeTransaction(pTrans);
 	  NdbSleep_MilliSleep(50);
+	  par = 1;
 	  goto restart;
 	}
 	goto failed;
       }
     }
+    if(check == -1){
+      err = pTrans->getNdbError();    
+      if(err.status == NdbError::TemporaryError){
+	ERR(err);
+	pNdb->closeTransaction(pTrans);
+	NdbSleep_MilliSleep(50);
+	par = 1;
+	goto restart;
+      }
+      goto failed;
+    }
     pNdb->closeTransaction(pTrans);
     return NDBT_OK;
   }
   return NDBT_FAILED;
-
+  
  failed:
   if(pTrans != 0) pNdb->closeTransaction(pTrans);
   ERR(err);
Thread
bk commit into 4.1 tree (joreland:1.1806)jonas.oreland4 May