List:Commits« Previous MessageNext Message »
From:Pekka Nousiainen Date:October 7 2011 5:06pm
Subject:bzr push into mysql-5.1-telco-7.0 branch (pekka.nousiainen:4550 to 4584)
View as plain text  
 4584 Maitrayi Sabaratnam	2011-10-07
      Bug 12598636 - DATA NODE SHOULD SHUTDOWN WHEN IT DETECTS INCORRECT TUPLE CHECKSUM

    modified:
      storage/ndb/include/mgmapi/mgmapi_config_parameters.h
      storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
      storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp
      storage/ndb/src/mgmsrv/ConfigInfo.cpp
 4583 jonas oreland	2011-10-07
      ndb - add ndbinfo.transactions showing ongoing transactions
        (patch also remove unused states in TC)
        TODO: - SQL
              - verify all outstanding calculations
              - maybe use coord-trans type transaction id (not to confuse things too much)
              - expose transaction id per mysql-connection, maybe using information_schema
              - ndbinfo.operations (in LQH)

    modified:
      mysql-test/suite/ndb/r/ndbinfo.result
      storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
      storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
      storage/ndb/src/kernel/vm/Ndbinfo.hpp
      storage/ndb/src/kernel/vm/NdbinfoTables.cpp
 4582 Mauritz Sundell	2011-10-07
      ndb - New test case for bigger tables.
      
      Demonstrating effect of making static arrays for
      schema transactions dynamic.
      Handles more blob-columns in wide table.

    modified:
      mysql-test/suite/ndb/r/ndb_alter_table.result
      mysql-test/suite/ndb/t/ndb_alter_table.test
 4581 Mauritz Sundell	2011-10-07
      ndb - Dynamic memory for schema transaction
      
      Replacing statically allocated memory pools (ArrayPool)
      with dynamically allocated (ArenaPool) for some objects
      seized and released within a schema transaction.
      
      A new resource SCHEMA_TRANS_MEMORY with atleast 2MiB
      created.

    modified:
      storage/ndb/include/kernel/ndb_limits.h
      storage/ndb/include/kernel/signaldata/SchemaTrans.hpp
      storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
      storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
      storage/ndb/src/kernel/blocks/record_types.hpp
      storage/ndb/src/kernel/ndbd.cpp
      storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp
      storage/ndb/src/ndbapi/ndberror.c
      storage/ndb/tools/ndbinfo_sql.cpp
 4580 Mauritz Sundell	2011-10-07
      ndb - Added names to already existing but unnamed resources.
      
      Added names to already existing but unnamed resources.
      Resources was named <unknown>' in table ndbinfo.resources.
      
      Recommit of earlier commit that disappered in previous commit,
      stupid me.

    modified:
      storage/ndb/tools/ndbinfo_sql.cpp
 4579 Mauritz Sundell	2011-10-07
      ndb - Adding pool parameter to container templates.
      
      Adding pool parameter to container templates, default to previous
      behaviour using ArrayPool<T>.
      Also let MAKE_TID construct Uint32 value to avoid signed/unsigned warnings.

    modified:
      storage/ndb/src/kernel/vm/DLFifoList.hpp
      storage/ndb/src/kernel/vm/DLHashTable.hpp
      storage/ndb/src/kernel/vm/DataBuffer2.hpp
      storage/ndb/src/kernel/vm/Pool.hpp
      storage/ndb/tools/ndbinfo_sql.cpp
 4578 Mauritz Sundell	2011-10-07
      Added names to already existing but unnamed resources.
      Resources was named <unknown>' in table ndbinfo.resources.

    modified:
      storage/ndb/tools/ndbinfo_sql.cpp
 4577 jonas oreland	2011-10-07
      ndb - fix result files and rate-limit for threadblocks

    modified:
      mysql-test/suite/ndb/r/ndbinfo.result
      mysql-test/suite/ndb/r/ndbinfo_dump.result
      storage/ndb/src/kernel/blocks/thrman.cpp
 4576 jonas oreland	2011-10-07
      ndb - add --loops and --delay to ndbinfo_select_all (to get rudementary vmstat similarity)

    modified:
      storage/ndb/tools/ndbinfo_select_all.cpp
 4575 jonas oreland	2011-10-07
      ndb - add thread statistics

    added:
      storage/ndb/include/portlib/NdbGetRUsage.h
      storage/ndb/src/common/portlib/NdbGetRUsage.cpp
      storage/ndb/src/kernel/blocks/thrman.cpp
      storage/ndb/src/kernel/blocks/thrman.hpp
    modified:
      storage/ndb/include/kernel/BlockNumbers.h
      storage/ndb/src/common/debugger/BlockNames.cpp
      storage/ndb/src/common/portlib/CMakeLists.txt
      storage/ndb/src/common/portlib/Makefile.am
      storage/ndb/src/kernel/SimBlockList.cpp
      storage/ndb/src/kernel/blocks/CMakeLists.txt
      storage/ndb/src/kernel/blocks/LocalProxy.cpp
      storage/ndb/src/kernel/blocks/LocalProxy.hpp
      storage/ndb/src/kernel/blocks/Makefile.am
      storage/ndb/src/kernel/blocks/PgmanProxy.cpp
      storage/ndb/src/kernel/blocks/PgmanProxy.hpp
      storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp
      storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp
      storage/ndb/src/kernel/blocks/dbspj/DbspjProxy.hpp
      storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.hpp
      storage/ndb/src/kernel/vm/Ndbinfo.hpp
      storage/ndb/src/kernel/vm/NdbinfoTables.cpp
      storage/ndb/src/kernel/vm/SimulatedBlock.hpp
      storage/ndb/src/kernel/vm/dummy_nonmt.cpp
      storage/ndb/src/kernel/vm/mt.cpp
      storage/ndb/src/kernel/vm/mt.hpp
      storage/ndb/src/kernel/vm/mt_thr_config.cpp
      storage/ndb/src/kernel/vm/mt_thr_config.hpp
 4574 jonas oreland	2011-10-07
      ndb - fix bug introduced by deadlock detector, causing recv-thread in ndbmtd to get incorrect tid

    modified:
      storage/ndb/src/common/portlib/NdbThread.c
 4573 Frazer Clement	2011-10-06
      Bug#13067813 mysqlbinlog --database option broken

    modified:
      client/mysqlbinlog.cc
      mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test
 4572 Jonas Oreland	2011-10-05
      ndb - promote well behaving tests in daily-devel to daily-basic

    modified:
      storage/ndb/test/run-test/daily-basic-tests.txt
      storage/ndb/test/run-test/daily-devel-tests.txt
 4571 Jonas Oreland	2011-10-05
      ndb - add new tools that does selects all rows from a ndb$info table

    added:
      storage/ndb/tools/ndbinfo_select_all.cpp
    modified:
      storage/ndb/tools/CMakeLists.txt
      storage/ndb/tools/Makefile.am
 4570 jonas oreland	2011-10-04
      ndb - fix spurious crash when dropping tablespace (incorrect gsn in delay)

    modified:
      storage/ndb/src/kernel/blocks/tsman.cpp
 4569 jonas oreland	2011-10-04
      ndb - remove HugoQueryBuilder::O_RANDOM_OPTIONS, (and enumerate values for OM_RANDOM_OPTIONS)

    modified:
      storage/ndb/test/include/HugoQueryBuilder.hpp
 4568 jonas oreland	2011-10-03
      ndb - more fixes for empty hostname

    modified:
      storage/ndb/test/run-test/main.cpp
 4567 Jonas Oreland	2011-10-03
      ndb - add "atrt r" which restarts cluster rather than initial starts it

    modified:
      storage/ndb/test/run-test/atrt.hpp
      storage/ndb/test/run-test/main.cpp
      storage/ndb/test/run-test/setup.cpp
 4566 Jonas Oreland	2011-10-03
      ndb - 1) add search paths for atrt (since make install is different in 5.5) 2) ignore empty host names

    modified:
      storage/ndb/test/run-test/atrt.hpp
      storage/ndb/test/run-test/files.cpp
      storage/ndb/test/run-test/main.cpp
      storage/ndb/test/run-test/setup.cpp
 4565 Jonas Oreland	2011-10-03
      ndb - add missing Dbdict pool to list

    modified:
      storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
 4564 Mauritz Sundell	2011-09-30
      ndb.test_mgmd now finds ndb_mgmd
        
        If one runned mtr test ndb.test_mgmd from installation 
        tree ndb_mgmd was not found and test failed.
        Added to search path are ../libexec, ../sbin, and ../bin.

    modified:
      storage/ndb/test/src/NDBT_Find.cpp
 4563 Martin Skold	2011-09-29
      Bug#11930428  NDB_BINLOG_INDEX: KILLED UNABLE TO LOCK TABLE NDB_BINLOG_INDEX AT SHUTDOWN: Removed error printouts before retrying to write to ndb_binlog_index at shutdown

    modified:
      sql/ha_ndbcluster_binlog.cc
 4562 Jan Wedvik	2011-09-29
      This patch will make the SPJ block fetch all rows for some non-root index scans 
      in one batch rather than two.
      This will happen if the first batch reads from a subset of the fragments and 
      receive few rows. The SPJ block will then
      try to read from the remaining fragments before finishing the batch.
      This is especially useful when doing bushy scans. If there are more branches in 
      the bushy scan, then these will have to be
      repeated for each batch of the current scan.

    modified:
      storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp
      storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp
 4561 Jan Wedvik	2011-09-29
      This patch fixes a bug that causes assert error in NdbQueryOperationDefImpl::printTree() for query trees that are more
      than 31 operations deep.

    modified:
      storage/ndb/src/ndbapi/NdbQueryBuilder.cpp
      storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp
 4560 Jan Wedvik	2011-09-29
      This patch fixes an assert error that happens in printSCANTABCONF() when enabling api signal logging and running
      the SQL script below:
      
      CREATE TABLE t1 (
        pk1 int NOT NULL,
        pk2 int NOT NULL,
        PRIMARY KEY (`pk1`,`pk2`)
      ) ENGINE=ndb partition by key(pk1) partitions 8;
      
      select count(*) from t1 where t1.pk1=0;
      
      The resulting ScanTabConf signal carries OpData for eight fragments in a separate segment, which printSCANTABCONF()
      does not handle.

    modified:
      storage/ndb/src/common/debugger/signaldata/ScanTab.cpp
 4559 Jonas Oreland	2011-09-29
      ndb - fix incorrect NdbRestarter usage

    modified:
      storage/ndb/test/ndbapi/testNdbApi.cpp
      storage/ndb/test/ndbapi/testRestartGci.cpp
 4558 Jonas Oreland	2011-09-28
      ndb - fix windows compiler warnings

    modified:
      storage/ndb/src/common/portlib/NdbCondition.c
      storage/ndb/test/ndbapi/testRestartGci.cpp
      storage/ndb/test/ndbapi/test_event.cpp
 4557 Jonas Oreland	2011-09-28
      ndb - fix incorrect argument

    modified:
      storage/ndb/test/tools/hugoJoin.cpp
 4556 Jonas Oreland	2011-09-28
      ndb - enable frazers new tests also in 7.0...(i'd be disappointed if windows doesn't get red now)

    modified:
      mysql-test/suite/ndb_binlog/t/ndb_binlog_log_transaction_id-master.opt
      mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict_epoch_trans.cnf
 4555 jonas oreland	2011-09-27
      ndb - implemented mutex deadlock detector ala linux kernel lockdep
        (google linux kernel lockdep dor description)
        1) currently only active if setting NDB_EXTRA_FLAGS=-DNDB_MUTEX_DEADLOCK_DETECTOR
        2) only "monitors" NdbMutex (e.g not mysql mutexes)
        3) only supports basic/simple schemes...i.e not nested locking etc..
           (but we don't use that anyway)
      
        Found the ndb_mgmd mutex deadlock directly
        When a potential deadlock is detected, code aborts

    added:
      storage/ndb/src/common/portlib/NdbMutex_DeadlockDetector.cpp
      storage/ndb/src/common/portlib/NdbMutex_DeadlockDetector.h
    modified:
      storage/ndb/include/portlib/NdbMutex.h
      storage/ndb/src/common/portlib/CMakeLists.txt
      storage/ndb/src/common/portlib/Makefile.am
      storage/ndb/src/common/portlib/NdbCondition.c
      storage/ndb/src/common/portlib/NdbMutex.c
      storage/ndb/src/common/portlib/NdbThread.c
      storage/ndb/src/common/util/ndb_init.cpp
 4554 jonas oreland	2011-09-27
      ndb - remove locking of m_local_config_mutex in MgmtSrvr::start as this introduces a lockdep assertion

    modified:
      storage/ndb/src/mgmsrv/MgmtSrvr.cpp
 4553 Jonas Oreland	2011-09-27
      ndb - remove mutex created as global object (before ndb_init), have it be created by EmulatorData::create() instead

    modified:
      storage/ndb/src/kernel/vm/ArrayPool.hpp
      storage/ndb/src/kernel/vm/Emulator.cpp
 4552 jonas oreland	2011-09-27
      ndb - This patch adds a few new NdbClusterConnectionConnect tests, and adds them to daily-basic

    modified:
      storage/ndb/test/ndbapi/testNdbApi.cpp
      storage/ndb/test/run-test/daily-basic-tests.txt
 4551 Jonas Oreland	2011-09-26 [merge]
      ndb - merge 7.0.27 into 7.0-main

    modified:
      storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
      storage/ndb/src/mgmsrv/MgmtSrvr.cpp
 4550 Jonas Oreland	2011-09-23
      ndb 
      - add config part (still only explicit, using ThreadConfig)
        of MT-TC
      - remove ThreadConfig-printout from ndbd (single threaded)

    modified:
      storage/ndb/src/kernel/SimBlockList.cpp
      storage/ndb/src/kernel/ndbd.cpp
      storage/ndb/src/kernel/vm/Configuration.cpp
      storage/ndb/src/kernel/vm/mt_thr_config.cpp
      storage/ndb/src/kernel/vm/mt_thr_config.hpp
=== modified file 'client/mysqlbinlog.cc'
--- a/client/mysqlbinlog.cc	2011-06-30 15:59:25 +0000
+++ b/client/mysqlbinlog.cc	2011-10-06 14:43:17 +0000
@@ -900,6 +900,11 @@ Exit_status process_event(PRINT_EVENT_IN
     case WRITE_ROWS_EVENT:
     case DELETE_ROWS_EVENT:
     case UPDATE_ROWS_EVENT:
+#ifndef MCP_WL5353
+    case WRITE_ROWS_EVENT_V1:
+    case DELETE_ROWS_EVENT_V1:
+    case UPDATE_ROWS_EVENT_V1:
+#endif
     case PRE_GA_WRITE_ROWS_EVENT:
     case PRE_GA_DELETE_ROWS_EVENT:
     case PRE_GA_UPDATE_ROWS_EVENT:

=== modified file 'mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test'
--- a/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test	2009-09-30 02:31:25 +0000
+++ b/mysql-test/suite/binlog/t/binlog_row_mysqlbinlog_db_filter.test	2011-10-06 14:43:17 +0000
@@ -140,6 +140,17 @@ while($i)
     -- echo **** ERROR **** Database name 'b42941' NOT FOUND in mysqlbinlog output ($flags $outfile.2).
   }
 
+  #bug #13067813
+  if (`SELECT INSTR(@b42941_output.1, 'unknown table')`)
+  {
+    -- echo **** ERROR **** Table mapping failure detected
+  }
+
+  if (`SELECT INSTR(@b42941_output.2, 'unknown table')`)
+  {
+    -- echo **** ERROR **** Table mapping failure detected
+  }
+
   dec $i;
 }
 

=== modified file 'mysql-test/suite/ndb/r/ndb_alter_table.result'
--- a/mysql-test/suite/ndb/r/ndb_alter_table.result	2009-07-13 10:51:28 +0000
+++ b/mysql-test/suite/ndb/r/ndb_alter_table.result	2011-10-07 14:28:37 +0000
@@ -283,7 +283,7 @@ c108 int(11) not null,
 c109 int(11) not null,
 primary key (ai),
 unique key tx1 (c002, c003, c004, c005)) engine=ndb;
-create index tx2 
+create index tx2
 on t1 (c010, c011, c012, c013);
 drop table t1;
 create table t1 (a int primary key auto_increment, b int) engine=ndb;
@@ -395,4 +395,136 @@ a	b
 2	200
 1	300
 drop table t1;
+create table t1 (
+ci001 int, ci002 int, ci003 int, ci004 int, ci005 int, ci006 int, ci007 int, ci008 int,
+ci009 int, ci010 int, ci011 int, ci012 int, ci013 int, ci014 int, ci015 int, ci016 int,
+ci017 int, ci018 int, ci019 int, ci020 int, ci021 int, ci022 int, ci023 int, ci024 int,
+ci025 int, ci026 int, ci027 int, ci028 int, ci029 int, ci030 int, ci031 int, ci032 int,
+ci033 int, ci034 int, ci035 int, ci036 int, ci037 int, ci038 int, ci039 int, ci040 int,
+ci041 int, ci042 int, ci043 int, ci044 int, ci045 int, ci046 int, ci047 int, ci048 int,
+ci049 int, ci050 int, ci051 int, ci052 int, ci053 int, ci054 int, ci055 int, ci056 int,
+ci057 int, ci058 int, ci059 int, ci060 int, ci061 int, ci062 int, ci063 int, ci064 int,
+ci065 int, ci066 int, ci067 int, ci068 int, ci069 int, ci070 int, ci071 int, ci072 int,
+ci073 int, ci074 int, ci075 int, ci076 int, ci077 int, ci078 int, ci079 int, ci080 int,
+ci081 int, ci082 int, ci083 int, ci084 int, ci085 int, ci086 int, ci087 int, ci088 int,
+ci089 int, ci090 int, ci091 int, ci092 int, ci093 int, ci094 int, ci095 int, ci096 int,
+ci097 int, ci098 int, ci099 int, ci100 int, ci101 int, ci102 int, ci103 int, ci104 int,
+ci105 int, ci106 int, ci107 int, ci108 int, ci109 int, ci110 int, ci111 int, ci112 int,
+ci113 int, ci114 int, ci115 int, ci116 int, ci117 int, ci118 int, ci119 int, ci120 int,
+ci121 int, ci122 int, ci123 int, ci124 int, ci125 int, ci126 int, ci127 int, ci128 int,
+ci129 int, ci130 int, ci131 int, ci132 int, ci133 int, ci134 int, ci135 int, ci136 int,
+ci137 int, ci138 int, ci139 int, ci140 int, ci141 int, ci142 int, ci143 int, ci144 int,
+ci145 int, ci146 int, ci147 int, ci148 int, ci149 int, ci150 int, ci151 int, ci152 int,
+ci153 int, ci154 int, ci155 int, ci156 int, ci157 int, ci158 int, ci159 int, ci160 int,
+ci161 int, ci162 int, ci163 int, ci164 int, ci165 int, ci166 int, ci167 int, ci168 int,
+ci169 int, ci170 int, ci171 int, ci172 int, ci173 int, ci174 int, ci175 int, ci176 int,
+ci177 int, ci178 int, ci179 int, ci180 int, ci181 int, ci182 int, ci183 int, ci184 int,
+ci185 int, ci186 int, ci187 int, ci188 int, ci189 int, ci190 int, ci191 int, ci192 int,
+ci193 int, ci194 int, ci195 int, ci196 int, ci197 int, ci198 int, ci199 int, ci200 int,
+ci201 int, ci202 int, ci203 int, ci204 int, ci205 int, ci206 int, ci207 int, ci208 int,
+ci209 int, ci210 int, ci211 int, ci212 int, ci213 int, ci214 int, ci215 int, ci216 int,
+ci217 int, ci218 int, ci219 int, ci220 int, ci221 int, ci222 int, ci223 int, ci224 int,
+ci225 int, ci226 int, ci227 int, ci228 int, ci229 int, ci230 int, ci231 int, ci232 int,
+ci233 int, ci234 int, ci235 int, ci236 int, ci237 int, ci238 int, ci239 int, ci240 int,
+ci241 int, ci242 int, ci243 int, ci244 int, ci245 int, ci246 int, ci247 int, ci248 int,
+ci249 int, ci250 int, ci251 int, ci252 int, ci253 int, ci254 int, ci255 int, ci256 int,
+ci257 int, ci258 int, ci259 int, ci260 int, ci261 int, ci262 int, ci263 int, ci264 int,
+ci265 int, ci266 int, ci267 int, ci268 int, ci269 int, ci270 int, ci271 int, ci272 int,
+ci273 int, ci274 int, ci275 int, ci276 int, ci277 int, ci278 int, ci279 int, ci280 int,
+ci281 int, ci282 int, ci283 int, ci284 int, ci285 int, ci286 int, ci287 int, ci288 int,
+ci289 int, ci290 int, ci291 int, ci292 int, ci293 int, ci294 int, ci295 int, ci296 int,
+ci297 int, ci298 int, ci299 int, ci300 int, ci301 int, ci302 int, ci303 int, ci304 int,
+ci305 int, ci306 int, ci307 int, ci308 int, ci309 int, ci310 int, ci311 int, ci312 int,
+ci313 int, ci314 int, ci315 int, ci316 int, ci317 int, ci318 int, ci319 int, ci320 int,
+ci321 int, ci322 int, ci323 int, ci324 int, ci325 int, ci326 int, ci327 int, ci328 int,
+ci329 int, ci330 int, ci331 int, ci332 int, ci333 int, ci334 int, ci335 int, ci336 int,
+ci337 int, ci338 int, ci339 int, ci340 int, ci341 int, ci342 int, ci343 int, ci344 int,
+ci345 int, ci346 int, ci347 int, ci348 int, ci349 int, ci350 int, ci351 int, ci352 int,
+ci353 int, ci354 int, ci355 int, ci356 int, ci357 int, ci358 int, ci359 int, ci360 int,
+ci361 int, ci362 int, ci363 int, ci364 int, ci365 int, ci366 int, ci367 int, ci368 int,
+ci369 int, ci370 int, ci371 int, ci372 int, ci373 int, ci374 int, ci375 int, ci376 int,
+ci377 int, ci378 int, ci379 int, ci380 int, ci381 int, ci382 int, ci383 int, ci384 int,
+ci385 int, ci386 int, ci387 int, ci388 int, ci389 int, ci390 int, ci391 int, ci392 int,
+ci393 int, ci394 int, ci395 int, ci396 int, ci397 int, ci398 int, ci399 int, ci400 int,
+ci401 int, ci402 int, ci403 int, ci404 int, ci405 int, ci406 int, ci407 int, ci408 int,
+ci409 int, ci410 int, ci411 int, ci412 int, ci413 int, ci414 int, ci415 int, ci416 int,
+ci417 int, ci418 int, ci419 int, ci420 int, ci421 int, ci422 int, ci423 int, ci424 int,
+ci425 int, ci426 int, ci427 int, ci428 int, ci429 int, ci430 int, ci431 int, ci432 int,
+ci433 int, ci434 int, ci435 int, ci436 int, ci437 int, ci438 int, ci439 int, ci440 int,
+ci441 int, ci442 int, ci443 int, ci444 int, ci445 int, ci446 int, ci447 int, ci448 int,
+ci449 int, ci450 int, ci451 int, ci452 int, ci453 int, ci454 int, ci455 int, ci456 int,
+ci457 int, ci458 int, ci459 int, ci460 int, ci461 int, ci462 int, ci463 int, ci464 int,
+ci465 int, ci466 int, ci467 int, ci468 int, ci469 int, ci470 int,
+cb471 blob, cb472 blob, cb473 blob, cb474 blob, cb475 blob, cb476 blob, cb477 blob, cb478 blob,
+cb479 blob, cb480 blob, cb481 blob, cb482 blob, cb483 blob, cb484 blob, cb485 blob, cb486 blob,
+cb487 blob, cb488 blob, cb489 blob, cb490 blob, cb491 blob, cb492 blob, cb493 blob, cb494 blob,
+cb495 blob, cb496 blob, cb497 blob, cb498 blob, cb499 blob, cb500 blob, cb501 blob, cb502 blob,
+cb503 blob, cb504 blob, cb505 blob, cb506 blob, cb507 blob, cb508 blob, cb509 blob, cb510 blob,
+cb511 blob, cb512 blob,
+primary key (ci001),
+unique i1 (ci002),
+unique i2 (ci003),
+unique i3 (ci004),
+unique i4 (ci005),
+unique i5 (ci006),
+unique i6 (ci007),
+unique i7 (ci008),
+unique i8 (ci009),
+unique i9 (ci010),
+unique i10 (ci011),
+unique i11 (ci012),
+unique i12 (ci013),
+unique i13 (ci014),
+unique i14 (ci015),
+unique i15 (ci016),
+unique i16 (ci017),
+unique i17 (ci018),
+unique i18 (ci019),
+unique i19 (ci020),
+unique i20 (ci021),
+unique i21 (ci022),
+unique i22 (ci023),
+unique i23 (ci024),
+unique i24 (ci025),
+unique i25 (ci026),
+unique i26 (ci027),
+unique i27 (ci028),
+unique i28 (ci029),
+unique i29 (ci030),
+unique i30 (ci031),
+unique i31 (ci032),
+unique i32 (ci033),
+unique i33 (ci034),
+unique i34 (ci035),
+unique i35 (ci036),
+unique i36 (ci037),
+unique i37 (ci038),
+unique i38 (ci039),
+unique i39 (ci040),
+unique i40 (ci041),
+unique i41 (ci042),
+unique i42 (ci043),
+unique i43 (ci044),
+unique i44 (ci045),
+unique i45 (ci046),
+unique i46 (ci047),
+unique i47 (ci048),
+unique i48 (ci049),
+unique i49 (ci050),
+unique i50 (ci051),
+unique i51 (ci052),
+unique i52 (ci053),
+unique i53 (ci054),
+unique i54 (ci055),
+unique i55 (ci056),
+unique i56 (ci057),
+unique i57 (ci058),
+unique i58 (ci059),
+unique i59 (ci060),
+unique i60 (ci061),
+unique i61 (ci062),
+unique i62 (ci063),
+unique i63 (ci064)
+) engine=ndb;
+drop table t1;
 End of 5.1 tests

=== modified file 'mysql-test/suite/ndb/r/ndbinfo.result'
--- a/mysql-test/suite/ndb/r/ndbinfo.result	2011-05-23 13:45:57 +0000
+++ b/mysql-test/suite/ndb/r/ndbinfo.result	2011-10-07 14:34:14 +0000
@@ -37,9 +37,12 @@ table_id	table_name	comment
 8	counters	monotonic counters
 9	nodes	node status
 10	diskpagebuffer	disk page buffer info
+11	threadblocks	which blocks are run in which threads
+12	threadstat	threadstat
+13	transactions	transactions
 SELECT COUNT(*) FROM ndb$tables;
 COUNT(*)
-11
+14
 SELECT * FROM ndb$tables WHERE table_id = 2;
 table_id	table_name	comment
 2	test	for testing
@@ -50,11 +53,14 @@ table_id	table_name	comment
 8	counters	monotonic counters
 9	nodes	node status
 10	diskpagebuffer	disk page buffer info
+11	threadblocks	which blocks are run in which threads
+12	threadstat	threadstat
+13	transactions	transactions
 SELECT * FROM ndb$tables WHERE table_name = 'LOGDESTINATION';
 table_id	table_name	comment
 SELECT COUNT(*) FROM ndb$tables t1, ndb$tables t2 WHERE t1.table_id = t1.table_id;
 COUNT(*)
-121
+196
 
 SELECT table_id, table_name, comment from ndb$tables
   WHERE table_id > 2 AND table_id <= 5 ORDER BY table_id;
@@ -77,6 +83,9 @@ table_id	table_name
 7	resources
 0	tables
 2	test
+11	threadblocks
+12	threadstat
+13	transactions
 4	transporters
 
 SELECT table_id, column_id, column_name FROM ndb$columns LIMIT 7;
@@ -124,6 +133,9 @@ table_id
 8
 9
 10
+11
+12
+13
 
 TRUNCATE ndb$tables;
 ERROR HY000: Table 'ndb$tables' is read only

=== modified file 'mysql-test/suite/ndb/r/ndbinfo_dump.result'
--- a/mysql-test/suite/ndb/r/ndbinfo_dump.result	2011-02-23 22:30:50 +0000
+++ b/mysql-test/suite/ndb/r/ndbinfo_dump.result	2011-10-07 09:28:24 +0000
@@ -1,7 +1,7 @@
 USE ndbinfo;
 select count(*) from blocks;
 count(*)
-21
+22
 select count(*) from blocks;
 count(*)
-21
+22

=== modified file 'mysql-test/suite/ndb/t/ndb_alter_table.test'
--- a/mysql-test/suite/ndb/t/ndb_alter_table.test	2009-07-13 10:51:28 +0000
+++ b/mysql-test/suite/ndb/t/ndb_alter_table.test	2011-10-07 14:28:37 +0000
@@ -22,7 +22,7 @@ CREATE TABLE t1 (
 ) ENGINE=ndbcluster;
 
 INSERT INTO t1 VALUES (9410,9412);
-  
+
 ALTER TABLE t1 ADD COLUMN c int not null;
 SELECT * FROM t1;
 
@@ -144,7 +144,7 @@ drop table t1;
 #create table t1 ( a int primary key, b varchar(10), c varchar(10), index (b) )
 #engine=ndb;
 #insert into t1 values (1,'one','one'), (2,'two','two'), (3,'three','three');
-#create index c on t1(c); 
+#create index c on t1(c);
 #connection server2;
 #select * from t1 where c = 'two';
 #connection server1;
@@ -194,7 +194,7 @@ drop table t1;
 ### This should work as transaction is ongoing...
 ##delete from t3;
 ##insert into t3 values (1);
-#commit; 
+#commit;
 
 ## This should fail as its a new transaction
 #--error 1146
@@ -318,7 +318,7 @@ c109 int(11) not null,
 primary key (ai),
 unique key tx1 (c002, c003, c004, c005)) engine=ndb;
 
-create index tx2 
+create index tx2
 on t1 (c010, c011, c012, c013);
 
 drop table t1;
@@ -384,4 +384,139 @@ alter table t1 order by b;
 select * from t1 order by b;
 drop table t1;
 
+# big table, 512 columns, 42 blob, 64x2 indices
+
+create table t1 (
+  ci001 int, ci002 int, ci003 int, ci004 int, ci005 int, ci006 int, ci007 int, ci008 int,
+  ci009 int, ci010 int, ci011 int, ci012 int, ci013 int, ci014 int, ci015 int, ci016 int,
+  ci017 int, ci018 int, ci019 int, ci020 int, ci021 int, ci022 int, ci023 int, ci024 int,
+  ci025 int, ci026 int, ci027 int, ci028 int, ci029 int, ci030 int, ci031 int, ci032 int,
+  ci033 int, ci034 int, ci035 int, ci036 int, ci037 int, ci038 int, ci039 int, ci040 int,
+  ci041 int, ci042 int, ci043 int, ci044 int, ci045 int, ci046 int, ci047 int, ci048 int,
+  ci049 int, ci050 int, ci051 int, ci052 int, ci053 int, ci054 int, ci055 int, ci056 int,
+  ci057 int, ci058 int, ci059 int, ci060 int, ci061 int, ci062 int, ci063 int, ci064 int,
+  ci065 int, ci066 int, ci067 int, ci068 int, ci069 int, ci070 int, ci071 int, ci072 int,
+  ci073 int, ci074 int, ci075 int, ci076 int, ci077 int, ci078 int, ci079 int, ci080 int,
+  ci081 int, ci082 int, ci083 int, ci084 int, ci085 int, ci086 int, ci087 int, ci088 int,
+  ci089 int, ci090 int, ci091 int, ci092 int, ci093 int, ci094 int, ci095 int, ci096 int,
+  ci097 int, ci098 int, ci099 int, ci100 int, ci101 int, ci102 int, ci103 int, ci104 int,
+  ci105 int, ci106 int, ci107 int, ci108 int, ci109 int, ci110 int, ci111 int, ci112 int,
+  ci113 int, ci114 int, ci115 int, ci116 int, ci117 int, ci118 int, ci119 int, ci120 int,
+  ci121 int, ci122 int, ci123 int, ci124 int, ci125 int, ci126 int, ci127 int, ci128 int,
+  ci129 int, ci130 int, ci131 int, ci132 int, ci133 int, ci134 int, ci135 int, ci136 int,
+  ci137 int, ci138 int, ci139 int, ci140 int, ci141 int, ci142 int, ci143 int, ci144 int,
+  ci145 int, ci146 int, ci147 int, ci148 int, ci149 int, ci150 int, ci151 int, ci152 int,
+  ci153 int, ci154 int, ci155 int, ci156 int, ci157 int, ci158 int, ci159 int, ci160 int,
+  ci161 int, ci162 int, ci163 int, ci164 int, ci165 int, ci166 int, ci167 int, ci168 int,
+  ci169 int, ci170 int, ci171 int, ci172 int, ci173 int, ci174 int, ci175 int, ci176 int,
+  ci177 int, ci178 int, ci179 int, ci180 int, ci181 int, ci182 int, ci183 int, ci184 int,
+  ci185 int, ci186 int, ci187 int, ci188 int, ci189 int, ci190 int, ci191 int, ci192 int,
+  ci193 int, ci194 int, ci195 int, ci196 int, ci197 int, ci198 int, ci199 int, ci200 int,
+  ci201 int, ci202 int, ci203 int, ci204 int, ci205 int, ci206 int, ci207 int, ci208 int,
+  ci209 int, ci210 int, ci211 int, ci212 int, ci213 int, ci214 int, ci215 int, ci216 int,
+  ci217 int, ci218 int, ci219 int, ci220 int, ci221 int, ci222 int, ci223 int, ci224 int,
+  ci225 int, ci226 int, ci227 int, ci228 int, ci229 int, ci230 int, ci231 int, ci232 int,
+  ci233 int, ci234 int, ci235 int, ci236 int, ci237 int, ci238 int, ci239 int, ci240 int,
+  ci241 int, ci242 int, ci243 int, ci244 int, ci245 int, ci246 int, ci247 int, ci248 int,
+  ci249 int, ci250 int, ci251 int, ci252 int, ci253 int, ci254 int, ci255 int, ci256 int,
+  ci257 int, ci258 int, ci259 int, ci260 int, ci261 int, ci262 int, ci263 int, ci264 int,
+  ci265 int, ci266 int, ci267 int, ci268 int, ci269 int, ci270 int, ci271 int, ci272 int,
+  ci273 int, ci274 int, ci275 int, ci276 int, ci277 int, ci278 int, ci279 int, ci280 int,
+  ci281 int, ci282 int, ci283 int, ci284 int, ci285 int, ci286 int, ci287 int, ci288 int,
+  ci289 int, ci290 int, ci291 int, ci292 int, ci293 int, ci294 int, ci295 int, ci296 int,
+  ci297 int, ci298 int, ci299 int, ci300 int, ci301 int, ci302 int, ci303 int, ci304 int,
+  ci305 int, ci306 int, ci307 int, ci308 int, ci309 int, ci310 int, ci311 int, ci312 int,
+  ci313 int, ci314 int, ci315 int, ci316 int, ci317 int, ci318 int, ci319 int, ci320 int,
+  ci321 int, ci322 int, ci323 int, ci324 int, ci325 int, ci326 int, ci327 int, ci328 int,
+  ci329 int, ci330 int, ci331 int, ci332 int, ci333 int, ci334 int, ci335 int, ci336 int,
+  ci337 int, ci338 int, ci339 int, ci340 int, ci341 int, ci342 int, ci343 int, ci344 int,
+  ci345 int, ci346 int, ci347 int, ci348 int, ci349 int, ci350 int, ci351 int, ci352 int,
+  ci353 int, ci354 int, ci355 int, ci356 int, ci357 int, ci358 int, ci359 int, ci360 int,
+  ci361 int, ci362 int, ci363 int, ci364 int, ci365 int, ci366 int, ci367 int, ci368 int,
+  ci369 int, ci370 int, ci371 int, ci372 int, ci373 int, ci374 int, ci375 int, ci376 int,
+  ci377 int, ci378 int, ci379 int, ci380 int, ci381 int, ci382 int, ci383 int, ci384 int,
+  ci385 int, ci386 int, ci387 int, ci388 int, ci389 int, ci390 int, ci391 int, ci392 int,
+  ci393 int, ci394 int, ci395 int, ci396 int, ci397 int, ci398 int, ci399 int, ci400 int,
+  ci401 int, ci402 int, ci403 int, ci404 int, ci405 int, ci406 int, ci407 int, ci408 int,
+  ci409 int, ci410 int, ci411 int, ci412 int, ci413 int, ci414 int, ci415 int, ci416 int,
+  ci417 int, ci418 int, ci419 int, ci420 int, ci421 int, ci422 int, ci423 int, ci424 int,
+  ci425 int, ci426 int, ci427 int, ci428 int, ci429 int, ci430 int, ci431 int, ci432 int,
+  ci433 int, ci434 int, ci435 int, ci436 int, ci437 int, ci438 int, ci439 int, ci440 int,
+  ci441 int, ci442 int, ci443 int, ci444 int, ci445 int, ci446 int, ci447 int, ci448 int,
+  ci449 int, ci450 int, ci451 int, ci452 int, ci453 int, ci454 int, ci455 int, ci456 int,
+  ci457 int, ci458 int, ci459 int, ci460 int, ci461 int, ci462 int, ci463 int, ci464 int,
+  ci465 int, ci466 int, ci467 int, ci468 int, ci469 int, ci470 int,
+  cb471 blob, cb472 blob, cb473 blob, cb474 blob, cb475 blob, cb476 blob, cb477 blob, cb478 blob,
+  cb479 blob, cb480 blob, cb481 blob, cb482 blob, cb483 blob, cb484 blob, cb485 blob, cb486 blob,
+  cb487 blob, cb488 blob, cb489 blob, cb490 blob, cb491 blob, cb492 blob, cb493 blob, cb494 blob,
+  cb495 blob, cb496 blob, cb497 blob, cb498 blob, cb499 blob, cb500 blob, cb501 blob, cb502 blob,
+  cb503 blob, cb504 blob, cb505 blob, cb506 blob, cb507 blob, cb508 blob, cb509 blob, cb510 blob,
+  cb511 blob, cb512 blob,
+  primary key (ci001),
+  unique i1 (ci002),
+  unique i2 (ci003),
+  unique i3 (ci004),
+  unique i4 (ci005),
+  unique i5 (ci006),
+  unique i6 (ci007),
+  unique i7 (ci008),
+  unique i8 (ci009),
+  unique i9 (ci010),
+  unique i10 (ci011),
+  unique i11 (ci012),
+  unique i12 (ci013),
+  unique i13 (ci014),
+  unique i14 (ci015),
+  unique i15 (ci016),
+  unique i16 (ci017),
+  unique i17 (ci018),
+  unique i18 (ci019),
+  unique i19 (ci020),
+  unique i20 (ci021),
+  unique i21 (ci022),
+  unique i22 (ci023),
+  unique i23 (ci024),
+  unique i24 (ci025),
+  unique i25 (ci026),
+  unique i26 (ci027),
+  unique i27 (ci028),
+  unique i28 (ci029),
+  unique i29 (ci030),
+  unique i30 (ci031),
+  unique i31 (ci032),
+  unique i32 (ci033),
+  unique i33 (ci034),
+  unique i34 (ci035),
+  unique i35 (ci036),
+  unique i36 (ci037),
+  unique i37 (ci038),
+  unique i38 (ci039),
+  unique i39 (ci040),
+  unique i40 (ci041),
+  unique i41 (ci042),
+  unique i42 (ci043),
+  unique i43 (ci044),
+  unique i44 (ci045),
+  unique i45 (ci046),
+  unique i46 (ci047),
+  unique i47 (ci048),
+  unique i48 (ci049),
+  unique i49 (ci050),
+  unique i50 (ci051),
+  unique i51 (ci052),
+  unique i52 (ci053),
+  unique i53 (ci054),
+  unique i54 (ci055),
+  unique i55 (ci056),
+  unique i56 (ci057),
+  unique i57 (ci058),
+  unique i58 (ci059),
+  unique i59 (ci060),
+  unique i60 (ci061),
+  unique i61 (ci062),
+  unique i62 (ci063),
+  unique i63 (ci064)
+) engine=ndb;
+drop table t1;
+
 --echo End of 5.1 tests

