Ndb.hpp 66.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   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 */

/**
   @mainpage                            NDB API Programmers' Guide

unknown's avatar
unknown committed
20 21 22 23
   This guide assumes a basic familiarity with MySQL Cluster concepts found
   on http://dev.mysql.com/doc/mysql/en/NDBCluster.html .
   Some of the fundamental ones are also described in section @ref secConcepts.

24
   The NDB API is a MySQL Cluster application interface 
unknown's avatar
unknown committed
25
   that implements transactions.
26
   The NDB API consists of the following fundamental classes:
27
   - Ndb_cluster_connection, representing a connection to a cluster, 
unknown's avatar
unknown committed
28
   - Ndb is the main class, representing a connection to a database, 
29 30 31 32 33
   - NdbTransaction represents a transaction, 
   - NdbOperation represents an operation using a primary key,
   - NdbScanOperation represents an operation performing a full table scan.
   - NdbIndexOperation represents an operation using a unique hash index,
   - NdbIndexScanOperation represents an operation performing a scan using
unknown's avatar
unknown committed
34
     an ordered index,
35 36
   - NdbRecAttr represents an attribute value
   - NdbDictionary represents meta information about tables and attributes.
37 38 39
     
   In addition, the NDB API defines a structure NdbError, which contains the 
   specification for an error.
unknown's avatar
unknown committed
40

41
   It is also possible to receive "events" triggered when data in the database in changed.
unknown's avatar
unknown committed
42 43
   This is done through the NdbEventOperation class.

44
   There are also some auxiliary classes, which are listed in the class hierarchy.
45 46
     
   The main structure of an application program is as follows:
47
   -# Connect to a cluster using the Ndb_cluster_connection
unknown's avatar
unknown committed
48
      object.
49
   -# Initiate a database connection by constructing and initialising one or more Ndb objects.
50
   -# Define and execute transactions using the NdbTransaction class.
unknown's avatar
unknown committed
51
   -# Delete Ndb objects.
52
   -# Terminate the connection to the cluster (terminate instance of Ndb_cluster_connection).
53

54 55
   The procedure for using transactions is as follows:
   -# Start transaction (instantiate an NdbTransaction object)
56 57 58
   -# Add and define operations associated with the transaction using instances of one or more of the
      NdbOperation, NdbScanOperation, NdbIndexOperation, and NdbIndexScanOperation classes
   -# Execute transaction (call NdbTransaction::execute())
59

60
   The operation can be of two different types, 
61
   <var>Commit</var> or <var>NoCommit</var>.
62 63
   If the operation is of type <var>NoCommit</var>, 
   then the application program executes the operation part of a transaction,
64
   but without actually committing the transaction.
65
   After executing a <var>NoCommit</var> operation, the program can continue 
66 67 68
   to add and define more operations to the transaction
   for later execution.

69
   If the operation is of type <var>Commit</var>, then the transaction is
70
   immediately committed. The transaction <em>must</em> be closed after it has been 
unknown's avatar
unknown committed
71
   commited (event if commit fails), and no further addition or definition of 
72
   operations for this transaction is allowed.
73 74 75

   @section secSync                     Synchronous Transactions
  
76
   Synchronous transactions are defined and executed as follows:
77
  
78
    -# Start (create) the transaction, which is
79 80
       referenced by an NdbTransaction object 
       (typically created using Ndb::startTransaction()).
81 82
       At this point, the transaction is only being defined,
       and is not yet sent to the NDB kernel.
83 84 85 86 87 88 89
    -# Define operations and add them to the transaction, using one or more of
       - NdbTransaction::getNdbOperation()
       - NdbTransaction::getNdbScanOperation()
       - NdbTransaction::getNdbIndexOperation()
       - NdbTransaction::getNdbIndexScanOperation()
       along with the appropriate methods of the respective NdbOperation class 
       (or one possiblt one or more of its subclasses).
90
       Note that the transaction has still not yet been sent to the NDB kernel.
91
    -# Execute the transaction, using the NdbTransaction::execute() method.
92
    -# Close the transaction (call Ndb::closeTransaction()).
93
  
unknown's avatar
unknown committed
94 95
   For an example of this process, see the program listing in 
   @ref ndbapi_simple.cpp.
96 97

   To execute several parallel synchronous transactions, one can either 
98
   use multiple Ndb objects in several threads, or start multiple 
99
   application programs.  
100

101 102
   @section secNdbOperations            Operations

103
   A NdbTransaction consists of a list of operations, each of which is represented 
104
   by an instance of NdbOperation, NdbScanOperation, NdbIndexOperation, or
unknown's avatar
unknown committed
105
   NdbIndexScanOperation.
106

unknown's avatar
unknown committed
107
   <h3>Single row operations</h3>
108 109
   After the operation is created using NdbTransaction::getNdbOperation()
   (or NdbTransaction::getNdbIndexOperation()), it is defined in the following 
110
   three steps:
111 112 113
   -# Define the standard operation type, using NdbOperation::readTuple()
   -# Specify search conditions, using NdbOperation::equal()
   -# Specify attribute actions, using NdbOperation::getValue()
114

unknown's avatar
unknown committed
115
   Here are two brief examples illustrating this process. For the sake of 
116
   brevity, we omit error handling.
117
   
118
   This first example uses an NdbOperation:
119
   @code
120 121 122 123 124
     // 1. Retrieve table object
     myTable= myDict->getTable("MYTABLENAME");

     // 2. Create
     myOperation= myTransaction->getNdbOperation(myTable);
125
    
126 127
     // 3. Define type of operation and lock mode
     myOperation->readTuple(NdbOperation::LM_Read);
unknown's avatar
unknown committed
128

129 130
     // 4. Specify Search Conditions
     myOperation->equal("ATTR1", i);
131
    
132 133
     // 5. Attribute Actions
     myRecAttr= myOperation->getValue("ATTR2", NULL);
134
   @endcode
unknown's avatar
unknown committed
135
   For additional examples of this sort, see @ref ndbapi_simple.cpp.
136

137
   The second example uses an NdbIndexOperation:
138
   @code
139 140 141 142 143
     // 1. Retrieve index object
     myIndex= myDict->getIndex("MYINDEX", "MYTABLENAME");

     // 2. Create
     myOperation= myTransaction->getNdbIndexOperation(myIndex);
unknown's avatar
unknown committed
144

145 146
     // 3. Define type of operation and lock mode
     myOperation->readTuple(NdbOperation::LM_Read);
147

148 149
     // 4. Specify Search Conditions
     myOperation->equal("ATTR1", i);
150

151 152
     // 5. Attribute Actions 
     myRecAttr = myOperation->getValue("ATTR2", NULL);
153
   @endcode
unknown's avatar
unknown committed
154 155
   Another example of this second type can be found in 
   @ref ndbapi_simple_index.cpp.
156

unknown's avatar
unknown committed
157 158
   We will now discuss in somewhat greater detail each step involved in the 
   creation and use of synchronous transactions.
159

unknown's avatar
unknown committed
160
   <h4>Step 1: Define single row operation type</h4>
161 162
   The following operation types are supported:
    -# NdbOperation::insertTuple() : 
163
       inserts a non-existing tuple
164
    -# NdbOperation::writeTuple() : 
165 166
       updates an existing tuple if is exists,
       otherwise inserts a new tuple
167
    -# NdbOperation::updateTuple() : 
168
       updates an existing tuple
169
    -# NdbOperation::deleteTuple() : 
170
       deletes an existing tuple
171
    -# NdbOperation::readTuple() : 
unknown's avatar
unknown committed
172
       reads an existing tuple with specified lock mode
173 174 175

   All of these operations operate on the unique tuple key.
   (When NdbIndexOperation is used then all of these operations 
unknown's avatar
unknown committed
176
   operate on a defined unique hash index.)
177 178

   @note If you want to define multiple operations within the same transaction,
unknown's avatar
unknown committed
179 180
         then you need to call NdbTransaction::getNdbOperation() or
	 NdbTransaction::getNdbIndexOperation() for each operation.
181 182

   <h4>Step 2: Specify Search Conditions</h4>
183
   The search condition is used to select tuples. Search conditions are set using NdbOperation::equal().
184 185

   <h4>Step 3: Specify Attribute Actions</h4>
186 187 188 189 190 191 192
   Next, it is necessary to determine which attributes should be read or updated.
   It is important to remember that: 
   - Deletes can neither read nor set values, but only delete them
   - Reads can only read values
   - Updates can only set values
   Normally the attribute is identified by name, but it is
   also possible to use the attribute's identity to determine the
193 194
   attribute.

unknown's avatar
unknown committed
195
   NdbOperation::getValue() returns an NdbRecAttr object
196
   containing the read value.
197 198
   To obtain the actual value, one of two methods can be used;
   the application can either
199
   - use its own memory (passed through a pointer aValue) to
unknown's avatar
unknown committed
200
     NdbOperation::getValue(), or
201 202 203
   - receive the attribute value in an NdbRecAttr object allocated
     by the NDB API.

unknown's avatar
unknown committed
204
   The NdbRecAttr object is released when Ndb::closeTransaction()
205
   is called.
206 207 208 209
   Thus, the application cannot reference this object following
   any subsequent call to Ndb::closeTransaction().
   Attempting to read data from an NdbRecAttr object before
   calling NdbTransaction::execute() yields an undefined result.
210 211


212 213
   @subsection secScan              Scan Operations 
   
214 215 216 217
   Scans are roughly the equivalent of SQL cursors, providing a means to
   preform high-speed row processing. A scan can be performed 
   on either a table (using @ref NdbScanOperation) or 
   an ordered index (by means of an @ref NdbIndexScanOperation).
218

219 220
   Scan operations are characterised by the following:
   - They can perform only reads (shared, exclusive or dirty)
221 222
   - They can potentially work with multiple rows
   - They can be used to update or delete multiple rows
223
   - They can operate on several nodes in parallel
224

225
   After the operation is created using NdbTransaction::getNdbScanOperation()
unknown's avatar
unknown committed
226
   (or NdbTransaction::getNdbIndexScanOperation()), 
227
   it is carried out in the following three steps:
228
   -# Define the standard operation type, using NdbScanOperation::readTuples()
unknown's avatar
unknown committed
229 230
   -# Specify search conditions, using @ref NdbScanFilter and/or 
      @ref NdbIndexScanOperation::setBound()
231 232
   -# Specify attribute actions, using NdbOperation::getValue()
   -# Executing the transaction, using NdbTransaction::execute()
233 234
   -# Traversing the result set by means of succssive calls to 
      NdbScanOperation::nextResult()
235

236 237
   Here are two brief examples illustrating this process. Once again, in order
   to keep things relatively short and simple, we will forego any error handling.
238
   
239
   This first example performs a table scan, using an NdbScanOperation:
240
   @code
241 242
     // 1. Retrieve table object
     myTable= myDict->getTable("MYTABLENAME");
243
    
244 245 246 247 248
     // 2. Create
     myOperation= myTransaction->getNdbScanOperation(myTable);
    
     // 3. Define type of operation and lock mode
     myOperation->readTuples(NdbOperation::LM_Read);
249

250 251
     // 4. Specify Search Conditions
     NdbScanFilter sf(myOperation);
252 253 254 255
     sf.begin(NdbScanFilter::OR);
     sf.eq(0, i);   // Return rows with column 0 equal to i or
     sf.eq(1, i+1); // column 1 equal to (i+1)
     sf.end();
256

257 258
     // 5. Attribute Actions
     myRecAttr= myOperation->getValue("ATTR2", NULL);
259
   @endcode
260

261
   Our second example uses an NdbIndexScanOperation to perform an index scan:
262
   @code
263 264 265 266 267
     // 1. Retrieve index object
     myIndex= myDict->getIndex("MYORDEREDINDEX", "MYTABLENAME");

     // 2. Create
     myOperation= myTransaction->getNdbIndexScanOperation(myIndex);
268

269 270
     // 3. Define type of operation and lock mode
     myOperation->readTuples(NdbOperation::LM_Read);
271

272
     // 4. Specify Search Conditions
273
     // All rows with ATTR1 between i and (i+1)
274 275
     myOperation->setBound("ATTR1", NdbIndexScanOperation::BoundGE, i);
     myOperation->setBound("ATTR1", NdbIndexScanOperation::BoundLE, i+1);
276

277 278
     // 5. Attribute Actions 
     myRecAttr = MyOperation->getValue("ATTR2", NULL);
279
   @endcode
280

281 282
   Some additional discussion of each step required to perform a scan follows:

283
   <h4>Step 1: Define Scan Operation Type</h4>
284 285
   It is important to remember that only a single operation is supported for each scan operation 
   (@ref NdbScanOperation::readTuples() or @ref NdbIndexScanOperation::readTuples()).
286

unknown's avatar
unknown committed
287 288 289
   @note If you want to define multiple scan operations within the same 
         transaction, then you need to call 
	 NdbTransaction::getNdbScanOperation() or 
290
	 NdbTransaction::getNdbIndexScanOperation() separately for <b>each</b> operation.
291

292 293 294 295
   <h4>Step 2: Specify Search Conditions</h4>
   The search condition is used to select tuples.
   If no search condition is specified, the scan will return all rows
   in the table.
296

297 298 299 300
   The search condition can be an @ref NdbScanFilter (which can be used on both
   @ref NdbScanOperation and @ref NdbIndexScanOperation) or bounds which
   can only be used on index scans (@ref NdbIndexScanOperation::setBound()).
   An index scan can use both NdbScanFilter and bounds.
301

302 303
   @note When NdbScanFilter is used, each row is examined, whether or not it is
   actually returned. However, when using bounds, only rows within the bounds will be examined.
304

305
   <h4>Step 3: Specify Attribute Actions</h4>
306

307 308 309
   Next, it is necessary to define which attributes should be read.
   As with transaction attributes, scan attributes are defined by name but it is
   also possible to use the attributes' identities to define attributes.
310

311 312
   As previously discussed (see @ref secSync), the value read is returned as 
   an NdbRecAttr object by the NdbOperation::getValue() method.
313

314 315
   <h3>Using Scan to Update/Delete</h3>
   Scanning can also be used to update or delete rows.
316
   This is performed by
317 318
   -# Scanning using exclusive locks (using NdbOperation::LM_Exclusive)
   -# When iterating through the result set, for each row optionally calling 
unknown's avatar
unknown committed
319 320
      either NdbScanOperation::updateCurrentTuple() or 
      NdbScanOperation::deleteCurrentTuple()
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
   -# (If performing NdbScanOperation::updateCurrentTuple():) 
      Setting new values for records simply by using @ref NdbOperation::setValue().
      NdbOperation::equal() should <em>not</em> be called in such cases, as the primary 
      key is retrieved from the scan.

   @note The actual update or delete will not be performed until the next 
   call to NdbTransaction::execute(), just as with single row operations. 
   NdbTransaction::execute() also must be called before any locks are released;
   see @ref secScanLocks for more information.

   <h4>Features Specific to Index Scans</h4> 
   
   When performing an index scan, it is possible to 
   scan only a subset of a table using @ref NdbIndexScanOperation::setBound().
   In addition, result sets can be sorted in either ascending or descending order, using
   @ref NdbIndexScanOperation::readTuples(). Note that rows are returned unordered 
337 338 339
   by default, that is, unless <var>sorted</var> is set to <b>true</b>.
   It is also important to note that, when using NdbIndexScanOperation::BoundEQ 
   on a partition key, only fragments containing rows will actually be scanned.
340
   
341 342 343 344 345
   @note When performing a sorted scan, any value passed as the 
   NdbIndexScanOperation::readTuples() method's <code>parallel</code> argument 
   will be ignored and maximum parallelism will be used instead. In other words, all 
   fragments which it is possible to scan will be scanned simultaneously and in parallel 
   in such cases.
unknown's avatar
unknown committed
346

347
   @subsection secScanLocks Lock handling with scans
348

349 350 351
   Performing scans on either a tables or an index has the potential 
   return a great many records; however, Ndb will lock only a predetermined 
   number of rows per fragment at a time.
352
   How many rows will be locked per fragment is controlled by the 
353
   <var>batch</var> parameter passed to NdbScanOperation::readTuples().
354

355 356 357 358 359
   In order to allow the application to handle how locks are released, 
   NdbScanOperation::nextResult() has a Boolean parameter <var>fetch_allow</var>.
   If NdbScanOperation::nextResult() is called with <var>fetch_allow</var> equal to 
   <b>false</b>, then no locks may be released as result of the function call. 
   Otherwise the locks for the current batch may be released.
360

361
   This next example shows a scan delete that handle locks in an efficient manner.
362 363 364 365 366 367 368 369 370 371 372
   For the sake of brevity, we omit error-handling.
   @code
     int check;

     // Outer loop for each batch of rows
     while((check = MyScanOperation->nextResult(true)) == 0)
     {
       do
       {
         // Inner loop for each row within batch
         MyScanOperation->deleteCurrentTuple();
373
       } while((check = MyScanOperation->nextResult(false)) == 0);
374 375 376 377 378 379

       // When no more rows in batch, exeute all defined deletes       
       MyTransaction->execute(NoCommit);
     }
   @endcode

380
   See @ref ndbapi_scan.cpp for a more complete example of a scan.
381 382 383

   @section secError                    Error Handling

384 385 386 387 388 389 390 391 392 393 394 395 396 397
   Errors can occur either when operations making up a transaction are being 
   defined, or when the transaction is actually being executed. Catching and 
   handling either sort of error requires testing the value returned by 
   NdbTransaction::execute(), and then, if an error is indicated (that is, 
   if this value is equal to -1), using the following two methods in order to 
   identify the error's type and location:

   - NdbTransaction::getNdbErrorOperation() returns a reference to the 
     operation causing the most recent error.
   - NdbTransaction::getNdbErrorLine() yields the method number of the 
     erroneous method in the operation.
   
   This short example illustrates how to detect an error and to use these 
   two methods to identify it:
398 399

   @code
400 401
     theTransaction = theNdb->startTransaction();
     theOperation = theTransaction->getNdbOperation("TEST_TABLE");
402
     if (theOperation == NULL) goto error;
403
     theOperation->readTuple(NdbOperation::LM_Read);
404
     theOperation->setValue("ATTR_1", at1);
405
     theOperation->setValue("ATTR_2", at1);  //  Error occurs here
406 407 408
     theOperation->setValue("ATTR_3", at1);
     theOperation->setValue("ATTR_4", at1);
    
409 410 411
     if (theTransaction->execute(Commit) == -1) {
       errorLine = theTransaction->getNdbErrorLine();
       errorOperation = theTransaction->getNdbErrorOperation();
412
     }
413 414
   @endcode

415
   Here <code>errorLine</code> will be 3, as the error occurred in the 
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
   third method called on the NdbOperation object (in this case, 
   <code>theOperation</code>); if the result of 
   NdbTransaction::getNdbErrorLine() is 0, this means that the error 
   occurred when the operations were executed. In this example, 
   <code>errorOperation</code> will be a pointer to the <code>theOperation</code> 
   object. The NdbTransaction::getNdbError() method returns an NdbError 
   object providing information about the error.

   @note Transactions are <b>not</b> automatically closed when an error occurs. Call
   Ndb::closeTransaction() to close the transaction.

   One recommended way to handle a transaction failure 
   (i.e. an error is reported) is to:
   -# Rollback transaction (call NdbTransaction::execute() with a special parameter)
   -# Close transaction (call NdbTransaction::closeTransaction())
   -# If the error was temporary, attempt to restart the transaction

   Several errors can occur when a transaction contains multiple 
   operations which are simultaneously executed.
   In this case the application has to go through all operations
   and query their NdbError objects to find out what really happened.

   It is also important to note that errors can occur even when a commit is 
   reported as successful. In order to handle such situations, the NDB API 
   provides an additional NdbTransaction::commitStatus() method to check the 
   transactions's commit status.
442

443
******************************************************************************/
444 445

/**
unknown's avatar
unknown committed
446 447
 * @page ndbapi_simple.cpp ndbapi_simple.cpp
 * @include ndbapi_simple.cpp 
448 449
 */

unknown's avatar
unknown committed
450
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
unknown's avatar
unknown committed
451 452 453 454
/**
 * @page ndbapi_async.cpp ndbapi_async.cpp
 * @include ndbapi_async.cpp 
 */
455
/**
unknown's avatar
unknown committed
456 457
 * @page ndbapi_async1.cpp ndbapi_async1.cpp
 * @include ndbapi_async1.cpp 
458
 */
unknown's avatar
unknown committed
459
#endif
460 461

/**
unknown's avatar
unknown committed
462 463
 * @page ndbapi_retries.cpp ndbapi_retries.cpp
 * @include ndbapi_retries.cpp 
464 465 466
 */

/**
unknown's avatar
unknown committed
467 468
 * @page ndbapi_simple_index.cpp ndbapi_simple_index.cpp
 * @include ndbapi_simple_index.cpp 
469 470 471 472 473 474 475
 */

/**
 * @page ndbapi_scan.cpp ndbapi_scan.cpp
 * @include ndbapi_scan.cpp
 */

unknown's avatar
unknown committed
476 477 478 479 480
/**
 * @page ndbapi_event.cpp ndbapi_event.cpp
 * @include ndbapi_event.cpp
 */