=== modified file 'mysql-test/suite/ndb_binlog/t/ndb_binlog_log_transaction_id-master.opt'
--- a/mysql-test/suite/ndb_binlog/t/ndb_binlog_log_transaction_id-master.opt	2011-09-07 22:50:01 +0000
+++ b/mysql-test/suite/ndb_binlog/t/ndb_binlog_log_transaction_id-master.opt	2011-09-28 09:40:14 +0000
@@ -1 +1 @@
---ndb-log-transaction-id
+--ndb-log-transaction-id --log-bin-use-v1-row-events=false

=== modified file 'mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict_epoch_trans.cnf'
--- a/mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict_epoch_trans.cnf	2011-09-07 22:50:01 +0000
+++ b/mysql-test/suite/ndb_rpl/t/ndb_rpl_conflict_epoch_trans.cnf	2011-09-28 09:40:14 +0000
@@ -11,10 +11,14 @@
 # Potential infinite loops are broken by both servers
 # on each cluster having the same server-id
 
+[cluster_config.slave]
+mysqld=,
+
 [mysqld]
 log-slave-updates
 ndb-log-apply-status
 ndb-log-transaction-id
+log-bin-use-v1-row-events=false
 
 [mysqld.1.1]
 server-id= 1

=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc	2011-09-21 10:11:58 +0000
+++ b/sql/ha_ndbcluster_binlog.cc	2011-09-29 13:32:44 +0000
@@ -3508,7 +3508,7 @@ ndb_binlog_index_table__open(THD *thd,
   if (simple_open_n_lock_tables(thd, tables))
   {
     if (thd->killed)
-      sql_print_error("NDB Binlog: Opening ndb_binlog_index: killed");
+      DBUG_PRINT("error", ("NDB Binlog: Opening ndb_binlog_index: killed"));
     else
       sql_print_error("NDB Binlog: Opening ndb_binlog_index: %d, '%s'",
                       thd_stmt_da(thd)->sql_errno(),
@@ -3543,7 +3543,10 @@ ndb_binlog_index_table__write_rows(THD *
 
   if (ndb_binlog_index_table__open(thd, &binlog_tables, &ndb_binlog_index))
   {
-    sql_print_error("NDB Binlog: Unable to lock table ndb_binlog_index");
+    if (thd->killed)
+      DBUG_PRINT("error", ("NDB Binlog: Unable to lock table ndb_binlog_index, killed"));
+    else
+      sql_print_error("NDB Binlog: Unable to lock table ndb_binlog_index");
     error= -1;
     goto add_ndb_binlog_index_err;
   }
@@ -7492,6 +7495,7 @@ restart_cluster_failure:
               */
               if (thd->killed)
               {
+                DBUG_PRINT("error", ("Failed to write to ndb_binlog_index at shutdown, retrying"));
                 (void) mysql_mutex_lock(&LOCK_thread_count);
                 volatile THD::killed_state killed= thd->killed;
                 /* We are cleaning up, allow for flushing last epoch */

=== modified file 'storage/ndb/include/kernel/BlockNumbers.h'
--- a/storage/ndb/include/kernel/BlockNumbers.h	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/include/kernel/BlockNumbers.h	2011-10-07 08:07:21 +0000
@@ -60,6 +60,7 @@
 #define RESTORE    0x106
 #define DBINFO     0x107
 #define DBSPJ      0x108
+#define THRMAN     0x109
 
 const BlockReference BACKUP_REF  = numberToRef(BACKUP, 0);
 const BlockReference DBTC_REF    = numberToRef(DBTC, 0);
@@ -82,6 +83,7 @@ const BlockReference PGMAN_REF   = numbe
 const BlockReference RESTORE_REF = numberToRef(RESTORE, 0);
 const BlockReference DBINFO_REF  = numberToRef(DBINFO, 0);
 const BlockReference DBSPJ_REF  = numberToRef(DBSPJ, 0);
+const BlockReference THRMAN_REF  = numberToRef(THRMAN, 0);
 
 static inline void __hide_warnings_unused_ref_vars(void) {
   // Hide annoying warnings about unused variables
@@ -92,10 +94,11 @@ static inline void __hide_warnings_unuse
   (void)DBUTIL_REF;  (void)SUMA_REF;    (void)DBTUX_REF;
   (void)TSMAN_REF;   (void)LGMAN_REF;   (void)PGMAN_REF;
   (void)RESTORE_REF; (void)DBINFO_REF;  (void)DBSPJ_REF;
+  (void)THRMAN_REF;
 }
 
 const BlockNumber MIN_BLOCK_NO = BACKUP;
-const BlockNumber MAX_BLOCK_NO = DBSPJ;
+const BlockNumber MAX_BLOCK_NO = THRMAN;
 const BlockNumber NO_OF_BLOCKS = (MAX_BLOCK_NO - MIN_BLOCK_NO + 1);
 
 /**

=== modified file 'storage/ndb/include/kernel/ndb_limits.h'
--- a/storage/ndb/include/kernel/ndb_limits.h	2011-07-04 13:37:56 +0000
+++ b/storage/ndb/include/kernel/ndb_limits.h	2011-10-07 13:15:08 +0000
@@ -172,7 +172,6 @@
 /*
  * Schema transactions
  */
-#define MAX_SCHEMA_TRANSACTIONS 5
 #define MAX_SCHEMA_OPERATIONS 256
 
 /*

=== modified file 'storage/ndb/include/kernel/signaldata/SchemaTrans.hpp'
--- a/storage/ndb/include/kernel/signaldata/SchemaTrans.hpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/include/kernel/signaldata/SchemaTrans.hpp	2011-10-07 13:15:08 +0000
@@ -44,7 +44,8 @@ struct SchemaTransBeginRef {
     BusyWithNR = 711,
     TooManySchemaTrans = 780,
     IncompatibleVersions = 763,
-    Nodefailure = 786
+    Nodefailure = 786,
+    OutOfSchemaTransMemory = 796
   };
   Uint32 senderRef;
   Uint32 transId;

=== modified file 'storage/ndb/include/mgmapi/mgmapi_config_parameters.h'
--- a/storage/ndb/include/mgmapi/mgmapi_config_parameters.h	2011-08-30 09:40:52 +0000
+++ b/storage/ndb/include/mgmapi/mgmapi_config_parameters.h	2011-10-07 16:12:13 +0000
@@ -197,6 +197,8 @@
 #define CFG_DB_MAX_DML_OPERATIONS_PER_TRANSACTION 627
 #define CFG_DB_MT_THREAD_CONFIG          628
 
+#define CFG_DB_CRASH_ON_CORRUPTED_TUPLE  629
+
 #define CFG_NODE_ARBIT_RANK           200
 #define CFG_NODE_ARBIT_DELAY          201
 #define CFG_RESERVED_SEND_BUFFER_MEMORY 202

=== added file 'storage/ndb/include/portlib/NdbGetRUsage.h'
--- a/storage/ndb/include/portlib/NdbGetRUsage.h	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/include/portlib/NdbGetRUsage.h	2011-10-07 08:07:21 +0000
@@ -0,0 +1,46 @@
+/*
+   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#ifndef NDB_GET_RUSAGE_H
+#define NDB_GET_RUSAGE_H
+
+#include <ndb_global.h>
+
+struct ndb_rusage
+{
+  Uint64 ru_utime;
+  Uint64 ru_stime;
+  Uint64 ru_minflt;
+  Uint64 ru_majflt;
+  Uint64 ru_nvcsw;
+  Uint64 ru_nivcsw;
+};
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+  /**
+   * Get resource usage for calling thread
+   */
+  int Ndb_GetRUSage(ndb_rusage * dst);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif

=== modified file 'storage/ndb/include/portlib/NdbMutex.h'
--- a/storage/ndb/include/portlib/NdbMutex.h	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/include/portlib/NdbMutex.h	2011-09-27 17:28:13 +0000
@@ -29,11 +29,12 @@ extern "C" {
 #else
 #include <pthread.h>
 #endif
-#ifndef NDB_MUTEX_STAT
+#if !defined NDB_MUTEX_STAT && !defined NDB_MUTEX_DEADLOCK_DETECTOR
 typedef pthread_mutex_t NdbMutex;
 #else
 typedef struct {
   pthread_mutex_t mutex;
+#ifdef NDB_MUTEX_STAT
   unsigned cnt_lock;
   unsigned cnt_lock_contention;
   unsigned cnt_trylock_ok;
@@ -46,6 +47,10 @@ typedef struct {
   unsigned long long max_hold_time_ns;
   unsigned long long lock_start_time_ns;
   char name[32];
+#endif
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  struct ndb_mutex_state * m_mutex_state;
+#endif
 } NdbMutex;
 #endif
 

=== modified file 'storage/ndb/src/common/debugger/BlockNames.cpp'
--- a/storage/ndb/src/common/debugger/BlockNames.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/common/debugger/BlockNames.cpp	2011-10-07 08:07:21 +0000
@@ -40,6 +40,7 @@ const BlockName BlockNames[] = {
   ,{ "RESTORE", RESTORE }
   ,{ "DBINFO", DBINFO }
   ,{ "DBSPJ", DBSPJ }
+  ,{ "THRMAN", THRMAN }
 };
 
 const BlockNumber NO_OF_BLOCK_NAMES = sizeof(BlockNames) / sizeof(BlockName);

=== modified file 'storage/ndb/src/common/debugger/signaldata/ScanTab.cpp'
--- a/storage/ndb/src/common/debugger/signaldata/ScanTab.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/common/debugger/signaldata/ScanTab.cpp	2011-09-29 11:31:28 +0000
@@ -78,9 +78,9 @@ printSCANTABCONF(FILE * output, const Ui
   size_t op_count= requestInfo & (~ScanTabConf::EndOfData);
   if (op_count)
   {
-    fprintf(output, " Operation(s) [api tc rows len]:\n");
     if (len == ScanTabConf::SignalLength + 4 * op_count)
     {
+      fprintf(output, " Operation(s) [api tc rows len]:\n");
       ScanTabConf::OpData * op = (ScanTabConf::OpData*)
         (theData + ScanTabConf::SignalLength);
       for(size_t i = 0; i<op_count; i++)
@@ -91,9 +91,9 @@ printSCANTABCONF(FILE * output, const Ui
         op++;
       }
     }
-    else
+    else if (len == ScanTabConf::SignalLength + 3 * op_count)
     {
-      assert(len == ScanTabConf::SignalLength + 3 * op_count);
+      fprintf(output, " Operation(s) [api tc rows len]:\n");      
       for(size_t i = 0; i<op_count; i++)
       {
         ScanTabConf::OpData * op = (ScanTabConf::OpData*)
@@ -104,6 +104,12 @@ printSCANTABCONF(FILE * output, const Ui
                 ScanTabConf::getLength(op->rows));
       }
     }
+    else
+    {
+      // ScanTabConf::OpData stored in section 0 of signal.
+      assert(len == ScanTabConf::SignalLength);
+      fprintf(output, " Long signal. Cannot print operations.");
+    }
     fprintf(output, "\n");
   }
   return false;

=== modified file 'storage/ndb/src/common/portlib/CMakeLists.txt'
--- a/storage/ndb/src/common/portlib/CMakeLists.txt	2011-07-04 13:37:56 +0000
+++ b/storage/ndb/src/common/portlib/CMakeLists.txt	2011-10-07 08:07:21 +0000
@@ -27,7 +27,8 @@ ADD_CONVENIENCE_LIBRARY(ndbportlib
             NdbEnv.c NdbThread.c NdbHost.c NdbTCP.cpp
             NdbMem.c NdbConfig.c NdbTick.c NdbDir.cpp
             ndb_daemon.cc ${EXTRA_SRC}
-            NdbNuma.cpp)
+            NdbNuma.cpp NdbMutex_DeadlockDetector.cpp
+            NdbGetRUsage.cpp)
 TARGET_LINK_LIBRARIES(ndbportlib mysys ${LIBSOCKET})
 
 ADD_EXECUTABLE(NdbDir-t

=== modified file 'storage/ndb/src/common/portlib/Makefile.am'
--- a/storage/ndb/src/common/portlib/Makefile.am	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/common/portlib/Makefile.am	2011-10-07 08:07:21 +0000
@@ -21,7 +21,9 @@ libportlib_la_SOURCES = \
 	NdbCondition.c NdbMutex.c NdbTick.c \
 	NdbEnv.c NdbThread.c NdbHost.c NdbTCP.cpp	    \
 	ndb_daemon.cc NdbMem.c \
-	NdbConfig.c NdbDir.cpp ndb_socket.cpp
+	NdbConfig.c NdbDir.cpp ndb_socket.cpp \
+        NdbMutex_DeadlockDetector.cpp \
+        NdbGetRUsage.cpp
 
 include $(top_srcdir)/storage/ndb/config/common.mk.am
 include $(top_srcdir)/storage/ndb/config/type_util.mk.am

=== modified file 'storage/ndb/src/common/portlib/NdbCondition.c'
--- a/storage/ndb/src/common/portlib/NdbCondition.c	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/common/portlib/NdbCondition.c	2011-09-28 10:04:03 +0000
@@ -27,6 +27,10 @@ static int init = 0;
 static int clock_id = CLOCK_REALTIME;
 #endif
 
+#if defined NDB_MUTEX_STAT || defined NDB_MUTEX_DEADLOCK_DETECTOR
+#define NDB_MUTEX_STRUCT
+#endif
+
 void
 NdbCondition_initialize(int need_monotonic)
 {
@@ -129,7 +133,7 @@ NdbCondition_Wait(struct NdbCondition* p
   if (p_cond == NULL || p_mutex == NULL)
     return 1;
   
-#ifdef NDB_MUTEX_STAT
+#ifdef NDB_MUTEX_STRUCT
   result = pthread_cond_wait(&p_cond->cond, &p_mutex->mutex);
 #else
   result = pthread_cond_wait(&p_cond->cond, p_mutex);
@@ -187,17 +191,23 @@ NdbCondition_WaitTimeoutAbs(struct NdbCo
                             const struct timespec * abstime)
 {
 #ifdef NDB_WIN
+  /**
+   * mysys windows wrapper of pthread_cond_timedwait
+   *   does not have a const argument for the timespec
+   */
   struct timespec tmp = *abstime;
-  abstime = &tmp;
+  struct timespec * waitarg = &tmp;
+#else
+  const struct timespec * waitarg = abstime;
 #endif
 
   if (p_cond == NULL || p_mutex == NULL)
     return 1;
 
-#ifdef NDB_MUTEX_STAT
-  return pthread_cond_timedwait(&p_cond->cond, &p_mutex->mutex, abstime);
+#ifdef NDB_MUTEX_STRUCT
+  return pthread_cond_timedwait(&p_cond->cond, &p_mutex->mutex, waitarg);
 #else
-  return pthread_cond_timedwait(&p_cond->cond, p_mutex, abstime);
+  return pthread_cond_timedwait(&p_cond->cond, p_mutex, waitarg);
 #endif
 }
 

=== added file 'storage/ndb/src/common/portlib/NdbGetRUsage.cpp'
--- a/storage/ndb/src/common/portlib/NdbGetRUsage.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/portlib/NdbGetRUsage.cpp	2011-10-07 08:07:21 +0000
@@ -0,0 +1,65 @@
+/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+#include <NdbGetRUsage.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifndef _WIN32
+static
+Uint64
+micros(struct timeval val)
+{
+  return
+    (Uint64)val.tv_sec * (Uint64)1000000 + val.tv_usec;
+}
+#endif
+
+extern "C"
+int
+Ndb_GetRUSage(ndb_rusage* dst)
+{
+  int res = -1;
+#ifdef HAVE_GETRUSAGE
+  struct rusage tmp;
+#ifdef RUSAGE_THREAD
+  res = getrusage(RUSAGE_THREAD, &tmp);
+#elif defined RUSAGE_LWP
+  res = getrusage(RUSAGE_LWP, &tmp);
+#endif
+
+  if (res == 0)
+  {
+    dst->ru_utime = micros(tmp.ru_utime);
+    dst->ru_stime = micros(tmp.ru_stime);
+    dst->ru_minflt = tmp.ru_minflt;
+    dst->ru_majflt = tmp.ru_majflt;
+    dst->ru_nvcsw = tmp.ru_nvcsw;
+    dst->ru_nivcsw = tmp.ru_nivcsw;
+  }
+#endif
+
+  if (res != 0)
+  {
+    bzero(dst, sizeof(* dst));
+  }
+  return res;
+}

=== modified file 'storage/ndb/src/common/portlib/NdbMutex.c'
--- a/storage/ndb/src/common/portlib/NdbMutex.c	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/common/portlib/NdbMutex.c	2011-09-27 17:28:13 +0000
@@ -21,10 +21,34 @@
 #include <NdbMutex.h>
 #include <NdbMem.h>
 
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+#include "NdbMutex_DeadlockDetector.h"
+#endif
+
 #ifdef NDB_MUTEX_STAT
 static FILE * statout = 0;
 #endif
 
+#if defined NDB_MUTEX_STAT || defined NDB_MUTEX_DEADLOCK_DETECTOR
+#define NDB_MUTEX_STRUCT
+#endif
+
+void
+NdbMutex_SysInit()
+{
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  NdbMutex_DeadlockDetectorInit();
+#endif
+}
+
+void
+NdbMutex_SysEnd()
+{
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  NdbMutex_DeadlockDetectorEnd();
+#endif
+}
+
 NdbMutex* NdbMutex_Create()
 {
   return NdbMutex_CreateWithName(0);
@@ -59,12 +83,15 @@ int NdbMutex_InitWithName(NdbMutex* pNdb
   int result;
   pthread_mutex_t * p;
   DBUG_ENTER("NdbMutex_Init");
+  (void)name;
 
-#ifdef NDB_MUTEX_STAT
+#ifdef NDB_MUTEX_STRUCT
   bzero(pNdbMutex, sizeof(NdbMutex));
+  p = &pNdbMutex->mutex;
+
+#ifdef NDB_MUTEX_STAT
   pNdbMutex->min_lock_wait_time_ns = ~(Uint64)0;
   pNdbMutex->min_hold_time_ns = ~(Uint64)0;
-  p = &pNdbMutex->mutex;
   if (name == 0)
   {
     snprintf(pNdbMutex->name, sizeof(pNdbMutex->name), "%p",
@@ -79,9 +106,10 @@ int NdbMutex_InitWithName(NdbMutex* pNdb
   {
     statout = stdout;
   }
+#endif
+
 #else
   p = pNdbMutex;
-  (void)name;
 #endif
 
 #if defined(VM_TRACE) && \
@@ -99,6 +127,13 @@ int NdbMutex_InitWithName(NdbMutex* pNdb
 #else
   result = pthread_mutex_init(p, 0);
 #endif
+
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  if (result == 0)
+  {
+    ndb_mutex_created(pNdbMutex);
+  }
+#endif
   DBUG_RETURN(result);
 }
 
@@ -109,7 +144,11 @@ int NdbMutex_Destroy(NdbMutex* p_mutex)
   if (p_mutex == NULL)
     return -1;
 
-#ifdef NDB_MUTEX_STAT
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  ndb_mutex_destoyed(p_mutex);
+#endif
+
+#ifdef NDB_MUTEX_STRUCT
   result = pthread_mutex_destroy(&p_mutex->mutex);
 #else
   result = pthread_mutex_destroy(p_mutex);
@@ -201,11 +240,17 @@ int NdbMutex_Lock(NdbMutex* p_mutex)
     p_mutex->cnt_lock++;
     p_mutex->lock_start_time_ns = stop;
   }
+#elif defined NDB_MUTEX_STRUCT
+  result = pthread_mutex_lock(&p_mutex->mutex);
 #else
   result = pthread_mutex_lock(p_mutex);
 #endif
   assert(result == 0);
 
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  ndb_mutex_locked(p_mutex);
+#endif
+
   return result;
 }
 
@@ -234,11 +279,17 @@ int NdbMutex_Unlock(NdbMutex* p_mutex)
       dumpstat(p_mutex);
     }
   }
+#elif defined NDB_MUTEX_STRUCT
+  result = pthread_mutex_unlock(&p_mutex->mutex);
 #else
   result = pthread_mutex_unlock(p_mutex);
 #endif
   assert(result == 0);
 
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  ndb_mutex_unlocked(p_mutex);
+#endif
+
   return result;
 }
 
@@ -261,11 +312,21 @@ int NdbMutex_Trylock(NdbMutex* p_mutex)
   {
     __sync_fetch_and_add(&p_mutex->cnt_trylock_nok, 1);
   }
+#elif defined NDB_MUTEX_STRUCT
+  result = pthread_mutex_trylock(&p_mutex->mutex);
 #else
   result = pthread_mutex_trylock(p_mutex);
 #endif
   assert(result == 0 || result == EBUSY);
 
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  if (result == 0)
+  {
+    ndb_mutex_try_locked(p_mutex);
+  }
+#endif
+
+
   return result;
 }
 

=== added file 'storage/ndb/src/common/portlib/NdbMutex_DeadlockDetector.cpp'
--- a/storage/ndb/src/common/portlib/NdbMutex_DeadlockDetector.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/portlib/NdbMutex_DeadlockDetector.cpp	2011-09-27 17:28:13 +0000
@@ -0,0 +1,422 @@
+/*
+   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#include <NdbMutex.h>
+#include <NdbThread.h>
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+
+#include "NdbMutex_DeadlockDetector.h"
+
+#define NDB_THREAD_TLS_SELF NDB_THREAD_TLS_MAX
+
+static NdbMutex g_mutex_no_mutex; // We need a mutex to assign numbers to mutexes...
+static nmdd_mask g_mutex_no_mask = { 0, 0 };
+
+static unsigned alloc_mutex_no();
+static void release_mutex_no(unsigned no);
+
+static NdbMutex* get_element(struct nmdd_mutex_array *, unsigned i);
+static void add_mutex_to_array(struct nmdd_mutex_array *, NdbMutex*);
+static void remove_mutex_from_array(struct nmdd_mutex_array *, NdbMutex*);
+
+static void set_bit(struct nmdd_mask *, unsigned no);
+static void clear_bit(struct nmdd_mask* , unsigned no);
+static bool check_bit(const struct nmdd_mask* , unsigned no);
+
+static void release(struct nmdd_mutex_array *);
+static void release(struct nmdd_mask*);
+
+extern "C"
+void
+NdbMutex_DeadlockDetectorInit()
+{
+  NdbMutex_Init(&g_mutex_no_mutex);
+}
+
+extern "C"
+void
+NdbMutex_DeadlockDetectorEnd()
+{
+  release(&g_mutex_no_mask);
+}
+
+extern "C"
+void
+ndb_mutex_created(NdbMutex* p)
+{
+  p->m_mutex_state = (ndb_mutex_state*)malloc(sizeof(ndb_mutex_state));
+  bzero(p->m_mutex_state, sizeof(ndb_mutex_state));
+
+  /**
+   * Assign mutex no
+   */
+  p->m_mutex_state->m_no = alloc_mutex_no();
+}
+
+extern "C"
+void
+ndb_mutex_destoyed(NdbMutex* p)
+{
+  unsigned no = p->m_mutex_state->m_no;
+
+  /**
+   * In order to be able to reuse mutex_no,
+   *   we need to clear this no from all mutexes that has it in before map...
+   *   this is all mutexes in after map
+   */
+  for (unsigned i = 0; i<p->m_mutex_state->m_locked_after_list.m_used; i++)
+  {
+    NdbMutex * m = get_element(&p->m_mutex_state->m_locked_after_list, i);
+    assert(check_bit(&p->m_mutex_state->m_locked_after_mask, m->m_mutex_state->m_no));
+
+    /**
+     * And we need to lock it while doing this
+     */
+    NdbMutex_Lock(m);
+    assert(check_bit(&m->m_mutex_state->m_locked_before_mask, no));
+    clear_bit(&m->m_mutex_state->m_locked_before_mask, no);
+    remove_mutex_from_array(&m->m_mutex_state->m_locked_before_list, p);
+    NdbMutex_Unlock(m);
+  }
+
+  /**
+   * And we need to remove ourselfs from after list of mutexes in out before list
+   */
+  for (unsigned i = 0; i<p->m_mutex_state->m_locked_before_list.m_used; i++)
+  {
+    NdbMutex * m = get_element(&p->m_mutex_state->m_locked_before_list, i);
+    NdbMutex_Lock(m);
+    assert(check_bit(&m->m_mutex_state->m_locked_after_mask, no));
+    clear_bit(&m->m_mutex_state->m_locked_after_mask, no);
+    remove_mutex_from_array(&m->m_mutex_state->m_locked_after_list, p);
+    NdbMutex_Unlock(m);
+  }
+
+  release(&p->m_mutex_state->m_locked_before_mask);
+  release(&p->m_mutex_state->m_locked_before_list);
+  release(&p->m_mutex_state->m_locked_after_mask);
+  release(&p->m_mutex_state->m_locked_after_list);
+  release_mutex_no(no);
+}
+
+static
+ndb_mutex_thr_state*
+get_thr()
+{
+  void * p = NdbThread_GetTlsKey(NDB_THREAD_TLS_SELF);
+  return (ndb_mutex_thr_state*)p;
+}
+
+#define INC_SIZE 16
+
+static
+void
+add_lock_to_thread(ndb_mutex_thr_state * t, NdbMutex * m)
+{
+  add_mutex_to_array(&t->m_mutexes_locked, m);
+}
+
+static
+void
+add_lock_to_mutex_before_list(ndb_mutex_state * m1, NdbMutex * m2)
+{
+  assert(m1 != m2->m_mutex_state);
+  unsigned no = m2->m_mutex_state->m_no;
+  if (!check_bit(&m1->m_locked_before_mask, no))
+  {
+    set_bit(&m1->m_locked_before_mask, no);
+    add_mutex_to_array(&m1->m_locked_before_list, m2);
+  }
+}
+
+static
+void
+add_lock_to_mutex_after_list(ndb_mutex_state * m1, NdbMutex* m2)
+{
+  assert(m1 != m2->m_mutex_state);
+  unsigned no = m2->m_mutex_state->m_no;
+  if (!check_bit(&m1->m_locked_after_mask, no))
+  {
+    set_bit(&m1->m_locked_after_mask, no);
+    add_mutex_to_array(&m1->m_locked_after_list, m2);
+  }
+}
+
+extern "C"
+void
+ndb_mutex_locked(NdbMutex* p)
+{
+  ndb_mutex_state * m = p->m_mutex_state;
+  ndb_mutex_thr_state * thr = get_thr();
+  if (thr == 0)
+  {
+    /**
+     * These are threads not started with NdbThread_Create(...)
+     *   e.g mysql-server threads...ignore these for now
+     */
+    return;
+  }
+
+  for (unsigned i = 0; i < thr->m_mutexes_locked.m_used; i++)
+  {
+    /**
+     * We want to lock m
+     * Check that none of the mutex we curreny have locked
+     *   have m in their *before* list
+     */
+    NdbMutex * h = get_element(&thr->m_mutexes_locked, i);
+    if (check_bit(&h->m_mutex_state->m_locked_before_mask, m->m_no))
+    {
+      abort();
+    }
+
+    /**
+     * Add h to m's list of before-locks
+     */
+    add_lock_to_mutex_before_list(m, h);
+
+    /**
+     * Add m to h's list of after locks
+     */
+    add_lock_to_mutex_after_list(h->m_mutex_state, p);
+  }
+
+  add_lock_to_thread(thr, p);
+}
+
+extern "C"
+void
+ndb_mutex_unlocked(NdbMutex* m)
+{
+  ndb_mutex_thr_state * thr = get_thr();
+  if (thr == 0)
+  {
+    /**
+     * These are threads not started with NdbThread_Create(...)
+     *   e.g mysql-server threads...ignore these for now
+     */
+    return;
+  }
+  unsigned pos = thr->m_mutexes_locked.m_used;
+  assert(pos > 0);
+  assert(get_element(&thr->m_mutexes_locked, pos-1) == m);
+  thr->m_mutexes_locked.m_used --;
+}
+
+extern "C"
+void
+ndb_mutex_try_locked(NdbMutex* p)
+{
+
+}
+
+extern "C"
+void
+ndb_mutex_thread_init(struct ndb_mutex_thr_state* p)
+{
+  bzero(p, sizeof(* p));
+  NdbThread_SetTlsKey(NDB_THREAD_TLS_SELF, p);
+}
+
+extern "C"
+void
+ndb_mutex_thread_exit()
+{
+  ndb_mutex_thr_state * thr = get_thr();
+  if (thr == 0)
+  {
+    /**
+     * These are threads not started with NdbThread_Create(...)
+     *   e.g mysql-server threads...ignore these for now
+     */
+    return;
+  }
+  release(&thr->m_mutexes_locked);
+}
+
+/**
+ * util
+ */
+static
+void
+set_bit(nmdd_mask * mask, unsigned no)
+{
+  unsigned byte_no = no / 8;
+  unsigned bit_no = no & 7;
+  if (byte_no >= mask->m_len)
+  {
+    unsigned new_len = mask->m_len + INC_SIZE;
+    if (byte_no >= new_len)
+    {
+      new_len = byte_no + 1;
+    }
+    unsigned char * new_arr = (unsigned char*)malloc(new_len);
+    bzero(new_arr, new_len);
+    if (mask->m_len != 0)
+    {
+      memcpy(new_arr, mask->m_mask, mask->m_len);
+      free(mask->m_mask);
+    }
+    mask->m_len = new_len;
+    mask->m_mask = new_arr;
+  }
+
+  mask->m_mask[byte_no] |= (1 << bit_no);
+}
+
+static
+void
+clear_bit(nmdd_mask * mask, unsigned no)
+{
+  unsigned byte_no = no / 8;
+  unsigned bit_no = no & 7;
+  if (byte_no >= mask->m_len)
+  {
+    return;
+  }
+
+  mask->m_mask[byte_no] &= ~(unsigned char)(1 << bit_no);
+}
+
+static
+bool
+check_bit(const nmdd_mask * mask, unsigned no)
+{
+  unsigned byte_no = no / 8;
+  unsigned bit_no = no & 7;
+  if (byte_no >= mask->m_len)
+  {
+    return false;
+  }
+
+  return (mask->m_mask[byte_no] & (1 << bit_no)) != 0;
+}
+
+static
+void
+release(nmdd_mask * mask)
+{
+  if (mask->m_len != 0)
+  {
+    free(mask->m_mask);
+  }
+}
+
+static
+NdbMutex*
+get_element(nmdd_mutex_array* arr, unsigned i)
+{
+  assert(i < arr->m_used);
+  return arr->m_array[i];
+}
+
+static
+void
+add_mutex_to_array(nmdd_mutex_array* arr, NdbMutex* m)
+{
+  unsigned pos = arr->m_used;
+  if (arr->m_used == arr->m_array_len)
+  {
+    unsigned new_len = arr->m_array_len + INC_SIZE;
+    NdbMutex** new_arr = (NdbMutex**)malloc(new_len * sizeof(NdbMutex*));
+    if (arr->m_array_len != 0)
+    {
+      memcpy(new_arr, arr->m_array, arr->m_array_len * sizeof(NdbMutex*));
+      free(arr->m_array);
+    }
+    arr->m_array = new_arr;
+    arr->m_array_len = new_len;
+  }
+  for (unsigned i = 0; i<arr->m_used; i++)
+    assert(arr->m_array[i] != m);
+
+  arr->m_array[pos] = m;
+  arr->m_used++;
+}
+
+static
+void
+remove_mutex_from_array(nmdd_mutex_array* arr, NdbMutex* m)
+{
+  for (unsigned i = 0; i < arr->m_used; i++)
+  {
+    unsigned idx = arr->m_used - i - 1;
+    if (arr->m_array[idx] == m)
+    {
+      memmove(arr->m_array+idx,
+              arr->m_array + idx + 1,
+              i * sizeof(NdbMutex*));
+      arr->m_used--;
+      return;
+    }
+  }
+  assert(false);
+}
+
+static
+void
+release(nmdd_mutex_array* arr)
+{
+  if (arr->m_array_len)
+  {
+    free(arr->m_array);
+  }
+}
+
+static
+unsigned
+ff(unsigned char b)
+{
+  for (unsigned i = 0; i<8; i++)
+    if ((b & (1 << i)) == 0)
+      return i;
+  assert(false);
+}
+
+static
+unsigned
+alloc_mutex_no()
+{
+  Guard g(&g_mutex_no_mutex);
+  unsigned no = 0;
+
+  for (unsigned i = 0; i < g_mutex_no_mask.m_len; i++)
+  {
+    if (g_mutex_no_mask.m_mask[i] != 255)
+    {
+      no = (8 * i) + ff(g_mutex_no_mask.m_mask[i]);
+      goto found;
+    }
+  }
+
+  no = 8 * g_mutex_no_mask.m_len;
+found:
+  set_bit(&g_mutex_no_mask, no);
+  assert(check_bit(&g_mutex_no_mask, no));
+  return no;
+}
+
+static
+void
+release_mutex_no(unsigned no)
+{
+  Guard g(&g_mutex_no_mutex);
+  assert(check_bit(&g_mutex_no_mask, no));
+  clear_bit(&g_mutex_no_mask, no);
+}
+
+#endif

=== added file 'storage/ndb/src/common/portlib/NdbMutex_DeadlockDetector.h'
--- a/storage/ndb/src/common/portlib/NdbMutex_DeadlockDetector.h	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/portlib/NdbMutex_DeadlockDetector.h	2011-09-27 17:28:13 +0000
@@ -0,0 +1,73 @@
+/*
+   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#ifndef NDB_MUTEX_DEADLOCK_DETECTOR_H
+#define NDB_MUTEX_DEADLOCK_DETECTOR_H
+
+#include <NdbMutex.h>
+
+struct nmdd_mask
+{
+  unsigned char * m_mask;
+  unsigned m_len;
+};
+
+struct nmdd_mutex_array
+{
+  NdbMutex ** m_array;
+  unsigned m_used;
+  unsigned m_array_len;
+};
+
+struct ndb_mutex_state
+{
+  struct nmdd_mask m_locked_before_mask; /* mutexes held when locking this mutex */
+  struct nmdd_mutex_array m_locked_before_list; /* mutexes held when locking this mutex */
+
+  struct nmdd_mutex_array m_locked_after_list; /* mutexes locked when holding this mutex*/
+  struct nmdd_mask m_locked_after_mask;        /* mask (for quick check) */
+
+  unsigned m_no; /* my mutex "id" (for access in masks) */
+};
+
+struct ndb_mutex_thr_state
+{
+  struct nmdd_mutex_array m_mutexes_locked;
+};
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+  void NdbMutex_DeadlockDetectorInit();
+  void NdbMutex_DeadlockDetectorEnd();
+
+  void ndb_mutex_created(NdbMutex*);
+  void ndb_mutex_destoyed(NdbMutex*);
+  void ndb_mutex_locked(NdbMutex*);
+  void ndb_mutex_unlocked(NdbMutex*);
+  void ndb_mutex_try_locked(NdbMutex*);
+
+  void ndb_mutex_thread_init(struct ndb_mutex_thr_state*);
+  void ndb_mutex_thread_exit();
+
+#ifdef	__cplusplus
+}
+#endif
+
+
+#endif

=== modified file 'storage/ndb/src/common/portlib/NdbThread.c'
--- a/storage/ndb/src/common/portlib/NdbThread.c	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/common/portlib/NdbThread.c	2011-10-07 07:37:47 +0000
@@ -38,6 +38,10 @@
 #include <sys/procset.h>
 #endif
 
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+#include "NdbMutex_DeadlockDetector.h"
+#endif
+
 static int g_min_prio = 0;
 static int g_max_prio = 0;
 static int g_prio = 0;
@@ -65,6 +69,9 @@ struct NdbThread
   char thread_name[16];
   NDB_THREAD_FUNC * func;
   void * object;
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  struct ndb_mutex_thr_state m_mutex_thr_state;
+#endif
 };
 
 #ifdef NDB_SHM_TRANSPORTER
@@ -141,6 +148,11 @@ ndb_thread_wrapper(void* _ss){
       void *ret;
       struct NdbThread * ss = (struct NdbThread *)_ss;
       settid(ss);
+
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+      ndb_mutex_thread_init(&ss->m_mutex_thr_state);
+#endif
+
       NdbMutex_Lock(g_ndb_thread_mutex);
       ss->inited = 1;
       NdbCondition_Signal(g_ndb_thread_condition);
@@ -154,6 +166,7 @@ ndb_thread_wrapper(void* _ss){
   }
 }
 
+static struct NdbThread* g_main_thread = 0;
 
 struct NdbThread*
 NdbThread_CreateObject(const char * name)
@@ -161,6 +174,16 @@ NdbThread_CreateObject(const char * name
   struct NdbThread* tmpThread;
   DBUG_ENTER("NdbThread_Create");
 
+  if (g_main_thread != 0)
+  {
+    settid(g_main_thread);
+    if (name)
+    {
+      strnmov(g_main_thread->thread_name, name, sizeof(tmpThread->thread_name));
+    }
+    DBUG_RETURN(g_main_thread);
+  }
+
   tmpThread = (struct NdbThread*)NdbMem_Allocate(sizeof(struct NdbThread));
   if (tmpThread == NULL)
     DBUG_RETURN(NULL);
@@ -183,7 +206,12 @@ NdbThread_CreateObject(const char * name
   settid(tmpThread);
   tmpThread->inited = 1;
 
-  return tmpThread;
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  ndb_mutex_thread_init(&tmpThread->m_mutex_thr_state);
+#endif
+
+  g_main_thread = tmpThread;
+  DBUG_RETURN(tmpThread);
 }
 
 struct NdbThread*
@@ -239,7 +267,7 @@ NdbThread_Create(NDB_THREAD_FUNC *p_thre
   tmpThread->object= p_thread_arg;
 
   NdbMutex_Lock(g_ndb_thread_mutex);
-  result = pthread_create(&tmpThread->thread, 
+  result = pthread_create(&tmpThread->thread,
 			  &thread_attr,
   		          ndb_thread_wrapper,
   		          tmpThread);
@@ -250,7 +278,7 @@ NdbThread_Create(NDB_THREAD_FUNC *p_thre
   {
     NdbMem_Free((char *)tmpThread);
     NdbMutex_Unlock(g_ndb_thread_mutex);
-    return 0;
+    DBUG_RETURN(0);
   }
 
   if (thread_prio == NDB_THREAD_PRIO_HIGH && f_high_prio_set)
@@ -471,7 +499,11 @@ NdbThread_LockCPU(struct NdbThread* pThr
   return error_no;
 }
 
+#ifndef NDB_MUTEX_DEADLOCK_DETECTOR
 static pthread_key(void*, tls_keys[NDB_THREAD_TLS_MAX]);
+#else
+static pthread_key(void*, tls_keys[NDB_THREAD_TLS_MAX + 1]);
+#endif
 
 void *NdbThread_GetTlsKey(NDB_THREAD_TLS key)
 {
@@ -490,6 +522,10 @@ NdbThread_Init()
   g_ndb_thread_condition = NdbCondition_Create();
   pthread_key_create(&(tls_keys[NDB_THREAD_TLS_JAM]), NULL);
   pthread_key_create(&(tls_keys[NDB_THREAD_TLS_THREAD]), NULL);
+#ifdef NDB_MUTEX_DEADLOCK_DETECTOR
+  pthread_key_create(&(tls_keys[NDB_THREAD_TLS_MAX]), NULL);
+#endif
+  NdbThread_CreateObject(0);
   return 0;
 }
 

=== modified file 'storage/ndb/src/common/util/ndb_init.cpp'
--- a/storage/ndb/src/common/util/ndb_init.cpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/common/util/ndb_init.cpp	2011-09-27 17:28:13 +0000
@@ -32,6 +32,8 @@ int g_ndb_init_need_monotonic = 0;
 
 static int ndb_init_called = 0;
 
+extern "C" void NdbMutex_SysInit();
+extern "C" void NdbMutex_SysEnd();
 extern "C" void NdbCondition_initialize(int need_monotonic);
 extern "C" void NdbTick_Init(int need_monotonic);
 extern "C" int NdbThread_Init();
@@ -45,6 +47,7 @@ void
 ndb_init_internal()
 {
   NdbOut_Init();
+  NdbMutex_SysInit();
   if (!g_ndb_connection_mutex)
     g_ndb_connection_mutex = NdbMutex_Create();
   if (!g_eventLogger)
@@ -88,7 +91,6 @@ ndb_init()
 void
 ndb_end_internal()
 {
-  NdbThread_End();
   if (g_ndb_connection_mutex) 
   {
     NdbMutex_Destroy(g_ndb_connection_mutex);
@@ -96,6 +98,9 @@ ndb_end_internal()
   }
   if (g_eventLogger)
     destroy_event_logger(&g_eventLogger);
+
+  NdbThread_End();
+  NdbMutex_SysEnd();
 }
 
 void

=== modified file 'storage/ndb/src/kernel/SimBlockList.cpp'
--- a/storage/ndb/src/kernel/SimBlockList.cpp	2011-09-23 09:13:22 +0000
+++ b/storage/ndb/src/kernel/SimBlockList.cpp	2011-10-07 08:07:21 +0000
@@ -51,6 +51,7 @@
 #include <PgmanProxy.hpp>
 #include <DbtcProxy.hpp>
 #include <DbspjProxy.hpp>
+#include <thrman.hpp>
 #include <mt.hpp>
 
 #ifndef VM_TRACE
@@ -89,6 +90,10 @@ void * operator new (size_t sz, SIMBLOCK
 void
 SimBlockList::load(EmulatorData& data){
   noOfBlocks = NO_OF_BLOCKS;
+#define THR 1
+#ifndef THR
+  noOfBlocks--;
+#endif
   theList = new SimulatedBlock * [noOfBlocks];
   if (!theList)
   {
@@ -160,7 +165,14 @@ SimBlockList::load(EmulatorData& data){
     theList[20]  = NEW_BLOCK(Dbspj)(ctx);
   else
     theList[20]  = NEW_BLOCK(DbspjProxy)(ctx);
-  assert(NO_OF_BLOCKS == 21);
+#ifdef THR
+  if (NdbIsMultiThreaded() == false)
+    theList[21] = NEW_BLOCK(Thrman)(ctx);
+  else
+    theList[21] = NEW_BLOCK(ThrmanProxy)(ctx);
+
+  assert(NO_OF_BLOCKS == 22);
+#endif
 
   // Check that all blocks could be created
   for (int i = 0; i < noOfBlocks; i++)
@@ -174,10 +186,10 @@ SimBlockList::load(EmulatorData& data){
 
   if (globalData.isNdbMt)
   {
-    add_main_thr_map();
+    mt_init_thr_map();
     for (int i = 0; i < noOfBlocks; i++)
       theList[i]->loadWorkers();
-    finalize_thr_map();
+    mt_finalize_thr_map();
   }
 }
 

=== modified file 'storage/ndb/src/kernel/blocks/CMakeLists.txt'
--- a/storage/ndb/src/kernel/blocks/CMakeLists.txt	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/blocks/CMakeLists.txt	2011-10-07 08:07:21 +0000
@@ -72,7 +72,8 @@ ADD_LIBRARY(ndbblocks STATIC
     dblqh/DblqhCommon.cpp
     PgmanProxy.cpp
     dbtup/DbtupClient.cpp
-    ${EXTRA_SRC})
+    ${EXTRA_SRC}
+    thrman.cpp)
 
 MYSQL_ADD_EXECUTABLE(ndb_print_file
   print_file.cpp

=== modified file 'storage/ndb/src/kernel/blocks/LocalProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/LocalProxy.cpp	2011-09-15 20:21:59 +0000
+++ b/storage/ndb/src/kernel/blocks/LocalProxy.cpp	2011-10-07 08:07:21 +0000
@@ -22,8 +22,6 @@ LocalProxy::LocalProxy(BlockNumber block
   BLOCK_CONSTRUCTOR(LocalProxy);
 
   ndbrequire(instance() == 0); // this is main block
-  c_lqhWorkers = 0;
-  c_extraWorkers = 0; // sub-class constructor can set
   c_workers = 0;
   Uint32 i;
   for (i = 0; i < MaxWorkers; i++)
@@ -187,13 +185,13 @@ LocalProxy::lastReply(const SsSequential
 }
 
 void
-LocalProxy::sendREQ(Signal* signal, SsParallel& ss)
+LocalProxy::sendREQ(Signal* signal, SsParallel& ss, bool skipLast)
 {
   ndbrequire(ss.m_sendREQ != 0);
 
   ss.m_workerMask.clear();
   ss.m_worker = 0;
-  const Uint32 count = ss.m_extraLast ? c_lqhWorkers : c_workers;
+  const Uint32 count = skipLast ? c_workers - 1 : c_workers;
   SectionHandle handle(this);
   restoreHandle(handle, ss);
   while (ss.m_worker < count) {
@@ -266,21 +264,6 @@ LocalProxy::lastReply(const SsParallel&
   return ss.m_workerMask.isclear();
 }
 
-bool
-LocalProxy::lastExtra(Signal* signal, SsParallel& ss)
-{
-  SectionHandle handle(this);
-  if (c_lqhWorkers + ss.m_extraSent < c_workers) {
-    jam();
-    ss.m_worker = c_lqhWorkers + ss.m_extraSent;
-    ss.m_workerMask.set(ss.m_worker);
-    (this->*ss.m_sendREQ)(signal, ss.m_ssId, &handle);
-    ss.m_extraSent++;
-    return false;
-  }
-  return true;
-}
-
 // used in "reverse" proxying (start with worker REQs)
 void
 LocalProxy::setMask(SsParallel& ss)
@@ -301,11 +284,9 @@ LocalProxy::setMask(SsParallel& ss, cons
 void
 LocalProxy::loadWorkers()
 {
-  c_lqhWorkers = getLqhWorkers();
-  c_workers = c_lqhWorkers + c_extraWorkers;
-
-  Uint32 i;
-  for (i = 0; i < c_workers; i++) {
+  c_workers = mt_get_instance_count(number());
+  for (Uint32 i = 0; i < c_workers; i++)
+  {
     jam();
     Uint32 instanceNo = workerInstance(i);
 
@@ -314,31 +295,7 @@ LocalProxy::loadWorkers()
     ndbrequire(this->getInstance(instanceNo) == worker);
     c_worker[i] = worker;
 
-    if (i < c_lqhWorkers) {
-      add_lqh_worker_thr_map(number(), instanceNo);
-    } else {
-      add_extra_worker_thr_map(number(), instanceNo);
-    }
-  }
-}
-
-void
-LocalProxy::tc_loadWorkers()
-{
-  c_workers = globalData.ndbMtTcThreads;
-  c_lqhWorkers = globalData.ndbMtTcThreads;
-  c_extraWorkers = 0;
-
-  Uint32 i;
-  for (i = 0; i < c_workers; i++) {
-    jam();
-    Uint32 instanceNo = workerInstance(i);
-
-    SimulatedBlock* worker = newWorker(instanceNo);
-    ndbrequire(worker->instance() == instanceNo);
-    ndbrequire(this->getInstance(instanceNo) == worker);
-    c_worker[i] = worker;
-    add_tc_worker_thr_map(number(), instanceNo);
+    mt_add_thr_map(number(), instanceNo);
   }
 }
 

=== modified file 'storage/ndb/src/kernel/blocks/LocalProxy.hpp'
--- a/storage/ndb/src/kernel/blocks/LocalProxy.hpp	2011-09-15 20:21:59 +0000
+++ b/storage/ndb/src/kernel/blocks/LocalProxy.hpp	2011-10-07 08:07:21 +0000
@@ -56,19 +56,14 @@ public:
   BLOCK_DEFINES(LocalProxy);
 
 protected:
-  enum { MaxLqhWorkers = MAX_NDBMT_LQH_WORKERS };
-  enum { MaxExtraWorkers = 1 };
-  enum { MaxWorkers = MaxLqhWorkers + MaxExtraWorkers };
+  enum { MaxWorkers = SimulatedBlock::MaxInstances };
   typedef Bitmask<(MaxWorkers+31)/32> WorkerMask;
-  Uint32 c_lqhWorkers;
-  Uint32 c_extraWorkers;
   Uint32 c_workers;
   // no gaps - extra worker has index c_lqhWorkers (not MaxLqhWorkers)
   SimulatedBlock* c_worker[MaxWorkers];
 
   virtual SimulatedBlock* newWorker(Uint32 instanceNo) = 0;
   virtual void loadWorkers();
-  virtual void tc_loadWorkers();
 
   // get worker block by index (not by instance)
 
@@ -78,43 +73,22 @@ protected:
     return c_worker[i];
   }
 
-  SimulatedBlock* extraWorkerBlock() {
-    return workerBlock(c_lqhWorkers);
-  }
-
   // get worker block reference by index (not by instance)
 
   BlockReference workerRef(Uint32 i) {
     return numberToRef(number(), workerInstance(i), getOwnNodeId());
   }
 
-  BlockReference extraWorkerRef() {
-    ndbrequire(c_workers == c_lqhWorkers + 1);
-    Uint32 i = c_lqhWorkers;
-    return workerRef(i);
-  }
-
   // convert between worker index and worker instance
 
   Uint32 workerInstance(Uint32 i) const {
     ndbrequire(i < c_workers);
-    Uint32 ino;
-    if (i < c_lqhWorkers)
-      ino = 1 + i;
-    else
-      ino = 1 + MaxLqhWorkers;
-    return ino;
+    return i + 1;
   }
 
   Uint32 workerIndex(Uint32 ino) const {
     ndbrequire(ino != 0);
-    Uint32 i;
-    if (ino != 1 + MaxLqhWorkers)
-      i = ino - 1;
-    else
-      i = c_lqhWorkers;
-    ndbrequire(i < c_workers);
-    return i;
+    return ino - 1;
   }
 
   // support routines and classes ("Ss" = signal state)
@@ -161,14 +135,10 @@ protected:
   // run workers in parallel
   struct SsParallel : SsCommon {
     WorkerMask m_workerMask;
-    bool m_extraLast;   // run extra after LQH workers
-    Uint32 m_extraSent;
     SsParallel() {
-      m_extraLast = false;
-      m_extraSent = 0;
     }
   };
-  void sendREQ(Signal*, SsParallel& ss);
+  void sendREQ(Signal*, SsParallel& ss, bool skipLast = false);
   void recvCONF(Signal*, SsParallel& ss);
   void recvREF(Signal*, SsParallel& ss, Uint32 error);
   // for use in sendREQ

=== modified file 'storage/ndb/src/kernel/blocks/Makefile.am'
--- a/storage/ndb/src/kernel/blocks/Makefile.am	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/blocks/Makefile.am	2011-10-07 08:07:21 +0000
@@ -68,7 +68,8 @@ libblocks_a_SOURCES = tsman.cpp lgman.cp
   dblqh/DblqhCommon.cpp \
   PgmanProxy.cpp \
   dbtup/DbtupClient.cpp \
-  dbtc/DbtcProxy.cpp
+  dbtc/DbtcProxy.cpp \
+  thrman.cpp
 
 ndbtools_PROGRAMS = ndb_print_file
 ndb_print_file_SOURCES = print_file.cpp diskpage.cpp dbtup/tuppage.cpp

=== modified file 'storage/ndb/src/kernel/blocks/PgmanProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/PgmanProxy.cpp	2011-02-02 00:40:07 +0000
+++ b/storage/ndb/src/kernel/blocks/PgmanProxy.cpp	2011-10-07 08:07:21 +0000
@@ -20,8 +20,6 @@
 PgmanProxy::PgmanProxy(Block_context& ctx) :
   LocalProxy(PGMAN, ctx)
 {
-  c_extraWorkers = 1;
-
   // GSN_LCP_FRAG_ORD
   addRecSignal(GSN_LCP_FRAG_ORD, &PgmanProxy::execLCP_FRAG_ORD);
 
@@ -88,11 +86,15 @@ PgmanProxy::execEND_LCP_REQ(Signal* sign
     req->senderRef = reference();
     req->requestType = ReleasePagesReq::RT_RELEASE_UNLOCKED;
     req->requestData = 0;
-    sendSignal(extraWorkerRef(), GSN_RELEASE_PAGES_REQ,
+    // Extra worker
+    sendSignal(workerRef(c_workers - 1), GSN_RELEASE_PAGES_REQ,
                signal, ReleasePagesReq::SignalLength, JBB);
     return;
   }
-  sendREQ(signal, ss);
+  /**
+   * Send to extra PGMAN *after* all other PGMAN has completed
+   */
+  sendREQ(signal, ss, /* skip last */ true);
 }
 
 void
@@ -137,8 +139,14 @@ PgmanProxy::sendEND_LCP_CONF(Signal* sig
     return;
   }
 
-  if (!lastExtra(signal, ss)) {
+  if (!ss.m_extraLast)
+  {
     jam();
+    ss.m_extraLast = true;
+    ss.m_worker = c_workers - 1; // send to last PGMAN
+    ss.m_workerMask.set(ss.m_worker);
+    SectionHandle handle(this);
+    (this->*ss.m_sendREQ)(signal, ss.m_ssId, &handle);
     return;
   }
 
@@ -170,7 +178,7 @@ PgmanProxy::get_page(Page_cache_client&
 {
   ndbrequire(blockToInstance(caller.m_block) == 0);
   SimulatedBlock* block = globalData.getBlock(caller.m_block);
-  Pgman* worker = (Pgman*)extraWorkerBlock();
+  Pgman* worker = (Pgman*)workerBlock(c_workers - 1); // extraWorkerBlock();
   Page_cache_client pgman(block, worker);
   int ret = pgman.get_page(signal, req, flags);
   caller.m_ptr = pgman.m_ptr;
@@ -183,7 +191,7 @@ PgmanProxy::update_lsn(Page_cache_client
 {
   ndbrequire(blockToInstance(caller.m_block) == 0);
   SimulatedBlock* block = globalData.getBlock(caller.m_block);
-  Pgman* worker = (Pgman*)extraWorkerBlock();
+  Pgman* worker = (Pgman*)workerBlock(c_workers - 1); // extraWorkerBlock();
   Page_cache_client pgman(block, worker);
   pgman.update_lsn(key, lsn);
 }
@@ -194,7 +202,7 @@ PgmanProxy::drop_page(Page_cache_client&
 {
   ndbrequire(blockToInstance(caller.m_block) == 0);
   SimulatedBlock* block = globalData.getBlock(caller.m_block);
-  Pgman* worker = (Pgman*)extraWorkerBlock();
+  Pgman* worker = (Pgman*)workerBlock(c_workers - 1); // extraWorkerBlock();
   Page_cache_client pgman(block, worker);
   int ret = pgman.drop_page(key, page_id);
   return ret;
@@ -209,10 +217,10 @@ PgmanProxy::drop_page(Page_cache_client&
 Uint32
 PgmanProxy::create_data_file(Signal* signal)
 {
-  Pgman* worker = (Pgman*)extraWorkerBlock();
+  Pgman* worker = (Pgman*)workerBlock(c_workers - 1); // extraWorkerBlock();
   Uint32 ret = worker->create_data_file();
   Uint32 i;
-  for (i = 0; i < c_lqhWorkers; i++) {
+  for (i = 0; i < c_workers - 1; i++) {
     jam();
     send_data_file_ord(signal, i, ret,
                        DataFileOrd::CreateDataFile);
@@ -223,10 +231,10 @@ PgmanProxy::create_data_file(Signal* sig
 Uint32
 PgmanProxy::alloc_data_file(Signal* signal, Uint32 file_no)
 {
-  Pgman* worker = (Pgman*)extraWorkerBlock();
+  Pgman* worker = (Pgman*)workerBlock(c_workers - 1); // extraWorkerBlock();
   Uint32 ret = worker->alloc_data_file(file_no);
   Uint32 i;
-  for (i = 0; i < c_lqhWorkers; i++) {
+  for (i = 0; i < c_workers - 1; i++) {
     jam();
     send_data_file_ord(signal, i, ret,
                        DataFileOrd::AllocDataFile, file_no);
@@ -237,10 +245,10 @@ PgmanProxy::alloc_data_file(Signal* sign
 void
 PgmanProxy::map_file_no(Signal* signal, Uint32 file_no, Uint32 fd)
 {
-  Pgman* worker = (Pgman*)extraWorkerBlock();
+  Pgman* worker = (Pgman*)workerBlock(c_workers - 1); // extraWorkerBlock();
   worker->map_file_no(file_no, fd);
   Uint32 i;
-  for (i = 0; i < c_lqhWorkers; i++) {
+  for (i = 0; i < c_workers - 1; i++) {
     jam();
     send_data_file_ord(signal, i, ~(Uint32)0,
                        DataFileOrd::MapFileNo, file_no, fd);
@@ -250,10 +258,10 @@ PgmanProxy::map_file_no(Signal* signal,
 void
 PgmanProxy::free_data_file(Signal* signal, Uint32 file_no, Uint32 fd)
 {
-  Pgman* worker = (Pgman*)extraWorkerBlock();
+  Pgman* worker = (Pgman*)workerBlock(c_workers - 1); // extraWorkerBlock();
   worker->free_data_file(file_no, fd);
   Uint32 i;
-  for (i = 0; i < c_lqhWorkers; i++) {
+  for (i = 0; i < c_workers - 1; i++) {
     jam();
     send_data_file_ord(signal, i, ~(Uint32)0,
                        DataFileOrd::FreeDataFile, file_no, fd);

=== modified file 'storage/ndb/src/kernel/blocks/PgmanProxy.hpp'
--- a/storage/ndb/src/kernel/blocks/PgmanProxy.hpp	2011-02-02 00:40:07 +0000
+++ b/storage/ndb/src/kernel/blocks/PgmanProxy.hpp	2011-10-07 08:07:21 +0000
@@ -62,11 +62,12 @@ protected:
      */
     static const char* name() { return "END_LCP_REQ"; }
     EndLcpReq m_req;
+    bool m_extraLast;
     Ss_END_LCP_REQ() {
       m_sendREQ = (SsFUNCREQ)&PgmanProxy::sendEND_LCP_REQ;
       m_sendCONF = (SsFUNCREP)&PgmanProxy::sendEND_LCP_CONF;
       // extra worker (for extent pages) must run after others
-      m_extraLast = true;
+      m_extraLast = false;
     }
     enum { poolSize = 1 };
     static SsPool<Ss_END_LCP_REQ>& pool(LocalProxy* proxy) {

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2011-07-04 13:37:56 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp	2011-10-07 13:15:08 +0000
@@ -322,120 +322,12 @@ void Dbdict::execDBINFO_SCANREQ(Signal *
           CFG_DB_NO_ORDERED_INDEXES,
           CFG_DB_NO_UNIQUE_HASH_INDEXES,
           CFG_DB_NO_TRIGGERS }},
-      { "Schema Operation",
-        c_schemaOpPool.getUsed(),
-        c_schemaOpPool.getSize(),
-        c_schemaOpPool.getEntrySize(),
-        c_schemaOpPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Schema Transaction",
-        c_schemaTransPool.getUsed(),
-        c_schemaTransPool.getSize(),
-        c_schemaTransPool.getEntrySize(),
-        c_schemaTransPool.getUsedHi(),
-        { 0,0,0,0 }},
       { "Transaction Handle",
         c_txHandlePool.getUsed(),
         c_txHandlePool.getSize(),
         c_txHandlePool.getEntrySize(),
         c_txHandlePool.getUsedHi(),
         { 0,0,0,0 }},
-      { "Create Table Record",
-        c_createTableRecPool.getUsed(),
-        c_createTableRecPool.getSize(),
-        c_createTableRecPool.getEntrySize(),
-        c_createTableRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Drop Table Record",
-        c_dropTableRecPool.getUsed(),
-        c_dropTableRecPool.getSize(),
-        c_dropTableRecPool.getEntrySize(),
-        c_dropTableRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Alter Table Record",
-        c_alterTableRecPool.getUsed(),
-        c_alterTableRecPool.getSize(),
-        c_alterTableRecPool.getEntrySize(),
-        c_alterTableRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Create Index Record",
-        c_createIndexRecPool.getUsed(),
-        c_createIndexRecPool.getSize(),
-        c_createIndexRecPool.getEntrySize(),
-        c_createIndexRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Drop Index Record",
-        c_dropIndexRecPool.getUsed(),
-        c_dropIndexRecPool.getSize(),
-        c_dropIndexRecPool.getEntrySize(),
-        c_dropIndexRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Alter Index Record",
-        c_alterIndexRecPool.getUsed(),
-        c_alterIndexRecPool.getSize(),
-        c_alterIndexRecPool.getEntrySize(),
-        c_alterIndexRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Build Index Record",
-        c_buildIndexRecPool.getUsed(),
-        c_buildIndexRecPool.getSize(),
-        c_buildIndexRecPool.getEntrySize(),
-        c_buildIndexRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Index Stat Record",
-        c_indexStatRecPool.getUsed(),
-        c_indexStatRecPool.getSize(),
-        c_indexStatRecPool.getEntrySize(),
-        c_indexStatRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Create Hash Map Record",
-        c_createHashMapRecPool.getUsed(),
-        c_createHashMapRecPool.getSize(),
-        c_createHashMapRecPool.getEntrySize(),
-        c_createHashMapRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Copy Data Record",
-        c_copyDataRecPool.getUsed(),
-        c_copyDataRecPool.getSize(),
-        c_copyDataRecPool.getEntrySize(),
-        c_copyDataRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Create Trigger Record",
-        c_createTriggerRecPool.getUsed(),
-        c_createTriggerRecPool.getSize(),
-        c_createTriggerRecPool.getEntrySize(),
-        c_createTriggerRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Drop Trigger Record",
-        c_dropTriggerRecPool.getUsed(),
-        c_dropTriggerRecPool.getSize(),
-        c_dropTriggerRecPool.getEntrySize(),
-        c_dropTriggerRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Create Filegroup Record",
-        c_createFilegroupRecPool.getUsed(),
-        c_createFilegroupRecPool.getSize(),
-        c_createFilegroupRecPool.getEntrySize(),
-        c_createFilegroupRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Create File Record",
-        c_createFileRecPool.getUsed(),
-        c_createFileRecPool.getSize(),
-        c_createFileRecPool.getEntrySize(),
-        c_createFileRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Drop Filegroup Record",
-        c_dropFilegroupRecPool.getUsed(),
-        c_dropFilegroupRecPool.getSize(),
-        c_dropFilegroupRecPool.getEntrySize(),
-        c_dropFilegroupRecPool.getUsedHi(),
-        { 0,0,0,0 }},
-      { "Drop File Record",
-        c_dropFileRecPool.getUsed(),
-        c_dropFileRecPool.getSize(),
-        c_dropFileRecPool.getEntrySize(),
-        c_dropFileRecPool.getUsedHi(),
-        { 0,0,0,0 }},
       { "Operation Record",
         c_opRecordPool.getUsed(),
         c_opRecordPool.getSize(),
@@ -1030,7 +922,8 @@ Dbdict::execCREATE_FRAGMENTATION_REQ(Sig
   Uint32 *theData = &signal->theData[0];
   const OpSection& fragSection =
     getOpSection(op_ptr, CreateTabReq::FRAGMENTATION);
-  copyOut(fragSection, &theData[25], ZNIL);
+  LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena,c_opSectionBufferPool);
+  copyOut(op_sec_pool, fragSection, &theData[25], ZNIL);
   theData[0] = 0;
 }
 
@@ -1279,7 +1172,7 @@ Dbdict::writeTableFile(Signal* signal, U
 
 // SchemaTrans variant
 void
-Dbdict::writeTableFile(Signal* signal, Uint32 tableId,
+Dbdict::writeTableFile(Signal* signal, SchemaOpPtr op_ptr, Uint32 tableId,
                        OpSection tabInfoSec, Callback* callback)
 {
   ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
@@ -1300,7 +1193,8 @@ Dbdict::writeTableFile(Signal* signal, U
     Uint32* dst = &pageRecPtr.p->word[ZPAGE_HEADER_SIZE];
     Uint32 dstSize = (ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS)
       - ZPAGE_HEADER_SIZE;
-    bool ok = copyOut(tabInfoSec, dst, dstSize);
+    LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
+    bool ok = copyOut(op_sec_pool, tabInfoSec, dst, dstSize);
     ndbrequire(ok);
 
     memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
@@ -2755,6 +2649,11 @@ void Dbdict::execREAD_CONFIG_REQ(Signal*
   ndb_mgm_get_int_parameter(p, CFG_DB_INDEX_STAT_AUTO_UPDATE,
                             &c_indexStatAutoUpdate);
 
+  Pool_context pc;
+  pc.m_block = this;
+
+  c_arenaAllocator.init(796, RT_DBDICT_SCHEMA_TRANS_ARENA, pc); // TODO: set size automagical? INFO: 796 is about 1/41 of a page, and bigger than CreateIndexRec (784 bytes)
+
   c_attributeRecordPool.setSize(attributesize);
   c_attributeRecordHash.setSize(64);
   c_fsConnectRecordPool.setSize(ZFS_CONNECT_SIZE);
@@ -2765,9 +2664,12 @@ void Dbdict::execREAD_CONFIG_REQ(Signal*
   g_key_descriptor_pool.setSize(tablerecSize);
   c_triggerRecordPool.setSize(c_maxNoOfTriggers);
 
-  c_opSectionBufferPool.setSize(1024); // units OpSectionSegmentSize
+  Record_info ri;
+  OpSectionBuffer::createRecordInfo(ri, RT_DBDICT_OP_SECTION_BUFFER);
+  c_opSectionBufferPool.init(&c_arenaAllocator, ri, pc);
+
   c_schemaOpHash.setSize(MAX_SCHEMA_OPERATIONS);
-  c_schemaTransPool.setSize(MAX_SCHEMA_TRANSACTIONS);
+  c_schemaTransPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_SCHEMA_TRANSACTION, pc);
   c_schemaTransHash.setSize(2);
   c_txHandlePool.setSize(2);
   c_txHandleHash.setSize(2);
@@ -2776,9 +2678,6 @@ void Dbdict::execREAD_CONFIG_REQ(Signal*
   c_obj_hash.setSize((tablerecSize+c_maxNoOfTriggers+1)/2);
   m_dict_lock_pool.setSize(MAX_NDB_NODES);
 
-  Pool_context pc;
-  pc.m_block = this;
-
   c_file_hash.setSize(16);
   c_filegroup_hash.setSize(16);
 
@@ -2792,31 +2691,31 @@ void Dbdict::execREAD_CONFIG_REQ(Signal*
   /**
    * TODO: Use arena-allocator for schema-transactions
    */
-  c_createTableRecPool.setSize(1 + 2 * MAX_INDEXES);
-  c_dropTableRecPool.setSize(1 + 2 * MAX_INDEXES);
-  c_alterTableRecPool.setSize(32);
-  c_createTriggerRecPool.setSize(4 * 2 * MAX_INDEXES);
-  c_dropTriggerRecPool.setSize(3 * 2 * MAX_INDEXES);
-  c_createIndexRecPool.setSize(2*MAX_INDEXES);
-  c_dropIndexRecPool.setSize(2 * MAX_INDEXES);
-  c_alterIndexRecPool.setSize(2 * MAX_INDEXES);
-  c_buildIndexRecPool.setSize(2 * 2 * MAX_INDEXES);
-  c_indexStatRecPool.setSize((1 + 4) * MAX_INDEXES); //main + 4 subs
-  c_createFilegroupRecPool.setSize(32);
-  c_createFileRecPool.setSize(32);
-  c_dropFilegroupRecPool.setSize(32);
-  c_dropFileRecPool.setSize(32);
-  c_createHashMapRecPool.setSize(32);
-  c_copyDataRecPool.setSize(32);
-  c_schemaOpPool.setSize(1 + 32 * MAX_INDEXES);
+  c_createTableRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_TABLE, pc);
+  c_dropTableRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_TABLE, pc);
+  c_alterTableRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_ALTER_TABLE, pc);
+  c_createTriggerRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_TRIGGER, pc);
+  c_dropTriggerRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_TRIGGER, pc);
+  c_createIndexRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_INDEX, pc);
+  c_dropIndexRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_INDEX, pc);
+  c_alterIndexRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_ALTER_INDEX, pc);
+  c_buildIndexRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_BUILD_INDEX, pc);
+  c_indexStatRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_INDEX_STAT, pc);
+  c_createFilegroupRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_FILEGROUP, pc);
+  c_createFileRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_FILE, pc);
+  c_dropFilegroupRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_FILEGROUP, pc);
+  c_dropFileRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_FILE, pc);
+  c_createHashMapRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_HASH_MAP, pc);
+  c_copyDataRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_COPY_DATA, pc);
+  c_schemaOpPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_SCHEMA_OPERATION, pc);
 
   c_hash_map_hash.setSize(4);
   c_hash_map_pool.setSize(32);
   g_hash_map.setSize(32);
 
-  c_createNodegroupRecPool.setSize(2);
-  c_dropNodegroupRecPool.setSize(2);
-  
+  c_createNodegroupRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_NODEGROUP, pc);
+  c_dropNodegroupRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_NODEGROUP, pc);
+
   c_opRecordPool.setSize(256);   // XXX need config params
   c_opCreateEvent.setSize(2);
   c_opSubEvent.setSize(2);
@@ -4010,8 +3909,11 @@ Dbdict::restart_nextOp(Signal* signal, b
 {
   c_restartRecord.m_op_cnt++;
 
-  if (OpSectionBuffer::getSegmentSize() *
-      c_opSectionBufferPool.getNoOfFree() < MAX_WORDS_META_FILE)
+  Resource_limit rl;
+  Uint32 free_words;
+  m_ctx.m_mm.get_resource_limit(RG_SCHEMA_TRANS_MEMORY, rl);
+  free_words = (rl.m_min - rl.m_curr) * GLOBAL_PAGE_SIZE_WORDS; // underestimate
+  if (free_words < 2*MAX_WORDS_META_FILE)
   {
     jam();
     /**
@@ -4379,6 +4281,12 @@ Dbdict::restartCreateObj_parse(Signal* s
   jam();
   Ptr<SchemaOp> op_ptr;
   
+  Ptr<TxHandle> tx_ptr;
+  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
+
+  Ptr<SchemaTrans> trans_ptr;
+  findSchemaTrans(trans_ptr, tx_ptr.p->m_transKey);
+
   switch(c_restartRecord.m_entry.m_tableType){
   case DictTabInfo::SystemTable:
   case DictTabInfo::UserTable:
@@ -4388,37 +4296,31 @@ Dbdict::restartCreateObj_parse(Signal* s
   case DictTabInfo::OrderedIndex:
   {
     Ptr<CreateTableRec> opRecPtr;
-    seizeSchemaOp(op_ptr, opRecPtr);
+    seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
     break;
   }
   case DictTabInfo::Undofile:
   case DictTabInfo::Datafile:
   {
     Ptr<CreateFileRec> opRecPtr;
-    seizeSchemaOp(op_ptr, opRecPtr);
+    seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
     break;
   }
   case DictTabInfo::Tablespace:
   case DictTabInfo::LogfileGroup:
   {
     Ptr<CreateFilegroupRec> opRecPtr;
-    seizeSchemaOp(op_ptr, opRecPtr);
+    seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
     break;
   }
   case DictTabInfo::HashMap:
   {
     Ptr<CreateHashMapRec> opRecPtr;
-    seizeSchemaOp(op_ptr, opRecPtr);
+    seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
     break;
   }
   }
 
-  Ptr<TxHandle> tx_ptr;
-  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
-
-  Ptr<SchemaTrans> trans_ptr;
-  findSchemaTrans(trans_ptr, tx_ptr.p->m_transKey);
-  addSchemaOp(trans_ptr, op_ptr);
   op_ptr.p->m_restart = file ? 1 : 2;
   op_ptr.p->m_state = SchemaOp::OS_PARSE_MASTER;
   
@@ -4463,6 +4365,12 @@ Dbdict::restartDropObj(Signal* signal,
   jam();
   Ptr<SchemaOp> op_ptr;
 
+  Ptr<TxHandle> tx_ptr;
+  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
+
+  Ptr<SchemaTrans> trans_ptr;
+  findSchemaTrans(trans_ptr, tx_ptr.p->m_transKey);
+
   switch(c_restartRecord.m_entry.m_tableType){
   case DictTabInfo::SystemTable:
   case DictTabInfo::UserTable:
@@ -4471,14 +4379,14 @@ Dbdict::restartDropObj(Signal* signal,
   case DictTabInfo::UniqueOrderedIndex:
   case DictTabInfo::OrderedIndex:
     Ptr<DropTableRec> opRecPtr;
-    seizeSchemaOp(op_ptr, opRecPtr);
+    seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
     ndbrequire(false);
     break;
   case DictTabInfo::Undofile:
   case DictTabInfo::Datafile:
   {
     Ptr<DropFileRec> opRecPtr;
-    seizeSchemaOp(op_ptr, opRecPtr);
+    seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
     opRecPtr.p->m_request.file_id = tableId;
     opRecPtr.p->m_request.file_version = entry->m_tableVersion;
     break;
@@ -4487,7 +4395,7 @@ Dbdict::restartDropObj(Signal* signal,
   case DictTabInfo::LogfileGroup:
   {
     Ptr<DropFilegroupRec> opRecPtr;
-    seizeSchemaOp(op_ptr, opRecPtr);
+    seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
     opRecPtr.p->m_request.filegroup_id = tableId;
     opRecPtr.p->m_request.filegroup_version = entry->m_tableVersion;
     break;
@@ -4496,12 +4404,6 @@ Dbdict::restartDropObj(Signal* signal,
 
   ndbout_c("restartDropObj(%u)", tableId);
   
-  Ptr<TxHandle> tx_ptr;
-  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
-
-  Ptr<SchemaTrans> trans_ptr;
-  findSchemaTrans(trans_ptr, tx_ptr.p->m_transKey);
-  addSchemaOp(trans_ptr, op_ptr);
   op_ptr.p->m_restart = 1; //
   op_ptr.p->m_state = SchemaOp::OS_PARSE_MASTER;
   
@@ -5623,6 +5525,7 @@ void Dbdict::execWAIT_GCP_REF(Signal* si
 const Dbdict::OpInfo
 Dbdict::CreateTableRec::g_opInfo = {
   { 'C', 'T', 'a', 0 },
+  ~RT_DBDICT_CREATE_TABLE,
   GSN_CREATE_TAB_REQ,
   CreateTabReq::SignalLength,
   //
@@ -6157,7 +6060,7 @@ Dbdict::createTable_prepare(Signal* sign
     jam();
     const OpSection& tabInfoSec =
       getOpSection(op_ptr, CreateTabReq::DICT_TAB_INFO);
-    writeTableFile(signal, createTabPtr.p->m_request.tableId,
+    writeTableFile(signal, op_ptr, createTabPtr.p->m_request.tableId,
                    tabInfoSec, &cb);
   }
   else
@@ -6517,7 +6420,8 @@ Dbdict::createTab_dih(Signal* signal, Sc
     // wl3600_todo add ndbrequire on SR, NR
     if (size != 0) {
       jam();
-      bool ok = copyOut(fragSec, page, 1024);
+      LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena,c_opSectionBufferPool);
+      bool ok = copyOut(op_sec_pool, fragSec, page, 1024);
       ndbrequire(ok);
       ptr[noOfSections].sz = size;
       ptr[noOfSections].p = page;
@@ -7068,11 +6972,11 @@ Dbdict::createTable_abortPrepare(Signal*
 
   // create drop table operation  wl3600_todo must pre-allocate
 
-  SchemaOpPtr& oplnk_ptr = op_ptr.p->m_oplnk_ptr;
-  ndbrequire(oplnk_ptr.isNull());
+  SchemaOpPtr oplnk_ptr;
   DropTableRecPtr dropTabPtr;
-  seizeSchemaOp(oplnk_ptr, dropTabPtr);
-  ndbrequire(!oplnk_ptr.isNull());
+  bool ok = seizeLinkedSchemaOp(op_ptr, oplnk_ptr, dropTabPtr);
+  ndbrequire(ok);
+
   DropTabReq* aux_impl_req = &dropTabPtr.p->m_request;
 
   aux_impl_req->senderRef = impl_req->senderRef;
@@ -7081,9 +6985,6 @@ Dbdict::createTable_abortPrepare(Signal*
   aux_impl_req->tableId = impl_req->tableId;
   aux_impl_req->tableVersion = impl_req->tableVersion;
 
-  // link other way too
-  oplnk_ptr.p->m_opbck_ptr = op_ptr;
-
   // wl3600_todo use ref count
   unlinkDictObject(op_ptr);
 
@@ -7253,6 +7154,7 @@ void Dbdict::releaseTableObject(Uint32 t
 const Dbdict::OpInfo
 Dbdict::DropTableRec::g_opInfo = {
   { 'D', 'T', 'a', 0 },
+  ~RT_DBDICT_DROP_TABLE,
   GSN_DROP_TAB_REQ,
   DropTabReq::SignalLength,
   //
@@ -7882,6 +7784,7 @@ void Dbdict::execDROP_TABLE_REF(Signal*
 const Dbdict::OpInfo
 Dbdict::AlterTableRec::g_opInfo = {
   { 'A', 'T', 'a', 0 },
+  ~RT_DBDICT_ALTER_TABLE,
   GSN_ALTER_TAB_REQ,
   AlterTabReq::SignalLength,
   //
@@ -7919,6 +7822,8 @@ Dbdict::alterTable_release(SchemaOpPtr o
     Rope r(c_rope_pool, alterTabPtr.p->m_oldFrmData);
     r.erase();
   }
+  LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
+  release(op_sec_pool, alterTabPtr.p->m_newAttrData);
   releaseOpRec<AlterTableRec>(op_ptr);
 }
 
@@ -8232,12 +8137,19 @@ Dbdict::alterTable_parse(Signal* signal,
     AttributeRecordPtr attrPtr;
     list.first(attrPtr);
     Uint32 i = 0;
+    LocalArenaPoolImpl op_sec_pool(trans_ptr.p->m_arena, c_opSectionBufferPool);
     for (i = 0; i < newTablePtr.p->noOfAttributes; i++) {
       if (i >= tablePtr.p->noOfAttributes) {
         jam();
-        Uint32 j = 2 * (i - tablePtr.p->noOfAttributes);
-        alterTabPtr.p->m_newAttrData[j + 0] = attrPtr.p->attributeDescriptor;
-        alterTabPtr.p->m_newAttrData[j + 1] = attrPtr.p->extPrecision & ~0xFFFF;
+        Uint32 attrData[2];
+        attrData[0] = attrPtr.p->attributeDescriptor;
+        attrData[1] = attrPtr.p->extPrecision & ~0xFFFF;
+        if(!copyIn(op_sec_pool, alterTabPtr.p->m_newAttrData, attrData, 2))
+        {
+          jam();
+          setError(error, SchemaTransBeginRef::OutOfSchemaTransMemory, __LINE__);
+          return;
+        }
       }
       list.next(attrPtr);
     }
@@ -8994,7 +8906,7 @@ Dbdict::alterTable_prepare(Signal* signa
      */
     {
       Ptr<SchemaOp> tmp = op_ptr;
-      LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+      LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
       for (list.prev(tmp); !tmp.isNull(); list.prev(tmp))
       {
         jam();
@@ -9069,7 +8981,7 @@ Dbdict::alterTable_backup_mutex_locked(S
 
   bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
   if (savetodisk) {
-    writeTableFile(signal, impl_req->tableId, tabInfoSec, &callback);
+    writeTableFile(signal, op_ptr, impl_req->tableId, tabInfoSec, &callback);
   } else {
     execute(signal, callback, 0);
   }
@@ -9147,7 +9059,14 @@ Dbdict::alterTable_toLocal(Signal* signa
   {
     jam();
     LinearSectionPtr ptr[3];
-    ptr[0].p = alterTabPtr.p->m_newAttrData;
+    Uint32 newAttrData[2 * MAX_ATTRIBUTES_IN_TABLE];
+    ndbrequire(impl_req->noOfNewAttr <= MAX_ATTRIBUTES_IN_TABLE);
+    ndbrequire(2 * impl_req->noOfNewAttr == alterTabPtr.p->m_newAttrData.getSize());
+    LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
+    bool ok = copyOut(op_sec_pool, alterTabPtr.p->m_newAttrData, newAttrData, 2 * impl_req->noOfNewAttr);
+    ndbrequire(ok);
+
+    ptr[0].p = newAttrData;
     ptr[0].sz = 2 * impl_req->noOfNewAttr;
     sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
                AlterTabReq::SignalLength, JBB, ptr, 1);
@@ -9158,7 +9077,8 @@ Dbdict::alterTable_toLocal(Signal* signa
     const OpSection& fragInfoSec =
       getOpSection(op_ptr, AlterTabReq::FRAGMENTATION);
     SegmentedSectionPtr fragInfoPtr;
-    bool ok = copyOut(fragInfoSec, fragInfoPtr);
+    LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena,c_opSectionBufferPool);
+    bool ok = copyOut(op_sec_pool, fragInfoSec, fragInfoPtr);
     ndbrequire(ok);
 
     if (AlterTableReq::getReorgFragFlag(req->changeMask))
@@ -9510,7 +9430,8 @@ Dbdict::alterTable_fromCommitComplete(Si
     const OpSection& tabInfoSec =
       getOpSection(op_ptr, AlterTabReq::DICT_TAB_INFO);
     SegmentedSectionPtr tabInfoPtr;
-    bool ok = copyOut(tabInfoSec, tabInfoPtr);
+    LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena,c_opSectionBufferPool);
+    bool ok = copyOut(op_sec_pool, tabInfoSec, tabInfoPtr);
     ndbrequire(ok);
 
     SectionHandle handle(this, tabInfoPtr.i);
@@ -10677,6 +10598,7 @@ flush:
 const Dbdict::OpInfo
 Dbdict::CreateIndexRec::g_opInfo = {
   { 'C', 'I', 'n', 0 },
+  ~RT_DBDICT_CREATE_INDEX,
   GSN_CREATE_INDX_IMPL_REQ,
   CreateIndxImplReq::SignalLength,
   //
@@ -11431,6 +11353,7 @@ Dbdict::execCREATE_INDX_IMPL_REF(Signal*
 const Dbdict::OpInfo
 Dbdict::DropIndexRec::g_opInfo = {
   { 'D', 'I', 'n', 0 },
+  ~RT_DBDICT_DROP_INDEX,
   GSN_DROP_INDX_IMPL_REQ,
   DropIndxImplReq::SignalLength,
   //
@@ -11874,6 +11797,7 @@ Dbdict::execDROP_INDX_IMPL_REF(Signal* s
 const Dbdict::OpInfo
 Dbdict::AlterIndexRec::g_opInfo = {
   { 'A', 'I', 'n', 0 },
+  ~RT_DBDICT_ALTER_INDEX,
   GSN_ALTER_INDX_IMPL_REQ,
   AlterIndxImplReq::SignalLength,
   //
@@ -12123,7 +12047,7 @@ Dbdict::alterIndex_parse(Signal* signal,
        *   (i.e recursivly, assuming that no operation can come inbetween)
        */
       Ptr<SchemaOp> baseop = op_ptr;
-      LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+      LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
       ndbrequire(list.prev(baseop));
       Uint32 sz = sizeof(baseop.p->m_oprec_ptr.p->m_opType);
       const char * opType = baseop.p->m_oprec_ptr.p->m_opType;
@@ -12822,7 +12746,8 @@ Dbdict::alterIndex_toAddPartitions(Signa
   const OpSection& fragInfoSec =
     getOpSection(base_op, AlterTabReq::FRAGMENTATION);
   SegmentedSectionPtr fragInfoPtr;
-  bool ok = copyOut(fragInfoSec, fragInfoPtr);
+  LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
+  bool ok = copyOut(op_sec_pool, fragInfoSec, fragInfoPtr);
   ndbrequire(ok);
   SectionHandle handle(this, fragInfoPtr.i);
 
@@ -13094,6 +13019,7 @@ Dbdict::execALTER_INDX_IMPL_REF(Signal*
 const Dbdict::OpInfo
 Dbdict::BuildIndexRec::g_opInfo = {
   { 'B', 'I', 'n', 0 },
+  ~RT_DBDICT_BUILD_INDEX,
   GSN_BUILD_INDX_IMPL_REQ,
   BuildIndxImplReq::SignalLength,
   //
@@ -13867,6 +13793,7 @@ Dbdict::execBUILD_INDX_IMPL_REF(Signal*
 const Dbdict::OpInfo
 Dbdict::IndexStatRec::g_opInfo = {
   { 'S', 'I', 'n', 0 },
+  ~RT_DBDICT_INDEX_STAT,
   GSN_INDEX_STAT_IMPL_REQ,
   IndexStatImplReq::SignalLength,
   //
@@ -14616,6 +14543,7 @@ Dbdict::indexStatBg_sendContinueB(Signal
 const Dbdict::OpInfo
 Dbdict::CopyDataRec::g_opInfo = {
   { 'D', 'C', 'D', 0 },
+  ~RT_DBDICT_COPY_DATA,
   GSN_COPY_DATA_IMPL_REQ,
   CopyDataImplReq::SignalLength,
 
@@ -17617,6 +17545,7 @@ void Dbdict::dropEvent_sendReply(Signal*
 const Dbdict::OpInfo
 Dbdict::CreateTriggerRec::g_opInfo = {
   { 'C', 'T', 'r', 0 },
+  ~RT_DBDICT_CREATE_TRIGGER,
   GSN_CREATE_TRIG_IMPL_REQ,
   CreateTrigImplReq::SignalLength,
   //
@@ -18004,7 +17933,6 @@ Dbdict::createTrigger_create_drop_trigge
 {
   jam();
 
-  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
   CreateTriggerRecPtr createTriggerPtr;
   getOpRec(op_ptr, createTriggerPtr);
   CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
@@ -18012,11 +17940,9 @@ Dbdict::createTrigger_create_drop_trigge
   /**
    * Construct a dropTrigger operation
    */
-  SchemaOpPtr& oplnk_ptr = op_ptr.p->m_oplnk_ptr;
-  ndbrequire(oplnk_ptr.isNull());
+  SchemaOpPtr oplnk_ptr;
   DropTriggerRecPtr dropTriggerPtr;
-  seizeSchemaOp(oplnk_ptr, dropTriggerPtr);
-  if (oplnk_ptr.isNull())
+  if(!seizeLinkedSchemaOp(op_ptr, oplnk_ptr, dropTriggerPtr))
   {
     jam();
     setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
@@ -18036,9 +17962,6 @@ Dbdict::createTrigger_create_drop_trigge
   aux_impl_req->triggerId = impl_req->triggerId;
   aux_impl_req->triggerInfo = impl_req->triggerInfo;
 
-  // link other way too
-  oplnk_ptr.p->m_opbck_ptr = op_ptr;
-  oplnk_ptr.p->m_trans_ptr = trans_ptr;
   dropTriggerPtr.p->m_main_op = createTriggerPtr.p->m_main_op;
 
   if (createTriggerPtr.p->m_main_op)
@@ -18568,6 +18491,7 @@ Dbdict::execCREATE_TRIG_IMPL_REF(Signal*
 const Dbdict::OpInfo
 Dbdict::DropTriggerRec::g_opInfo = {
   { 'D', 'T', 'r', 0 },
+  ~RT_DBDICT_DROP_TRIGGER,
   GSN_DROP_TRIG_IMPL_REQ,
   DropTrigImplReq::SignalLength,
   //
@@ -19542,7 +19466,7 @@ Dbdict::execDICT_TAKEOVER_REQ(Signal* si
 #endif
      
      SchemaOpPtr op_ptr;
-     LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
      bool pending_op = list.first(op_ptr);
      if (pending_op &&
          (trans_ptr.p->m_state == SchemaTrans::TS_COMPLETING ||
@@ -20119,7 +20043,8 @@ void Dbdict::check_takeover_replies(Sign
               SchemaOpPtr missing_op_ptr;
               const OpInfo& info =
                 *findOpInfo(nodePtr.p->takeOverConf.highest_op_impl_req_gsn);
-              if (seizeSchemaOp(missing_op_ptr,
+              if (seizeSchemaOp(trans_ptr,
+                                missing_op_ptr,
                                 nodePtr.p->takeOverConf.highest_op,
                                 info))
               {
@@ -20127,7 +20052,6 @@ void Dbdict::check_takeover_replies(Sign
 #ifdef VM_TRACE
                 ndbout_c("Created missing operation %u, on new master", missing_op_ptr.p->op_key);
 #endif
-                addSchemaOp(trans_ptr, missing_op_ptr);
                 missing_op_ptr.p->m_state = nodePtr.p->takeOverConf.highest_op_state;
                 masterNodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLBACK;
                 masterNodePtr.p->start_op = masterNodePtr.p->takeOverConf.highest_op;
@@ -20162,7 +20086,8 @@ void Dbdict::check_takeover_replies(Sign
             Uint32 op_state = nodePtr.p->takeOverConf.lowest_op_state;
             const OpInfo& info =
               *findOpInfo(nodePtr.p->takeOverConf.lowest_op_impl_req_gsn);
-            if (seizeSchemaOp(missing_op_ptr,
+            if (seizeSchemaOp(trans_ptr,
+                              missing_op_ptr,
                               op_key,
                               info))
             {
@@ -20170,7 +20095,6 @@ void Dbdict::check_takeover_replies(Sign
 #ifdef VM_TRACE
               ndbout_c("Created ressurected operation %u, on new master", op_key);
 #endif
-              addSchemaOp(trans_ptr, missing_op_ptr);
               trans_ptr.p->ressurected_op = true;
               missing_op_ptr.p->m_state = op_state;
               nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
@@ -20631,6 +20555,7 @@ Dbdict::getTableEntry(const XSchemaFile
 const Dbdict::OpInfo
 Dbdict::CreateFileRec::g_opInfo = {
   { 'C', 'F', 'l', 0 },
+  ~RT_DBDICT_CREATE_FILE,
   GSN_CREATE_FILE_IMPL_REQ,
   CreateFileImplReq::SignalLength,
   //
@@ -21147,7 +21072,7 @@ Dbdict::createFile_prepare(Signal* signa
   }
 
   const OpSection& objInfoSec = getOpSection(op_ptr, 0);
-  writeTableFile(signal, impl_req->file_id, objInfoSec, &cb);
+  writeTableFile(signal, op_ptr, impl_req->file_id, objInfoSec, &cb);
 }
 
 void
@@ -21381,6 +21306,7 @@ Dbdict::execCREATE_FILE_IMPL_CONF(Signal
 const Dbdict::OpInfo
 Dbdict::CreateFilegroupRec::g_opInfo = {
   { 'C', 'F', 'G', 0 },
+  ~RT_DBDICT_CREATE_FILEGROUP,
   GSN_CREATE_FILEGROUP_IMPL_REQ,
   CreateFilegroupImplReq::SignalLength,
   //
@@ -21834,7 +21760,7 @@ Dbdict::createFilegroup_prepare(Signal*
   }
 
   const OpSection& objInfoSec = getOpSection(op_ptr, 0);
-  writeTableFile(signal, impl_req->filegroup_id, objInfoSec, &cb);
+  writeTableFile(signal, op_ptr, impl_req->filegroup_id, objInfoSec, &cb);
 }
 
 void
@@ -21994,6 +21920,7 @@ Dbdict::execCREATE_FILEGROUP_IMPL_CONF(S
 const Dbdict::OpInfo
 Dbdict::DropFileRec::g_opInfo = {
   { 'D', 'F', 'l', 0 },
+  ~RT_DBDICT_DROP_FILE,
   GSN_DROP_FILE_IMPL_REQ,
   DropFileImplReq::SignalLength,
   //
@@ -22351,6 +22278,7 @@ Dbdict::send_drop_file(Signal* signal, U
 const Dbdict::OpInfo
 Dbdict::DropFilegroupRec::g_opInfo = {
   { 'D', 'F', 'g', 0 },
+  ~RT_DBDICT_DROP_FILEGROUP,
   GSN_DROP_FILEGROUP_IMPL_REQ,
   DropFilegroupImplReq::SignalLength,
   //
@@ -22778,6 +22706,7 @@ Dbdict::send_drop_fg(Signal* signal, Uin
 const Dbdict::OpInfo
 Dbdict::CreateNodegroupRec::g_opInfo = {
   { 'C', 'N', 'G', 0 },
+  ~RT_DBDICT_CREATE_NODEGROUP,
   GSN_CREATE_NODEGROUP_IMPL_REQ,
   CreateNodegroupImplReq::SignalLength,
   //
@@ -23377,6 +23306,7 @@ Dbdict::execCREATE_HASH_MAP_CONF(Signal*
 const Dbdict::OpInfo
 Dbdict::DropNodegroupRec::g_opInfo = {
   { 'D', 'N', 'G', 0 },
+  ~RT_DBDICT_DROP_NODEGROUP,
   GSN_DROP_NODEGROUP_IMPL_REQ,
   DropNodegroupImplReq::SignalLength,
   //
@@ -24057,7 +23987,7 @@ Dbdict::findOpInfo(Uint32 gsn)
 // OpSection
 
 bool
-Dbdict::copyIn(OpSection& op_sec, const SegmentedSectionPtr& ss_ptr)
+Dbdict::copyIn(OpSectionBufferPool& pool, OpSection& op_sec, const SegmentedSectionPtr& ss_ptr)
 {
   const Uint32 size = 1024;
   Uint32 buf[size];
@@ -24069,7 +23999,7 @@ Dbdict::copyIn(OpSection& op_sec, const
   {
     jam();
     ndbrequire(reader.getWords(buf, size));
-    if (!copyIn(op_sec, buf, size))
+    if (!copyIn(pool, op_sec, buf, size))
     {
       jam();
       return false;
@@ -24078,7 +24008,7 @@ Dbdict::copyIn(OpSection& op_sec, const
   }
 
   ndbrequire(reader.getWords(buf, len));
-  if (!copyIn(op_sec, buf, len))
+  if (!copyIn(pool, op_sec, buf, len))
   {
     jam();
     return false;
@@ -24088,9 +24018,9 @@ Dbdict::copyIn(OpSection& op_sec, const
 }
 
 bool
-Dbdict::copyIn(OpSection& op_sec, const Uint32* src, Uint32 srcSize)
+Dbdict::copyIn(OpSectionBufferPool& pool, OpSection& op_sec, const Uint32* src, Uint32 srcSize)
 {
-  OpSectionBuffer buffer(c_opSectionBufferPool, op_sec.m_head);
+  OpSectionBuffer buffer(pool, op_sec.m_head);
   if (!buffer.append(src, srcSize)) {
     jam();
     return false;
@@ -24115,14 +24045,15 @@ Dbdict::copyOut(Dbdict::OpSectionBuffer
 }
 
 bool
-Dbdict::copyOut(const OpSection& op_sec, SegmentedSectionPtr& ss_ptr)
+Dbdict::copyOut(OpSectionBufferPool& pool, const OpSection& op_sec, SegmentedSectionPtr& ss_ptr)
 {
   const Uint32 size = 1024;
   Uint32 buf[size];
 
   Uint32 len = op_sec.getSize();
   OpSectionBufferHead tmp_head = op_sec.m_head;
-  OpSectionBuffer buffer(c_opSectionBufferPool, tmp_head);
+
+  OpSectionBuffer buffer(pool, tmp_head);
 
   OpSectionBufferConstIterator iter;
   buffer.first(iter);
@@ -24163,7 +24094,7 @@ fail:
 }
 
 bool
-Dbdict::copyOut(const OpSection& op_sec, Uint32* dst, Uint32 dstSize)
+Dbdict::copyOut(OpSectionBufferPool& pool, const OpSection& op_sec, Uint32* dst, Uint32 dstSize)
 {
   if (op_sec.getSize() > dstSize) {
     jam();
@@ -24172,7 +24103,7 @@ Dbdict::copyOut(const OpSection& op_sec,
 
   // there is no const version of LocalDataBuffer
   OpSectionBufferHead tmp_head = op_sec.m_head;
-  OpSectionBuffer buffer(c_opSectionBufferPool, tmp_head);
+  OpSectionBuffer buffer(pool, tmp_head);
 
   OpSectionBufferConstIterator iter;
   Uint32 n = 0;
@@ -24186,9 +24117,9 @@ Dbdict::copyOut(const OpSection& op_sec,
 }
 
 void
-Dbdict::release(OpSection& op_sec)
+Dbdict::release(OpSectionBufferPool& pool, OpSection& op_sec)
 {
-  OpSectionBuffer buffer(c_opSectionBufferPool, op_sec.m_head);
+  OpSectionBuffer buffer(pool, op_sec.m_head);
   buffer.release();
 }
 
@@ -24204,7 +24135,7 @@ Dbdict::getOpInfo(SchemaOpPtr op_ptr)
 }
 
 bool
-Dbdict::seizeSchemaOp(SchemaOpPtr& op_ptr, Uint32 op_key, const OpInfo& info)
+Dbdict::seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Uint32 op_key, const OpInfo& info, bool linked)
 {
   if ((ERROR_INSERTED(6111) && 
        (info.m_impl_req_gsn == GSN_CREATE_TAB_REQ ||
@@ -24229,14 +24160,20 @@ Dbdict::seizeSchemaOp(SchemaOpPtr& op_pt
 
   if (!findSchemaOp(op_ptr, op_key)) {
     jam();
-    if (c_schemaOpHash.seize(op_ptr)) {
+    if (c_schemaOpPool.seize(trans_ptr.p->m_arena, op_ptr)) {
       jam();
       new (op_ptr.p) SchemaOp();
       op_ptr.p->op_key = op_key;
+      op_ptr.p->m_trans_ptr = trans_ptr;
       if ((this->*(info.m_seize))(op_ptr)) {
         jam();
+
+        if(!linked) {
+          jam();
+          addSchemaOp(op_ptr);
+        }
+
         c_schemaOpHash.add(op_ptr);
-        op_ptr.p->m_magic = SchemaOp::DICT_MAGIC;
         D("seizeSchemaOp" << V(op_key) << V(info.m_opType));
         return true;
       }
@@ -24288,8 +24225,9 @@ Dbdict::releaseSchemaOp(SchemaOpPtr& op_
   }
 
   ndbrequire(op_ptr.p->m_magic == SchemaOp::DICT_MAGIC);
-  op_ptr.p->m_magic = 0;
-  c_schemaOpHash.release(op_ptr);
+  c_schemaOpHash.remove(op_ptr);
+  c_schemaOpPool.release(op_ptr);
+  ndbrequire(op_ptr.p->m_magic == 0);
   op_ptr.setNull();
 }
 
@@ -24320,7 +24258,8 @@ Dbdict::saveOpSection(SchemaOpPtr op_ptr
   OpSection& op_sec = op_ptr.p->m_section[ss_no];
   op_ptr.p->m_sections++;
 
-  bool ok = copyIn(op_sec, ss_ptr);
+  LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
+  bool ok =  copyIn(op_sec_pool, op_sec, ss_ptr);
   ndbrequire(ok);
   return true;
 }
@@ -24330,20 +24269,20 @@ Dbdict::releaseOpSection(SchemaOpPtr op_
 {
   ndbrequire(ss_no + 1 == op_ptr.p->m_sections);
   OpSection& op_sec = op_ptr.p->m_section[ss_no];
-  release(op_sec);
+  LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
+  release(op_sec_pool, op_sec);
   op_ptr.p->m_sections = ss_no;
 }
 
 // add schema op to trans during parse phase
 
 void
-Dbdict::addSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr)
+Dbdict::addSchemaOp(SchemaOpPtr op_ptr)
 {
-  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
+  LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
   list.addLast(op_ptr);
 
-  op_ptr.p->m_trans_ptr = trans_ptr;
-
   // jonas_todo REMOVE side effect
   // add global flags from trans
   const Uint32& src_info = trans_ptr.p->m_requestInfo;
@@ -24520,7 +24459,7 @@ Dbdict::findDictObjectOp(SchemaOpPtr& op
     D("found" << *trans_ptr.p);
 
     {
-      LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+      LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
       SchemaOpPtr loop_ptr;
       list.first(loop_ptr);
       while (!loop_ptr.isNull()) {
@@ -24553,17 +24492,21 @@ Dbdict::seizeSchemaTrans(SchemaTransPtr&
   }
   if (!findSchemaTrans(trans_ptr, trans_key)) {
     jam();
-    if (c_schemaTransHash.seize(trans_ptr)) {
+    ArenaHead arena;
+    bool ok = c_arenaAllocator.seize(arena);
+    ndbrequire(ok); // TODO: report error
+    if (c_schemaTransPool.seize(arena, trans_ptr)) {
       jam();
       new (trans_ptr.p) SchemaTrans();
       trans_ptr.p->trans_key = trans_key;
+      trans_ptr.p->m_arena = arena;
       c_schemaTransHash.add(trans_ptr);
       c_schemaTransList.addLast(trans_ptr);
       c_schemaTransCount++;
-      trans_ptr.p->m_magic = SchemaTrans::DICT_MAGIC;
       D("seizeSchemaTrans" << V(trans_key));
       return true;
     }
+    c_arenaAllocator.release(arena);
   }
   trans_ptr.setNull();
   return false;
@@ -24605,26 +24548,29 @@ Dbdict::releaseSchemaTrans(SchemaTransPt
 {
   D("releaseSchemaTrans" << V(trans_ptr.p->trans_key));
 
-  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+  LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
   SchemaOpPtr op_ptr;
   while (list.first(op_ptr)) {
     list.remove(op_ptr);
     releaseSchemaOp(op_ptr);
   }
   ndbrequire(trans_ptr.p->m_magic == SchemaTrans::DICT_MAGIC);
-  trans_ptr.p->m_magic = 0;
   ndbrequire(c_schemaTransCount != 0);
   c_schemaTransCount--;
   c_schemaTransList.remove(trans_ptr);
-  c_schemaTransHash.release(trans_ptr);
+  c_schemaTransHash.remove(trans_ptr);
+  ArenaHead arena = trans_ptr.p->m_arena;
+  c_schemaTransPool.release(trans_ptr);
+  c_arenaAllocator.release(arena);
   trans_ptr.setNull();
 
   if (c_schemaTransCount == 0)
   {
     jam();
 
-    ndbrequire(c_schemaOpPool.getNoOfFree() == c_schemaOpPool.getSize());
-    ndbrequire(c_opSectionBufferPool.getNoOfFree() == c_opSectionBufferPool.getSize());
+    Resource_limit rl;
+    m_ctx.m_mm.get_resource_limit(RG_SCHEMA_TRANS_MEMORY, rl);
+    ndbrequire(rl.m_curr <= 1); // ArenaAllocator can keep one page for empty pool
 #ifdef VM_TRACE
     if (getNodeState().startLevel == NodeState::SL_STARTED)
       check_consistency();
@@ -25443,7 +25389,7 @@ Dbdict::trans_prepare_first(Signal* sign
   {
     bool first;
     {
-      LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+      LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
       first = list.first(op_ptr);
     }
     if (first)
@@ -25479,7 +25425,7 @@ Dbdict::trans_prepare_next(Signal* signa
   if (ERROR_INSERTED(6143))
   {
     jam();
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     if (!list.hasNext(op_ptr))
     {
       /*
@@ -25528,7 +25474,7 @@ Dbdict::trans_prepare_recv_reply(Signal*
   {
     bool next;
     {
-      LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+      LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
       next = list.next(op_ptr);
     }
     if (next)
@@ -25574,7 +25520,7 @@ Dbdict::trans_abort_parse_start(Signal*
   SchemaOpPtr op_ptr;
   bool last = false;
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     last =  list.last(op_ptr);
   }
 
@@ -25599,7 +25545,7 @@ Dbdict::trans_abort_parse_recv_reply(Sig
     SchemaOpPtr last_op = op_ptr;
     bool prev = false;
     {
-      LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+      LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
       prev = list.prev(op_ptr);
       list.remove(last_op);         // Release aborted op
     }
@@ -25684,7 +25630,7 @@ Dbdict::trans_abort_parse_next(Signal* s
   if (ERROR_INSERTED(6144))
   {
     jam();
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     if (!list.hasNext(op_ptr))
     {
       /*
@@ -25731,7 +25677,7 @@ Dbdict::trans_abort_prepare_start(Signal
   bool last = false;
   SchemaOpPtr op_ptr;
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     last = list.last(op_ptr);
   }
 
@@ -25759,7 +25705,7 @@ Dbdict::trans_abort_prepare_recv_reply(S
 
   bool prev = false;
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     prev = list.prev(op_ptr);
   }
 
@@ -25873,7 +25819,7 @@ Dbdict::trans_abort_prepare_next(Signal*
   if (ERROR_INSERTED(6145))
   {
     jam();
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     if (!list.hasPrev(op_ptr))
     {
       /*
@@ -25928,7 +25874,7 @@ Dbdict::trans_rollback_sp_start(Signal*
   SchemaOpPtr op_ptr;
 
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     ndbrequire(list.last(op_ptr));
   }
 
@@ -25975,7 +25921,7 @@ Dbdict::trans_rollback_sp_recv_reply(Sig
   }
 
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
 
     SchemaOpPtr last_op = op_ptr;
     ndbrequire(list.prev(op_ptr)); // Must have prev, as not SP
@@ -26007,7 +25953,7 @@ Dbdict::trans_rollback_sp_next(Signal* s
   if (ERROR_INSERTED(6144))
   {
     jam();
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     if (!list.hasPrev(op_ptr))
     {
       /*
@@ -26049,7 +25995,7 @@ Dbdict::trans_rollback_sp_done(Signal* s
   const OpInfo info = getOpInfo(op_ptr);
   (this->*(info.m_reply))(signal, op_ptr, error);
 
-  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+  LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
   list.remove(op_ptr);
   releaseSchemaOp(op_ptr);
 
@@ -26286,7 +26232,7 @@ Dbdict::trans_commit_mutex_locked(Signal
   bool first = false;
   SchemaOpPtr op_ptr;
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     first = list.first(op_ptr);
   }
 
@@ -26377,7 +26323,7 @@ Dbdict::trans_commit_next(Signal* signal
 
   if (ERROR_INSERTED(6147))
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     if (!list.hasNext(op_ptr))
     {
       jam();
@@ -26448,7 +26394,7 @@ Dbdict::trans_commit_recv_reply(Signal*
 
   bool next = false;
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     next = list.next(op_ptr);
   }
 
@@ -26624,7 +26570,7 @@ Dbdict::trans_complete_first(Signal * si
   bool first = false;
   SchemaOpPtr op_ptr;
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     first = list.first(op_ptr);
   }
 
@@ -26702,7 +26648,7 @@ Dbdict::trans_complete_recv_reply(Signal
 
   bool next = false;
   {
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     next = list.next(op_ptr);
   }
   
@@ -26789,7 +26735,7 @@ Dbdict::check_partial_trans_end_recv_rep
      */
     jam();
     SchemaOpPtr op_ptr;
-    LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+    LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
     list.remove(op_ptr);
 #ifdef VM_TRACE
     ndbout_c("Releasing ressurected op %u", op_ptr.p->op_key);
@@ -27108,7 +27054,7 @@ Dbdict::execSCHEMA_TRANS_IMPL_REQ(Signal
         /**
          * Remove op (except at coordinator
          */
-        LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
+        LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
         list.remove(op_ptr);
         releaseSchemaOp(op_ptr);
       }
@@ -27234,7 +27180,7 @@ Dbdict::slave_run_parse(Signal *signal,
       jam();
       setError(error, AlterTableRef::SingleUser, __LINE__);
     }
-    else if (seizeSchemaOp(op_ptr, op_key, info))
+    else if (seizeSchemaOp(trans_ptr, op_ptr, op_key, info))
     {
       jam();
 
@@ -27245,7 +27191,6 @@ Dbdict::slave_run_parse(Signal *signal,
       Uint32* dst = oprec_ptr.p->m_impl_req_data;
       memcpy(dst, src, len << 2);
 
-      addSchemaOp(trans_ptr, op_ptr);
       op_ptr.p->m_state = SchemaOp::OS_PARSING;
       (this->*(info.m_parse))(signal, false, op_ptr, handle, error);
     } else {
@@ -28301,6 +28246,7 @@ ArrayPool<Hash2FragmentMap> g_hash_map;
 const Dbdict::OpInfo
 Dbdict::CreateHashMapRec::g_opInfo = {
   { 'C', 'H', 'M', 0 },
+  ~RT_DBDICT_CREATE_HASH_MAP,
   GSN_CREATE_HASH_MAP_REQ,
   CreateHashMapReq::SignalLength,
   //
@@ -28863,7 +28809,7 @@ Dbdict::createHashMap_prepare(Signal* si
   cb.m_callbackFunction = safe_cast(&Dbdict::createHashMap_writeObjConf);
 
   const OpSection& tabInfoSec = getOpSection(op_ptr, 0);
-  writeTableFile(signal, impl_req->objectId, tabInfoSec, &cb);
+  writeTableFile(signal, op_ptr, impl_req->objectId, tabInfoSec, &cb);
 }
 
 void

=== modified file 'storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp'
--- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp	2011-10-07 13:15:08 +0000
@@ -24,6 +24,8 @@
 #include <ndb_limits.h>
 #include <trigger_definitions.h>
 #include <pc.hpp>
+#include <ArenaPool.hpp>
+#include <DataBuffer2.hpp>
 #include <DLHashTable.hpp>
 #include <DLFifoList.hpp>
 #include <CArray.hpp>
@@ -1358,7 +1360,8 @@ private:
   // OpInfo
 
   struct OpInfo {
-    const char m_opType[4]; // e.g. CTa for CreateTable
+    const char m_opType[4]; // e.g. CTa for CreateTable. TODO: remove. use only m_magic?
+    Uint32 m_magic;
     Uint32 m_impl_req_gsn;
     Uint32 m_impl_req_length;
 
@@ -1389,10 +1392,12 @@ private:
 
   struct OpRec
   {
-    char m_opType[4];
+    char m_opType[4]; // TODO: remove. only use m_magic
 
     Uint32 nextPool;
 
+    Uint32 m_magic;
+
     // reference to the static member in subclass
     const OpInfo& m_opInfo;
 
@@ -1403,6 +1408,7 @@ private:
     Uint32 m_obj_ptr_i;
 
     OpRec(const OpInfo& info, Uint32* impl_req_data) :
+      m_magic(info.m_magic),
       m_opInfo(info),
       m_impl_req_data(impl_req_data) {
       m_obj_ptr_i = RNIL;
@@ -1420,19 +1426,19 @@ private:
 
   enum { OpSectionSegmentSize = 127 };
   typedef
-    LocalDataBuffer<OpSectionSegmentSize>
+    LocalDataBuffer2<OpSectionSegmentSize, LocalArenaPoolImpl>
     OpSectionBuffer;
   typedef
-    OpSectionBuffer::Head
+    DataBuffer2<OpSectionSegmentSize, LocalArenaPoolImpl>::Head
     OpSectionBufferHead;
   typedef
     OpSectionBuffer::DataBufferPool
     OpSectionBufferPool;
   typedef
-    DataBuffer<OpSectionSegmentSize>::ConstDataBufferIterator
+    DataBuffer2<OpSectionSegmentSize, LocalArenaPoolImpl>::ConstDataBufferIterator
     OpSectionBufferConstIterator;
 
-  OpSectionBufferPool c_opSectionBufferPool;
+  ArenaPool c_opSectionBufferPool;
 
   struct OpSection {
     OpSectionBufferHead m_head;
@@ -1441,13 +1447,13 @@ private:
     }
   };
 
-  bool copyIn(OpSection&, const SegmentedSectionPtr&);
-  bool copyIn(OpSection&, const Uint32* src, Uint32 srcSize);
-  bool copyOut(const OpSection&, SegmentedSectionPtr&);
-  bool copyOut(const OpSection&, Uint32* dst, Uint32 dstSize);
+  bool copyIn(OpSectionBufferPool&, OpSection&, const SegmentedSectionPtr&);
+  bool copyIn(OpSectionBufferPool&, OpSection&, const Uint32* src, Uint32 srcSize);
+  bool copyOut(OpSectionBufferPool&, const OpSection&, SegmentedSectionPtr&);
+  bool copyOut(OpSectionBufferPool&, const OpSection&, Uint32* dst, Uint32 dstSize);
   bool copyOut(OpSectionBuffer & buffer, OpSectionBufferConstIterator & iter,
                Uint32 * dst, Uint32 len);
-  void release(OpSection&);
+  void release(OpSectionBufferPool&, OpSection&);
 
   // SchemaOp
 
@@ -1558,7 +1564,7 @@ private:
     SchemaFile::TableEntry m_orig_entry;
 
     // magic is on when record is seized
-    enum { DICT_MAGIC = 0xd1c70001 };
+    enum { DICT_MAGIC = ~RT_DBDICT_SCHEMA_OPERATION };
     Uint32 m_magic;
 
     SchemaOp() {
@@ -1573,7 +1579,7 @@ private:
       m_callback.m_callbackData = 0;
       m_oplnk_ptr.setNull();
       m_opbck_ptr.setNull();
-      m_magic = 0;
+      m_magic = DICT_MAGIC;
       m_base_op_ptr_i = RNIL;
 
       m_orig_entry_id = RNIL;
@@ -1589,8 +1595,13 @@ private:
 #endif
   };
 
-  ArrayPool<SchemaOp> c_schemaOpPool;
-  DLHashTable<SchemaOp> c_schemaOpHash;
+  typedef RecordPool<SchemaOp,ArenaPool> SchemaOp_pool;
+  typedef LocalDLFifoList<SchemaOp,SchemaOp,SchemaOp_pool> LocalSchemaOp_list;
+  typedef DLHashTable<SchemaOp,SchemaOp,SchemaOp_pool> SchemaOp_hash;
+  typedef DLFifoList<SchemaOp,SchemaOp,SchemaOp_pool>::Head  SchemaOp_head;
+
+  SchemaOp_pool c_schemaOpPool;
+  SchemaOp_hash c_schemaOpHash;
 
   const OpInfo& getOpInfo(SchemaOpPtr op_ptr);
 
@@ -1622,9 +1633,9 @@ private:
   inline bool
   seizeOpRec(SchemaOpPtr op_ptr) {
     OpRecPtr& oprec_ptr = op_ptr.p->m_oprec_ptr;
-    ArrayPool<T>& pool = T::getPool(this);
+    RecordPool<T,ArenaPool>& pool = T::getPool(this);
     Ptr<T> t_ptr;
-    if (pool.seize(t_ptr)) {
+    if (pool.seize(op_ptr.p->m_trans_ptr.p->m_arena, t_ptr)) {
       new (t_ptr.p) T();
       setOpRec<T>(op_ptr, t_ptr);
       return true;
@@ -1637,7 +1648,7 @@ private:
   inline void
   releaseOpRec(SchemaOpPtr op_ptr) {
     OpRecPtr& oprec_ptr = op_ptr.p->m_oprec_ptr;
-    ArrayPool<T>& pool = T::getPool(this);
+    RecordPool<T,ArenaPool>& pool = T::getPool(this);
     Ptr<T> t_ptr;
     getOpRec<T>(op_ptr, t_ptr);
     pool.release(t_ptr);
@@ -1646,18 +1657,18 @@ private:
 
   // seize / find / release, atomic on op rec + data rec
 
-  bool seizeSchemaOp(SchemaOpPtr& op_ptr, Uint32 op_key, const OpInfo& info);
+  bool seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Uint32 op_key, const OpInfo& info, bool linked=false);
 
   template <class T>
   inline bool
-  seizeSchemaOp(SchemaOpPtr& op_ptr, Uint32 op_key) {
-    return seizeSchemaOp(op_ptr, op_key, T::g_opInfo);
+  seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Uint32 op_key, bool linked) {
+    return seizeSchemaOp(trans_ptr, op_ptr, op_key, T::g_opInfo, linked);
   }
 
   template <class T>
   inline bool
-  seizeSchemaOp(SchemaOpPtr& op_ptr, Ptr<T>& t_ptr, Uint32 op_key) {
-    if (seizeSchemaOp<T>(op_ptr, op_key)) {
+  seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Ptr<T>& t_ptr, Uint32 op_key) {
+    if (seizeSchemaOp<T>(trans_ptr, op_ptr, op_key)) {
       getOpRec<T>(op_ptr, t_ptr);
       return true;
     }
@@ -1666,14 +1677,14 @@ private:
 
   template <class T>
   inline bool
-  seizeSchemaOp(SchemaOpPtr& op_ptr) {
+  seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, bool linked) {
     /*
       Store node id in high 8 bits to make op_key globally unique
      */
     Uint32 op_key = 
       (getOwnNodeId() << 24) +
       ((c_opRecordSequence + 1) & 0x00FFFFFF);
-    if (seizeSchemaOp<T>(op_ptr, op_key)) {
+    if (seizeSchemaOp<T>(trans_ptr, op_ptr, op_key, linked)) {
       c_opRecordSequence++;
       return true;
     }
@@ -1682,14 +1693,28 @@ private:
 
   template <class T>
   inline bool
-  seizeSchemaOp(SchemaOpPtr& op_ptr, Ptr<T>& t_ptr) {
-    if (seizeSchemaOp<T>(op_ptr)) {
+  seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Ptr<T>& t_ptr, bool linked=false) {
+    if (seizeSchemaOp<T>(trans_ptr, op_ptr, linked)) {
       getOpRec<T>(op_ptr, t_ptr);
       return true;
     }
     return false;
   }
 
+  template <class T>
+  inline bool
+  seizeLinkedSchemaOp(SchemaOpPtr op_ptr, SchemaOpPtr& oplnk_ptr, Ptr<T>& t_ptr) {
+    ndbrequire(op_ptr.p->m_oplnk_ptr.isNull());
+    if (seizeSchemaOp<T>(op_ptr.p->m_trans_ptr, oplnk_ptr, true)) {
+      op_ptr.p->m_oplnk_ptr = oplnk_ptr;
+      oplnk_ptr.p->m_opbck_ptr = op_ptr;
+      getOpRec<T>(oplnk_ptr, t_ptr);
+      return true;
+    }
+    oplnk_ptr.setNull();
+    return false;
+  }
+
   bool findSchemaOp(SchemaOpPtr& op_ptr, Uint32 op_key);
 
   template <class T>
@@ -1711,7 +1736,7 @@ private:
   void releaseOpSection(SchemaOpPtr, Uint32 ss_no);
 
   // add operation to transaction OpList
-  void addSchemaOp(SchemaTransPtr, SchemaOpPtr&);
+  void addSchemaOp(SchemaOpPtr);
 
   void updateSchemaOpStep(SchemaTransPtr, SchemaOpPtr);
 
@@ -1848,8 +1873,9 @@ private:
     NdbNodeBitmask m_ref_nodes;  // Nodes replying REF to req
     SafeCounterHandle m_counter; // Outstanding REQ's
 
+    ArenaHead m_arena;
     Uint32 m_curr_op_ptr_i;
-    DLFifoList<SchemaOp>::Head m_op_list;
+    SchemaOp_head m_op_list;
 
     // Master takeover
     enum TakeoverRecoveryState
@@ -1893,7 +1919,7 @@ private:
     bool m_wait_gcp_on_commit;
 
     // magic is on when record is seized
-    enum { DICT_MAGIC = 0xd1c70002 };
+    enum { DICT_MAGIC = ~RT_DBDICT_SCHEMA_TRANSACTION };
     Uint32 m_magic;
 
     SchemaTrans() {
@@ -1909,7 +1935,7 @@ private:
       bzero(&m_lockReq, sizeof(m_lockReq));
       m_callback.m_callbackFunction = 0;
       m_callback.m_callbackData = 0;
-      m_magic = 0;
+      m_magic = DICT_MAGIC;
       m_obj_id = RNIL;
       m_flush_prepare = false;
       m_flush_commit = false;
@@ -1932,9 +1958,10 @@ private:
   Uint32 check_write_obj(Uint32 objId, Uint32 transId = 0);
   Uint32 check_write_obj(Uint32, Uint32, SchemaFile::EntryState, ErrorInfo&);
 
-  ArrayPool<SchemaTrans> c_schemaTransPool;
-  DLHashTable<SchemaTrans> c_schemaTransHash;
-  DLFifoList<SchemaTrans> c_schemaTransList;
+  typedef RecordPool<SchemaTrans,ArenaPool> SchemaTrans_pool;
+  SchemaTrans_pool c_schemaTransPool;
+  DLHashTable<SchemaTrans,SchemaTrans,SchemaTrans_pool> c_schemaTransHash;
+  DLFifoList<SchemaTrans,SchemaTrans,SchemaTrans_pool> c_schemaTransList;
   Uint32 c_schemaTransCount;
 
   bool seizeSchemaTrans(SchemaTransPtr&, Uint32 trans_key);
@@ -2075,7 +2102,7 @@ private:
       return;
     }
 
-    if (!seizeSchemaOp(op_ptr, t_ptr)) {
+    if (!seizeSchemaOp(trans_ptr, op_ptr, t_ptr)) {
       jam();
       setError(error, SchemaTransImplRef::TooManySchemaOps, __LINE__);
       return;
@@ -2086,9 +2113,6 @@ private:
     DictSignal::setRequestExtra(op_ptr.p->m_requestInfo, requestExtra);
     DictSignal::addRequestFlags(op_ptr.p->m_requestInfo, requestInfo);
 
-    // add op and global flags from trans level
-    addSchemaOp(trans_ptr, op_ptr);
-
     // impl_req was passed via reference
     impl_req = &t_ptr.p->m_request;
 
@@ -2227,10 +2251,13 @@ private:
 
   // MODULE: CreateTable
 
+  struct CreateTableRec;
+  typedef RecordPool<CreateTableRec,ArenaPool> CreateTableRec_pool;
+
   struct CreateTableRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::CreateTableRec>&
+    static CreateTableRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_createTableRecPool;
     }
@@ -2270,7 +2297,7 @@ private:
   };
 
   typedef Ptr<CreateTableRec> CreateTableRecPtr;
-  ArrayPool<CreateTableRec> c_createTableRecPool;
+  CreateTableRec_pool c_createTableRecPool;
 
   // OpInfo
   bool createTable_seize(SchemaOpPtr);
@@ -2303,10 +2330,13 @@ private:
 
   // MODULE: DropTable
 
+  struct DropTableRec;
+  typedef RecordPool<DropTableRec,ArenaPool> DropTableRec_pool;
+
   struct DropTableRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::DropTableRec>&
+    static DropTableRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_dropTableRecPool;
     }
@@ -2333,7 +2363,7 @@ private:
   };
 
   typedef Ptr<DropTableRec> DropTableRecPtr;
-  ArrayPool<DropTableRec> c_dropTableRecPool;
+  DropTableRec_pool c_dropTableRecPool;
 
   // OpInfo
   bool dropTable_seize(SchemaOpPtr);
@@ -2366,10 +2396,13 @@ private:
 
   // MODULE: AlterTable
 
+  struct AlterTableRec;
+  typedef RecordPool<AlterTableRec,ArenaPool> AlterTableRec_pool;
+
   struct AlterTableRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::AlterTableRec>&
+    static AlterTableRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_alterTableRecPool;
     }
@@ -2377,7 +2410,7 @@ private:
     AlterTabReq m_request;
 
     // added attributes
-    Uint32 m_newAttrData[2 * MAX_ATTRIBUTES_IN_TABLE];
+    OpSection m_newAttrData;
 
     // wl3600_todo check mutex name and number later
     MutexHandle2<BACKUP_DEFINE_MUTEX> m_define_backup_mutex;
@@ -2413,7 +2446,6 @@ private:
     AlterTableRec() :
       OpRec(g_opInfo, (Uint32*)&m_request) {
       memset(&m_request, 0, sizeof(m_request));
-      memset(&m_newAttrData, 0, sizeof(m_newAttrData));
       m_tablePtr.setNull();
       m_newTablePtr.setNull();
       m_dihAddFragPtr = RNIL;
@@ -2437,7 +2469,7 @@ private:
   };
 
   typedef Ptr<AlterTableRec> AlterTableRecPtr;
-  ArrayPool<AlterTableRec> c_alterTableRecPool;
+  AlterTableRec_pool c_alterTableRecPool;
 
   // OpInfo
   bool alterTable_seize(SchemaOpPtr);
@@ -2494,6 +2526,9 @@ private:
     Uint32 attr_ptr_i;
   } AttributeMap[MAX_ATTRIBUTES_IN_INDEX];
 
+  struct CreateIndexRec;
+  typedef RecordPool<CreateIndexRec,ArenaPool> CreateIndexRec_pool;
+
   struct CreateIndexRec : public OpRec {
     CreateIndxImplReq m_request;
     char m_indexName[MAX_TAB_NAME_SIZE];
@@ -2507,7 +2542,7 @@ private:
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::CreateIndexRec>&
+    static CreateIndexRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_createIndexRecPool;
     }
@@ -2535,7 +2570,7 @@ private:
   };
 
   typedef Ptr<CreateIndexRec> CreateIndexRecPtr;
-  ArrayPool<CreateIndexRec> c_createIndexRecPool;
+  CreateIndexRec_pool c_createIndexRecPool;
 
   // OpInfo
   bool createIndex_seize(SchemaOpPtr);
@@ -2561,13 +2596,16 @@ private:
 
   // MODULE: DropIndex
 
+  struct DropIndexRec;
+  typedef RecordPool<DropIndexRec,ArenaPool> DropIndexRec_pool;
+
   struct DropIndexRec : public OpRec {
     DropIndxImplReq m_request;
 
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::DropIndexRec>&
+    static DropIndexRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_dropIndexRecPool;
     }
@@ -2588,7 +2626,7 @@ private:
   };
 
   typedef Ptr<DropIndexRec> DropIndexRecPtr;
-  ArrayPool<DropIndexRec> c_dropIndexRecPool;
+  DropIndexRec_pool c_dropIndexRecPool;
 
   // OpInfo
   bool dropIndex_seize(SchemaOpPtr);
@@ -2624,6 +2662,9 @@ private:
   static const TriggerTmpl g_buildIndexConstraintTmpl[1];
   static const TriggerTmpl g_reorgTriggerTmpl[1];
 
+  struct AlterIndexRec;
+  typedef RecordPool<AlterIndexRec,ArenaPool> AlterIndexRec_pool;
+
   struct AlterIndexRec : public OpRec {
     AlterIndxImplReq m_request;
     IndexAttributeList m_attrList;
@@ -2632,7 +2673,7 @@ private:
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::AlterIndexRec>&
+    static AlterIndexRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_alterIndexRecPool;
     }
@@ -2670,7 +2711,7 @@ private:
   };
 
   typedef Ptr<AlterIndexRec> AlterIndexRecPtr;
-  ArrayPool<AlterIndexRec> c_alterIndexRecPool;
+  AlterIndexRec_pool c_alterIndexRecPool;
 
   // OpInfo
   bool alterIndex_seize(SchemaOpPtr);
@@ -2719,10 +2760,13 @@ private:
   // this prepends 1 column used for FRAGMENT in hash index table key
   typedef Id_array<1 + MAX_ATTRIBUTES_IN_INDEX> FragAttributeList;
 
+  struct BuildIndexRec;
+  typedef RecordPool<BuildIndexRec,ArenaPool> BuildIndexRec_pool;
+
   struct BuildIndexRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::BuildIndexRec>&
+    static BuildIndexRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_buildIndexRecPool;
     }
@@ -2755,7 +2799,7 @@ private:
   };
 
   typedef Ptr<BuildIndexRec> BuildIndexRecPtr;
-  ArrayPool<BuildIndexRec> c_buildIndexRecPool;
+  BuildIndexRec_pool c_buildIndexRecPool;
 
   // OpInfo
   bool buildIndex_seize(SchemaOpPtr);
@@ -2795,10 +2839,13 @@ private:
 
   // MODULE: IndexStat
 
+  struct IndexStatRec;
+  typedef RecordPool<IndexStatRec,ArenaPool> IndexStatRec_pool;
+
   struct IndexStatRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::IndexStatRec>&
+    static IndexStatRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_indexStatRecPool;
     }
@@ -2819,7 +2866,7 @@ private:
   };
 
   typedef Ptr<IndexStatRec> IndexStatRecPtr;
-  ArrayPool<IndexStatRec> c_indexStatRecPool;
+  IndexStatRec_pool c_indexStatRecPool;
 
   Uint32 c_indexStatAutoCreate;
   Uint32 c_indexStatAutoUpdate;
@@ -2894,10 +2941,13 @@ private:
   RSS_AP_SNAPSHOT(c_hash_map_pool);
   RSS_AP_SNAPSHOT(g_hash_map);
 
+  struct CreateHashMapRec;
+  typedef RecordPool<CreateHashMapRec,ArenaPool> CreateHashMapRec_pool;
+
   struct CreateHashMapRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::CreateHashMapRec>&
+    static CreateHashMapRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_createHashMapRecPool;
     }
@@ -2911,7 +2961,7 @@ private:
   };
 
   typedef Ptr<CreateHashMapRec> CreateHashMapRecPtr;
-  ArrayPool<CreateHashMapRec> c_createHashMapRecPool;
+  CreateHashMapRec_pool c_createHashMapRecPool;
   void execCREATE_HASH_MAP_REQ(Signal* signal);
 
   // OpInfo
@@ -2935,10 +2985,13 @@ private:
 
   // MODULE: CopyData
 
+  struct CopyDataRec;
+  typedef RecordPool<CopyDataRec,ArenaPool> CopyDataRec_pool;
+
   struct CopyDataRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::CopyDataRec>&
+    static CopyDataRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_copyDataRecPool;
     }
@@ -2952,7 +3005,7 @@ private:
   };
 
   typedef Ptr<CopyDataRec> CopyDataRecPtr;
-  ArrayPool<CopyDataRec> c_copyDataRecPool;
+  CopyDataRec_pool c_copyDataRecPool;
   void execCOPY_DATA_REQ(Signal* signal);
   void execCOPY_DATA_REF(Signal* signal);
   void execCOPY_DATA_CONF(Signal* signal);
@@ -3097,10 +3150,14 @@ private:
   typedef Ptr<OpDropEvent> OpDropEventPtr;
 
   // MODULE: CreateTrigger
+
+  struct CreateTriggerRec;
+  typedef RecordPool<CreateTriggerRec,ArenaPool> CreateTriggerRec_pool;
+
   struct CreateTriggerRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::CreateTriggerRec>&
+    static CreateTriggerRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_createTriggerRecPool;
     }
@@ -3127,7 +3184,7 @@ private:
   };
 
   typedef Ptr<CreateTriggerRec> CreateTriggerRecPtr;
-  ArrayPool<CreateTriggerRec> c_createTriggerRecPool;
+  CreateTriggerRec_pool c_createTriggerRecPool;
 
   // OpInfo
   bool createTrigger_seize(SchemaOpPtr);
@@ -3158,10 +3215,13 @@ private:
 
   // MODULE: DropTrigger
 
+  struct DropTriggerRec;
+  typedef RecordPool<DropTriggerRec,ArenaPool> DropTriggerRec_pool;
+
   struct DropTriggerRec : public OpRec {
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::DropTriggerRec>&
+    static DropTriggerRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_dropTriggerRecPool;
     }
@@ -3186,7 +3246,7 @@ private:
   };
 
   typedef Ptr<DropTriggerRec> DropTriggerRecPtr;
-  ArrayPool<DropTriggerRec> c_dropTriggerRecPool;
+  DropTriggerRec_pool c_dropTriggerRecPool;
 
   // OpInfo
   bool dropTrigger_seize(SchemaOpPtr);
@@ -3214,6 +3274,9 @@ private:
 
   // MODULE: CreateFilegroup
 
+  struct CreateFilegroupRec;
+  typedef RecordPool<CreateFilegroupRec,ArenaPool> CreateFilegroupRec_pool;
+
   struct CreateFilegroupRec : public OpRec {
     bool m_parsed, m_prepared;
     CreateFilegroupImplReq m_request;
@@ -3222,7 +3285,7 @@ private:
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::CreateFilegroupRec>&
+    static CreateFilegroupRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_createFilegroupRecPool;
     }
@@ -3236,7 +3299,7 @@ private:
   };
 
   typedef Ptr<CreateFilegroupRec> CreateFilegroupRecPtr;
-  ArrayPool<CreateFilegroupRec> c_createFilegroupRecPool;
+  CreateFilegroupRec_pool c_createFilegroupRecPool;
 
   // OpInfo
   bool createFilegroup_seize(SchemaOpPtr);
@@ -3259,6 +3322,9 @@ private:
 
   // MODULE: CreateFile
 
+  struct CreateFileRec;
+  typedef RecordPool<CreateFileRec,ArenaPool> CreateFileRec_pool;
+
   struct CreateFileRec : public OpRec {
     bool m_parsed, m_prepared;
     CreateFileImplReq m_request;
@@ -3267,7 +3333,7 @@ private:
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::CreateFileRec>&
+    static CreateFileRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_createFileRecPool;
     }
@@ -3281,7 +3347,7 @@ private:
   };
 
   typedef Ptr<CreateFileRec> CreateFileRecPtr;
-  ArrayPool<CreateFileRec> c_createFileRecPool;
+  CreateFileRec_pool c_createFileRecPool;
 
   // OpInfo
   bool createFile_seize(SchemaOpPtr);
@@ -3304,6 +3370,9 @@ private:
 
   // MODULE: DropFilegroup
 
+  struct DropFilegroupRec;
+  typedef RecordPool<DropFilegroupRec,ArenaPool> DropFilegroupRec_pool;
+
   struct DropFilegroupRec : public OpRec {
     bool m_parsed, m_prepared;
     DropFilegroupImplReq m_request;
@@ -3311,7 +3380,7 @@ private:
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::DropFilegroupRec>&
+    static DropFilegroupRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_dropFilegroupRecPool;
     }
@@ -3324,7 +3393,7 @@ private:
   };
 
   typedef Ptr<DropFilegroupRec> DropFilegroupRecPtr;
-  ArrayPool<DropFilegroupRec> c_dropFilegroupRecPool;
+  DropFilegroupRec_pool c_dropFilegroupRecPool;
 
   // OpInfo
   bool dropFilegroup_seize(SchemaOpPtr);
@@ -3346,6 +3415,9 @@ private:
 
   // MODULE: DropFile
 
+  struct DropFileRec;
+  typedef RecordPool<DropFileRec,ArenaPool> DropFileRec_pool;
+
   struct DropFileRec : public OpRec {
     bool m_parsed, m_prepared;
     DropFileImplReq m_request;
@@ -3353,7 +3425,7 @@ private:
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::DropFileRec>&
+    static DropFileRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_dropFileRecPool;
     }
@@ -3366,7 +3438,7 @@ private:
   };
 
   typedef Ptr<DropFileRec> DropFileRecPtr;
-  ArrayPool<DropFileRec> c_dropFileRecPool;
+  DropFileRec_pool c_dropFileRecPool;
 
   // OpInfo
   bool dropFile_seize(SchemaOpPtr);
@@ -3388,6 +3460,9 @@ private:
 
   // MODULE: CreateNodegroup
 
+  struct CreateNodegroupRec;
+  typedef RecordPool<CreateNodegroupRec,ArenaPool> CreateNodegroupRec_pool;
+
   struct CreateNodegroupRec : public OpRec {
     bool m_map_created;
     CreateNodegroupImplReq m_request;
@@ -3395,7 +3470,7 @@ private:
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::CreateNodegroupRec>&
+    static CreateNodegroupRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_createNodegroupRecPool;
     }
@@ -3423,7 +3498,7 @@ private:
   };
 
   typedef Ptr<CreateNodegroupRec> CreateNodegroupRecPtr;
-  ArrayPool<CreateNodegroupRec> c_createNodegroupRecPool;
+  CreateNodegroupRec_pool c_createNodegroupRecPool;
 
   // OpInfo
   void execCREATE_NODEGROUP_REQ(Signal*);
@@ -3456,13 +3531,16 @@ private:
 
   // MODULE: DropNodegroup
 
+  struct DropNodegroupRec;
+  typedef RecordPool<DropNodegroupRec,ArenaPool> DropNodegroupRec_pool;
+
   struct DropNodegroupRec : public OpRec {
     DropNodegroupImplReq m_request;
 
     // reflection
     static const OpInfo g_opInfo;
 
-    static ArrayPool<Dbdict::DropNodegroupRec>&
+    static DropNodegroupRec_pool&
     getPool(Dbdict* dict) {
       return dict->c_dropNodegroupRecPool;
     }
@@ -3489,7 +3567,7 @@ private:
   };
 
   typedef Ptr<DropNodegroupRec> DropNodegroupRecPtr;
-  ArrayPool<DropNodegroupRec> c_dropNodegroupRecPool;
+  DropNodegroupRec_pool c_dropNodegroupRecPool;
 
   // OpInfo
   void execDROP_NODEGROUP_REQ(Signal*);
@@ -3637,7 +3715,7 @@ private:
   
   void writeTableFile(Signal* signal, Uint32 tableId, 
 		      SegmentedSectionPtr tabInfo, Callback*);
-  void writeTableFile(Signal* signal, Uint32 tableId,
+  void writeTableFile(Signal* signal, SchemaOpPtr op_ptr, Uint32 tableId,
 		      OpSection opSection, Callback*);
   void startWriteTableFile(Signal* signal, Uint32 tableId);
   void openTableFile(Signal* signal, 
@@ -3930,6 +4008,8 @@ public:
 
 protected:
   virtual bool getParam(const char * param, Uint32 * retVal);
+private:
+  ArenaAllocator c_arenaAllocator;
 };
 
 inline bool

=== modified file 'storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp'
--- a/storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dbinfo/Dbinfo.cpp	2011-10-07 08:07:21 +0000
@@ -29,7 +29,7 @@
 
 Uint32 dbinfo_blocks[] = { DBACC, DBTUP, BACKUP, DBTC, SUMA, DBUTIL,
                            TRIX, DBTUX, DBDICT, CMVMI, DBLQH, LGMAN,
-                           PGMAN, DBSPJ, 0};
+                           PGMAN, DBSPJ, THRMAN, 0};
 
 Dbinfo::Dbinfo(Block_context& ctx) :
   SimulatedBlock(DBINFO, ctx)

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2011-09-23 07:47:41 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp	2011-09-26 07:58:35 +0000
@@ -11348,8 +11348,8 @@ void Dblqh::scanTupkeyRefLab(Signal* sig
     scanReleaseLocksLab(signal);
     return;
   }//if
-  Uint32 time_passed= tcConnectptr.p->tcTimer - cLqhTimeOutCount;
-  if (rows) 
+  Uint32 time_passed= cLqhTimeOutCount - tcConnectptr.p->tcTimer;
+  if (rows)
   {
     if (time_passed > 1) 
     {

=== modified file 'storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp'
--- a/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dblqh/DblqhProxy.cpp	2011-10-07 08:07:21 +0000
@@ -690,7 +690,7 @@ DblqhProxy::completeLCP_2(Signal* signal
    *   that will checkpoint extent-pages
    */
   // NOTE: ugly to use MaxLqhWorkers directly
-  Uint32 instance = MaxLqhWorkers + 1;
+  Uint32 instance = c_workers + 1;
   sendSignal(numberToRef(PGMAN, instance, getOwnNodeId()),
              GSN_END_LCP_REQ, signal, EndLcpReq::SignalLength, JBB);
 }

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2011-08-22 08:35:35 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/Dbspj.hpp	2011-09-29 11:43:27 +0000
@@ -580,6 +580,8 @@ public:
     Uint32 m_fragCount;
     // The number of fragments that we scan in parallel.
     Uint32 m_parallelism;
+    // True if we are still receiving the first batch for this operation.
+    bool   m_firstBatch;
     /**
      * True if this is the first instantiation of this operation. A child
      * operation will be instantiated once for each batch of its parent.
@@ -1229,7 +1231,6 @@ private:
   void scanIndex_execSCAN_FRAGCONF(Signal*, Ptr<Request>, Ptr<TreeNode>, Ptr<ScanFragHandle>);
   void scanIndex_parent_row(Signal*,Ptr<Request>,Ptr<TreeNode>, const RowPtr&);
   void scanIndex_fixupBound(Ptr<ScanFragHandle> fragPtr, Uint32 ptrI, Uint32);
-  void scanIndex_send(Signal*,Ptr<Request>,Ptr<TreeNode>);
   void scanIndex_send(Signal* signal,
                       Ptr<Request> requestPtr,
                       Ptr<TreeNode> treeNodePtr,

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2011-09-23 07:43:25 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/DbspjMain.cpp	2011-09-29 11:43:27 +0000
@@ -5023,6 +5023,7 @@ Dbspj::scanIndex_parent_batch_complete(S
   const ScanFragReq * org = (const ScanFragReq*)data.m_scanFragReq;
   ndbrequire(org->batch_size_rows > 0);
 
+  data.m_firstBatch = true;
   if (treeNodePtr.p->m_bits & TreeNode::T_SCAN_PARALLEL)
   {
     jam();
@@ -5171,6 +5172,9 @@ Dbspj::scanIndex_send(Signal* signal,
                       Uint32 bs_rows,
                       Uint32& batchRange)
 {
+  jam();
+  ndbassert(bs_bytes > 0);
+  ndbassert(bs_rows > 0);
   /**
    * if (m_bits & prunemask):
    * - Range keys sliced out to each ScanFragHandle
@@ -5451,6 +5455,9 @@ Dbspj::scanIndex_execSCAN_FRAGCONF(Signa
 
   if (data.m_frags_outstanding == 0)
   {
+    const bool isFirstBatch = data.m_firstBatch;
+    data.m_firstBatch = false;
+
     const ScanFragReq * const org
       = reinterpret_cast<const ScanFragReq*>(data.m_scanFragReq);
 
@@ -5486,24 +5493,78 @@ Dbspj::scanIndex_execSCAN_FRAGCONF(Signa
     {
       jam();
       ndbrequire((requestPtr.p->m_state & Request::RS_ABORTING) != 0);
-    }
-    else if (! (data.m_rows_received == data.m_rows_expecting))
-    {
-      jam();
+      checkBatchComplete(signal, requestPtr, 1);
       return;
     }
-    else
+
+    if (isFirstBatch && data.m_frags_not_started > 0)
     {
-      if (treeNodePtr.p->m_bits & TreeNode::T_REPORT_BATCH_COMPLETE)
+      /**
+       * Check if we can expect to be able to fetch the entire result set by
+       * asking for more fragments within the same batch. This may improve 
+       * performance for bushy scans, as subsequent bushy branches must be
+       * re-executed for each batch of this scan.
+       */
+      
+      /**
+       * Find the maximal correlation value that we may have seen so far.
+       * Correlation value must be unique within batch and smaller than 
+       * org->batch_size_rows.
+       */
+      const Uint32 maxCorrVal = (data.m_totalRows) == 0 ? 0 :
+        org->batch_size_rows / data.m_parallelism * (data.m_parallelism - 1)
+        + data.m_totalRows;
+      
+      // Number of rows that we can still fetch in this batch.
+      const Int32 remainingRows 
+        = static_cast<Int32>(org->batch_size_rows - maxCorrVal);
+      
+      if (remainingRows >= data.m_frags_not_started &&
+          /**
+           * Check that (remaning row capacity)/(remaining fragments) is 
+           * greater or equal to (rows read so far)/(finished fragments).
+           */
+          remainingRows * static_cast<Int32>(data.m_parallelism) >=
+          static_cast<Int32>(data.m_totalRows * data.m_frags_not_started) &&
+          (org->batch_size_bytes - data.m_totalBytes) * data.m_parallelism >=
+          data.m_totalBytes * data.m_frags_not_started)
       {
         jam();
-        reportBatchComplete(signal, requestPtr, treeNodePtr);
+        Uint32 batchRange = maxCorrVal;
+        DEBUG("::scanIndex_execSCAN_FRAGCONF() first batch was not full."
+              " Asking for new batches from " << data.m_frags_not_started <<
+              " fragments with " << 
+              remainingRows / data.m_frags_not_started 
+              <<" rows and " << 
+              (org->batch_size_bytes - data.m_totalBytes)
+              / data.m_frags_not_started 
+              << " bytes.");
+        scanIndex_send(signal,
+                       requestPtr,
+                       treeNodePtr,
+                       data.m_frags_not_started,
+                       (org->batch_size_bytes - data.m_totalBytes)
+                       / data.m_frags_not_started,
+                       remainingRows / data.m_frags_not_started,
+                       batchRange);
+        return;
       }
     }
+    
+    if (data.m_rows_received != data.m_rows_expecting)
+    {
+      jam();
+      return;
+    }
+    
+    if (treeNodePtr.p->m_bits & TreeNode::T_REPORT_BATCH_COMPLETE)
+    {
+      jam();
+      reportBatchComplete(signal, requestPtr, treeNodePtr);
+    }
 
     checkBatchComplete(signal, requestPtr, 1);
-    return;
-  }
+  } // if (data.m_frags_outstanding == 0)
 }
 
 void

=== modified file 'storage/ndb/src/kernel/blocks/dbspj/DbspjProxy.hpp'
--- a/storage/ndb/src/kernel/blocks/dbspj/DbspjProxy.hpp	2011-09-15 20:21:59 +0000
+++ b/storage/ndb/src/kernel/blocks/dbspj/DbspjProxy.hpp	2011-10-07 08:07:21 +0000
@@ -24,7 +24,6 @@ public:
   virtual ~DbspjProxy();
   BLOCK_DEFINES(DbspjProxy);
 
-  virtual void loadWorkers() { tc_loadWorkers(); }
 protected:
   virtual SimulatedBlock* newWorker(Uint32 instanceNo);
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2011-07-04 13:37:56 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp	2011-10-07 14:34:14 +0000
@@ -157,9 +157,6 @@ public:
     CS_DISCONNECTED = 1,
     CS_STARTED = 2,
     CS_RECEIVING = 3,
-    CS_PREPARED = 4,
-    CS_START_PREPARING = 5,
-    CS_REC_PREPARING = 6,
     CS_RESTART = 7,
     CS_ABORTING = 8,
     CS_COMPLETING = 9,
@@ -1989,6 +1986,10 @@ private:
 
   bool validate_filter(Signal*);
   bool match_and_print(Signal*, ApiConnectRecordPtr);
+  void ndbinfo_write_trans(Signal* signal,
+                           DbinfoScanReq * req,
+                           Ndbinfo::Ratelimit * rl,
+                           ApiConnectRecordPtr transPtr);
 
 #ifdef ERROR_INSERT
   bool testFragmentDrop(Signal* signal);

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2011-09-15 06:02:57 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp	2011-10-07 14:34:14 +0000
@@ -106,9 +106,6 @@ operator<<(NdbOut& out, Dbtc::Connection
   case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
   case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
   case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
-  case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break;
-  case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break;
-  case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break;
   case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
   case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
   case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
@@ -1055,17 +1052,6 @@ Dbtc::handleFailedApiNode(Signal* signal
         abort010Lab(signal);
         TloopCount = 256;
         break;
-      case CS_PREPARED:
-        jam();
-      case CS_REC_PREPARING:
-        jam();
-      case CS_START_PREPARING:
-        jam();
-        /*********************************************************************/
-        // Not implemented yet.
-        /*********************************************************************/
-        systemErrorLab(signal, __LINE__);
-        break;
       case CS_RESTART:
         jam();
       case CS_COMPLETING:
@@ -6582,16 +6568,6 @@ void Dbtc::execTC_COMMITREQ(Signal* sign
       /***********************************************************************/
       errorCode = ZSCANINPROGRESS;
       break;
-    case CS_PREPARED:
-      jam();
-      return;
-    case CS_START_PREPARING:
-      jam();
-      return;
-    case CS_REC_PREPARING:
-      jam();
-      return;
-      break;
     default:
       warningHandlerLab(signal, __LINE__);
       return;
@@ -6709,12 +6685,6 @@ void Dbtc::execTCROLLBACKREQ(Signal* sig
     jam();
     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
     break;
-  case CS_START_PREPARING:
-    jam();
-  case CS_PREPARED:
-    jam();
-  case CS_REC_PREPARING:
-    jam();
   default:
     goto TC_ROLL_system_error;
     break;
@@ -7739,12 +7709,6 @@ void Dbtc::timeOutFoundLab(Signal* signa
     jam();
   case CS_FAIL_COMMITTED:
     jam();
-  case CS_REC_PREPARING:
-    jam();
-  case CS_START_PREPARING:
-    jam();
-  case CS_PREPARED:
-    jam();
   case CS_RESTART:
     jam();
   case CS_FAIL_ABORTED:
@@ -13324,14 +13288,125 @@ void Dbtc::execDBINFO_SCANREQ(Signal *si
 
     break;
   }
+  case Ndbinfo::TRANSACTIONS_TABLEID:{
+    ApiConnectRecordPtr ptr;
+    ptr.i = cursor->data[0];
+    const Uint32 maxloop = 256;
+    for (Uint32 i = 0; i < maxloop; i++)
+    {
+      ptrCheckGuard(ptr, capiConnectFilesize, apiConnectRecord);
+      ndbinfo_write_trans(signal, &req, &rl, ptr);
 
+      ptr.i ++;
+      if (ptr.i == capiConnectFilesize)
+      {
+        goto done;
+      }
+      else if (rl.need_break(req))
+      {
+        break;
+      }
+    }
+    ndbinfo_send_scan_break(signal, req, rl, ptr.i);
+    return;
+  }
   default:
     break;
   }
 
+done:
   ndbinfo_send_scan_conf(signal, req, rl);
 }
 
+void
+Dbtc::ndbinfo_write_trans(Signal* signal,
+                          DbinfoScanReq * req,
+                          Ndbinfo::Ratelimit * rl,
+                          ApiConnectRecordPtr transPtr)
+{
+  Uint32 conState = transPtr.p->apiConnectstate;
+
+  if (conState == CS_ABORTING && transPtr.p->abortState == AS_IDLE)
+  {
+    /**
+     * These is for all practical purposes equal
+     */
+    conState = CS_CONNECTED;
+  }
+
+  if (conState == CS_CONNECTED ||
+      conState == CS_DISCONNECTED ||
+      conState == CS_RESTART)
+  {
+    return;
+  }
+
+  char transid[64];
+  BaseString::snprintf(transid, sizeof(transid),
+                       "%.8x.%.8x",
+                       transPtr.p->transid[0],
+                       transPtr.p->transid[1]);
+
+  Ndbinfo::Row row(signal, *req);
+  row.write_uint32(getOwnNodeId());
+  row.write_uint32(instance());   // block instance
+  row.write_uint32(transPtr.i);
+  row.write_uint32(transPtr.p->ndbapiBlockref);
+  row.write_string(transid);
+  row.write_uint32(conState);
+  row.write_uint32(transPtr.p->m_flags);
+  row.write_uint32(transPtr.p->lqhkeyreqrec);
+  Uint32 outstanding = 0;
+  switch((ConnectionState)conState) {
+  case CS_CONNECTED:
+  case CS_DISCONNECTED:
+    break;
+  case CS_STARTED:
+  case CS_RECEIVING:
+  case CS_REC_COMMITTING:
+  case CS_START_COMMITTING:
+  case CS_SEND_FIRE_TRIG_REQ:
+  case CS_WAIT_FIRE_TRIG_REQ:
+    outstanding = transPtr.p->lqhkeyreqrec - transPtr.p->lqhkeyconfrec;
+    break;
+  case CS_COMMITTING:
+  case CS_COMPLETING:
+  case CS_COMMIT_SENT:
+  case CS_COMPLETE_SENT:
+  case CS_ABORTING:
+    outstanding = transPtr.p->counter;
+    break;
+  case CS_PREPARE_TO_COMMIT:
+    break;
+  case CS_START_SCAN:
+    // TODO
+    break;
+  case CS_WAIT_ABORT_CONF:
+  case CS_WAIT_COMMIT_CONF:
+  case CS_WAIT_COMPLETE_CONF:
+    // not easily computed :-(
+    break;
+  case CS_FAIL_PREPARED:
+  case CS_FAIL_ABORTED:
+    // we're assembling a state...
+    break;
+  case CS_FAIL_COMMITTING:
+  case CS_FAIL_COMMITTED:
+  case CS_FAIL_ABORTING:
+  case CS_FAIL_COMPLETED:
+    // not easily computed :_(
+    break;
+  case CS_RESTART:
+    break;
+  }
+
+  row.write_uint32(outstanding);
+
+  Uint32 apiTimer = getApiConTimer(transPtr.i);
+  row.write_uint32(apiTimer ? (ctcTimer - apiTimer) / 100 : 0);
+  ndbinfo_send_row(signal, *req, row, *rl);
+}
+
 bool
 Dbtc::validate_filter(Signal* signal)
 {
@@ -13464,9 +13539,6 @@ Dbtc::match_and_print(Signal* signal, Ap
   case CS_FAIL_PREPARED:
   case CS_FAIL_COMMITTING:
   case CS_FAIL_COMMITTED:
-  case CS_REC_PREPARING:
-  case CS_START_PREPARING:
-  case CS_PREPARED:
   case CS_RESTART:
   case CS_FAIL_ABORTED:
   case CS_DISCONNECTED:

=== modified file 'storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.hpp	2011-09-15 20:21:59 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtc/DbtcProxy.hpp	2011-10-07 08:07:21 +0000
@@ -37,7 +37,6 @@ public:
   virtual ~DbtcProxy();
   BLOCK_DEFINES(DbtcProxy);
 
-  virtual void loadWorkers() { tc_loadWorkers(); }
 protected:
   virtual SimulatedBlock* newWorker(Uint32 instanceNo);
 

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2011-09-01 18:42:31 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/Dbtup.hpp	2011-10-07 16:12:13 +0000
@@ -579,6 +579,9 @@ typedef Ptr<Fragoperrec> FragoperrecPtr;
   // for md5 of key (could maybe reuse existing temp buffer)
   Uint64 c_dataBuffer[ZWORDS_ON_PAGE/2 + 1];
 
+  // Crash the node when a tuple got corrupted
+  bool c_crashOnCorruptedTuple;
+
   struct Page_request 
   {
     Page_request() {}
@@ -2894,6 +2897,7 @@ private:
   
   Uint32 calculateChecksum(Tuple_header*, Tablerec* regTabPtr);
   void setChecksum(Tuple_header*, Tablerec* regTabPtr);
+  int corruptedTupleDetected(KeyReqStruct*);
 
   void complexTrigger(Signal* signal,
                       KeyReqStruct *req_struct,

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2011-05-25 13:19:02 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp	2011-10-07 16:12:13 +0000
@@ -166,6 +166,20 @@ Dbtup::calculateChecksum(Tuple_header* t
   return checksum;
 }
 
+int
+Dbtup::corruptedTupleDetected(KeyReqStruct *req_struct)
+{
+  ndbout_c("Tuple corruption detected."); 
+  if (c_crashOnCorruptedTuple)
+  {
+    ndbout_c(" Exiting."); 
+    ndbrequire(false);
+  }
+  terrorCode= ZTUPLE_CORRUPTED_ERROR;
+  tupkeyErrorLab(req_struct);
+  return -1;
+}
+
 /* ----------------------------------------------------------------- */
 /* -----------       INSERT_ACTIVE_OP_LIST            -------------- */
 /* ----------------------------------------------------------------- */
@@ -1014,10 +1028,7 @@ int Dbtup::handleReadReq(Signal* signal,
   if ((regTabPtr->m_bits & Tablerec::TR_Checksum) &&
       (calculateChecksum(req_struct->m_tuple_ptr, regTabPtr) != 0)) {
     jam();
-    ndbout_c("here2");
-    terrorCode= ZTUPLE_CORRUPTED_ERROR;
-    tupkeyErrorLab(req_struct);
-    return -1;
+    return corruptedTupleDetected(req_struct);
   }
 
   const Uint32 node = refToNode(sendBref);
@@ -1139,8 +1150,8 @@ int Dbtup::handleUpdateReq(Signal* signa
   if ((regTabPtr->m_bits & Tablerec::TR_Checksum) &&
       (calculateChecksum(req_struct->m_tuple_ptr, regTabPtr) != 0)) 
   {
-    terrorCode= ZTUPLE_CORRUPTED_ERROR;
-    goto error;
+    jam();
+    return corruptedTupleDetected(req_struct);
   }
 
   req_struct->m_tuple_ptr= dst;

=== modified file 'storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp'
--- a/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2011-05-17 23:29:55 +0000
+++ b/storage/ndb/src/kernel/blocks/dbtup/DbtupGen.cpp	2011-10-07 16:12:13 +0000
@@ -497,6 +497,14 @@ void Dbtup::execREAD_CONFIG_REQ(Signal*
   }
   
   initialiseRecordsLab(signal, 0, ref, senderData);
+
+  {
+    Uint32 val = 0;
+    ndb_mgm_get_int_parameter(p, CFG_DB_CRASH_ON_CORRUPTED_TUPLE,
+                              &val);
+    c_crashOnCorruptedTuple = val ? true : false;
+  }
+
 }//Dbtup::execSIZEALT_REP()
 
 void Dbtup::initRecords() 

=== modified file 'storage/ndb/src/kernel/blocks/record_types.hpp'
--- a/storage/ndb/src/kernel/blocks/record_types.hpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/blocks/record_types.hpp	2011-10-07 13:15:08 +0000
@@ -67,10 +67,15 @@
 #define RG_QUERY_MEMORY         8
 
 /**
+ * Schema transaction memory
+ */
+#define RG_SCHEMA_TRANS_MEMORY  9
+
+/**
  * 
  */
 #define RG_RESERVED             0
-#define RG_COUNT                9
+#define RG_COUNT                10
 
 /**
  * Record types
@@ -100,4 +105,27 @@
 #define RT_SPJ_DATABUFFER          MAKE_TID( 4, RG_QUERY_MEMORY)
 #define RT_SPJ_SCANFRAG            MAKE_TID( 5, RG_QUERY_MEMORY)
 
+#define RT_DBDICT_SCHEMA_TRANS_ARENA MAKE_TID( 1, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_SCHEMA_TRANSACTION MAKE_TID( 2, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_SCHEMA_OPERATION   MAKE_TID( 3, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_CREATE_TABLE       MAKE_TID( 4, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_DROP_TABLE         MAKE_TID( 5, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_ALTER_TABLE        MAKE_TID( 6, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_CREATE_TRIGGER     MAKE_TID( 7, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_DROP_TRIGGER       MAKE_TID( 8, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_CREATE_INDEX       MAKE_TID( 9, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_DROP_INDEX         MAKE_TID( 10, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_ALTER_INDEX        MAKE_TID( 11, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_BUILD_INDEX        MAKE_TID( 12, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_INDEX_STAT         MAKE_TID( 13, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_CREATE_FILEGROUP   MAKE_TID( 14, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_CREATE_FILE        MAKE_TID( 15, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_DROP_FILEGROUP     MAKE_TID( 16, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_DROP_FILE          MAKE_TID( 17, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_CREATE_HASH_MAP    MAKE_TID( 18, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_COPY_DATA          MAKE_TID( 19, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_CREATE_NODEGROUP   MAKE_TID( 20, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_DROP_NODEGROUP     MAKE_TID( 21, RG_SCHEMA_TRANS_MEMORY)
+#define RT_DBDICT_OP_SECTION_BUFFER  MAKE_TID( 22, RG_SCHEMA_TRANS_MEMORY)
+
 #endif

=== added file 'storage/ndb/src/kernel/blocks/thrman.cpp'
--- a/storage/ndb/src/kernel/blocks/thrman.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/blocks/thrman.cpp	2011-10-07 09:28:24 +0000
@@ -0,0 +1,129 @@
+/*
+   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#include "thrman.hpp"
+#include <mt.hpp>
+#include <signaldata/DbinfoScan.hpp>
+#include <NdbGetRUsage.h>
+
+#include <EventLogger.hpp>
+extern EventLogger * g_eventLogger;
+
+Thrman::Thrman(Block_context & ctx, Uint32 instanceno) :
+  SimulatedBlock(THRMAN, ctx, instanceno)
+{
+  BLOCK_CONSTRUCTOR(Thrman);
+
+  addRecSignal(GSN_DBINFO_SCANREQ, &Thrman::execDBINFO_SCANREQ);
+}
+
+Thrman::~Thrman()
+{
+}
+
+BLOCK_FUNCTIONS(Thrman)
+
+void
+Thrman::execDBINFO_SCANREQ(Signal* signal)
+{
+  jamEntry();
+
+  DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
+  const Ndbinfo::ScanCursor* cursor =
+    CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
+  Ndbinfo::Ratelimit rl;
+
+  switch(req.tableId) {
+  case Ndbinfo::THREADBLOCKS_TABLEID: {
+    Uint32 arr[NO_OF_BLOCKS];
+    Uint32 len = mt_get_blocklist(this, arr, NDB_ARRAY_SIZE(arr));
+    Uint32 pos = cursor->data[0];
+    for (; ; )
+    {
+      Ndbinfo::Row row(signal, req);
+      row.write_uint32(getOwnNodeId());
+      row.write_uint32(getThreadId());             // thr_no
+      row.write_uint32(blockToMain(arr[pos]));     // block_number
+      row.write_uint32(blockToInstance(arr[pos])); // block_instance
+      ndbinfo_send_row(signal, req, row, rl);
+
+      pos++;
+      if (pos == len)
+      {
+        jam();
+        break;
+      }
+      else if (rl.need_break(req))
+      {
+        jam();
+        ndbinfo_send_scan_break(signal, req, rl, pos);
+        return;
+      }
+    }
+    break;
+  }
+  case Ndbinfo::THREADSTAT_TABLEID:{
+    ndb_thr_stat stat;
+    mt_get_thr_stat(this, &stat);
+    Ndbinfo::Row row(signal, req);
+    row.write_uint32(getOwnNodeId());
+    row.write_uint32(getThreadId());  // thr_no
+    row.write_string(stat.name);
+    row.write_uint64(stat.loop_cnt);
+    row.write_uint64(stat.exec_cnt);
+    row.write_uint64(stat.wait_cnt);
+    row.write_uint64(stat.local_sent_prioa);
+    row.write_uint64(stat.local_sent_priob);
+    row.write_uint64(stat.remote_sent_prioa);
+    row.write_uint64(stat.remote_sent_priob);
+
+    row.write_uint64(stat.os_tid);
+    row.write_uint64(NdbTick_CurrentMillisecond());
+
+    struct ndb_rusage os_rusage;
+    Ndb_GetRUSage(&os_rusage);
+    row.write_uint64(os_rusage.ru_utime);
+    row.write_uint64(os_rusage.ru_stime);
+    row.write_uint64(os_rusage.ru_minflt);
+    row.write_uint64(os_rusage.ru_majflt);
+    row.write_uint64(os_rusage.ru_nvcsw);
+    row.write_uint64(os_rusage.ru_nivcsw);
+    ndbinfo_send_row(signal, req, row, rl);
+    break;
+  }
+  default:
+    break;
+  }
+
+  ndbinfo_send_scan_conf(signal, req, rl);
+}
+
+ThrmanProxy::ThrmanProxy(Block_context & ctx) :
+  LocalProxy(THRMAN, ctx)
+{
+}
+
+ThrmanProxy::~ThrmanProxy()
+{
+}
+
+SimulatedBlock*
+ThrmanProxy::newWorker(Uint32 instanceNo)
+{
+  return new Thrman(m_ctx, instanceNo);
+}
+

=== added file 'storage/ndb/src/kernel/blocks/thrman.hpp'
--- a/storage/ndb/src/kernel/blocks/thrman.hpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/kernel/blocks/thrman.hpp	2011-10-07 08:07:21 +0000
@@ -0,0 +1,48 @@
+/*
+   Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#ifndef THRMAN_H
+#define THRMAN_H
+
+#include <SimulatedBlock.hpp>
+#include <LocalProxy.hpp>
+
+class Thrman : public SimulatedBlock
+{
+public:
+  Thrman(Block_context& ctx, Uint32 instanceNumber = 0);
+  virtual ~Thrman();
+  BLOCK_DEFINES(Thrman);
+
+  void execDBINFO_SCANREQ(Signal*);
+protected:
+
+};
+
+class ThrmanProxy : public LocalProxy
+{
+public:
+  ThrmanProxy(Block_context& ctx);
+  virtual ~ThrmanProxy();
+  BLOCK_DEFINES(ThrmanProxy);
+
+protected:
+  virtual SimulatedBlock* newWorker(Uint32 instanceNo);
+
+};
+
+#endif

=== modified file 'storage/ndb/src/kernel/blocks/tsman.cpp'
--- a/storage/ndb/src/kernel/blocks/tsman.cpp	2011-03-15 16:11:47 +0000
+++ b/storage/ndb/src/kernel/blocks/tsman.cpp	2011-10-04 07:56:40 +0000
@@ -488,7 +488,7 @@ Tsman::execDROP_FILEGROUP_IMPL_REQ(Signa
       if (ptr.p->m_ref_count)
       {
         jam();
-        sendSignalWithDelay(reference(), GSN_DROP_FILEGROUP_REQ, signal,
+        sendSignalWithDelay(reference(), GSN_DROP_FILEGROUP_IMPL_REQ, signal,
                             100, signal->getLength());
         return;
       }

=== modified file 'storage/ndb/src/kernel/ndbd.cpp'
--- a/storage/ndb/src/kernel/ndbd.cpp	2011-09-23 09:13:22 +0000
+++ b/storage/ndb/src/kernel/ndbd.cpp	2011-10-07 13:15:08 +0000
@@ -239,8 +239,17 @@ init_global_memory_manager(EmulatorData
     ed.m_mem_manager->set_resource_limit(rl);
   }
 
+  Uint32 stpages = 64;
+  {
+    Resource_limit rl;
+    rl.m_min = stpages;
+    rl.m_max = 0;
+    rl.m_resource_id = RG_SCHEMA_TRANS_MEMORY;
+    ed.m_mem_manager->set_resource_limit(rl);
+  }
+
   Uint32 sum = shared_pages + tupmem + filepages + jbpages + sbpages +
-    pgman_pages;
+    pgman_pages + stpages;
 
   if (sum)
   {

=== modified file 'storage/ndb/src/kernel/vm/ArrayPool.hpp'
--- a/storage/ndb/src/kernel/vm/ArrayPool.hpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/vm/ArrayPool.hpp	2011-09-27 06:44:06 +0000
@@ -1385,7 +1385,7 @@ UnsafeArrayPool<T>::getPtrForce(ConstPtr
 template <class T>
 class SafeArrayPool : public ArrayPool<T> {
 public:
-  SafeArrayPool(NdbMutex* mutex = 0);
+  SafeArrayPool();
   ~SafeArrayPool();
   int lock();
   int unlock();
@@ -1393,6 +1393,8 @@ public:
   void release(Uint32 i);
   void release(Ptr<T>&);
 
+  void setMutex(NdbMutex* mutex = 0);
+
 private:
   NdbMutex* m_mutex;
   bool m_mutex_owner;
@@ -1403,7 +1405,16 @@ private:
 
 template <class T>
 inline
-SafeArrayPool<T>::SafeArrayPool(NdbMutex* mutex)
+SafeArrayPool<T>::SafeArrayPool()
+{
+  m_mutex = 0;
+  m_mutex_owner = false;
+}
+
+template <class T>
+inline
+void
+SafeArrayPool<T>::setMutex(NdbMutex* mutex)
 {
   if (mutex != 0) {
     m_mutex = mutex;

=== modified file 'storage/ndb/src/kernel/vm/DLFifoList.hpp'
--- a/storage/ndb/src/kernel/vm/DLFifoList.hpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/vm/DLFifoList.hpp	2011-10-07 11:46:40 +0000
@@ -465,18 +465,18 @@ DLFifoListImpl<P,T,U>::hasPrev(const Ptr
 
 // Specializations
 
-template <typename T, typename U = T>
-class DLFifoList : public DLFifoListImpl<ArrayPool<T>, T, U>
+template <typename T, typename U = T, typename P = ArrayPool<T> >
+class DLFifoList : public DLFifoListImpl<P, T, U>
 {
 public:
-  DLFifoList(ArrayPool<T> & p) : DLFifoListImpl<ArrayPool<T>, T, U>(p) {}
+  DLFifoList(P & p) : DLFifoListImpl<P, T, U>(p) {}
 };
 
-template <typename T, typename U = T>
-class LocalDLFifoList : public LocalDLFifoListImpl<ArrayPool<T>,T,U> {
+template <typename T, typename U = T, typename P = ArrayPool<T> >
+class LocalDLFifoList : public LocalDLFifoListImpl<P,T,U> {
 public:
-  LocalDLFifoList(ArrayPool<T> & p, typename DLFifoList<T,U>::Head & _src)
-    : LocalDLFifoListImpl<ArrayPool<T>,T,U>(p, _src) {}
+  LocalDLFifoList(P & p, typename DLFifoList<T,U,P>::Head & _src)
+    : LocalDLFifoListImpl<P,T,U>(p, _src) {}
 };
 
 #endif

=== modified file 'storage/ndb/src/kernel/vm/DLHashTable.hpp'
--- a/storage/ndb/src/kernel/vm/DLHashTable.hpp	2011-06-30 15:55:35 +0000
+++ b/storage/ndb/src/kernel/vm/DLHashTable.hpp	2011-10-07 11:46:40 +0000
@@ -517,11 +517,11 @@ DLHashTableImpl<P, T, U>::find(Ptr<T> &
 
 // Specializations
 
-template <typename T, typename U = T>
-class DLHashTable : public DLHashTableImpl<ArrayPool<T>, T, U>
+template <typename T, typename U = T, typename P = ArrayPool<T> >
+class DLHashTable : public DLHashTableImpl<P, T, U>
 {
 public:
-  DLHashTable(ArrayPool<T> & p) : DLHashTableImpl<ArrayPool<T>, T, U>(p) {}
+  DLHashTable(P & p) : DLHashTableImpl<P, T, U>(p) {}
 };
 
 #endif

=== modified file 'storage/ndb/src/kernel/vm/DataBuffer2.hpp'
--- a/storage/ndb/src/kernel/vm/DataBuffer2.hpp	2010-10-27 06:54:54 +0000
+++ b/storage/ndb/src/kernel/vm/DataBuffer2.hpp	2011-10-07 11:46:40 +0000
@@ -18,6 +18,8 @@
 #ifndef DATA_BUFFER2_HPP
 #define DATA_BUFFER2_HPP
 
+#include <ErrorReporter.hpp>
+
 /**
  * @class  DataBuffer
  * @brief  Buffer of data words

=== modified file 'storage/ndb/src/kernel/vm/Emulator.cpp'
--- a/storage/ndb/src/kernel/vm/Emulator.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/vm/Emulator.cpp	2011-09-27 06:44:06 +0000
@@ -89,6 +89,7 @@ EmulatorData::create(){
   theSimBlockList  = new SimBlockList();
   m_socket_server  = new SocketServer();
   m_mem_manager    = new Ndbd_mem_manager();
+  globalData.m_global_page_pool.setMutex();
 
   if (theConfiguration == NULL ||
       theWatchDog == NULL ||

=== modified file 'storage/ndb/src/kernel/vm/Ndbinfo.hpp'
--- a/storage/ndb/src/kernel/vm/Ndbinfo.hpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/vm/Ndbinfo.hpp	2011-10-07 14:34:14 +0000
@@ -46,7 +46,10 @@ public:
     RESOURCES_TABLEID =          7,
     COUNTERS_TABLEID =           8,
     NODES_TABLEID =              9,
-    DISKPAGEBUFFER_TABLEID =     10
+    DISKPAGEBUFFER_TABLEID =     10,
+    THREADBLOCKS_TABLEID =       11,
+    THREADSTAT_TABLEID =         12,
+    TRANSACTIONS_TABLEID =       13
   };
 
   struct Table {

=== modified file 'storage/ndb/src/kernel/vm/NdbinfoTables.cpp'
--- a/storage/ndb/src/kernel/vm/NdbinfoTables.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/src/kernel/vm/NdbinfoTables.cpp	2011-10-07 14:34:14 +0000
@@ -169,6 +169,57 @@ DECLARE_NDBINFO_TABLE(DISKPAGEBUFFER, 9)
   }
 };
 
+DECLARE_NDBINFO_TABLE(THREADBLOCKS, 4) =
+{ { "threadblocks", 4, 0, "which blocks are run in which threads" },
+  {
+    {"node_id",                     Ndbinfo::Number, ""},
+    {"thr_no",                      Ndbinfo::Number, ""},
+    {"block_number",                Ndbinfo::Number, ""},
+    {"block_instance",              Ndbinfo::Number, ""},
+  }
+};
+
+DECLARE_NDBINFO_TABLE(THREADSTAT, 18) =
+{ { "threadstat", 18, 0, "threadstat" },
+  {
+    //{"0123456701234567"}
+    {"node_id",             Ndbinfo::Number, ""},
+    {"thr_no",              Ndbinfo::Number, ""},
+    {"thr_nm",              Ndbinfo::String, ""},
+    {"c_loop",              Ndbinfo::Number64,""},
+    {"c_exec",              Ndbinfo::Number64,""},
+    {"c_wait",              Ndbinfo::Number64,""},
+    {"c_l_sent_prioa",      Ndbinfo::Number64,""},
+    {"c_l_sent_priob",      Ndbinfo::Number64,""},
+    {"c_r_sent_prioa",      Ndbinfo::Number64,""},
+    {"c_r_sent_priob",      Ndbinfo::Number64,""},
+    {"os_tid",              Ndbinfo::Number64,""},
+    {"os_now",              Ndbinfo::Number64,""},
+    {"os_ru_utime",         Ndbinfo::Number64,""},
+    {"os_ru_stime",         Ndbinfo::Number64,""},
+    {"os_ru_minflt",        Ndbinfo::Number64,""},
+    {"os_ru_majflt",        Ndbinfo::Number64,""},
+    {"os_ru_nvcsw",         Ndbinfo::Number64,""},
+    {"os_ru_nivcsw",        Ndbinfo::Number64,""}
+  }
+};
+
+DECLARE_NDBINFO_TABLE(TRANSACTIONS, 10) =
+{ { "transactions", 10, 0, "transactions" },
+  {
+    {"node_id",             Ndbinfo::Number, ""},
+    {"block_instance",      Ndbinfo::Number, ""},
+    {"objid",               Ndbinfo::Number, ""},
+    {"apiref",              Ndbinfo::Number, ""},
+    {"transid",             Ndbinfo::String, ""},
+    {"state",               Ndbinfo::Number, ""},
+    {"flags",               Ndbinfo::Number, ""},
+    {"c_ops",               Ndbinfo::Number, "No of operations" },
+    {"outstanding",         Ndbinfo::Number, "Outstanding request" },
+    {"timer",               Ndbinfo::Number, "(in seconds)"},
+  }
+};
+
 #define DBINFOTBL(x) { Ndbinfo::x##_TABLEID, (Ndbinfo::Table*)&ndbinfo_##x }
 
 static
@@ -188,7 +239,10 @@ struct ndbinfo_table_list_entry {
   DBINFOTBL(RESOURCES),
   DBINFOTBL(COUNTERS),
   DBINFOTBL(NODES),
-  DBINFOTBL(DISKPAGEBUFFER)
+  DBINFOTBL(DISKPAGEBUFFER),
+  DBINFOTBL(THREADBLOCKS),
+  DBINFOTBL(THREADSTAT),
+  DBINFOTBL(TRANSACTIONS)
 };
 
 static int no_ndbinfo_tables =

=== modified file 'storage/ndb/src/kernel/vm/Pool.hpp'
--- a/storage/ndb/src/kernel/vm/Pool.hpp	2011-02-01 23:27:25 +0000
+++ b/storage/ndb/src/kernel/vm/Pool.hpp	2011-10-07 11:46:40 +0000
@@ -33,7 +33,7 @@
  */
 #define RG_BITS 5
 #define RG_MASK ((1 << RG_BITS) - 1)
-#define MAKE_TID(TID,RG) ((TID << RG_BITS) | RG)
+#define MAKE_TID(TID,RG) Uint32((TID << RG_BITS) | RG)
 
 /**
  * Page bits

=== modified file 'storage/ndb/src/kernel/vm/SimulatedBlock.hpp'
--- a/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2011-08-27 06:06:02 +0000
+++ b/storage/ndb/src/kernel/vm/SimulatedBlock.hpp	2011-10-07 08:07:21 +0000
@@ -634,7 +634,9 @@ private:
    * In MT LQH main instance is the LQH proxy and the others ("workers")
    * are real LQHs run by multiple threads.
    */
-  enum { MaxInstances = 1 + MAX_NDBMT_LQH_WORKERS + 1 }; // main+lqh+extra
+protected:
+  enum { MaxInstances = 3 + MAX_NDBMT_TC_THREADS + MAX_NDBMT_LQH_WORKERS + 1 };
+private:
   SimulatedBlock** theInstanceList; // set in main, indexed by instance
   SimulatedBlock* theMainInstance;  // set in all
   /*

=== modified file 'storage/ndb/src/kernel/vm/dummy_nonmt.cpp'
--- a/storage/ndb/src/kernel/vm/dummy_nonmt.cpp	2011-09-15 20:21:59 +0000
+++ b/storage/ndb/src/kernel/vm/dummy_nonmt.cpp	2011-10-07 08:07:21 +0000
@@ -20,49 +20,62 @@
 #include <ndb_types.h>
 
 void
-add_thr_map(Uint32, Uint32, Uint32)
+mt_init_thr_map()
 {
   assert(false);
 }
 
 void
-add_main_thr_map()
+mt_add_thr_map(Uint32, Uint32)
 {
   assert(false);
 }
 
 void
-add_lqh_worker_thr_map(Uint32, Uint32)
+mt_finalize_thr_map()
 {
   assert(false);
 }
 
-void
-add_extra_worker_thr_map(Uint32, Uint32)
+Uint32
+mt_get_instance_count(Uint32 block)
 {
   assert(false);
+  return 0;
 }
 
-void
-add_tc_worker_thr_map(Uint32, Uint32)
+Uint32
+compute_jb_pages(struct EmulatorData*)
 {
-  assert(false);
+  return 0;
 }
 
-void
-finalize_thr_map()
+
+bool
+NdbIsMultiThreaded()
 {
-  assert(false);
+  return false;
 }
 
+#include <BlockNumbers.h>
+
 Uint32
-compute_jb_pages(struct EmulatorData*)
+mt_get_blocklist(class SimulatedBlock * block, Uint32 arr[], Uint32 len)
 {
-  return 0;
+  (void)block;
+  for (Uint32 i = 0; i<NO_OF_BLOCKS; i++)
+  {
+    arr[i] = numberToBlock(MIN_BLOCK_NO + i, 0);
+  }
+  return NO_OF_BLOCKS;
 }
 
-bool
-NdbIsMultiThreaded()
+#include "mt.hpp"
+
+void
+mt_get_thr_stat(class SimulatedBlock *, ndb_thr_stat* dst)
 {
-  return false;
+  bzero(dst, sizeof(* dst));
+  dst->name = "main";
 }
+

=== modified file 'storage/ndb/src/kernel/vm/mt.cpp'
--- a/storage/ndb/src/kernel/vm/mt.cpp	2011-09-15 20:21:59 +0000
+++ b/storage/ndb/src/kernel/vm/mt.cpp	2011-10-07 08:07:21 +0000
@@ -72,11 +72,11 @@ static const Uint32 MAX_SIGNALS_BEFORE_W
 
 //#define NDB_MT_LOCK_TO_CPU
 
-#define MAX_BLOCK_INSTANCES (1 + MAX_NDBMT_LQH_WORKERS + 1) //main+lqh+extra
 #define NUM_MAIN_THREADS 2 // except receiver
 #define MAX_THREADS (NUM_MAIN_THREADS +       \
                      MAX_NDBMT_LQH_THREADS +  \
                      MAX_NDBMT_TC_THREADS + 1)
+#define MAX_BLOCK_INSTANCES (MAX_THREADS)
 
 /* If this is too small it crashes before first signal. */
 #define MAX_INSTANCES_PER_THREAD (16 + 8 * MAX_NDBMT_LQH_THREADS)
@@ -876,10 +876,16 @@ struct thr_data
   /* Watchdog counter for this thread. */
   Uint32 m_watchdog_counter;
   /* Signal delivery statistics. */
-  Uint32 m_prioa_count;
-  Uint32 m_prioa_size;
-  Uint32 m_priob_count;
-  Uint32 m_priob_size;
+  struct
+  {
+    Uint64 m_loop_cnt;
+    Uint64 m_exec_cnt;
+    Uint64 m_wait_cnt;
+    Uint64 m_prioa_count;
+    Uint64 m_prioa_size;
+    Uint64 m_priob_count;
+    Uint64 m_priob_size;
+  } m_stat;
 
   /* Array of node ids with pending remote send data. */
   Uint8 m_pending_send_nodes[MAX_NTRANSPORTERS];
@@ -2592,7 +2598,7 @@ add_thr_map(Uint32 main, Uint32 instance
 
 /* Static assignment of main instances (before first signal). */
 void
-add_main_thr_map()
+mt_init_thr_map()
 {
   /* Keep mt-classic assignments in MT LQH. */
   const Uint32 thr_GLOBAL = 0;
@@ -2620,33 +2626,72 @@ add_main_thr_map()
   add_thr_map(RESTORE, 0, thr_LOCAL);
   add_thr_map(DBINFO, 0, thr_LOCAL);
   add_thr_map(DBSPJ, 0, thr_GLOBAL);
+  add_thr_map(THRMAN, 0, thr_GLOBAL);
 }
 
-/* Workers added by LocalProxy (before first signal). */
-void
-add_lqh_worker_thr_map(Uint32 block, Uint32 instance)
+Uint32
+mt_get_instance_count(Uint32 block)
 {
-  require(instance != 0);
-  Uint32 i = instance - 1;
-  Uint32 thr_no = NUM_MAIN_THREADS + i % num_lqh_threads;
-  add_thr_map(block, instance, thr_no);
+  switch(block){
+  case DBLQH:
+  case DBACC:
+  case DBTUP:
+  case DBTUX:
+  case BACKUP:
+  case RESTORE:
+    return globalData.ndbMtLqhWorkers;
+    break;
+  case PGMAN:
+    return globalData.ndbMtLqhWorkers + 1;
+    break;
+  case DBTC:
+  case DBSPJ:
+    return globalData.ndbMtTcThreads;
+    break;
+  case THRMAN:
+    return num_threads;
+  default:
+    require(false);
+  }
+  return 0;
 }
 
 void
-add_tc_worker_thr_map(Uint32 block, Uint32 instance)
+mt_add_thr_map(Uint32 block, Uint32 instance)
 {
   require(instance != 0);
-  Uint32 i = instance - 1;
-  Uint32 thr_no = NUM_MAIN_THREADS + num_lqh_threads + i;
-  add_thr_map(block, instance, thr_no);
-}
+  Uint32 thr_no = NUM_MAIN_THREADS;
+  switch(block){
+  case DBLQH:
+  case DBACC:
+  case DBTUP:
+  case DBTUX:
+  case BACKUP:
+  case RESTORE:
+    thr_no += (instance - 1) % num_lqh_threads;
+    break;
+  case PGMAN:
+    if (instance == num_lqh_threads + 1)
+    {
+      // Put extra PGMAN together with it's Proxy
+      thr_no = block2ThreadId(block, 0);
+    }
+    else
+    {
+      thr_no += (instance - 1) % num_lqh_threads;
+    }
+    break;
+  case DBTC:
+  case DBSPJ:
+    thr_no += num_lqh_threads + (instance - 1);
+    break;
+  case THRMAN:
+    thr_no = instance - 1;
+    break;
+  default:
+    require(false);
+  }
 
-/* Extra workers run`in proxy thread. */
-void
-add_extra_worker_thr_map(Uint32 block, Uint32 instance)
-{
-  require(instance != 0);
-  Uint32 thr_no = block2ThreadId(block, 0);
   add_thr_map(block, instance, thr_no);
 }
 
@@ -2661,7 +2706,7 @@ add_extra_worker_thr_map(Uint32 block, U
  * NOTE: extra pgman worker is instance 5
  */
 void
-finalize_thr_map()
+mt_finalize_thr_map()
 {
   for (Uint32 b = 0; b < NO_OF_BLOCKS; b++)
   {
@@ -2694,60 +2739,6 @@ finalize_thr_map()
   }
 }
 
-static void reportSignalStats(Uint32 self, Uint32 a_count, Uint32 a_size,
-                              Uint32 b_count, Uint32 b_size)
-{
-  SignalT<6> sT;
-  Signal *s= new (&sT) Signal(0);
-
-  memset(&s->header, 0, sizeof(s->header));
-  s->header.theLength = 6;
-  s->header.theSendersSignalId = 0;
-  s->header.theSendersBlockRef = numberToRef(0, 0);
-  s->header.theVerId_signalNumber = GSN_EVENT_REP;
-  s->header.theReceiversBlockNumber = CMVMI;
-  s->theData[0] = NDB_LE_MTSignalStatistics;
-  s->theData[1] = self;
-  s->theData[2] = a_count;
-  s->theData[3] = a_size;
-  s->theData[4] = b_count;
-  s->theData[5] = b_size;
-  /* ToDo: need this really be prio A like in old code? */
-  sendlocal(self, &s->header, s->theData,
-            NULL);
-}
-
-static inline void
-update_sched_stats(thr_data *selfptr)
-{
-  if(selfptr->m_prioa_count + selfptr->m_priob_count >= 2000000)
-  {
-    reportSignalStats(selfptr->m_thr_no,
-                      selfptr->m_prioa_count,
-                      selfptr->m_prioa_size,
-                      selfptr->m_priob_count,
-                      selfptr->m_priob_size);
-    selfptr->m_prioa_count = 0;
-    selfptr->m_prioa_size = 0;
-    selfptr->m_priob_count = 0;
-    selfptr->m_priob_size = 0;
-
-#if 0
-    Uint32 thr_no = selfptr->m_thr_no;
-    ndbout_c("--- %u fifo: %u jba: %u global: %u",
-             thr_no,
-             fifo_used_pages(selfptr),
-             selfptr->m_jba_head.used(),
-             g_thr_repository.m_free_list.m_cnt);
-    for (Uint32 i = 0; i<num_threads; i++)
-    {
-      ndbout_c("  %u-%u : %u",
-               thr_no, i, selfptr->m_in_queue_head[i].used());
-    }
-#endif
-  }
-}
-
 static void
 init_thread(thr_data *selfptr)
 {
@@ -2854,8 +2845,6 @@ mt_receiver_thread_main(void *thr_arg)
   { 
     static int cnt = 0;
 
-    update_sched_stats(selfptr);
-
     if (cnt == 0)
     {
       watchDogCounter = 5;
@@ -2892,6 +2881,8 @@ mt_receiver_thread_main(void *thr_arg)
         has_received = true;
       }
     }
+    selfptr->m_stat.m_loop_cnt++;
+    selfptr->m_stat.m_exec_cnt += sum;
   }
 
   globalEmulatorData.theWatchDog->unregisterWatchedThread(thr_no);
@@ -3028,14 +3019,14 @@ mt_job_thread_main(void *thr_arg)
 
   Uint32 pending_send = 0;
   Uint32 send_sum = 0;
-  int loops = 0;
-  int maxloops = 10;/* Loops before reading clock, fuzzy adapted to 1ms freq. */
+  Uint32 loops = 0;
+  Uint32 maxloops = 10;/* Loops before reading clock, fuzzy adapted to 1ms freq. */
+  Uint32 waits = 0;
   NDB_TICKS now = selfptr->m_time;
 
   while (globalData.theRestartFlag != perform_stop)
   { 
     loops++;
-    update_sched_stats(selfptr);
 
     watchDogCounter = 2;
     scan_time_queues(selfptr, now);
@@ -3080,9 +3071,12 @@ mt_job_thread_main(void *thr_arg)
                             selfptr);
         if (waited)
         {
+          waits++;
           /* Update current time after sleeping */
           now = NdbTick_CurrentMillisecond();
-          loops = 0;
+          selfptr->m_stat.m_wait_cnt += waits;
+          selfptr->m_stat.m_loop_cnt += loops;
+          waits = loops = 0;
         }
       }
     }
@@ -3097,7 +3091,9 @@ mt_job_thread_main(void *thr_arg)
       {
         /* Update current time after sleeping */
         now = NdbTick_CurrentMillisecond();
-        loops = 0;
+        selfptr->m_stat.m_wait_cnt += waits;
+        selfptr->m_stat.m_loop_cnt += loops;
+        waits = loops = 0;
       }
     }
     else
@@ -3120,8 +3116,11 @@ mt_job_thread_main(void *thr_arg)
       else if (diff > 1 && maxloops > 1)
         maxloops -= ((maxloops/10) + 1); /* Overslept: Need more frequent read*/
 
-      loops = 0;
+      selfptr->m_stat.m_wait_cnt += waits;
+      selfptr->m_stat.m_loop_cnt += loops;
+      waits = loops = 0;
     }
+    selfptr->m_stat.m_exec_cnt += sum;
   }
 
   globalEmulatorData.theWatchDog->unregisterWatchedThread(thr_no);
@@ -3150,9 +3149,9 @@ sendlocal(Uint32 self, const SignalHeade
   assert(pthread_equal(selfptr->m_thr_id, pthread_self()));
   struct thr_data * dstptr = rep->m_thread + dst;
 
-  selfptr->m_priob_count++;
+  selfptr->m_stat.m_priob_count++;
   Uint32 siglen = (sizeof(*s) >> 2) + s->theLength + s->m_noOfSections;
-  selfptr->m_priob_size += siglen;
+  selfptr->m_stat.m_priob_size += siglen;
 
   thr_job_queue *q = dstptr->m_in_queue + self;
   thr_jb_write_state *w = selfptr->m_write_states + dst;
@@ -3178,9 +3177,9 @@ sendprioa(Uint32 self, const SignalHeade
          pthread_equal(selfptr->m_thr_id, pthread_self()));
   struct thr_data *dstptr = rep->m_thread + dst;
 
-  selfptr->m_prioa_count++;
+  selfptr->m_stat.m_prioa_count++;
   Uint32 siglen = (sizeof(*s) >> 2) + s->theLength + s->m_noOfSections;
-  selfptr->m_prioa_size += siglen;  
+  selfptr->m_stat.m_prioa_size += siglen;
 
   thr_job_queue *q = &(dstptr->m_jba);
   thr_jb_write_state w;
@@ -3359,10 +3358,7 @@ thr_init(struct thr_repository* rep, str
   }
   queue_init(&selfptr->m_tq);
 
-  selfptr->m_prioa_count = 0;
-  selfptr->m_prioa_size = 0;
-  selfptr->m_priob_count = 0;
-  selfptr->m_priob_size = 0;
+  bzero(&selfptr->m_stat, sizeof(selfptr->m_stat));
 
   selfptr->m_pending_send_count = 0;
   selfptr->m_pending_send_mask.clear();
@@ -4086,6 +4082,40 @@ mt_assert_own_thread(SimulatedBlock* blo
 }
 #endif
 
+
+Uint32
+mt_get_blocklist(SimulatedBlock * block, Uint32 arr[], Uint32 len)
+{
+  Uint32 thr_no = block->getThreadId();
+  thr_data *thr_ptr = g_thr_repository.m_thread + thr_no;
+
+  for (Uint32 i = 0; i < thr_ptr->m_instance_count; i++)
+  {
+    arr[i] = thr_ptr->m_instance_list[i];
+  }
+
+  return thr_ptr->m_instance_count;
+}
+
+void
+mt_get_thr_stat(class SimulatedBlock * block, ndb_thr_stat* dst)
+{
+  bzero(dst, sizeof(* dst));
+  Uint32 thr_no = block->getThreadId();
+  thr_data *selfptr = g_thr_repository.m_thread + thr_no;
+
+  THRConfigApplier & conf = globalEmulatorData.theConfiguration->m_thr_config;
+  dst->thr_no = thr_no;
+  dst->name = conf.getName(selfptr->m_instance_list, selfptr->m_instance_count);
+  dst->os_tid = NdbThread_GetTid(selfptr->m_thread);
+  dst->loop_cnt = selfptr->m_stat.m_loop_cnt;
+  dst->exec_cnt = selfptr->m_stat.m_exec_cnt;
+  dst->wait_cnt = selfptr->m_stat.m_wait_cnt;
+  dst->local_sent_prioa = selfptr->m_stat.m_prioa_count;
+  dst->local_sent_priob = selfptr->m_stat.m_priob_count;
+}
+
+
 /**
  * Global data
  */

=== modified file 'storage/ndb/src/kernel/vm/mt.hpp'
--- a/storage/ndb/src/kernel/vm/mt.hpp	2011-09-15 20:21:59 +0000
+++ b/storage/ndb/src/kernel/vm/mt.hpp	2011-10-07 08:07:21 +0000
@@ -29,13 +29,12 @@
 */
 extern Uint32 receiverThreadId;
 
+Uint32 mt_get_instance_count(Uint32 block);
+
 /* Assign block instances to thread */
-void add_thr_map(Uint32 block, Uint32 instance, Uint32 thr_no);
-void add_main_thr_map();
-void add_lqh_worker_thr_map(Uint32 block, Uint32 instance);
-void add_tc_worker_thr_map(Uint32 block, Uint32 instance);
-void add_extra_worker_thr_map(Uint32 block, Uint32 instance);
-void finalize_thr_map();
+void mt_init_thr_map();
+void mt_add_thr_map(Uint32 block, Uint32 instance);
+void mt_finalize_thr_map();
 
 void sendlocal(Uint32 self, const struct SignalHeader *s,
                const Uint32 *data, const Uint32 secPtr[3]);
@@ -87,4 +86,28 @@ void mt_wakeup(class SimulatedBlock*);
 void mt_assert_own_thread(class SimulatedBlock*);
 #endif
 
+/**
+ * return list of references running in this thread
+ */
+Uint32
+mt_get_blocklist(class SimulatedBlock*, Uint32 dst[], Uint32 len);
+
+
+struct ndb_thr_stat
+{
+  Uint32 thr_no;
+  Uint64 os_tid;
+  const char * name;
+  Uint64 loop_cnt;
+  Uint64 exec_cnt;
+  Uint64 wait_cnt;
+  Uint64 local_sent_prioa;
+  Uint64 local_sent_priob;
+  Uint64 remote_sent_prioa;
+  Uint64 remote_sent_priob;
+};
+
+void
+mt_get_thr_stat(class SimulatedBlock *, ndb_thr_stat* dst);
+
 #endif

=== modified file 'storage/ndb/src/kernel/vm/mt_thr_config.cpp'
--- a/storage/ndb/src/kernel/vm/mt_thr_config.cpp	2011-09-23 09:13:22 +0000
+++ b/storage/ndb/src/kernel/vm/mt_thr_config.cpp	2011-10-07 08:07:21 +0000
@@ -964,6 +964,14 @@ THRConfigApplier::appendInfo(BaseString&
   }
 }
 
+const char *
+THRConfigApplier::getName(const unsigned short list[], unsigned cnt) const
+{
+  const T_Thread* thr = find_thread(list, cnt);
+  assert(thr != 0);
+  return getEntryName(thr->m_type);
+}
+
 int
 THRConfigApplier::create_cpusets()
 {

=== modified file 'storage/ndb/src/kernel/vm/mt_thr_config.hpp'
--- a/storage/ndb/src/kernel/vm/mt_thr_config.hpp	2011-09-23 09:13:22 +0000
+++ b/storage/ndb/src/kernel/vm/mt_thr_config.hpp	2011-10-07 08:07:21 +0000
@@ -124,6 +124,7 @@ class THRConfigApplier : public THRConfi
 public:
   int create_cpusets();
 
+  const char * getName(const unsigned short list[], unsigned cnt) const;
   void appendInfo(BaseString&, const unsigned short list[], unsigned cnt) const;
   int do_bind(NdbThread*, const unsigned short list[], unsigned cnt);
   int do_bind_io(NdbThread*);

=== modified file 'storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp'
--- a/storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp	2011-08-16 08:27:14 +0000
+++ b/storage/ndb/src/kernel/vm/ndbd_malloc_impl.hpp	2011-10-07 13:15:08 +0000
@@ -94,7 +94,7 @@ public:
 private:
   void grow(Uint32 start, Uint32 cnt);
 
-#define XX_RL_COUNT 9
+#define XX_RL_COUNT 10
   /**
    * Return pointer to free page data on page
    */

=== modified file 'storage/ndb/src/mgmsrv/ConfigInfo.cpp'
--- a/storage/ndb/src/mgmsrv/ConfigInfo.cpp	2011-09-02 17:24:52 +0000
+++ b/storage/ndb/src/mgmsrv/ConfigInfo.cpp	2011-10-07 16:12:13 +0000
@@ -2122,6 +2122,22 @@ const ConfigInfo::ParamInfo ConfigInfo::
     STR_VALUE(MAX_INT_RNIL)
   },
 
+  {
+    CFG_DB_CRASH_ON_CORRUPTED_TUPLE,
+    "CrashOnCorruptedTuple",
+    DB_TOKEN,
+    "To be failfast or not, when checksum indicates corruption.",
+    ConfigInfo::CI_USED,
+    false,
+    ConfigInfo::CI_BOOL,
+#if NDB_VERSION_D < NDB_MAKE_VERSION(7,2,1)
+    "false",
+#else
+    "true",
+#endif
+    "false",
+    "true"},
+
   /***************************************************************************
    * API
    ***************************************************************************/

=== modified file 'storage/ndb/src/mgmsrv/MgmtSrvr.cpp'
--- a/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2011-09-19 14:10:19 +0000
+++ b/storage/ndb/src/mgmsrv/MgmtSrvr.cpp	2011-09-27 07:35:34 +0000
@@ -528,8 +528,6 @@ MgmtSrvr::start()
 {
   DBUG_ENTER("MgmtSrvr::start");
 
-  Guard g(m_local_config_mutex);
-
   /* Start transporter */
   if(!start_transporter(m_local_config))
   {
@@ -3451,15 +3449,17 @@ MgmtSrvr::try_alloc_from_list(NodeId& no
   for (unsigned i = 0; i < nodes.size(); i++)
   {
     const unsigned id= nodes[i].id;
-    if (m_reserved_nodes.get(id))
+    if (theFacade->ext_isConnected(id))
     {
-      // Node is already reserved(locally in this node)
+      // Node is already reserved(connected via transporter)
       continue;
     }
 
-    if (theFacade->ext_isConnected(id))
+    NdbMutex_Lock(m_reserved_nodes_mutex);
+    if (m_reserved_nodes.get(id))
     {
-      // Node is already reserved(connected via transporter)
+      // Node is already reserved(locally in this node)
+      NdbMutex_Unlock(m_reserved_nodes_mutex);
       continue;
     }
 
@@ -3483,16 +3483,14 @@ MgmtSrvr::try_alloc_from_list(NodeId& no
           more than one thread asked for same nodeid) since it's
           now reserved in data node
         */
-        m_reserved_nodes.clear(id);
+        release_local_nodeid_reservation(id);
       }
 
-      NdbMutex_Lock(m_reserved_nodes_mutex);
       return true;
     }
 
     /* Release the local reservation */
-    m_reserved_nodes.clear(id);
-    NdbMutex_Lock(m_reserved_nodes_mutex);
+    release_local_nodeid_reservation(id);
 
     if (res < 0)
     {
@@ -3601,8 +3599,6 @@ MgmtSrvr::alloc_node_id_impl(NodeId& nod
     return false;
   }
 
-  Guard g(m_reserved_nodes_mutex);
-
   /* Check timeout of nodeid reservations for NDB */
   if (type == NDB_MGM_NODE_TYPE_NDB)
   {
@@ -3610,8 +3606,11 @@ MgmtSrvr::alloc_node_id_impl(NodeId& nod
     for (unsigned i = 0; i < nodes.size(); i++)
     {
       const NodeId ndb_nodeid = nodes[i].id;
-      if (!m_reserved_nodes.has_timedout(ndb_nodeid, now))
-        continue;
+      {
+        Guard g(m_reserved_nodes_mutex);
+        if (!m_reserved_nodes.has_timedout(ndb_nodeid, now))
+          continue;
+      }
 
       // Found a timedout reservation
       if (theFacade->ext_isConnected(ndb_nodeid))
@@ -3621,7 +3620,7 @@ MgmtSrvr::alloc_node_id_impl(NodeId& nod
                              "releasing it", ndb_nodeid);
 
       // Clear the reservation
-      m_reserved_nodes.clear(ndb_nodeid);
+      release_local_nodeid_reservation(ndb_nodeid);
     }
   }
 

=== modified file 'storage/ndb/src/ndbapi/NdbQueryBuilder.cpp'
--- a/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp	2011-09-14 10:30:08 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryBuilder.cpp	2011-09-29 11:35:02 +0000
@@ -343,7 +343,8 @@ NdbQueryDef::destroy() const
 void
 NdbQueryDef::print() const
 {
-  m_impl.getQueryOperation(0U).printTree(0, Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32>());
+  m_impl.getQueryOperation(0U)
+    .printTree(0, NdbQueryOperationDefImpl::SiblingMask());
 }
 
 /*************************************************************************
@@ -1188,7 +1189,8 @@ NdbQueryBuilderImpl::prepare()
   if (doPrintQueryTree)
   {
     ndbout << "Query tree:" << endl;
-    def->getQueryOperation(0U).printTree(0, Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32>());
+    def->getQueryOperation(0U)
+      .printTree(0, NdbQueryOperationDefImpl::SiblingMask());
   }
 
   return def;
@@ -2159,7 +2161,8 @@ NdbQueryOperationDefImpl::appendChildPro
  * that connect the tree nodes.
  */
 static void printMargin(Uint32 depth, 
-                        Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> hasMoreSiblingsMask, 
+                        NdbQueryOperationDefImpl::SiblingMask 
+                        hasMoreSiblingsMask, 
                         bool header)
 {
   if (depth > 0)
@@ -2193,11 +2196,10 @@ static void printMargin(Uint32 depth,
 
 void 
 NdbQueryOperationDefImpl::printTree(Uint32 depth, 
-                                    Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> 
-                                    hasMoreSiblingsMask) const
+                                    SiblingMask hasMoreSiblingsMask) const
 {
   // Print vertical line leading down to this node.
-  Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> firstLineMask = hasMoreSiblingsMask;
+  SiblingMask firstLineMask = hasMoreSiblingsMask;
   firstLineMask.set(depth);
   printMargin(depth, firstLineMask, false);
   ndbout << endl;
@@ -2214,22 +2216,24 @@ NdbQueryOperationDefImpl::printTree(Uint
     printMargin(depth, hasMoreSiblingsMask, false);
     ndbout << " index: " << getIndex()->getName() << endl; 
   }
-  /* For each child but the last one, use a mask with an extra bit set to
-   * indicate that there are more siblings.
-   */
-  hasMoreSiblingsMask.set(depth+1);
+
   for (int childNo = 0; 
-       childNo < static_cast<int>(getNoOfChildOperations()) - 1; 
+       childNo < static_cast<int>(getNoOfChildOperations()); 
        childNo++)
   {
-    getChildOperation(childNo).printTree(depth+1, hasMoreSiblingsMask);
-  }
-  if (getNoOfChildOperations() > 0)
-  {
-    // The last child has no more siblings.
-    hasMoreSiblingsMask.clear(depth+1);
-    getChildOperation(getNoOfChildOperations() - 1)
-      .printTree(depth+1, hasMoreSiblingsMask);
+    if (childNo == 0)
+    {
+      /* For each child but the last one, use a mask with an extra bit set to
+       * indicate that there are more siblings.
+       */
+      hasMoreSiblingsMask.set(depth+1);
+    }
+    if (childNo == static_cast<int>(getNoOfChildOperations()) - 1)
+    {
+      // The last child has no more siblings.
+      hasMoreSiblingsMask.clear(depth+1);
+    }
+    getChildOperation(childNo).printTree(depth+1, hasMoreSiblingsMask); 
   }
 } // NdbQueryOperationDefImpl::printTree()
 

=== modified file 'storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp'
--- a/storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp	2011-09-14 10:30:08 +0000
+++ b/storage/ndb/src/ndbapi/NdbQueryBuilderImpl.hpp	2011-09-29 11:35:02 +0000
@@ -429,6 +429,12 @@ public:
   // Get type of query operation
   virtual NdbQueryOperationDef::Type getType() const = 0;
 
+  /**
+   * Used for telling if parent at depth n has more siblings. (In that case
+   * we need to draw a horisontal line leading to that sibling.)
+   */
+  typedef Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> SiblingMask;
+
   /** Print query tree graph to trace file (using recursion).
    * @param depth Number of ancestor nodes that this node has.
    * @param hasMoreSiblingsMask The n'th bit should be set if the n'th ancestor
@@ -436,7 +442,7 @@ public:
    */
   void printTree(
            Uint32 depth, 
-           Bitmask<(NDB_SPJ_MAX_TREE_NODES+31)/32> hasMoreSiblingsMask) const;
+           SiblingMask hasMoreSiblingsMask) const;
 
 protected:
   // QueryTree building:

=== modified file 'storage/ndb/src/ndbapi/ndberror.c'
--- a/storage/ndb/src/ndbapi/ndberror.c	2011-09-22 11:48:33 +0000
+++ b/storage/ndb/src/ndbapi/ndberror.c	2011-10-07 13:15:08 +0000
@@ -493,7 +493,8 @@ ErrorBundle ErrorCodes[] = {
   { 786,  DMEC, NR, "Schema transaction aborted due to node-failure" },
   { 792,  DMEC, SE, "Default value for primary key column not supported" },
   { 794,  DMEC, AE, "Schema feature requires data node upgrade" },
-  
+  { 796,  DMEC, SE, "Out of schema transaction memory" },
+
   /**
    * FunctionNotImplemented
    */

=== modified file 'storage/ndb/test/include/HugoQueryBuilder.hpp'
--- a/storage/ndb/test/include/HugoQueryBuilder.hpp	2011-07-04 13:37:56 +0000
+++ b/storage/ndb/test/include/HugoQueryBuilder.hpp	2011-10-04 06:23:21 +0000
@@ -60,15 +60,9 @@ public:
     /**
      * Query might table scan
      */
-    O_TABLE_SCAN = 0x20,
-
-    /**
-     * If not any options set, random query qill be created
-     */
-    O_RANDOM_OPTIONS = (OptionMask)((~(OptionMask)0) & 
-                                    ~(OptionMask)(O_SCAN | O_LOOKUP))
+    O_TABLE_SCAN = 0x20
   };
-  static const OptionMask OM_RANDOM_OPTIONS = (OptionMask)O_RANDOM_OPTIONS;
+  static const OptionMask OM_RANDOM_OPTIONS = (OptionMask)(O_PK_INDEX | O_UNIQUE_INDEX | O_ORDERED_INDEX | O_TABLE_SCAN);
 
   HugoQueryBuilder(Ndb* ndb, const NdbDictionary::Table**tabptr, 
                    OptionMask om = OM_RANDOM_OPTIONS){

=== modified file 'storage/ndb/test/ndbapi/testNdbApi.cpp'
--- a/storage/ndb/test/ndbapi/testNdbApi.cpp	2011-09-19 12:08:00 +0000
+++ b/storage/ndb/test/ndbapi/testNdbApi.cpp	2011-09-29 06:48:39 +0000
@@ -4580,8 +4580,17 @@ public:
         m_id(id), m_res(res) {
       m_res.lock(m_id);
     }
-    ~Reserve(){
+
+    void unlock() {
       m_res.unlock(m_id);
+      m_id = 0;
+    }
+
+    ~Reserve(){
+      if (m_id)
+      {
+        m_res.unlock(m_id);
+      }
     }
   };
 };
@@ -4644,6 +4653,8 @@ int runNdbClusterConnect(NDBT_Context* c
 {
   const Uint32 api_nodes = ctx->getProperty("API_NODES");
   const Uint32 step_no = step->getStepNo();
+  const Uint32 timeout_after_first_alive = ctx->getProperty("TimeoutAfterFirst",
+                                                            30);
   if (step_no > api_nodes)
   {
     // Don't run with more threads than API node slots
@@ -4652,8 +4663,8 @@ int runNdbClusterConnect(NDBT_Context* c
 
   // Get connectstring from main connection
   char constr[256];
-  if(!ctx->m_cluster_connection.get_connectstring(constr,
-                                                  sizeof(constr)))
+  if (!ctx->m_cluster_connection.get_connectstring(constr,
+                                                   sizeof(constr)))
   {
     g_err << "Too short buffer for connectstring" << endl;
     return NDBT_FAILED;
@@ -4661,9 +4672,17 @@ int runNdbClusterConnect(NDBT_Context* c
 
   Uint32 l = 0;
   const Uint32 loops = ctx->getNumLoops();
-  while (l < loops)
+  while (l < loops && !ctx->isTestStopped())
   {
     g_info << "loop: " << l << endl;
+    if (ctx->getProperty("WAIT") > 0)
+    {
+      ndbout_c("thread %u waiting", step_no);
+      ctx->incProperty("WAITING");
+      while (ctx->getProperty("WAIT") > 0 && !ctx->isTestStopped())
+        NdbSleep_MilliSleep(10);
+      ndbout_c("thread %u waiting complete", step_no);
+    }
     Ndb_cluster_connection con(constr);
 
     const int retries = 12;
@@ -4679,11 +4698,12 @@ int runNdbClusterConnect(NDBT_Context* c
     NodeIdReservations::Reserve res(g_reservations, con.node_id());
 
     const int timeout = 30;
-    const int timeout_after_first_alive = 30;
-    if (con.wait_until_ready(timeout, timeout_after_first_alive) != 0)
+    int ret = con.wait_until_ready(timeout, timeout_after_first_alive);
+    if (! (ret == 0 || (timeout_after_first_alive == 0 && ret > 0)))
     {
       g_err << "Cluster connection was not ready, nodeid: "
             << con.node_id() << endl;
+      abort();
       return NDBT_FAILED;
     }
 
@@ -4699,12 +4719,153 @@ int runNdbClusterConnect(NDBT_Context* c
     NdbSleep_MilliSleep(10 + rand() % max_sleep);
 
     l++;
+    res.unlock(); // make sure it's called before ~Ndb_cluster_connection
+  }
+
+  ctx->incProperty("runNdbClusterConnect_FINISHED");
+
+  return NDBT_OK;
+}
+
+int
+runRestarts(NDBT_Context* ctx, NDBT_Step* step)
+{
+  int result = NDBT_OK;
+  Uint32 threads = ctx->getProperty("API_NODES", (unsigned)0);
+  Uint32 sr = ctx->getProperty("ClusterRestart", (unsigned)0);
+  Uint32 master = ctx->getProperty("Master", (unsigned)0);
+  Uint32 slow = ctx->getProperty("SlowNR", (unsigned)0);
+  NdbRestarter restarter;
+
+  if (restarter.waitClusterStarted() != 0)
+  {
+    g_err << "Cluster failed to start" << endl;
+    return NDBT_FAILED;
+  }
+
+  if (sr == 0 && restarter.getNumDbNodes() < 2)
+    return NDBT_OK;
+
+  while (ctx->getProperty("runNdbClusterConnect_FINISHED") < threads
+         && !ctx->isTestStopped())
+  {
+    ndbout_c("%u %u",
+             ctx->getProperty("runNdbClusterConnect_FINISHED"),
+             threads);
+    if (sr == 0)
+    {
+      int id = rand() % restarter.getNumDbNodes();
+      int nodeId = restarter.getDbNodeId(id);
+      if (master == 1)
+      {
+        nodeId = restarter.getMasterNodeId();
+      }
+      else if (master == 2)
+      {
+        nodeId = restarter.getRandomNotMasterNodeId(rand());
+      }
+      ndbout << "Restart node " << nodeId
+             << "(master: " << restarter.getMasterNodeId() << ")"
+             << endl;
+      if (restarter.restartOneDbNode(nodeId, false, true, true) != 0)
+      {
+        g_err << "Failed to restartNextDbNode" << endl;
+        result = NDBT_FAILED;
+        break;
+      }
+
+      if (restarter.waitNodesNoStart(&nodeId, 1))
+      {
+        g_err << "Failed to waitNodesNoStart" << endl;
+        result = NDBT_FAILED;
+        break;
+      }
+
+      if (slow)
+      {
+        /**
+         * Block starting node in sp4
+         */
+        int dump[] = { 71, 4 };
+        restarter.dumpStateOneNode(nodeId, dump, NDB_ARRAY_SIZE(dump));
+      }
+
+      if (restarter.startNodes(&nodeId, 1))
+      {
+        g_err << "Failed to start node" << endl;
+        result = NDBT_FAILED;
+        break;
+      }
+
+      if (slow)
+      {
+        Uint32 blockTime = 3 * 60 * 1000;
+        Uint64 end = NdbTick_CurrentMillisecond() + blockTime;
+        while (ctx->getProperty("runNdbClusterConnect_FINISHED") < threads
+               && !ctx->isTestStopped() &&
+               NdbTick_CurrentMillisecond() < end)
+        {
+          NdbSleep_MilliSleep(100);
+        }
+
+        // unblock
+        int dump[] = { 71 };
+        restarter.dumpStateOneNode(nodeId, dump, NDB_ARRAY_SIZE(dump));
+      }
+    }
+    else
+    {
+      ndbout << "Blocking threads" << endl;
+      ctx->setProperty("WAITING", Uint32(0));
+      ctx->setProperty("WAIT", 1);
+      while (ctx->getProperty("WAITING") <
+             (threads - ctx->getProperty("runNdbClusterConnect_FINISHED")) &&
+             !ctx->isTestStopped())
+      {
+        NdbSleep_MilliSleep(10);
+      }
+
+      ndbout << "Restart cluster" << endl;
+      if (restarter.restartAll2(Uint32(NdbRestarter::NRRF_NOSTART |
+                                       NdbRestarter::NRRF_ABORT)) != 0)
+      {
+        g_err << "Failed to restartAll" << endl;
+        result = NDBT_FAILED;
+        break;
+      }
+
+      ctx->setProperty("WAITING", Uint32(0));
+      ctx->setProperty("WAIT", Uint32(0));
+
+      ndbout << "Starting cluster" << endl;
+      restarter.startAll();
+    }
+
+    if (restarter.waitClusterStarted() != 0)
+    {
+      g_err << "Cluster failed to start" << endl;
+      result = NDBT_FAILED;
+      break;
+    }
+  }
+
+  return result;
+}
+
+int runCheckAllNodesStarted(NDBT_Context* ctx, NDBT_Step* step){
+  NdbRestarter restarter;
+
+  if (restarter.waitClusterStarted(1) != 0)
+  {
+    g_err << "All nodes was not started " << endl;
+    return NDBT_FAILED;
   }
 
   return NDBT_OK;
 }
 
 
+
 static bool
 check_connect_no_such_host()
 {
@@ -5040,7 +5201,50 @@ TESTCASE("NdbClusterConnectionConnect",
 {
   INITIALIZER(runNdbClusterConnectionConnect);
 }
-
+TESTCASE("NdbClusterConnectNR",
+         "Make sure that every Ndb_cluster_connection get a unique nodeid")
+{
+  TC_PROPERTY("TimeoutAfterFirst", (Uint32)0);
+  INITIALIZER(runNdbClusterConnectInit);
+  STEPS(runNdbClusterConnect, MAX_NODES);
+  STEP(runRestarts); // Note after runNdbClusterConnect or else counting wrong
+}
+TESTCASE("NdbClusterConnectNR_master",
+         "Make sure that every Ndb_cluster_connection get a unique nodeid")
+{
+  TC_PROPERTY("Master", 1);
+  TC_PROPERTY("TimeoutAfterFirst", (Uint32)0);
+  INITIALIZER(runNdbClusterConnectInit);
+  STEPS(runNdbClusterConnect, MAX_NODES);
+  STEP(runRestarts); // Note after runNdbClusterConnect or else counting wrong
+}
+TESTCASE("NdbClusterConnectNR_non_master",
+         "Make sure that every Ndb_cluster_connection get a unique nodeid")
+{
+  TC_PROPERTY("Master", 2);
+  TC_PROPERTY("TimeoutAfterFirst", (Uint32)0);
+  INITIALIZER(runNdbClusterConnectInit);
+  STEPS(runNdbClusterConnect, MAX_NODES);
+  STEP(runRestarts); // Note after runNdbClusterConnect or else counting wrong
+}
+TESTCASE("NdbClusterConnectNR_slow",
+         "Make sure that every Ndb_cluster_connection get a unique nodeid")
+{
+  TC_PROPERTY("Master", 2);
+  TC_PROPERTY("TimeoutAfterFirst", (Uint32)0);
+  TC_PROPERTY("SlowNR", 1);
+  INITIALIZER(runNdbClusterConnectInit);
+  STEPS(runNdbClusterConnect, MAX_NODES);
+  STEP(runRestarts); // Note after runNdbClusterConnect or else counting wrong
+}
+TESTCASE("NdbClusterConnectSR",
+         "Make sure that every Ndb_cluster_connection get a unique nodeid")
+{
+  TC_PROPERTY("ClusterRestart", (Uint32)1);
+  INITIALIZER(runNdbClusterConnectInit);
+  STEPS(runNdbClusterConnect, MAX_NODES);
+  STEP(runRestarts); // Note after runNdbClusterConnect or else counting wrong
+}
 NDBT_TESTSUITE_END(testNdbApi);
 
 int main(int argc, const char** argv){

=== modified file 'storage/ndb/test/ndbapi/testRestartGci.cpp'
--- a/storage/ndb/test/ndbapi/testRestartGci.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/ndbapi/testRestartGci.cpp	2011-09-29 06:48:39 +0000
@@ -486,7 +486,7 @@ int runNodeInitialRestarts(NDBT_Context*
     int nodeId = restarter.getNode(NdbRestarter::NS_RANDOM);
     ndbout_c("Restarting node %u", nodeId);
 
-    if (restarter.restartOneDbNode(nodeId, NdbRestarter::NRRF_INITIAL) != 0)
+    if (restarter.restartOneDbNode2(nodeId, NdbRestarter::NRRF_INITIAL) != 0)
     {
       ndbout_c("Error restarting node");
       ctx->stopTest();
@@ -546,7 +546,7 @@ int runUpdateVerifyGCI(NDBT_Context* ctx
     CHECK(rowGci != NULL);
 
     /* Define an update op to set the next GCI */
-    CHECK(hugoOps.pkUpdateRecord(pNdb, 0, 1, loopCount+1) == 0);
+    CHECK(hugoOps.pkUpdateRecord(pNdb, 0, 1, (int)(loopCount+1)) == 0);
 
     if (hugoOps.execute_Commit(pNdb) != 0)
     {

=== modified file 'storage/ndb/test/ndbapi/test_event.cpp'
--- a/storage/ndb/test/ndbapi/test_event.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/ndbapi/test_event.cpp	2011-09-28 10:04:03 +0000
@@ -168,7 +168,7 @@ Uint32 setAnyValue(Ndb* ndb, NdbTransact
 {
   /* XOR 2 32bit words of transid together */
   Uint64 transId = trans->getTransactionId();
-  return transId ^ (transId >> 32);
+  return (Uint32)(transId ^ (transId >> 32));
 }
 
 bool checkAnyValueTransId(Uint64 transId, Uint32 anyValue)

=== modified file 'storage/ndb/test/run-test/atrt.hpp'
--- a/storage/ndb/test/run-test/atrt.hpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/run-test/atrt.hpp	2011-10-03 11:06:06 +0000
@@ -187,9 +187,23 @@ extern int          g_baseport;
 extern int          g_fqpn;
 extern int          g_fix_nodeid;
 extern int          g_default_ports;
+extern int          g_restart;
 
 extern const char * g_clusters;
 
+/**
+ * Since binaries move location between 5.1 and 5.5
+ *   we keep full path to them here
+ */
+char * find_bin_path(const char * basename);
+extern const char * g_ndb_mgmd_bin_path;
+extern const char * g_ndbd_bin_path;
+extern const char * g_ndbmtd_bin_path;
+extern const char * g_mysqld_bin_path;
+extern const char * g_mysql_install_db_bin_path;
+
+extern const char * g_search_path[];
+
 #ifdef _WIN32
 #include <direct.h>
 

=== modified file 'storage/ndb/test/run-test/daily-basic-tests.txt'
--- a/storage/ndb/test/run-test/daily-basic-tests.txt	2011-09-09 10:48:14 +0000
+++ b/storage/ndb/test/run-test/daily-basic-tests.txt	2011-10-05 13:18:31 +0000
@@ -96,6 +96,10 @@ max-time: 600
 cmd: atrt-testBackup
 args: -n Bug57650 T1
 
+max-time: 1000
+cmd: atrt-testBackup
+args: -n BackupBank T6 
+
 # BASIC FUNCTIONALITY
 max-time: 500
 cmd: testBasic
@@ -356,6 +360,18 @@ max-time: 300
 cmd: testIndex
 args: -n FireTrigOverload T1
 
+max-time: 500
+cmd: testIndex
+args: -n Bug25059 -r 3000 T1
+
+max-time: 2500
+cmd: testIndex
+args: -l 2 -n SR1 T6 T13 
+
+max-time: 2500
+cmd: testIndex
+args: -l 2 -n SR1_O T6 T13 
+
 #
 # SCAN TESTS
 #
@@ -713,6 +729,10 @@ args: -n NFNR1_O T6 T13
 
 max-time: 2500
 cmd: testIndex
+args: -n NFNR2 T6 T13 
+
+max-time: 2500
+cmd: testIndex
 args: -n NFNR2_O T6 T13 
 
 max-time: 2500
@@ -809,6 +829,10 @@ max-time: 500
 cmd: testDict
 args: -n Bug54651 T1
 
+max-time: 1500
+cmd: testDict
+args: -n CreateMaxTables T6 
+
 #
 # TEST NDBAPI
 #
@@ -1034,6 +1058,14 @@ max-time: 5000
 cmd: testSystemRestart
 args: -n SR_UNDO T6 
 
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR3 T6 
+
+max-time: 1500
+cmd: testSystemRestart
+args: -n SR4 T6 
+
 #
 max-time: 5000
 cmd: testSystemRestart
@@ -1185,6 +1217,26 @@ max-time: 2500
 cmd: testNodeRestart
 args: -n RestartRandomNodeError T6 T13 
 
+max-time: 2500
+cmd: testNodeRestart
+args: -l 1 -n MixedReadUpdateScan 
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n Terror T6 T13 
+
+max-time: 3600
+cmd: testNodeRestart
+args: -l 1 -n RestartNFDuringNR T6 T13 
+
+max-time: 3600
+cmd: testNodeRestart
+args: -n RestartNodeDuringLCP T6 
+
+max-time: 2500
+cmd: testNodeRestart
+args: -n FiftyPercentStopAndWait T6 T13 
+
 #
 # MGMAPI AND MGSRV
 #
@@ -1366,6 +1418,10 @@ max-time: 600
 cmd: testSystemRestart
 args: -n Bug22696 T1
 
+max-time: 1000
+cmd: testSRBank
+args: -n SR -l 300 -r 15 T1
+
 max-time: 600
 cmd: testNodeRestart
 args: -n pnr --nologging T1
@@ -1753,3 +1809,24 @@ max-time: 500
 cmd: testAsynchMultiwait
 args: -n AsynchMultiwaitWakeup T1
 
+# alloc node id
+max-time: 500
+cmd: testNdbApi
+args: -n NdbClusterConnect T1
+
+max-time: 500
+cmd: testNdbApi
+args: -n NdbClusterConnectionConnect T1
+
+max-time: 500
+cmd: testNdbApi
+args: -n NdbClusterConnectNR_non_master T1
+
+max-time: 500
+cmd: testNdbApi
+args: -n NdbClusterConnectNR_slow T1
+
+max-time: 500
+cmd: testNdbApi
+args: -n NdbClusterConnectSR T1
+

=== modified file 'storage/ndb/test/run-test/daily-devel-tests.txt'
--- a/storage/ndb/test/run-test/daily-devel-tests.txt	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/run-test/daily-devel-tests.txt	2011-10-05 13:18:31 +0000
@@ -15,10 +15,6 @@
 #
 # BACKUP
 #
-max-time: 1000
-cmd: atrt-testBackup
-args: -n BackupBank T6 
-
 max-time: 500
 cmd: testNdbApi
 args: -n MaxOperations T1 T6 T13 
@@ -27,18 +23,6 @@ max-time: 1500
 cmd: testDict
 args: -n CreateTableWhenDbIsFull T6 
 
-max-time: 1500
-cmd: testDict
-args: -n CreateMaxTables T6 
-
-max-time: 500
-cmd: testIndex
-args: -n Bug25059 -r 3000 T1
-
-max-time: 1000
-cmd: testSRBank
-args: -n SR -l 300 -r 15 T1
-
 max-time: 1000
 cmd: testSRBank
 args: -n NR -l 300 -r 15 T1
@@ -51,14 +35,6 @@ args: -n Mix -l 300 -r 15 T1
 #
 # SYSTEM RESTARTS
 #
-max-time: 1500
-cmd: testSystemRestart
-args: -n SR3 T6 
-
-max-time: 1500
-cmd: testSystemRestart
-args: -n SR4 T6 
-
 #
 max-time: 1500
 cmd: testSystemRestart
@@ -73,28 +49,8 @@ args: -l 1 -n MixedPkReadPkUpdate
 
 max-time: 2500
 cmd: testNodeRestart
-args: -l 1 -n MixedReadUpdateScan 
-
-max-time: 2500
-cmd: testNodeRestart
-args: -n Terror T6 T13 
-
-max-time: 2500
-cmd: testNodeRestart
 args: -n FullDb T6 T13 
 
-max-time: 3600
-cmd: testNodeRestart
-args: -l 1 -n RestartNFDuringNR T6 T13 
-
-max-time: 3600
-cmd: testNodeRestart
-args: -n RestartNodeDuringLCP T6 
-
-max-time: 2500
-cmd: testNodeRestart
-args: -n FiftyPercentStopAndWait T6 T13 
-
 max-time: 500
 cmd: testNodeRestart
 args: -n Bug16772 T1
@@ -106,24 +62,12 @@ args: -n Bug16772 T1
 #
 max-time: 2500
 cmd: testIndex
-args: -n NFNR2 T6 T13 
-
-max-time: 2500
-cmd: testIndex
 args: -n NFNR3 T6 T13 
 
 max-time: 2500
 cmd: testIndex
-args: -l 2 -n SR1 T6 T13 
-
-max-time: 2500
-cmd: testIndex
 args: -n NFNR3_O T6 T13 
 
-max-time: 2500
-cmd: testIndex
-args: -l 2 -n SR1_O T6 T13 
-
 # dict trans
 max-time: 1800
 cmd: testDict

=== modified file 'storage/ndb/test/run-test/files.cpp'
--- a/storage/ndb/test/run-test/files.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/run-test/files.cpp	2011-10-03 08:46:52 +0000
@@ -179,8 +179,8 @@ setup_files(atrt_config& config, int set
 	  const char * val;
 	  require(proc.m_options.m_loaded.get("--datadir=", &val));
 	  BaseString tmp;
-	  tmp.assfmt("%s/bin/mysql_install_db --defaults-file=%s/my.cnf --datadir=%s > %s/mysql_install_db.log 2>&1",
-		     g_prefix, g_basedir, val, proc.m_proc.m_cwd.c_str());
+	  tmp.assfmt("%s --defaults-file=%s/my.cnf --datadir=%s > %s/mysql_install_db.log 2>&1",
+		     g_mysql_install_db_bin_path, g_basedir, val, proc.m_proc.m_cwd.c_str());
 
           to_fwd_slashes(tmp);
 	  if (sh(tmp.c_str()) != 0)
@@ -305,8 +305,13 @@ setup_files(atrt_config& config, int set
 	  }
 	  fprintf(fenv, "\"\nexport CMD\n");
 	}
-	
-	fprintf(fenv, "PATH=%s/bin:%s/libexec:$PATH\n", g_prefix, g_prefix);
+
+        fprintf(fenv, "PATH=");
+        for (int i = 0; g_search_path[i] != 0; i++)
+        {
+          fprintf(fenv, "%s/%s:", g_prefix, g_search_path[i]);
+        }
+        fprintf(fenv, "$PATH\n");
 	keys.push_back("PATH");
 	for (size_t k = 0; k<keys.size(); k++)
 	  fprintf(fenv, "export %s\n", keys[k].c_str());
@@ -314,7 +319,7 @@ setup_files(atrt_config& config, int set
 	fclose(fenv);
       }
       free(env);
-      
+
       {
         tmp.assfmt("%s/ssh-login.sh", proc.m_proc.m_cwd.c_str());
         FILE* fenv = fopen(tmp.c_str(), "w+");

=== modified file 'storage/ndb/test/run-test/main.cpp'
--- a/storage/ndb/test/run-test/main.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/run-test/main.cpp	2011-10-03 14:59:24 +0000
@@ -66,6 +66,7 @@ int          g_fix_nodeid= 0;
 int          g_default_ports = 0;
 int          g_mt = 0;
 int          g_mt_rr = 0;
+int          g_restart = 0;
 
 const char * g_cwd = 0;
 const char * g_basedir = 0;
@@ -80,6 +81,37 @@ const char * g_dummy;
 char * g_env_path = 0;
 const char* g_mysqld_host = 0;
 
+const char * g_ndb_mgmd_bin_path = 0;
+const char * g_ndbd_bin_path = 0;
+const char * g_ndbmtd_bin_path = 0;
+const char * g_mysqld_bin_path = 0;
+const char * g_mysql_install_db_bin_path = 0;
+
+static struct
+{
+  bool is_required;
+  const char * exe;
+  const char ** var;
+} g_binaries[] = {
+  { true,  "ndb_mgmd",         &g_ndb_mgmd_bin_path},
+  { true,  "ndbd",             &g_ndbd_bin_path },
+  { false, "ndbmtd",           &g_ndbmtd_bin_path },
+  { true,  "mysqld",           &g_mysqld_bin_path },
+  { true,  "mysql_install_db", &g_mysql_install_db_bin_path },
+  { true, 0, 0 }
+};
+
+const char *
+g_search_path[] =
+{
+  "bin",
+  "libexec",
+  "sbin",
+  "scripts",
+  0
+};
+static bool find_binaries();
+
 static struct my_option g_options[] =
 {
   { "help", '?', "Display this help and exit.", 
@@ -178,6 +210,12 @@ main(int argc, char ** argv)
   }
   
   g_logger.info("Starting...");
+
+  if (!find_binaries())
+  {
+    goto end;
+  }
+
   g_config.m_generated = false;
   g_config.m_replication = g_replicate;
   if (!setup_config(g_config, g_mysqld_host))
@@ -638,6 +676,9 @@ parse_args(int argc, char** argv)
       case 'q':
 	g_do_quit = 1;
 	break;
+      case 'r':
+        g_restart = 1;
+        break;
       default:
 	g_logger.error("Unknown switch '%c'", *arg);
 	return false;
@@ -796,7 +837,11 @@ parse_args(int argc, char** argv)
 
 bool
 connect_hosts(atrt_config& config){
-  for(size_t i = 0; i<config.m_hosts.size(); i++){
+  for(size_t i = 0; i<config.m_hosts.size(); i++)
+  {
+    if (config.m_hosts[i]->m_hostname.length() == 0)
+      continue;
+
     if(config.m_hosts[i]->m_cpcd->connect() != 0){
       g_logger.error("Unable to connect to cpc %s:%d",
 		     config.m_hosts[i]->m_cpcd->getHost(),
@@ -1088,7 +1133,11 @@ update_status(atrt_config& config, int){
   
   Vector<SimpleCpcClient::Process> dummy;
   m_procs.fill(config.m_hosts.size(), dummy);
-  for(size_t i = 0; i<config.m_hosts.size(); i++){
+  for(size_t i = 0; i<config.m_hosts.size(); i++)
+  {
+    if (config.m_hosts[i]->m_hostname.length() == 0)
+      continue;
+
     Properties p;
     config.m_hosts[i]->m_cpcd->list_processes(m_procs[i], p);
   }
@@ -1261,11 +1310,14 @@ setup_test_case(atrt_config& config, con
        proc.m_type == atrt_process::AP_CLIENT)
     {
       BaseString cmd;
-      if (tc.m_command.c_str()[0] != '/')
+      char * p = find_bin_path(tc.m_command.c_str());
+      if (p == 0)
       {
-        cmd.appfmt("%s/bin/", g_prefix);
+        g_logger.critical("Failed to locate '%s'", tc.m_command.c_str());
+        return false;
       }
-      cmd.append(tc.m_command.c_str());
+      cmd.assign(p);
+      free(p);
 
       if (0) // valgrind
       {
@@ -1299,6 +1351,9 @@ gather_result(atrt_config& config, int *
 
   for(size_t i = 0; i<config.m_hosts.size(); i++)
   {
+    if (config.m_hosts[i]->m_hostname.length() == 0)
+      continue;
+
     tmp.appfmt(" %s:%s/*", 
 	       config.m_hosts[i]->m_hostname.c_str(),
 	       config.m_hosts[i]->m_basedir.c_str());
@@ -1333,7 +1388,10 @@ setup_hosts(atrt_config& config){
     return false;
   }
 
-  for(size_t i = 0; i<config.m_hosts.size(); i++){
+  for(size_t i = 0; i<config.m_hosts.size(); i++)
+  {
+    if (config.m_hosts[i]->m_hostname.length() == 0)
+      continue;
     BaseString tmp = g_setup_progname;
     tmp.appfmt(" %s %s/ %s/", 
 	       config.m_hosts[i]->m_hostname.c_str(),
@@ -1375,6 +1433,9 @@ deploy(int d, atrt_config & config)
 {
   for (size_t i = 0; i<config.m_hosts.size(); i++)
   {
+    if (config.m_hosts[i]->m_hostname.length() == 0)
+      continue;
+
     if (d & 1)
     {
       if (!do_rsync(g_basedir, config.m_hosts[i]->m_hostname.c_str()))
@@ -1509,6 +1570,35 @@ reset_config(atrt_config & config)
   return changed;
 }
 
+static
+bool
+find_binaries()
+{
+  g_logger.info("Locating binaries...");
+  bool ok = true;
+  for (int i = 0; g_binaries[i].exe != 0; i++)
+  {
+    const char * p = find_bin_path(g_binaries[i].exe);
+    if (p == 0)
+    {
+      if (g_binaries[i].is_required)
+      {
+        g_logger.critical("Failed to locate '%s'", g_binaries[i].exe);
+        ok = false;
+      }
+      else
+      {
+        g_logger.info("Failed to locate '%s'...ok", g_binaries[i].exe);
+      }
+    }
+    else
+    {
+      * g_binaries[i].var = p;
+    }
+  }
+  return ok;
+}
+
 template class Vector<Vector<SimpleCpcClient::Process> >;
 template class Vector<atrt_host*>;
 template class Vector<atrt_cluster*>;

=== modified file 'storage/ndb/test/run-test/setup.cpp'
--- a/storage/ndb/test/run-test/setup.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/test/run-test/setup.cpp	2011-10-03 11:06:06 +0000
@@ -20,6 +20,7 @@
 #include <util/ndb_opts.h>
 #include <util/NdbOut.hpp>
 #include <util/BaseString.hpp>
+#include <util/File.hpp>
 
 extern int g_mt;
 extern int g_mt_rr;
@@ -321,7 +322,7 @@ load_process(atrt_config& config, atrt_c
   case atrt_process::AP_NDB_MGMD:
   {
     proc.m_proc.m_name.assfmt("%u-%s", proc_no, "ndb_mgmd");
-    proc.m_proc.m_path.assign(g_prefix).append("/libexec/ndb_mgmd");
+    proc.m_proc.m_path.assign(g_ndb_mgmd_bin_path);
     proc.m_proc.m_args.assfmt("--defaults-file=%s/my.cnf",
 			      proc.m_host->m_basedir.c_str());
     proc.m_proc.m_args.appfmt(" --defaults-group-suffix=%s",
@@ -336,13 +337,15 @@ load_process(atrt_config& config, atrt_c
   } 
   case atrt_process::AP_NDBD:
   {
-    if (g_mt == 0 || (g_mt == 1 && ((g_mt_rr++) & 1) == 0))
+    if (g_mt == 0 ||
+        (g_mt == 1 && ((g_mt_rr++) & 1) == 0) ||
+        g_ndbmtd_bin_path == 0)
     {
-      proc.m_proc.m_path.assign(g_prefix).append("/libexec/ndbd");
+      proc.m_proc.m_path.assign(g_ndbd_bin_path);
     }
     else
     {
-      proc.m_proc.m_path.assign(g_prefix).append("/libexec/ndbmtd");
+      proc.m_proc.m_path.assign(g_ndbmtd_bin_path);
     }
     
     proc.m_proc.m_name.assfmt("%u-%s", proc_no, "ndbd");
@@ -350,7 +353,9 @@ load_process(atrt_config& config, atrt_c
 			      proc.m_host->m_basedir.c_str());
     proc.m_proc.m_args.appfmt(" --defaults-group-suffix=%s",
 			      cluster.m_name.c_str());
-    proc.m_proc.m_args.append(" --nodaemon --initial -n");
+    proc.m_proc.m_args.append(" --nodaemon -n");
+    if (!g_restart)
+      proc.m_proc.m_args.append(" --initial");
     if (g_fix_nodeid)
       proc.m_proc.m_args.appfmt(" --ndb-nodeid=%u", proc.m_nodeid);
     proc.m_proc.m_cwd.assfmt("%sndbd.%u", dir.c_str(), proc.m_index);
@@ -361,7 +366,7 @@ load_process(atrt_config& config, atrt_c
   case atrt_process::AP_MYSQLD:
   {
     proc.m_proc.m_name.assfmt("%u-%s", proc_no, "mysqld");
-    proc.m_proc.m_path.assign(g_prefix).append("/libexec/mysqld");
+    proc.m_proc.m_path.assign(g_mysqld_bin_path);
     proc.m_proc.m_args.assfmt("--defaults-file=%s/my.cnf",
 			      proc.m_host->m_basedir.c_str());
     proc.m_proc.m_args.appfmt(" --defaults-group-suffix=.%d%s",
@@ -1037,3 +1042,28 @@ operator<<(NdbOut& out, const atrt_proce
   return out;
 }
 
+char *
+find_bin_path(const char * exe)
+{
+  if (exe == 0)
+    return 0;
+
+  if (exe[0] == '/')
+  {
+    /**
+     * Trust that path is correct...
+     */
+    return strdup(exe);
+  }
+
+  for (int i = 0; g_search_path[i] != 0; i++)
+  {
+    BaseString p;
+    p.assfmt("%s/%s/%s", g_prefix, g_search_path[i], exe);
+    if (File_class::exists(p.c_str()))
+    {
+      return strdup(p.c_str());
+    }
+  }
+  return 0;
+}

=== modified file 'storage/ndb/test/src/NDBT_Find.cpp'
--- a/storage/ndb/test/src/NDBT_Find.cpp	2011-07-04 13:37:56 +0000
+++ b/storage/ndb/test/src/NDBT_Find.cpp	2011-09-30 20:37:26 +0000
@@ -81,7 +81,10 @@ NDBT_find_ndb_mgmd(BaseString& path)
 {
   NDBT_find_binary(path, "ndb_mgmd",
                    "../../src/mgmsrv",
-                   "../storage/ndb/src/mgmsrv/",
+                   "../storage/ndb/src/mgmsrv",
+                   "../libexec",
+                   "../sbin",
+                   "../bin",
                    NULL);
 }
 

=== modified file 'storage/ndb/test/tools/hugoJoin.cpp'
--- a/storage/ndb/test/tools/hugoJoin.cpp	2011-04-06 14:16:13 +0000
+++ b/storage/ndb/test/tools/hugoJoin.cpp	2011-09-28 09:54:05 +0000
@@ -192,7 +192,7 @@ int main(int argc, char** argv){
     }
     HugoQueryBuilder builder(&MyNdb, tables.getBase(), mask);
     builder.setJoinLevel(_depth);
-    const NdbQueryDef * q = builder.createQuery(&MyNdb);
+    const NdbQueryDef * q = builder.createQuery();
     if (_verbose >= 2)
     {
       q->print(); ndbout << endl;

=== modified file 'storage/ndb/tools/CMakeLists.txt'
--- a/storage/ndb/tools/CMakeLists.txt	2011-07-04 13:37:56 +0000
+++ b/storage/ndb/tools/CMakeLists.txt	2011-10-05 11:21:23 +0000
@@ -91,6 +91,11 @@ ADD_EXECUTABLE(ndb_dump_frm_data
   ndb_dump_frm_data.cpp)
 TARGET_LINK_LIBRARIES(ndb_dump_frm_data ndbNDBT ndbgeneral)
 
+MYSQL_ADD_EXECUTABLE(ndbinfo_select_all
+  ndbinfo_select_all.cpp
+  COMPONENT ClusterTools)
+TARGET_LINK_LIBRARIES(ndbinfo_select_all ndbNDBT)
+
 IF (MYSQL_VERSION_ID LESS "50501")
   # Don't build or install this program anymore in 5.5+
   ADD_EXECUTABLE(ndb_test_platform ndb_test_platform.cpp)

=== modified file 'storage/ndb/tools/Makefile.am'
--- a/storage/ndb/tools/Makefile.am	2011-09-02 17:24:52 +0000
+++ b/storage/ndb/tools/Makefile.am	2011-10-05 11:21:23 +0000
@@ -32,7 +32,8 @@ ndbtools_PROGRAMS = \
   ndb_select_all \
   ndb_select_count \
   ndb_restore ndb_config \
-  ndb_index_stat
+  ndb_index_stat \
+  ndbinfo_select_all
 
 tools_common_sources = ../test/src/NDBT_ReturnCodes.cpp \
                        ../test/src/NDBT_Table.cpp \
@@ -81,6 +82,7 @@ ndbinfo.sql: $(ndbinfo_sql_SOURCES)
 
 ndb_index_stat_SOURCES = ndb_index_stat.cpp $(tools_common_sources)
 ndb_dump_frm_data_SOURCES = ndb_dump_frm_data.cpp
+ndbinfo_select_all_SOURCES = ndbinfo_select_all.cpp
 
 include $(top_srcdir)/storage/ndb/config/common.mk.am
 include $(top_srcdir)/storage/ndb/config/type_ndbapitools.mk.am
@@ -99,4 +101,5 @@ ndb_config_LDFLAGS = @ndb_bin_am_ldflags
 ndbinfo_sql_LDFLAGS = @ndb_bin_am_ldflags@
 ndb_index_stat_LDFLAGS = @ndb_bin_am_ldflags@
 ndb_dump_frm_data_LDFLAGS = @ndb_bin_am_ldflags@
+ndbinfo_select_all_LDFLAGS = @ndb_bin_am_ldflags@
 

=== added file 'storage/ndb/tools/ndbinfo_select_all.cpp'
--- a/storage/ndb/tools/ndbinfo_select_all.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/tools/ndbinfo_select_all.cpp	2011-10-07 09:17:10 +0000
@@ -0,0 +1,189 @@
+/*
+   Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+
+#include <ndb_global.h>
+#include <ndb_opts.h>
+
+#include <NdbApi.hpp>
+#include <NdbOut.hpp>
+#include "../src/ndbapi/NdbInfo.hpp"
+#include <NdbSleep.h>
+
+static int loops = 1;
+static int delay = 5;
+const char *load_default_groups[]= { "mysql_cluster",0 };
+
+static struct my_option my_long_options[] =
+{
+  NDB_STD_OPTS("ndbinfo_select_all"),
+  { "loops", 'l', "Run same select several times",
+    (uchar**) &loops, (uchar**) &loops, 0,
+    GET_INT, REQUIRED_ARG, loops, 0, 0, 0, 0, 0 },
+  { "delay", 256, "Delay between loops (in seconds)",
+    (uchar**) &delay, (uchar**) &delay, 0,
+    GET_INT, REQUIRED_ARG, delay, 0, 0, 0, 0, 0 },
+  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+static void short_usage_sub(void)
+{
+  ndb_short_usage_sub(NULL);
+}
+
+static void usage()
+{
+  ndb_usage(short_usage_sub, load_default_groups, my_long_options);
+}
+
+int
+main(int argc, char** argv)
+{
+  NDB_INIT(argv[0]);
+  ndb_opt_set_usage_funcs(short_usage_sub, usage);
+  load_defaults("my",load_default_groups,&argc,&argv);
+  int ho_error;
+#ifndef DBUG_OFF
+  opt_debug= "d:t:O,/tmp/ndbinfo_select_all.trace";
+#endif
+  if ((ho_error=handle_options(&argc, &argv, my_long_options,
+			       ndb_std_get_one_option)))
+    return 1;
+
+  if (argv[0] == 0)
+  {
+    return 0;
+  }
+
+  Ndb_cluster_connection con(opt_ndb_connectstring, opt_ndb_nodeid);
+  con.set_name("ndbinfo_select_all");
+  if(con.connect(12, 5, 1) != 0)
+  {
+    ndbout << "Unable to connect to management server." << endl;
+    return 1;
+  }
+
+  if (con.wait_until_ready(30,0) < 0)
+  {
+    ndbout << "Cluster nodes not ready in 30 seconds." << endl;
+    return 1;
+  }
+
+  NdbInfo info(&con, "");
+  if (!info.init())
+  {
+    ndbout << "Failed to init ndbinfo!" << endl;
+    return 1;
+  }
+
+  const Uint32 batchsizerows = 32;
+
+  for (int ll = 0; loops == 0 || ll < loops; ll++)
+  {
+    for (int ii = 0; argv[ii] != 0; ii++)
+    {
+      ndbout << "== " << argv[ii] << " ==" << endl;
+
+      const NdbInfo::Table * pTab = 0;
+      int res = info.openTable(argv[ii], &pTab);
+      if (res != 0)
+      {
+        ndbout << "Failed to open: " << argv[ii] << ", res: " << res << endl;
+        continue;
+      }
+
+      unsigned cols = pTab->columns();
+      for (unsigned i = 0; i<cols; i++)
+      {
+        const NdbInfo::Column * pCol = pTab->getColumn(i);
+        ndbout << pCol->m_name.c_str() << "\t";
+      }
+      ndbout << endl;
+
+      NdbInfoScanOperation * pScan = 0;
+      res= info.createScanOperation(pTab, &pScan, batchsizerows);
+      if (res != 0)
+      {
+        ndbout << "Failed to createScan: " << argv[ii] << ", res: " << res<< endl;
+        info.closeTable(pTab);
+        continue;
+      }
+
+      if (pScan->readTuples() != 0)
+      {
+        ndbout << "scanOp->readTuples failed" << endl;
+        return 1;
+      }
+
+      Vector<const NdbInfoRecAttr*> recAttrs;
+      for (unsigned i = 0; i<cols; i++)
+      {
+        const NdbInfoRecAttr* pRec = pScan->getValue(i);
+        if (pRec == 0)
+        {
+          ndbout << "Failed to getValue(" << i << ")" << endl;
+          return 1;
+        }
+        recAttrs.push_back(pRec);
+      }
+
+      if(pScan->execute() != 0)
+      {
+        ndbout << "scanOp->execute failed" << endl;
+        return 1;
+      }
+
+      while(pScan->nextResult() == 1)
+      {
+        for (unsigned i = 0; i<cols; i++)
+        {
+          if (recAttrs[i]->isNULL())
+          {
+            ndbout << "NULL";
+          }
+          else
+          {
+            switch(pTab->getColumn(i)->m_type){
+            case NdbInfo::Column::String:
+              ndbout << recAttrs[i]->c_str();
+              break;
+            case NdbInfo::Column::Number:
+              ndbout << recAttrs[i]->u_32_value();
+              break;
+            case NdbInfo::Column::Number64:
+              ndbout << recAttrs[i]->u_64_value();
+              break;
+            }
+          }
+          ndbout << "\t";
+        }
+        ndbout << endl;
+      }
+
+      info.releaseScanOperation(pScan);
+      info.closeTable(pTab);
+    }
+
+    if ((loops == 0 || ll + 1 != loops) && delay > 0)
+    {
+      NdbSleep_SecSleep(delay);
+    }
+  }
+  return 0;
+}
+
+template class Vector<const NdbInfoRecAttr*>;

=== modified file 'storage/ndb/tools/ndbinfo_sql.cpp'
--- a/storage/ndb/tools/ndbinfo_sql.cpp	2011-06-30 15:59:25 +0000
+++ b/storage/ndb/tools/ndbinfo_sql.cpp	2011-10-07 13:15:08 +0000
@@ -99,6 +99,9 @@ struct view {
     "  WHEN 4 THEN \"JOBBUFFER\""
     "  WHEN 5 THEN \"FILE_BUFFERS\""
     "  WHEN 6 THEN \"TRANSPORTER_BUFFERS\""
+    "  WHEN 7 THEN \"DISK_PAGE_BUFFER\""
+    "  WHEN 8 THEN \"QUERY_MEMORY\""
+    "  WHEN 9 THEN \"SCHEMA_TRANS_MEMORY\""
     "  ELSE \"<unknown>\" "
     " END AS resource_name, "
     "reserved, used, max "

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.1-telco-7.0 branch (pekka.nousiainen:4550 to 4584) Pekka Nousiainen10 Oct