481 482 483 484

/**
   @page secAdapt  Adaptive Send Algorithm

485
   At the time of "sending" a transaction 
486
   (using NdbTransaction::execute()), the transactions 
487 488 489 490
   are in reality <em>not</em> immediately transfered to the NDB Kernel.  
   Instead, the "sent" transactions are only kept in a 
   special send list (buffer) in the Ndb object to which they belong.
   The adaptive send algorithm decides when transactions should
491
   actually be transferred to the NDB kernel.
492
  
493 494
   The NDB API is designed as a multi-threaded interface and so
   it is often desirable to transfer database operations from more than 
495
   one thread at a time. 
496
   The NDB API keeps track of which Ndb objects are active in transferring
497 498
   information to the NDB kernel and the expected amount of threads to 
   interact with the NDB kernel.
499 500
   Note that a given instance of Ndb should be used in at most one thread; 
   different threads should <em>not</em> use the same Ndb object.
501
  
502 503
   There are four conditions leading to the transfer of database 
   operations from Ndb object buffers to the NDB kernel:
504 505
   -# The NDB Transporter (TCP/IP, OSE, SCI or shared memory)
      decides that a buffer is full and sends it off. 
506 507 508
      The buffer size is implementation-dependent and
      may change between MySQL Cluster releases.
      On TCP/IP the buffer size is usually around 64 KB;
509
      on OSE/Delta it is usually less than 2000 bytes. 
510 511 512 513 514 515 516
      Since each Ndb object provides a single buffer per storage node, 
      the notion of a "full" buffer is local to this storage node.
   -# The accumulation of statistical data on transferred information
      may force sending of buffers to all storage nodes.
   -# Every 10 ms, a special transmission thread checks whether or not
      any send activity has occurred. If not, then the thread will 
      force transmission to all nodes. 
517
      This means that 20 ms is the maximum time database operations 
518
      are kept waiting before being sent off. The 10-millisecond limit 
519
      is likely to become a configuration parameter in
520 521 522 523
      future releases of MySQL Cluster; however, for checks that
      are more frequent than each 10 ms, 
      additional support from the operating system is required.
   -# For methods that are affected by the adaptive send alorithm
unknown's avatar
unknown committed
524 525
      (such as NdbTransaction::execute()), there is a <var>force</var> 
      parameter 
526 527 528 529 530 531
      that overrides its default behaviour in this regard and forces 
      immediate transmission to all nodes. See the inidvidual NDB API class 
      listings for more information.

   @note The conditions listed above are subject to change in future releases 
   of MySQL Cluster.
532 533
*/

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**

   For each of these "sent" transactions, there are three 
   possible states:
   -# Waiting to be transferred to NDB Kernel.
   -# Has been transferred to the NDB Kernel and is currently 
      being processed.
   -# Has been transferred to the NDB Kernel and has 
      finished processing.
      Now it is waiting for a call to a poll method.  
      (When the poll method is invoked, 
      then the transaction callback method will be executed.)
      
   The poll method invoked (either Ndb::pollNdb() or Ndb::sendPollNdb())
   will return when:
   -# at least 'minNoOfEventsToWakeup' of the transactions
      in the send list have transitioned to state 3 as described above, and 
   -# all of these transactions have executed their callback methods.
*/
#endif

556
/**
557
   @page secConcepts  MySQL Cluster Concepts
558

unknown's avatar
unknown committed
559
   The <em>NDB Kernel</em> is the collection of storage nodes
560
   belonging to a MySQL Cluster.
561
   The application programmer can for most purposes view the
562 563 564 565 566 567 568 569 570 571 572 573
   set of all storage nodes as a single entity.
   Each storage node is made up of three main components:
   - TC : The transaction co-ordinator
   - ACC : Index storage component
   - TUP : Data storage component

   When an application program executes a transaction,
   it connects to one transaction co-ordinator on one storage node.  
   Usually, the programmer does not need to specify which TC should be used, 
   but in some cases when performance is important, the programmer can
   provide "hints" to use a certain TC.  
   (If the node with the desired transaction co-ordinator is down, then another TC will 
574 575
   automatically take over the work.)

576 577
   Every storage node has an ACC and a TUP which store 
   the indexes and data portions of the database table fragment.
578
   Even though one TC is responsible for the transaction,
579
   several ACCs and TUPs on other storage nodes might be involved in the 
580 581 582
   execution of the transaction.


583
   @section secNdbKernelConnection   Selecting a Transaction Co-ordinator 
584

585 586 587 588 589 590 591 592
   The default method is to select the transaction co-ordinator (TC) determined to be
   the "closest" storage node, using a heuristic for proximity based on
   the type of transporter connection. In order of closest to most distant, these are
   - SCI 
   - SHM
   - TCP/IP (localhost)
   - TCP/IP (remote host)
   If there are several connections available with the same proximity, they will each be 
593
   selected in a round robin fashion for every transaction. Optionally
594 595 596
   one may set the method for TC selection to round-robin mode, where each new set of 
   transactions is placed on the next DB node. The pool of connections from which this
   selection is made consists of all available connections.
597
   
598 599
   As noted previously, the application programmer can provide hints to the NDB API as to 
   which transaction co-ordinator it should use. This is done by
unknown's avatar
unknown committed
600 601
   providing a <em>table</em> and <em>partition key</em> 
   (usually the primary key).
602
   By using the primary key as the partition key, 
603 604
   the transaction will be placed on the node where the primary replica
   of that record resides.
605 606 607 608 609
   Note that this is only a hint; the system can be 
   reconfigured at any time, in which case the NDB API will choose a transaction
   co-ordinator without using the hint.
   For more information, see NdbDictionary::Column::getPartitionKey() and
   Ndb::startTransaction(). The application programmer can specify
610
   the partition key from SQL by using the construct, 
611
   <code>CREATE TABLE ... ENGINE=NDB PARTITION BY KEY (<var>attribute-list</var>);</code>.
612 613


614 615 616 617 618 619 620
   @section secRecordStruct          NDB Record Structure 
   The NDB Cluster engine used by MySQL Cluster is a relational database engine
   storing records in tables just as with any other RDBMS.
   Table rows represent records as tuples of relational data.
   When a new table is created, its attribute schema is specified for the table as a whole,
   and thus each record of the table has the same structure. Again, this is typical
   of relational databases, and NDB is no different in this regard.
621 622
   

623 624
   @subsection secKeys               Primary Keys
   Each record has from 1 up to 32 attributes which belong
625 626 627 628
   to the primary key of the table.
   
   @section secTrans                 Transactions

629 630
   Transactions are committed first to main memory, 
   and then to disk after a global checkpoint (GCP) is issued.
631 632 633 634 635
   Since all data is (in most NDB Cluster configurations) 
   synchronously replicated and stored on multiple NDB nodes,
   the system can still handle processor failures without loss 
   of data.
   However, in the case of a system failure (e.g. the whole system goes down), 
636
   then all (committed or not) transactions occurring since the latest GCP are lost.
637 638 639 640 641 642 643 644


   @subsection secConcur                Concurrency Control
   NDB Cluster uses pessimistic concurrency control based on locking.
   If a requested lock (implicit and depending on database operation)
   cannot be attained within a specified time, 
   then a timeout error occurs.

645 646 647 648 649 650 651
   Concurrent transactions as requested by parallel application programs and 
   thread-based applications can sometimes deadlock when they try to access 
   the same information simultaneously.
   Thus, applications need to be written in a manner so that timeout errors
   occurring due to such deadlocks are handled gracefully. This generally
   means that the transaction encountering a timeout should be rolled back 
   and restarted.
unknown's avatar
unknown committed
652 653


654
   @section secHint                 Hints and Performance
unknown's avatar
unknown committed
655

656
   Placing the transaction co-ordinator in close proximity
unknown's avatar
unknown committed
657 658
   to the actual data used in the transaction can in many cases
   improve performance significantly. This is particularly true for
659 660
   systems using TCP/IP. For example, a Solaris system using a single 500 MHz processor
   has a cost model for TCP/IP communication which can be represented by the formula
unknown's avatar
unknown committed
661

662
     <code>[30 microseconds] + ([100 nanoseconds] * [<var>number of bytes</var>])</code>
unknown's avatar
unknown committed
663 664 665

   This means that if we can ensure that we use "popular" links we increase
   buffering and thus drastically reduce the communication cost.
666
   The same system using SCI has a different cost model:
unknown's avatar
unknown committed
667

668
     <code>[5 microseconds] + ([10 nanoseconds] * [<var>number of bytes</var>])</code>
unknown's avatar
unknown committed
669

670 671 672 673 674 675 676
   Thus, the efficiency of an SCI system is much less dependent on selection of 
   transaction co-ordinators. 
   Typically, TCP/IP systems spend 30-60% of their working time on communication,
   whereas for SCI systems this figure is closer to 5-10%. 
   Thus, employing SCI for data transport means that less care from the NDB API 
   programmer is required and greater scalability can be achieved, even for 
   applications using data from many different parts of the database.
unknown's avatar
unknown committed
677 678 679 680

   A simple example is an application that uses many simple updates where
   a transaction needs to update one record. 
   This record has a 32 bit primary key, 
681
   which is also the partition key. 
unknown's avatar
unknown committed
682 683
   Then the keyData will be the address of the integer 
   of the primary key and keyLen will be 4.
684 685
*/

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
   (A transaction's execution can also be divided into three 
   steps: prepare, send, and poll. This allows us to perform asynchronous
   transactions.  More about this later.)
*/
#endif
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
   Another way to execute several parallel transactions is to use
   asynchronous transactions.
*/
#endif  
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
   Operations are of two different kinds:
   -# standard operations, and
   -# interpreted program operations.
*/
#endif
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
   <h3>Interpreted Program Operations</h3>
   The following types of interpreted program operations exist:
    -# NdbOperation::interpretedUpdateTuple :
       updates a tuple using an interpreted program
    -# NdbOperation::interpretedDeleteTuple :
       delete a tuple using an interpreted program

   The operations interpretedUpdateTuple and interpretedDeleteTuple both
   work using the unique tuple key.

   These <em>interpreted programs</em> 
   make it possible to perform computations
   inside the NDB Cluster Kernel instead of in the application
   program.
   This is sometimes very effective, since no intermediate results
   are sent to the application, only the final result.


  <h3>Interpreted Update and Delete</h3>

   Operations for interpreted updates and deletes must follow a
   certain order when defining operations on a tuple.
   As for read and write operations,
   one must first define the operation type and then the search key.
   -# The first step is to define the initial readings.
      In this phase it is only allowed to use the
      NdbOperation::getValue method.
      This part might be empty.
   -# The second step is to define the interpreted part.
      The methods supported are the methods listed below except
      NdbOperation::def_subroutine and NdbOperation::ret_sub
      which can only be used in a subroutine.
      NdbOperation::incValue and NdbOperation::subValue
      increment and decrement attributes
      (currently only unsigned integers supported).
      This part can also be empty since interpreted updates
      can be used for reading and updating the same tuple.
      <p>
      Even though getValue and setValue are not really interpreted
      program instructions, it is still allowed to use them as
      the last instruction of the program.
      (If a getValue or setValue is found when an interpret_exit_ok
      could have been issued then the interpreted_exit_ok
      will be inserted.
      A interpret_exit_ok should be viewed as a jump to the first
      instruction after the interpreted instructions.)
   -# The third step is to define all updates without any
      interpreted program instructions.
      Here a set of NdbOperation::setValue methods are called.
      There might be zero such calls.
   -# The fourth step is the final readings.
      The initial readings reads the initial value of attributes
      and the final readings reads them after their updates.
      There might be zero NdbOperation::getValue calls.
   -# The fifth step is possible subroutine definitions using
      NdbOperation::def_subroutine and NdbOperation::ret_sub.
*/
#endif
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
   <h3>Interpreted Programs</h3>
   Interpretation programs are executed in a
   register-based virtual machine.
   The virtual machine has eight 64 bit registers numbered 0-7.
   Each register contains type information which is used both
   for type conversion and for type checking.

   @note Arrays are currently <b>not</b> supported in the virtual machine.
         Currently only unsigned integers are supported and of size
         maximum 64 bits.

   All errors in the interpretation program will cause a
   transaction abort, but will not affect any other transactions.

   The following are legal interpreted program instructions:
   -# incValue        : Add to an attribute
   -# subValue        : Subtract from an attribute
   -# def_label       : Define a label in the interpreted program
   -# add_reg         : Add two registers
   -# sub_reg         : Subtract one register from another
   -# load_const_u32  : Load an unsigned 32 bit value into a register
   -# load_const_u64  : Load an unsigned 64 bit value into a register
   -# load_const_null : Load a NULL value into a register
   -# read_attr       : Read attribute value into a register
   -# write_attr      : Write a register value into an attribute
   -# branch_ge       : Compares registers and possibly jumps to specified label
   -# branch_gt       : Compares registers and possibly jumps to specified label
   -# branch_le       : Compares registers and possibly jumps to specified label
   -# branch_lt       : Compares registers and possibly jumps to specified label
   -# branch_eq       : Compares registers and possibly jumps to specified label
   -# branch_ne       : Compares registers and possibly jumps to specified label
   -# branch_ne_null  : Jumps if register does not contain NULL value
   -# branch_eq_null  : Jumps if register contains NULL value
   -# branch_label    : Unconditional jump to label
   -# interpret_exit_ok  : Exit interpreted program
                           (approving tuple if used in scan)
   -# interpret_exit_nok : Exit interpreted program
                           (disqualifying tuple if used in scan)

   There are also three instructions for subroutines, which
   are described in the next section.

   @subsection subsubSub                Interpreted Programs: Subroutines

   The following are legal interpreted program instructions for
   subroutines:
   -# NdbOperation::def_subroutine : 
      Defines start of subroutine in interpreted program code
   -# NdbOperation::call_sub : 
      Calls a subroutine
   -# NdbOperation::ret_sub : 
      Return from subroutine

   The virtual machine executes subroutines using a stack for
   its operation.
   The stack allows for up to 24 subroutine calls in succession.
   Deeper subroutine nesting will cause an abort of the transaction.

   All subroutines starts with the instruction
   NdbOperation::def_subroutine and ends with the instruction
   NdbOperation::ret_sub.
   If it is necessary to return earlier in the subroutine
   it has to be done using a branch_label instruction
   to a label defined right before the 
   NdbOperation::ret_sub instruction.

   @note The subroutines are automatically numbered starting with 0.
         The parameter used by NdbOperation::def_subroutine 
	 should match the automatic numbering to make it easier to 
	 debug the interpreted program.
*/
#endif

#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/**
   @section secAsync                    Asynchronous Transactions
   The asynchronous interface is used to increase the speed of
   transaction executing by better utilizing the connection
   between the application and the NDB Kernel.
   The interface is used to send many transactions 
   at the same time to the NDB kernel.  
   This is often much more efficient than using synchronous transactions.
   The main reason for using this method is to ensure that 
   Sending many transactions at the same time ensures that bigger 
   chunks of data are sent when actually sending and thus decreasing 
   the operating system overhead.

   The synchronous call to NdbTransaction::execute 
   normally performs three main steps:<br>
   -# <b>Prepare</b> 
      Check transaction status
      - if problems, abort the transaction
      - if ok, proceed
   -# <b>Send</b> 
      Send the defined operations since last execute
      or since start of transaction.
   -# <b>Poll</b>
      Wait for response from NDB kernel.

   The asynchronous method NdbTransaction::executeAsynchPrepare 
   only perform step 1.
   (The abort part in step 1 is only prepared for.  The actual 
   aborting of the transaction is performed in a later step.)

   Asynchronous transactions are defined and executed 
   in the following way.
   -# Start (create) transactions (same way as for the 
       synchronous transactions)
   -# Add and define operations (also as in the synchronous case)
   -# <b>Prepare</b> transactions 
       (using NdbTransaction::executeAsynchPrepare or 
       NdbTransaction::executeAsynch)
   -# <b>Send</b> transactions to NDB Kernel
       (using Ndb::sendPreparedTransactions, 
       NdbTransaction::executeAsynch, or Ndb::sendPollNdb)
   -# <b>Poll</b> NDB kernel to find completed transactions 
       (using Ndb::pollNdb or Ndb::sendPollNdb)
   -# Close transactions (same way as for the synchronous transactions)

   See example program in section @ref ndbapi_example2.cpp.
   
   This prepare-send-poll protocol actually exists in four variants:
   - (Prepare-Send-Poll).  This is the one-step variant provided
     by synchronous transactions.
   - (Prepare-Send)-Poll.  This is the two-step variant using
     NdbTransaction::executeAsynch and Ndb::pollNdb.
   - Prepare-(Send-Poll).  This is the two-step variant using
     NdbTransaction::executeAsynchPrepare and Ndb::sendPollNdb.
   - Prepare-Send-Poll.  This is the three-step variant using
     NdbTransaction::executeAsynchPrepare, Ndb::sendPreparedTransactions, and
     Ndb::pollNdb.
  
   Transactions first has to be prepared by using method
   NdbTransaction::executeAsynchPrepare or NdbTransaction::executeAsynch.
   The difference between these is that 
   NdbTransaction::executeAsynch also sends the transaction to 
   the NDB kernel.
   One of the arguments to these methods is a callback method.
   The callback method is executed during polling (item 5 above).
  
   Note that NdbTransaction::executeAsynchPrepare does not 
   send the transaction to the NDB kernel.  When using 
   NdbTransaction::executeAsynchPrepare, you either have to call 
   Ndb::sendPreparedTransactions or Ndb::sendPollNdb to send the 
   database operations.
   (Ndb::sendPollNdb also polls Ndb for completed transactions.)
  
   The methods Ndb::pollNdb and Ndb::sendPollNdb checks if any 
   sent transactions are completed.  The method Ndb::sendPollNdb 
   also send all prepared transactions before polling NDB.
   Transactions still in the definition phase (i.e. items 1-3 above, 
   transactions which has not yet been sent to the NDB kernel) are not 
   affected by poll-calls.
   The poll method invoked (either Ndb::pollNdb or Ndb::sendPollNdb)
   will return when:
    -# at least 'minNoOfEventsToWakeup' of the transactions
       are finished processing, and
    -# all of these transactions have executed their 
       callback methods.
  
   The poll method returns the number of transactions that 
   have finished processing and executed their callback methods.

   @note When an asynchronous transaction has been started and sent to
         the NDB kernel, it is not allowed to execute any methods on
         objects belonging to this transaction until the transaction
         callback method have been executed.
         (The transaction is stated and sent by either
	 NdbTransaction::executeAsynch or through the combination of
         NdbTransaction::executeAsynchPrepare and either
         Ndb::sendPreparedTransactions or Ndb::sendPollNdb).

   More about how transactions are sent the NDB Kernel is 
   available in section @ref secAdapt.
*/
#endif


/**
   
   Put this back when real array ops are supported
   i.e. get/setValue("kalle[3]");

   @subsection secArrays             Array Attributes
952 953 954 955 956
   A table attribute in NDB Cluster can be of type <var>Array</var>,
   meaning that the attribute consists of an ordered sequence of 
   elements. In such cases, <var>attribute size</var> is the size
   (expressed in bits) of any one element making up the array; the 
   <var>array size</var> is the number of elements in the array.
957 958 959

*/

960 961 962 963 964
#ifndef Ndb_H
#define Ndb_H

#include <ndb_types.h>
#include <ndbapi_limits.h>
965
#include <ndb_cluster_connection.hpp>
966
#include <NdbError.hpp>
967
#include <NdbDictionary.hpp>
968 969 970 971 972

class NdbObjectIdMap;
class NdbOperation;
class NdbEventOperationImpl;
class NdbScanOperation;
unknown's avatar
unknown committed
973
class NdbIndexScanOperation;
974
class NdbIndexOperation;
975
class NdbTransaction;
976 977 978 979 980 981 982 983 984
class NdbApiSignal;
class NdbRecAttr;
class NdbLabel;
class NdbBranch;
class NdbSubroutine;
class NdbCall;
class Table;
class BaseString;
class NdbEventOperation;
unknown's avatar
unknown committed
985
class NdbBlob;
unknown's avatar
unknown committed
986
class NdbReceiver;
unknown's avatar
unknown committed
987 988
class TransporterFacade;
class PollGuard;
unknown's avatar
ndb  
unknown committed
989
template <class T> struct Ndb_free_list_t;
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030

typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);

#if defined NDB_OSE
/**
 * Default time to wait for response after request has been sent to 
 * NDB Cluster (Set to 10 seconds usually, but to 100 s in 
 * the OSE operating system)
 */
#define WAITFOR_RESPONSE_TIMEOUT 100000 // Milliseconds
#else
#define WAITFOR_RESPONSE_TIMEOUT 120000 // Milliseconds
#endif

/**
 * @class Ndb 
 * @brief Represents the NDB kernel and is the main class of the NDB API.
 *
 * Always start your application program by creating an Ndb object. 
 * By using several Ndb objects it is possible to design 
 * a multi-threaded application, but note that Ndb objects 
 * cannot be shared by several threads. 
 * Different threads should use different Ndb objects. 
 * A thread might however use multiple Ndb objects.
 * Currently there is a limit of maximum 128 Ndb objects 
 * per application process.
 *
 * @note It is not allowed to call methods in the NDB API 
 *       on the same Ndb object in different threads 
 *       simultaneously (without special handling of the 
 *       Ndb object).
 *
 * @note The Ndb object is multi-thread safe in the following manner. 
 *       Each Ndb object can ONLY be handled in one thread. 
 *       If an Ndb object is handed over to another thread then the 
 *       application must ensure that a memory barrier is used to 
 *       ensure that the new thread see all updates performed by 
 *       the previous thread. 
 *       Semaphores, mutexes and so forth are easy ways of issuing memory 
 *       barriers without having to bother about the memory barrier concept.
 *
unknown's avatar
unknown committed
1031 1032 1033 1034 1035
 */

#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
// to be documented later
/*
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
 * If one Ndb object is used to handle parallel transactions through the 
 * asynchronous programming interface, please read the notes regarding
 * asynchronous transactions (Section @ref secAsync).
 * The asynchronous interface provides much higher performance 
 * in some situations, but is more complicated for the application designer. 
 *
 * @note Each Ndb object should either use the methods for 
 *       asynchronous transaction or the methods for 
 *       synchronous transactions but not both.
 */
unknown's avatar
unknown committed
1046 1047
#endif

1048 1049
class Ndb
{
1050
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
1051 1052 1053
  friend class NdbReceiver;
  friend class NdbOperation;
  friend class NdbEventOperationImpl;
unknown's avatar
unknown committed
1054
  friend class NdbEventBuffer;
1055
  friend class NdbTransaction;
1056 1057 1058
  friend class Table;
  friend class NdbApiSignal;
  friend class NdbIndexOperation;
unknown's avatar
unknown committed
1059 1060
  friend class NdbScanOperation;
  friend class NdbIndexScanOperation;
1061 1062
  friend class NdbDictionaryImpl;
  friend class NdbDictInterface;
unknown's avatar
unknown committed
1063
  friend class NdbBlob;
unknown's avatar
unknown committed
1064
  friend class NdbImpl;
1065
#endif
1066 1067 1068 1069 1070 1071 1072

public:
  /** 
   * @name General 
   * @{
   */
  /**
unknown's avatar
unknown committed
1073 1074
   * The Ndb object represents a connection to a database.
   *
1075
   * @note The init() method must be called before the Ndb object may actually be used.
1076
   *
1077
   * @param ndb_cluster_connection is a connection to the cluster containing
unknown's avatar
unknown committed
1078
   *        the database to be used
1079 1080
   * @param aCatalogName is the name of the catalog to be used.
   * @note The catalog name provides a namespace for the tables and
1081 1082
   *       indexes created in any connection from the Ndb object.
   * @param aSchemaName is the name of the schema you 
unknown's avatar
unknown committed
1083
   *        want to use.
1084
   * @note The schema name provides an additional namespace 
1085 1086
   *       for the tables and indexes created in a given catalog.
   */
1087 1088
  Ndb(Ndb_cluster_connection *ndb_cluster_connection,
      const char* aCatalogName = "", const char* aSchemaName = "def");
1089 1090 1091

  ~Ndb();

unknown's avatar
unknown committed
1092
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
  /**
   * The current catalog name can be fetched by getCatalogName.
   *
   * @return the current catalog name
   */
  const char * getCatalogName() const;

  /**
   * The current catalog name can be set by setCatalogName.
   *
   * @param aCatalogName is the new name of the current catalog
   */
  void setCatalogName(const char * aCatalogName);

  /**
   * The current schema name can be fetched by getSchemaName.
   *
   * @return the current schema name
   */
  const char * getSchemaName() const;

  /**
   * The current schema name can be set by setSchemaName.
   *
   * @param aSchemaName is the new name of the current schema
   */
  void setSchemaName(const char * aSchemaName);
unknown's avatar
unknown committed
1120
#endif
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150

  /**
   * The current database name can be fetched by getDatabaseName.
   *
   * @return the current database name
   */
  const char * getDatabaseName() const;

  /**
   * The current database name can be set by setDatabaseName.
   *
   * @param aDatabaseName is the new name of the current database
   */
  void setDatabaseName(const char * aDatabaseName);

  /**
   * The current database schema name can be fetched by getDatabaseSchemaName.
   *
   * @return the current database schema name
   */
  const char * getDatabaseSchemaName() const;

  /**
   * The current database schema name can be set by setDatabaseSchemaName.
   *
   * @param aDatabaseSchemaName is the new name of the current database schema
   */
  void setDatabaseSchemaName(const char * aDatabaseSchemaName);

  /**
unknown's avatar
unknown committed
1151
   * Initializes the Ndb object
1152 1153 1154
   *
   * @param  maxNoOfTransactions 
   *         Maximum number of parallel 
1155
   *         NdbTransaction objects that can be handled by the Ndb object.
unknown's avatar
unknown committed
1156 1157 1158
   *         Maximum value is 1024.
   *
   * @note each scan or index scan operation uses one extra
1159
   *       NdbTransaction object
1160
   *
unknown's avatar
unknown committed
1161
   * @return 0 if successful, -1 otherwise.
1162 1163 1164
   */
  int init(int maxNoOfTransactions = 4);

1165
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
  /**
   * Wait for Ndb object to successfully set-up connections to 
   * the NDB kernel. 
   * Starting to use the Ndb object without using this method 
   * gives unspecified behavior. 
   * 
   * @param  timeout  The maximum time we will wait for 
   *                  the initiation process to finish.
   *                  Timeout is expressed in seconds.
   * @return  0: Ndb is ready and timeout has not occurred.<br>
   *          -1: Timeout has expired
   */
  int waitUntilReady(int timeout = 60);
unknown's avatar
unknown committed
1179
#endif
1180

1181 1182 1183 1184 1185 1186 1187 1188
  /** @} *********************************************************************/

  /** 
   * @name Meta Information
   * @{
   */

  /**
unknown's avatar
unknown committed
1189 1190 1191
   * Get an object for retrieving or manipulating database schema information 
   *
   * @note this object operates outside any transaction
1192 1193 1194 1195 1196 1197
   *
   * @return Object containing meta information about all tables 
   *         in NDB Cluster.
   */
  class NdbDictionary::Dictionary* getDictionary() const;
  
unknown's avatar
unknown committed
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213

  /** @} *********************************************************************/

  /** 
   * @name Event subscriptions
   * @{
   */

  /**
   * Create a subcription to an event defined in the database
   *
   * @param eventName
   *        unique identifier of the event
   *
   * @return Object representing an event, NULL on failure
   */
unknown's avatar
unknown committed
1214
  NdbEventOperation* createEventOperation(const char* eventName);
unknown's avatar
unknown committed
1215 1216 1217
  /**
   * Drop a subscription to an event
   *
1218 1219
   * @param eventOp
   *        Event operation
unknown's avatar
unknown committed
1220 1221 1222
   *
   * @return 0 on success
   */
1223
  int dropEventOperation(NdbEventOperation* eventOp);
1224 1225

  /**
unknown's avatar
unknown committed
1226 1227
   * Wait for an event to occur. Will return as soon as an event
   * is detected on any of the created events.
1228
   *
unknown's avatar
unknown committed
1229 1230
   * @param aMillisecondNumber
   *        maximum time to wait
1231
   *
unknown's avatar
unknown committed
1232
   * @return > 0 if events available, 0 if no events available, < 0 on failure
1233
   */
unknown's avatar
unknown committed
1234 1235 1236 1237 1238 1239 1240 1241 1242
  int pollEvents(int aMillisecondNumber, Uint64 *latestGCI= 0);

  /**
   * Returns an event operation that has data after a pollEvents
   *
   * @return an event operations that has data, NULL if no events left with data.
   */
  NdbEventOperation *nextEvent();

1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
  /**
   * Iterate over distinct event operations which are part of current
   * GCI.  Valid after nextEvent.  Used to get summary information for
   * the epoch (e.g. list of all tables) before processing event data.
   *
   * Set *iter=0 to start.  Returns NULL when no more.  If event_types
   * is not NULL, it returns bitmask of received event types.
   */
  const NdbEventOperation*
    getGCIEventOperations(Uint32* iter, Uint32* event_types);
  

unknown's avatar
unknown committed
1255 1256 1257 1258 1259 1260 1261
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
  NdbEventOperation *getEventOperation(NdbEventOperation* eventOp= 0);
  Uint64 getLatestGCI();
  void forceGCP();
  void setReportThreshEventGCISlip(unsigned thresh);
  void setReportThreshEventFreeMem(unsigned thresh);
#endif
1262 1263 1264 1265 1266 1267 1268 1269 1270

  /** @} *********************************************************************/

  /** 
   * @name Starting and Closing Transactions
   * @{
   */

  /**
unknown's avatar
unknown committed
1271
   * Start a transaction
1272
   *
unknown's avatar
unknown committed
1273
   * @note When the transaction is completed it must be closed using
1274
   *       Ndb::closeTransaction or NdbTransaction::close. 
unknown's avatar
unknown committed
1275 1276
   *       The transaction must be closed independent of its outcome, i.e.
   *       even if there is an error.
1277
   *
1278
   * @param  table    Pointer to table object used for deciding 
unknown's avatar
unknown committed
1279
   *                  which node to run the Transaction Coordinator on
1280 1281
   * @param  keyData  Pointer to partition key corresponding to
   *                  <var>table</var>
unknown's avatar
unknown committed
1282
   * @param  keyLen   Length of partition key expressed in bytes
1283
   * 
1284
   * @return NdbTransaction object, or NULL on failure.
1285
   */
1286 1287 1288
  NdbTransaction* startTransaction(const NdbDictionary::Table *table= 0,
				   const char  *keyData = 0, 
				   Uint32       keyLen = 0);
1289 1290

  /**
unknown's avatar
unknown committed
1291 1292 1293 1294
   * Close a transaction.
   *
   * @note should be called after the transaction has completed, irrespective
   *       of success or failure
1295
   */
1296
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
1297
  /**
1298 1299 1300 1301 1302 1303 1304 1305 1306
   * @note It is not allowed to call Ndb::closeTransaction after sending the
   *       transaction asynchronously with either 
   *       Ndb::sendPreparedTransactions or
   *       Ndb::sendPollNdb before the callback method has been called.
   *       (The application should keep track of the number of 
   *       outstanding transactions and wait until all of them 
   *       has completed before calling Ndb::closeTransaction).
   *       If the transaction is not committed it will be aborted.
   */
1307
#endif
1308
  void closeTransaction(NdbTransaction*);
1309 1310 1311

  /** @} *********************************************************************/

unknown's avatar
unknown committed
1312 1313
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
  // to be documented later
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
  /** 
   * @name Asynchronous Transactions
   * @{
   */

  /**
   * Wait for prepared transactions.
   * Will return as soon as at least 'minNoOfEventsToWakeUp' 
   * of them have completed, or the maximum time given as timeout has passed.
   *
unknown's avatar
unknown committed
1324 1325 1326 1327
   * @param aMillisecondNumber 
   *        Maximum time to wait for transactions to complete. Polling 
   *        without wait is achieved by setting the timer to zero.
   *        Time is expressed in milliseconds.
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
   * @param minNoOfEventsToWakeup Minimum number of transactions 
   *            which has to wake up before the poll-call will return.
   *            If minNoOfEventsToWakeup is
   *            set to a value larger than 1 then this is the minimum 
   *            number of transactions that need to complete before the 
   *            poll will return.
   *            Setting it to zero means that one should wait for all
   *            outstanding transactions to return before waking up.
   * @return Number of transactions polled.
   */
  int  pollNdb(int aMillisecondNumber = WAITFOR_RESPONSE_TIMEOUT,
	      int minNoOfEventsToWakeup = 1);

  /**
   * This send method will send all prepared database operations. 
   * The default method is to do it non-force and instead
   * use the adaptive algorithm.  (See Section @ref secAdapt.)
   * The second option is to force the sending and 
   * finally there is the third alternative which is 
   * also non-force but also making sure that the 
   * adaptive algorithm do not notice the send. 
   * In this case the sending will be performed on a 
   * cyclical 10 millisecond event.
   *
   * @param forceSend When operations should be sent to NDB Kernel.
   *                  (See @ref secAdapt.)
   *                  - 0: non-force, adaptive algorithm notices it (default); 
   *                  - 1: force send, adaptive algorithm notices it; 
   *                  - 2: non-force, adaptive algorithm do not notice the send.
   */
  void sendPreparedTransactions(int forceSend = 0);

  /**
   * This is a send-poll variant that first calls 
   * Ndb::sendPreparedTransactions and then Ndb::pollNdb. 
   * It is however somewhat faster than calling the methods 
   * separately, since some mutex-operations are avoided. 
   * See documentation of Ndb::pollNdb and Ndb::sendPreparedTransactions
   * for more details.
   *
   * @param aMillisecondNumber Timeout specifier
   *            Polling without wait is achieved by setting the 
   *            millisecond timer to zero.
   * @param minNoOfEventsToWakeup Minimum number of transactions 
   *            which has to wake up before the poll-call will return.
   *            If minNoOfEventsToWakeup is
   *            set to a value larger than 1 then this is the minimum 
   *            number of transactions that need to complete before the 
   *            poll-call will return.
   *            Setting it to zero means that one should wait for all
   *            outstanding transactions to return before waking up.
   * @param forceSend When operations should be sent to NDB Kernel.
   *                  (See @ref secAdapt.)
   * - 0: non-force, adaptive algorithm notices it (default); 
   * - 1: force send, adaptive algorithm notices it; 
   * - 2: non-force, adaptive algorithm does not notice the send.
   * @return Number of transactions polled.
   */
  int  sendPollNdb(int aMillisecondNumber = WAITFOR_RESPONSE_TIMEOUT,
		   int minNoOfEventsToWakeup = 1,
		   int forceSend = 0);
unknown's avatar
unknown committed
1389
  /** @} *********************************************************************/
unknown's avatar
unknown committed
1390
#endif
1391 1392 1393 1394 1395 1396 1397 1398 1399
  
  /** 
   * @name Error Handling
   * @{
   */

  /**
   * Get the NdbError object
   *
unknown's avatar
unknown committed
1400
   * @note The NdbError object is valid until a new NDB API method is called.
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411
   */
  const NdbError & getNdbError() const;
  
  /**
   * Get a NdbError object for a specific error code
   *
   * The NdbError object is valid until you call a new NDB API method.
   */
  const NdbError & getNdbError(int errorCode);


unknown's avatar
unknown committed
1412 1413 1414 1415 1416 1417 1418 1419 1420 1421
  /** @} *********************************************************************/

#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
  /**
   * Get the application node identity.  
   *
   * @return Node id of this application.
   */
  int getNodeId();

1422
  bool usingFullyQualifiedNames();
1423

1424 1425 1426 1427 1428
  /**
   * Different types of tampering with the NDB Cluster.
   * <b>Only for debugging purposes only.</b>
   */
  enum TamperType	{ 
unknown's avatar
unknown committed
1429 1430 1431 1432 1433 1434
    LockGlbChp = 1,           ///< Lock GCP
    UnlockGlbChp,             ///< Unlock GCP
    CrashNode,                ///< Crash an NDB node
    ReadRestartGCI,           ///< Request the restart GCI id from NDB Cluster
    InsertError               ///< Execute an error in NDB Cluster 
                              ///< (may crash system)
1435 1436
  };

1437 1438 1439 1440 1441 1442 1443
  /**
   * For testing purposes it is possible to tamper with the NDB Cluster
   * (i.e. send a special signal to DBDIH, the NDB distribution handler).
   * <b>This feature should only used for debugging purposes.</b>
   * In a release versions of NDB Cluster,
   * this call always return -1 and does nothing.
   * 
1444
   * @param aAction Action to be taken according to TamperType above
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463
   *
   * @param aNode  Which node the action will be taken
   *              -1:   Master DIH.
   *            0-16:   Nodnumber.
   * @return -1 indicates error, other values have meaning dependent 
   *          on type of tampering.
   */
  int NdbTamper(TamperType aAction, int aNode);  

  /**
   * Return a unique tuple id for a table.  The id sequence is
   * ascending but may contain gaps.
   *
   * @param aTableName table name
   *
   * @param cacheSize number of values to cache in this Ndb object
   *
   * @return tuple id or 0 on error
   */
unknown's avatar
unknown committed
1464 1465
  Uint64 getAutoIncrementValue(const char* aTableName, 
			       Uint32 cacheSize = 1);
unknown's avatar
unknown committed
1466
  Uint64 getAutoIncrementValue(const NdbDictionary::Table * aTable, 
1467
			       Uint32 cacheSize = 1);
unknown's avatar
unknown committed
1468
  Uint64 readAutoIncrementValue(const char* aTableName);
unknown's avatar
unknown committed
1469
  Uint64 readAutoIncrementValue(const NdbDictionary::Table * aTable);
unknown's avatar
unknown committed
1470 1471
  bool setAutoIncrementValue(const char* aTableName, Uint64 val, 
			     bool increase = false);
unknown's avatar
unknown committed
1472
  bool setAutoIncrementValue(const NdbDictionary::Table * aTable, Uint64 val, 
1473
			     bool increase = false);
unknown's avatar
unknown committed
1474 1475 1476 1477 1478 1479 1480 1481
  Uint64 getTupleIdFromNdb(const char* aTableName, 
			   Uint32 cacheSize = 1000);
  Uint64 getTupleIdFromNdb(Uint32 aTableId, 
			   Uint32 cacheSize = 1000);
  Uint64 readTupleIdFromNdb(Uint32 aTableId);
  bool setTupleIdInNdb(const char* aTableName, Uint64 val, 
		       bool increase);
  bool setTupleIdInNdb(Uint32 aTableId, Uint64 val, bool increase);
1482 1483 1484 1485
  Uint64 opTupleIdOnNdb(Uint32 aTableId, Uint64 opValue, Uint32 op);

  /**
   */
1486
  NdbTransaction* hupp( NdbTransaction* );
1487
  Uint32 getReference() const { return theMyRef;}
unknown's avatar
ndb  
unknown committed
1488 1489 1490 1491 1492 1493 1494 1495 1496 1497

  struct Free_list_usage
  {
    const char * m_name;
    Uint32 m_created;
    Uint32 m_free;
    Uint32 m_sizeof;
  };

  Free_list_usage * get_free_list_usage(Free_list_usage*);
1498 1499
#endif

unknown's avatar
ndb  
unknown committed
1500 1501
  

1502 1503 1504
/*****************************************************************************
 *	These are service routines used by the other classes in the NDBAPI.
 ****************************************************************************/
unknown's avatar
unknown committed
1505 1506
 Uint32 get_cond_wait_index() { return cond_wait_index; }
 void set_cond_wait_index(Uint32 index) { cond_wait_index = index; }
1507
private:
unknown's avatar
unknown committed
1508 1509 1510
  Uint32 cond_wait_index;
  Ndb *cond_signal_ndb;
  void cond_signal();
1511
  
1512 1513 1514
  void setup(Ndb_cluster_connection *ndb_cluster_connection,
	     const char* aCatalogName, const char* aSchemaName);

unknown's avatar
unknown committed
1515 1516 1517
  void connected(Uint32 block_reference);
 

1518
  NdbTransaction*  startTransactionLocal(Uint32 aPrio, Uint32 aFragmentId); 
1519 1520 1521

// Connect the connection object to the Database.
  int NDB_connect(Uint32 tNode);
1522
  NdbTransaction* doConnect(Uint32 nodeId); 
1523 1524
  void    doDisconnect();	 
  
unknown's avatar
unknown committed
1525
  NdbReceiver*	        getNdbScanRec();// Get a NdbScanReceiver from idle list
1526 1527 1528 1529 1530 1531 1532 1533
  NdbLabel*		getNdbLabel();	// Get a NdbLabel from idle list
  NdbBranch*            getNdbBranch();	// Get a NdbBranch from idle list
  NdbSubroutine*	getNdbSubroutine();// Get a NdbSubroutine from idle
  NdbCall*		getNdbCall();	// Get a NdbCall from idle list
  NdbApiSignal*	        getSignal();	// Get an operation from idle list
  NdbRecAttr*	        getRecAttr();	// Get a receeive attribute object from
					// idle list of the Ndb object.
  NdbOperation* 	getOperation();	// Get an operation from idle list
unknown's avatar
unknown committed
1534
  NdbIndexScanOperation* getScanOperation(); // Get a scan operation from idle
1535 1536
  NdbIndexOperation* 	getIndexOperation();// Get an index operation from idle

unknown's avatar
unknown committed
1537
  NdbBlob*              getNdbBlob();// Get a blob handle etc
1538 1539 1540

  void			releaseSignal(NdbApiSignal* anApiSignal);
  void                  releaseSignalsInList(NdbApiSignal** pList);
unknown's avatar
unknown committed
1541
  void			releaseNdbScanRec(NdbReceiver* aNdbScanRec);
1542 1543 1544 1545 1546 1547
  void			releaseNdbLabel(NdbLabel* anNdbLabel);
  void			releaseNdbBranch(NdbBranch* anNdbBranch);
  void			releaseNdbSubroutine(NdbSubroutine* anNdbSubroutine);
  void			releaseNdbCall(NdbCall* anNdbCall);
  void			releaseRecAttr (NdbRecAttr* aRecAttr);	
  void		 	releaseOperation(NdbOperation* anOperation);	
unknown's avatar
unknown committed
1548
  void		 	releaseScanOperation(NdbIndexScanOperation*);
unknown's avatar
unknown committed
1549
  void                  releaseNdbBlob(NdbBlob* aBlob);
1550 1551 1552

  void                  check_send_timeout();
  void                  remove_sent_list(Uint32);
1553 1554
  Uint32                insert_completed_list(NdbTransaction*);
  Uint32                insert_sent_list(NdbTransaction*);
1555 1556 1557 1558 1559 1560 1561 1562

  // Handle a received signal. Used by both
  // synchronous and asynchronous interface
  void handleReceivedSignal(NdbApiSignal* anApiSignal, struct LinearSectionPtr ptr[3]);
  
  int			sendRecSignal(Uint16 aNodeId,
				      Uint32 aWaitState,
				      NdbApiSignal* aSignal,
unknown's avatar
unknown committed
1563 1564
                                      Uint32 nodeSequence,
                                      Uint32 *ret_conn_seq= 0);
1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589
  
  // Sets Restart GCI in Ndb object
  void			RestartGCI(int aRestartGCI);

  // Get block number of this NDBAPI object
  int			getBlockNumber();
  
  /****************************************************************************
   *	These are local service routines used by this class.	
   ***************************************************************************/
  
  int			createConIdleList(int aNrOfCon);
  int 		createOpIdleList( int nrOfOp );	

  void	freeOperation();          // Free the first idle operation.
  void	freeScanOperation();      // Free the first idle scan operation.
  void	freeIndexOperation();     // Free the first idle index operation.
  void	freeNdbCon();	// Free the first idle connection.
  void	freeSignal();	// Free the first idle signal	
  void	freeRecAttr();	// Free the first idle receive attr obj	
  void	freeNdbLabel();	// Free the first idle NdbLabel obj
  void	freeNdbBranch();// Free the first idle NdbBranch obj
  void	freeNdbSubroutine();// Free the first idle NdbSubroutine obj
  void	freeNdbCall();	    // Free the first idle NdbCall obj
  void	freeNdbScanRec();   // Free the first idle NdbScanRec obj
unknown's avatar
unknown committed
1590
  void  freeNdbBlob();      // Free the first etc
1591

1592
  NdbTransaction* getNdbCon();	// Get a connection from idle list
1593 1594
  
  /**
1595
   * Get a connected NdbTransaction to nodeId
1596 1597
   *   Returns NULL if none found
   */
1598
  NdbTransaction* getConnectedNdbTransaction(Uint32 nodeId);
1599 1600 1601

  // Release and disconnect from DBTC a connection
  // and seize it to theConIdleList
1602
  void	releaseConnectToNdb (NdbTransaction*);
1603 1604

  // Release a connection to idle list
1605
  void 	releaseNdbCon (NdbTransaction*);
1606 1607 1608 1609 1610 1611 1612 1613 1614
  
  int	checkInitState();		// Check that we are initialized
  void	report_node_failure(Uint32 node_id);           // Report Failed node
  void	report_node_failure_completed(Uint32 node_id); // Report Failed node(NF comp.)

  void	checkFailedNode();		// Check for failed nodes

  int   NDB_connect();     // Perform connect towards NDB Kernel

1615
  // Release arrays of NdbTransaction pointers
1616 1617
  void  releaseTransactionArrays();     

1618
  Uint32  pollCompleted(NdbTransaction** aCopyArray);
1619
  void    sendPrepTrans(int forceSend);
1620
  void    reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfComplTrans);
unknown's avatar
unknown committed
1621 1622 1623
  int     poll_trans(int milliSecs, int noOfEventsToWaitFor, PollGuard *pg);
  void    waitCompletedTransactions(int milliSecs, int noOfEventsToWaitFor,
		                    PollGuard *pg);
1624 1625
  void    completedTransaction(NdbTransaction* aTransaction);
  void    completedScanTransaction(NdbTransaction* aTransaction);
1626 1627 1628 1629

  void    abortTransactionsAfterNodeFailure(Uint16 aNodeId);

  static
1630 1631
  const char * externalizeTableName(const char * internalTableName,
                                    bool fullyQualifiedNames);
1632
  const char * externalizeTableName(const char * internalTableName);
1633
  const BaseString internalize_table_name(const char * external_name) const;
1634 1635

  static
1636 1637
  const char * externalizeIndexName(const char * internalIndexName,
                                    bool fullyQualifiedNames);
1638
  const char * externalizeIndexName(const char * internalIndexName);
1639 1640
  const BaseString internalize_index_name(const NdbTableImpl * table,
                                          const char * external_name) const;
1641 1642 1643 1644 1645 1646 1647 1648

  static
  const BaseString getDatabaseFromInternalName(const char * internalName);
  static 
  const BaseString getSchemaFromInternalName(const char * internalName);

  void*              int2void     (Uint32 val);
  NdbReceiver*       void2rec     (void* val);
1649
  NdbTransaction*     void2con     (void* val);
1650 1651 1652 1653 1654 1655
  NdbOperation*      void2rec_op  (void* val);
  NdbIndexOperation* void2rec_iop (void* val);

/******************************************************************************
 *	These are the private variables in this class.	
 *****************************************************************************/
1656 1657 1658
  NdbTransaction**       thePreparedTransactionsArray;
  NdbTransaction**       theSentTransactionsArray;
  NdbTransaction**       theCompletedTransactionsArray;
1659 1660 1661 1662

  Uint32                theNoOfPreparedTransactions;
  Uint32                theNoOfSentTransactions;
  Uint32                theNoOfCompletedTransactions;
1663
  Uint32                theRemainingStartTransactions;
1664 1665 1666 1667 1668
  Uint32                theMaxNoOfTransactions;
  Uint32                theMinNoOfEventsToWakeUp;

  Uint32                theNextConnectNode;

1669 1670
  bool fullyQualifiedNames;

unknown's avatar
unknown committed
1671

1672 1673 1674

  class NdbImpl * theImpl;
  class NdbDictionaryImpl* theDictionary;
unknown's avatar
unknown committed
1675
  class NdbEventBuffer* theEventBuffer;
1676

1677 1678
  NdbTransaction*	theTransactionList;
  NdbTransaction**      theConnectionArray;
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695

  Uint32   theMyRef;        // My block reference  
  Uint32   theNode;         // The node number of our node
  
  Uint64               the_last_check_time;
  Uint64               theFirstTransId;
  
  // The tupleId is retreived from DB the 
  // tupleId is unique for each tableid. 
  Uint64               theFirstTupleId[2048]; 
  Uint64               theLastTupleId[2048];           

  Uint32		theRestartGCI;	// the Restart GCI used by DIHNDBTAMPER
  
  NdbError              theError;

  Int32        	        theNdbBlockNumber;
1696 1697 1698 1699 1700 1701 1702 1703

  enum InitType {
    NotConstructed,
    NotInitialised,
    StartingInit,
    Initialised,
    InitConfigError
  } theInitState;
1704 1705 1706

  NdbApiSignal* theCommitAckSignal;

unknown's avatar
unknown committed
1707 1708

#ifdef POORMANSPURIFY
1709 1710 1711 1712
  int cfreeSignals;
  int cnewSignals;
  int cgetSignals;
  int creleaseSignals;
unknown's avatar
unknown committed
1713
#endif
1714 1715 1716

  static void executeMessage(void*, NdbApiSignal *, 
			     struct LinearSectionPtr ptr[3]);
1717
  static void statusMessage(void*, Uint32, bool, bool);
1718 1719 1720 1721 1722 1723
#ifdef VM_TRACE
  void printState(const char* fmt, ...);
#endif
};

#endif