Dbtup.hpp 108 KB
Newer Older
1 2 3 4
/* 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
5
   the Free Software Foundation; version 2 of the License.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#ifndef DBTUP_H
#define DBTUP_H

#include <pc.hpp>
#include <SimulatedBlock.hpp>
#include <ndb_limits.h>
#include <trigger_definitions.h>
#include <AttributeHeader.hpp>
#include <Bitmask.hpp>
#include <signaldata/TupKey.hpp>
#include <signaldata/CreateTrig.hpp>
#include <signaldata/DropTrig.hpp>
#include <signaldata/TrigAttrInfo.hpp>
#include <signaldata/BuildIndx.hpp>
30 31 32 33
#include "Undo_buffer.hpp"
#include "tuppage.hpp"
#include <../pgman.hpp>
#include <../tsman.hpp>
34

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
// jams
#undef jam
#undef jamEntry
#ifdef DBTUP_BUFFER_CPP
#define jam()	 	jamLine(10000 + __LINE__)
#define jamEntry() 	jamEntryLine(10000 + __LINE__)
#endif
#ifdef DBTUP_ROUTINES_CPP
#define jam()           jamLine(15000 + __LINE__)
#define jamEntry()      jamEntryLine(15000 + __LINE__)
#endif
#ifdef DBTUP_COMMIT_CPP
#define jam()           jamLine(20000 + __LINE__)
#define jamEntry()      jamEntryLine(20000 + __LINE__)
#endif
#ifdef DBTUP_FIXALLOC_CPP
#define jam()           jamLine(25000 + __LINE__)
#define jamEntry()      jamEntryLine(25000 + __LINE__)
#endif
#ifdef DBTUP_TRIGGER_CPP
#define jam()           jamLine(30000 + __LINE__)
#define jamEntry()      jamEntryLine(30000 + __LINE__)
#endif
#ifdef DBTUP_ABORT_CPP
#define jam()           jamLine(35000 + __LINE__)
#define jamEntry()      jamEntryLine(35000 + __LINE__)
#endif
#ifdef DBTUP_PAGE_MAP_CPP
#define jam()           jamLine(40000 + __LINE__)
#define jamEntry()      jamEntryLine(40000 + __LINE__)
#endif
#ifdef DBTUP_PAG_MAN_CPP
#define jam()           jamLine(45000 + __LINE__)
#define jamEntry()      jamEntryLine(45000 + __LINE__)
#endif
#ifdef DBTUP_STORE_PROC_DEF_CPP
#define jam()           jamLine(50000 + __LINE__)
#define jamEntry()      jamEntryLine(50000 + __LINE__)
#endif
#ifdef DBTUP_META_CPP
#define jam()           jamLine(55000 + __LINE__)
#define jamEntry()      jamEntryLine(55000 + __LINE__)
#endif
#ifdef DBTUP_TAB_DES_MAN_CPP
#define jam()           jamLine(60000 + __LINE__)
#define jamEntry()      jamEntryLine(60000 + __LINE__)
#endif
#ifdef DBTUP_GEN_CPP
#define jam()           jamLine(65000 + __LINE__)
#define jamEntry()      jamEntryLine(65000 + __LINE__)
#endif
#ifdef DBTUP_INDEX_CPP
#define jam()           jamLine(70000 + __LINE__)
#define jamEntry()      jamEntryLine(70000 + __LINE__)
#endif
#ifdef DBTUP_DEBUG_CPP
#define jam()           jamLine(75000 + __LINE__)
#define jamEntry()      jamEntryLine(75000 + __LINE__)
#endif
#ifdef DBTUP_VAR_ALLOC_CPP
#define jam()           jamLine(80000 + __LINE__)
#define jamEntry()      jamEntryLine(80000 + __LINE__)
#endif
#ifdef DBTUP_SCAN_CPP
#define jam()           jamLine(85000 + __LINE__)
#define jamEntry()      jamEntryLine(85000 + __LINE__)
#endif
#ifdef DBTUP_DISK_ALLOC_CPP
#define jam()           jamLine(90000 + __LINE__)
#define jamEntry()      jamEntryLine(90000 + __LINE__)
#endif
#ifndef jam
#define jam()           jamLine(__LINE__)
#define jamEntry()      jamEntryLine(__LINE__)
#endif

111 112 113 114 115 116 117 118 119
#ifdef VM_TRACE
inline const char* dbgmask(const Bitmask<MAXNROFATTRIBUTESINWORDS>& bm) {
  static int i=0; static char buf[5][200];
  bm.getText(buf[i%5]); return buf[i++%5]; }
inline const char* dbgmask(const Uint32 bm[2]) {
  static int i=0; static char buf[5][200];
  sprintf(buf[i%5],"%08x%08x",bm[1],bm[0]); return buf[i++%5]; }
#endif

120 121 122 123
#define ZWORDS_ON_PAGE 8192          /* NUMBER OF WORDS ON A PAGE.      */
#define ZATTRBUF_SIZE 32             /* SIZE OF ATTRIBUTE RECORD BUFFER */
#define ZMIN_PAGE_LIMIT_TUPKEYREQ 5
#define ZTUP_VERSION_BITS 15
124 125 126 127 128 129 130 131 132 133 134 135
#define ZTUP_VERSION_MASK ((1 << ZTUP_VERSION_BITS) - 1)
#define MAX_FREE_LIST 4

inline Uint32* ALIGN_WORD(void * ptr)
{
  return (Uint32*)(((UintPtr(ptr) + 3) >> 2) << 2);
}

inline const Uint32* ALIGN_WORD(const void* ptr)
{
  return (Uint32*)(((UintPtr(ptr) + 3) >> 2) << 2);
}
136 137 138 139 140 141 142 143 144 145 146 147 148

#ifdef DBTUP_C
//------------------------------------------------------------------
// Jam Handling:
//
// When DBTUP reports lines through jam in the trace files it has to
// be interpreted. 4024 means as an example line 24 in DbtupCommit.cpp
// Thus 4000 is added to the line number beacuse it is located in the
// file DbtupCommit.cpp. The following is the exhaustive list of the
// added value in the various files. ndbrequire, ptrCheckGuard still
// only reports the line number in the file it currently is located in.
// 
// DbtupExecQuery.cpp         0
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
// DbtupBuffer.cpp         10000
// DbtupRoutines.cpp       15000
// DbtupCommit.cpp         20000
// DbtupFixAlloc.cpp       25000
// DbtupTrigger.cpp        30000
// DbtupAbort.cpp          35000
// DbtupPageMap.cpp        40000
// DbtupPagMan.cpp         45000
// DbtupStoredProcDef.cpp  50000
// DbtupMeta.cpp           55000
// DbtupTabDesMan.cpp      60000
// DbtupGen.cpp            65000
// DbtupIndex.cpp          70000
// DbtupDebug.cpp          75000
// DbtupVarAlloc.cpp       80000
// DbtupScan.cpp           85000
// DbtupDiskAlloc.cpp      90000
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
//------------------------------------------------------------------

/*
2.2 LOCAL SYMBOLS
-----------------
*/
/* ---------------------------------------------------------------- */
/*       S I Z E              O F               R E C O R D S       */
/* ---------------------------------------------------------------- */
#define ZNO_OF_ATTRBUFREC 10000             /* SIZE   OF ATTRIBUTE INFO FILE   */
#define ZNO_OF_CONCURRENT_OPEN_OP 40        /* NUMBER OF CONCURRENT OPENS      */
#define ZNO_OF_CONCURRENT_WRITE_OP 80       /* NUMBER OF CONCURRENT DISK WRITES*/
#define ZNO_OF_FRAGOPREC 20                 /* NUMBER OF CONCURRENT ADD FRAG.  */
#define TOT_PAGE_RECORD_SPACE 262144        /* SIZE OF PAGE RECORD FILE.       */
#define ZNO_OF_PAGE TOT_PAGE_RECORD_SPACE/ZWORDS_ON_PAGE   
#define ZNO_OF_PAGE_RANGE_REC 128           /* SIZE OF PAGE RANGE FILE         */
// Trigger constants
#define ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE 16

/* ---------------------------------------------------------------- */
/* A ATTRIBUTE MAY BE NULL, DYNAMIC OR NORMAL. A NORMAL ATTRIBUTE   */
/* IS A ATTRIBUTE THAT IS NOT NULL OR DYNAMIC. A NULL ATTRIBUTE     */
/* MAY HAVE NO VALUE. A DYNAMIC ATTRIBUTE IS A NULL ATTRIBUTE THAT  */
/* DOES NOT HAVE TO BE A MEMBER OF EVERY TUPLE I A CERTAIN TABLE.   */
/* ---------------------------------------------------------------- */
/**
 * #defines moved into include/kernel/Interpreter.hpp
 */
#define ZINSERT_DELETE 0
195
#define ZUPDATE_ALL 8
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
/* ---------------------------------------------------------------- */
/* THE MINIMUM SIZE OF AN 'EMPTY' TUPLE HEADER IN R-WORDS           */
/* ---------------------------------------------------------------- */
          /* THE TUPLE HEADER FIELD 'SIZE OF NULL ATTR. FIELD' SPECIFYES    */
          /* THE SIZE OF THE TUPLE HEADER FIELD 'NULL ATTR. FIELD'.         */
          /* THE TUPLE HEADER FIELD 'TYPE' SPECIFYES THE TYPE OF THE TUPLE  */
          /* HEADER.                                                        */
                               /* TUPLE ATTRIBUTE INDEX CLUSTERS, ATTRIBUTE */
                               /* CLUSTERS AND A DYNAMIC ATTRIBUTE HEADER.  */
                               /* IT MAY ALSO CONTAIN SHORT ATTRIBUTES AND  */
                               /* POINTERS TO LONG ATTRIBUTE HEADERS.       */
                               /* TUPLE ATTRIBUTE INDEX CLUSTERS, ATTRIBUTE */
                               /* CLUSTERS AND A DYNAMIC ATTRIBUTE HEADER.  */

          /* DATA STRUCTURE TYPES */
          /* WHEN ATTRIBUTE INFO IS SENT WITH A ATTRINFO-SIGNAL THE         */
          /* VARIABLE TYPE IS SPECIFYED. THIS MUST BE DONE TO BE ABLE TO    */
          /* NOW HOW MUCH DATA OF A ATTRIBUTE TO READ FROM ATTRINFO.        */

          /* WHEN A REQUEST CAN NOT BE EXECUTED BECAUSE OF A ERROR THE      */
          /* ERROR MUST BE IDENTIFYED BY MEANS OF A ERROR CODE AND SENT TO  */
          /* THE REQUESTER.                                                 */
#define ZGET_OPREC_ERROR 804            // TUP_SEIZEREF

#define ZEXIST_FRAG_ERROR 816           // Add fragment
#define ZFULL_FRAGRECORD_ERROR 817      // Add fragment
#define ZNO_FREE_PAGE_RANGE_ERROR 818   // Add fragment
#define ZNOFREE_FRAGOP_ERROR 830        // Add fragment
#define ZTOO_LARGE_TUPLE_ERROR 851      // Add fragment
#define ZNO_FREE_TAB_ENTRY_ERROR 852    // Add fragment
#define ZNO_PAGES_ALLOCATED_ERROR 881   // Add fragment

#define ZGET_REALPID_ERROR 809
#define ZNOT_IMPLEMENTED_ERROR 812
#define ZSEIZE_ATTRINBUFREC_ERROR 805
#define ZTOO_MUCH_ATTRINFO_ERROR 823
#define ZMEM_NOTABDESCR_ERROR 826
#define ZMEM_NOMEM_ERROR 827
#define ZAI_INCONSISTENCY_ERROR 829
#define ZNO_ILLEGAL_NULL_ATTR 839
#define ZNOT_NULL_ATTR 840
#define ZNO_INSTRUCTION_ERROR 871
#define ZOUTSIDE_OF_PROGRAM_ERROR 876
#define ZSTORED_PROC_ID_ERROR 877
#define ZREGISTER_INIT_ERROR 878
#define ZATTRIBUTE_ID_ERROR 879
#define ZTRY_TO_READ_TOO_MUCH_ERROR 880
#define ZTOTAL_LEN_ERROR 882
#define ZATTR_INTERPRETER_ERROR 883
#define ZSTACK_OVERFLOW_ERROR 884
#define ZSTACK_UNDERFLOW_ERROR 885
#define ZTOO_MANY_INSTRUCTIONS_ERROR 886
#define ZTRY_TO_UPDATE_ERROR 888
#define ZCALL_ERROR 890
#define ZTEMPORARY_RESOURCE_FAILURE 891
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
251
#define ZUNSUPPORTED_BRANCH 892
252 253 254 255 256 257 258 259 260 261 262 263

#define ZSTORED_SEIZE_ATTRINBUFREC_ERROR 873 // Part of Scan

#define ZREAD_ONLY_CONSTRAINT_VIOLATION 893
#define ZVAR_SIZED_NOT_SUPPORTED 894
#define ZINCONSISTENT_NULL_ATTRIBUTE_COUNT 895
#define ZTUPLE_CORRUPTED_ERROR 896
#define ZTRY_UPDATE_PRIMARY_KEY 897
#define ZMUST_BE_ABORTED_ERROR 898
#define ZTUPLE_DELETED_ERROR 626
#define ZINSERT_ERROR 630

264
#define ZINVALID_CHAR_FORMAT 744
265
#define ZROWID_ALLOCATED 899
266 267

          /* SOME WORD POSITIONS OF FIELDS IN SOME HEADERS */
268

269 270 271 272
#define ZFREE_COMMON 1                    /* PAGE STATE, PAGE IN COMMON AREA                   */
#define ZEMPTY_MM 2                       /* PAGE STATE, PAGE IN EMPTY LIST                    */
#define ZTH_MM_FREE 3                     /* PAGE STATE, TUPLE HEADER PAGE WITH FREE AREA      */
#define ZTH_MM_FULL 4                     /* PAGE STATE, TUPLE HEADER PAGE WHICH IS FULL       */
273

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
#define ZTD_HEADER 0                      /* HEADER POSITION                   */
#define ZTD_DATASIZE 1                    /* SIZE OF THE DATA IN THIS CHUNK    */
#define ZTD_SIZE 2                        /* TOTAL SIZE OF TABLE DESCRIPTOR    */

          /* TRAILER POSITIONS FROM END OF TABLE DESCRIPTOR RECORD               */
#define ZTD_TR_SIZE 1                     /* SIZE DESCRIPTOR POS FROM END+1    */
#define ZTD_TR_TYPE 2
#define ZTD_TRAILER_SIZE 2                /* TOTAL SIZE OF TABLE TRAILER       */
#define ZAD_SIZE 2                        /* TOTAL SIZE OF ATTR DESCRIPTOR     */
#define ZAD_LOG_SIZE 1                    /* TWO LOG OF TOTAL SIZE OF ATTR DESCRIPTOR     */

          /* CONSTANTS USED TO HANDLE TABLE DESCRIPTOR AS A FREELIST             */
#define ZTD_FL_HEADER 0                   /* HEADER POSITION                   */
#define ZTD_FL_SIZE 1                     /* TOTAL SIZE OF THIS FREELIST ENTRY */
#define ZTD_FL_PREV 2                     /* PREVIOUS RECORD IN FREELIST       */
#define ZTD_FL_NEXT 3                     /* NEXT RECORD IN FREELIST           */
#define ZTD_FREE_SIZE 16                  /* SIZE NEEDED TO HOLD ONE FL ENTRY  */

          /* CONSTANTS USED IN LSB OF TABLE DESCRIPTOR HEADER DESCRIBING USAGE   */
#define ZTD_TYPE_FREE 0                   /* RECORD LINKED INTO FREELIST       */
#define ZTD_TYPE_NORMAL 1                 /* RECORD USED AS TABLE DESCRIPTOR   */
          /* ATTRIBUTE OPERATION CONSTANTS */
#define ZLEAF 1
#define ZNON_LEAF 2

          /* ATTRINBUFREC VARIABLE POSITIONS. */
#define ZBUF_PREV 29                      /* POSITION OF 'PREV'-VARIABLE (USED BY INTERPRETED EXEC) */
#define ZBUF_DATA_LEN 30                  /* POSITION OF 'DATA LENGTH'-VARIABLE. */
#define ZBUF_NEXT 31                      /* POSITION OF 'NEXT'-VARIABLE.        */
#define ZSAVE_BUF_NEXT 28
#define ZSAVE_BUF_DATA_LEN 27

          /* RETURN POINTS. */
          /* RESTART PHASES */
#define ZSTARTPHASE1 1
#define ZSTARTPHASE2 2
#define ZSTARTPHASE3 3
#define ZSTARTPHASE4 4
#define ZSTARTPHASE6 6

#define ZADDFRAG 0

//------------------------------------------------------------
// TUP_CONTINUEB codes
//------------------------------------------------------------
#define ZINITIALISE_RECORDS 6
#define ZREL_FRAG 7
#define ZREPORT_MEMORY_USAGE 8
#define ZBUILD_INDEX 9
323 324 325
#define ZTUP_SCAN 10
#define ZFREE_EXTENT 11
#define ZUNMAP_PAGES 12
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
326
#define ZFREE_VAR_PAGES 13
327 328 329 330 331 332

#define ZSCAN_PROCEDURE 0
#define ZCOPY_PROCEDURE 2
#define ZSTORED_PROCEDURE_DELETE 3
#define ZSTORED_PROCEDURE_FREE 0xffff
#define ZMIN_PAGE_LIMIT_TUP_COMMITREQ 2
333

334 335
#define ZSKIP_TUX_TRIGGERS 0x1 // flag for TUP_ABORTREQ

336 337 338
#endif

class Dbtup: public SimulatedBlock {
339
friend class Suma;
340
public:
341
struct KeyReqStruct;
342
friend struct KeyReqStruct; // CC
343 344 345 346 347 348
typedef bool (Dbtup::* ReadFunction)(Uint32*,
                                     KeyReqStruct*,
                                     AttributeHeader*,
                                     Uint32);
typedef bool (Dbtup::* UpdateFunction)(Uint32*,
                                       KeyReqStruct*,
349
                                       Uint32);
350 351 352 353 354 355 356 357 358 359 360
private:
  
  typedef Tup_fixsize_page Fix_page;
  typedef Tup_varsize_page Var_page;

public:
  class Dblqh *c_lqh;
  Tsman* c_tsman;
  Lgman* c_lgman;
  Page_cache_client m_pgman;

361
// State values
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
enum ChangeMaskState {
  DELETE_CHANGES = 0,
  SET_ALL_MASK = 1,
  USE_SAVED_CHANGE_MASK = 2,
  RECALCULATE_CHANGE_MASK = 3
};

enum TransState {
  TRANS_IDLE = 0,
  TRANS_STARTED = 1,
  TRANS_WAIT_STORED_PROCEDURE_ATTR_INFO = 2,
  TRANS_ERROR_WAIT_STORED_PROCREQ = 3,
  TRANS_ERROR_WAIT_TUPKEYREQ = 4,
  TRANS_TOO_MUCH_AI = 5,
  TRANS_DISCONNECTED = 6
};

enum TupleState {
  TUPLE_PREPARED = 1,
  TUPLE_ALREADY_ABORTED = 2,
  TUPLE_TO_BE_COMMITTED = 3
};
  
385 386 387 388 389 390 391 392 393
enum State {
  NOT_INITIALIZED = 0,
  IDLE = 17,
  ACTIVE = 18,
  SYSTEM_RESTART = 19,
  DEFINED = 34,
  NOT_DEFINED = 37,
  NORMAL_PAGE = 40,
  DEFINING = 65,
394
  DROPPING = 68
395 396 397 398 399 400 401 402 403 404 405 406
};

// Records
/* ************** ATTRIBUTE INFO BUFFER RECORD ****************** */
/* THIS RECORD IS USED AS A BUFFER FOR INCOMING AND OUTGOING DATA */
/* ************************************************************** */
struct Attrbufrec {
  Uint32 attrbuf[ZATTRBUF_SIZE];
}; /* p2c: size = 128 bytes */

typedef Ptr<Attrbufrec> AttrbufrecPtr;

407

408 409

struct Fragoperrec {
410 411
  Uint64 minRows;
  Uint64 maxRows;
412 413 414 415 416 417
  Uint32 nextFragoprec;
  Uint32 lqhPtrFrag;
  Uint32 fragidFrag;
  Uint32 tableidFrag;
  Uint32 fragPointer;
  Uint32 attributeCount;
418
  Uint32 charsetIndex;
419 420 421
  Uint32 m_null_bits[2];
  Uint32 m_fix_attributes_size[2]; // In words
  Uint32 m_var_attributes_size[2]; // In bytes
422
  BlockReference lqhBlockrefFrag;
423
  bool inUse;
424
  bool definingFragment;
425 426 427
};
typedef Ptr<Fragoperrec> FragoperrecPtr;

428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451

  typedef Tup_page Page;
  typedef Ptr<Page> PagePtr;

  // Scan position
  struct ScanPos {
    enum Get {
      Get_undef = 0,
      Get_next_page,
      Get_page,
      Get_next_page_mm,
      Get_page_mm,
      Get_next_page_dd,
      Get_page_dd,
      Get_next_tuple,
      Get_tuple,
      Get_next_tuple_fs,
      Get_tuple_fs
    };
    Get m_get;                  // entry point in scanNext
    Local_key m_key;            // scan position pointer MM or DD
    Page* m_page;               // scanned MM or DD (cache) page
    Local_key m_key_mm;         // MM local key returned
    Uint32 m_realpid_mm;        // MM real page id
452
    Uint32 m_extent_info_ptr_i;
453 454
  };

455 456 457 458 459 460 461 462 463 464 465 466 467 468
  // Scan Lock
  struct ScanLock {
    Uint32 m_accLockOp;
    union {
      Uint32 nextPool;
      Uint32 nextList;
    };
    Uint32 prevList;
  };
  typedef Ptr<ScanLock> ScanLockPtr;
  ArrayPool<ScanLock> c_scanLockPool;

  // Tup scan, similar to Tux scan.  Later some of this could
  // be moved to common superclass.
469
  struct ScanOp {
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
    ScanOp() :
      m_state(Undef),
      m_bits(0),
      m_userPtr(RNIL),
      m_userRef(RNIL),
      m_tableId(RNIL),
      m_fragId(~(Uint32)0),
      m_fragPtrI(RNIL),
      m_transId1(0),
      m_transId2(0),
      m_savePointId(0),
      m_accLockOp(RNIL)
    {}

    enum State {
485 486
      Undef = 0,
      First = 1,                // before first entry
487 488 489
      Current = 2,              // at current before locking
      Blocked = 3,              // at current waiting for ACC lock
      Locked = 4,               // at current and locked or no lock needed
490 491
      Next = 5,                 // looking for next extry
      Last = 6,                 // after last entry
492
      Aborting = 7,             // lock wait at scan close
493 494 495
      Invalid = 9               // cannot return REF to LQH currently
    };
    Uint16 m_state;
496

497 498 499 500 501 502 503 504 505 506 507
    enum Bits {
      SCAN_DD        = 0x01,        // scan disk pages
      SCAN_VS        = 0x02,        // page format is var size
      SCAN_LCP       = 0x04,        // LCP mem page scan
      SCAN_LOCK_SH   = 0x10,        // lock mode shared
      SCAN_LOCK_EX   = 0x20,        // lock mode exclusive
      SCAN_LOCK_WAIT = 0x40,        // lock wait
      // any lock mode
      SCAN_LOCK      = SCAN_LOCK_SH | SCAN_LOCK_EX,
      SCAN_NR        = 0x80        // Node recovery scan
    };
508 509
    Uint16 m_bits;
    
510 511 512
    Uint32 m_userPtr;           // scanptr.i in LQH
    Uint32 m_userRef;
    Uint32 m_tableId;
513
    Uint32 m_fragId;
514
    Uint32 m_fragPtrI;
515 516
    Uint32 m_transId1;
    Uint32 m_transId2;
517 518 519 520 521 522 523 524 525 526 527
    union {
      Uint32 m_savePointId;
      Uint32 m_scanGCI;
    };
    // lock waited for or obtained and not yet passed to LQH
    Uint32 m_accLockOp;

    ScanPos m_scanPos;

    DLFifoList<ScanLock>::Head m_accLockOps;

528 529 530 531 532 533 534 535 536
    union {
    Uint32 nextPool;
    Uint32 nextList;
    };
    Uint32 prevList;
  };
  typedef Ptr<ScanOp> ScanOpPtr;
  ArrayPool<ScanOp> c_scanOpPool;

537 538 539 540 541 542 543 544 545 546 547 548
  void scanReply(Signal*, ScanOpPtr scanPtr);
  void scanFirst(Signal*, ScanOpPtr scanPtr);
  bool scanNext(Signal*, ScanOpPtr scanPtr);
  void scanCont(Signal*, ScanOpPtr scanPtr);
  void disk_page_tup_scan_callback(Signal*, Uint32 scanPtrI, Uint32 page_i);
  void scanClose(Signal*, ScanOpPtr scanPtr);
  void addAccLockOp(ScanOp& scan, Uint32 accLockOp);
  void removeAccLockOp(ScanOp& scan, Uint32 accLockOp);
  void releaseScanOp(ScanOpPtr& scanPtr);

  // for md5 of key (could maybe reuse existing temp buffer)
  Uint64 c_dataBuffer[ZWORDS_ON_PAGE/2 + 1];
549 550 551 552 553 554

  struct Page_request 
  {
    Local_key m_key;
    Uint32 m_frag_ptr_i;
    Uint32 m_extent_info_ptr;
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
555 556 557
    Uint16 m_estimated_free_space; // in bytes/records
    Uint16 m_list_index;           // in Disk_alloc_info.m_page_requests
    Uint16 m_ref_count;            // Waiters for page
558
    Uint16 m_uncommitted_used_space;
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
559
    Uint32 nextList;
560
    Uint32 prevList;
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
561
    Uint32 m_magic;
562
  }; // 32 bytes
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
563 564 565 566
  
  typedef RecordPool<Page_request, WOPool> Page_request_pool;
  typedef DLFifoListImpl<Page_request_pool, Page_request> Page_request_list;
  typedef LocalDLFifoListImpl<Page_request_pool, Page_request> Local_page_request_list;
567 568 569 570 571 572 573 574 575 576 577 578

  STATIC_CONST( EXTENT_SEARCH_MATRIX_COLS = 4 ); // Guarantee size
  STATIC_CONST( EXTENT_SEARCH_MATRIX_ROWS = 5 ); // Total size
  STATIC_CONST( EXTENT_SEARCH_MATRIX_SIZE = 20 );
  
  struct Extent_list_t
  {
    Uint32 nextList;
  };

  struct Extent_info : public Extent_list_t
  {
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
579
    Uint32 m_magic;
580
    Uint32 m_first_page_no;
581 582 583 584 585 586 587 588 589 590 591 592 593 594
    Local_key m_key;
    Uint32 m_free_space;
    Uint32 m_free_matrix_pos;
    Uint16 m_free_page_count[EXTENT_SEARCH_MATRIX_COLS];
    union {
      Uint32 nextList;
      Uint32 nextPool;
    };
    Uint32 prevList;
    Uint32 nextHash, prevHash;

    Uint32 hashValue() const {
      return (m_key.m_file_no << 16) ^ m_key.m_page_idx;
    }
595

596
    Extent_info() {}
597 598 599 600 601 602
    bool equal(const Extent_info & rec) const {
      return m_key.m_file_no == rec.m_key.m_file_no &&
	m_key.m_page_idx == rec.m_key.m_page_idx;
    }
  }; // 40 bytes

jonas@eel.(none)'s avatar
jonas@eel.(none) committed
603 604 605 606 607 608
  typedef RecordPool<Extent_info, RWPool> Extent_info_pool;
  typedef DLListImpl<Extent_info_pool, Extent_info> Extent_info_list;
  typedef LocalDLListImpl<Extent_info_pool, Extent_info> Local_extent_info_list;
  typedef DLHashTableImpl<Extent_info_pool, Extent_info> Extent_info_hash;
  typedef SLListImpl<Extent_info_pool, Extent_info, Extent_list_t> Fragment_extent_list;
  typedef LocalSLListImpl<Extent_info_pool, Extent_info, Extent_list_t> Local_fragment_extent_list;
609 610 611 612 613 614
  struct Tablerec;
  struct Disk_alloc_info 
  {
    Disk_alloc_info() {}
    Disk_alloc_info(const Tablerec* tabPtrP, 
		    Uint32 extent_size_in_pages);
615
    Uint32 m_extent_size;
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
    
    /**
     * Disk allocation
     *
     * 1) Allocate space on pages that already are dirty
     *    (4 free lists for different requests)
     * 2) Allocate space on pages waiting to maped that will be dirty
     *    (4 free lists for different requests)
     * 3) Check if "current" extent can accommodate request
     *    If so, allocate page from there
     *    Else put "current" into free matrix
     * 4) Search free matrix for extent with greatest amount of free space
     *    while still accommodating current request
     *    (20 free lists for different requests)
     */
    
    /**
     * Free list of pages in different size
     *   that are dirty
     */
    DLList<Page>::Head m_dirty_pages[MAX_FREE_LIST];   // In real page id's

    /**
     * Requests (for update) that have sufficient space left after request
     *   these are currently being "mapped"
     */
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
642
    Page_request_list::Head m_page_requests[MAX_FREE_LIST];
643 644 645 646 647 648 649 650 651 652

    /**
     * Current extent
     */
    Uint32 m_curr_extent_info_ptr_i;
    
    /**
     * 
     */
    STATIC_CONST( SZ = EXTENT_SEARCH_MATRIX_SIZE );
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
653
    Extent_info_list::Head m_free_extents[SZ];
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
    Uint32 m_total_extent_free_space_thresholds[EXTENT_SEARCH_MATRIX_ROWS];
    Uint32 m_page_free_bits_map[EXTENT_SEARCH_MATRIX_COLS];

    Uint32 find_extent(Uint32 sz) const;
    Uint32 calc_extent_pos(const Extent_info*) const;

    /**
     * Compute minimum free space on page given bits
     */
    Uint32 calc_page_free_space(Uint32 bits) const {
      return m_page_free_bits_map[bits];
    }
  
    /**
     * Compute page free bits, given free space
     */
    Uint32 calc_page_free_bits(Uint32 free) const {
      for(Uint32 i = 0; i<EXTENT_SEARCH_MATRIX_COLS-1; i++)
	if(free >= m_page_free_bits_map[i])
	  return i;
      return EXTENT_SEARCH_MATRIX_COLS - 1;
    }

jonas@eel.(none)'s avatar
jonas@eel.(none) committed
677
    Fragment_extent_list::Head m_extent_list;
678 679
  };
  
680 681
  void dump_disk_alloc(Disk_alloc_info&);

682 683 684 685 686
struct Fragrecord {
  Uint32 nextStartRange;
  Uint32 currentPageRange;
  Uint32 rootPageRange;
  Uint32 noOfPages;
687
  Uint32 noOfVarPages;
688
  Uint32 noOfPagesToGrow;
689

690 691 692 693
  DLList<Page>::Head emptyPrimPage; // allocated pages (not init)
  DLList<Page>::Head thFreeFirst;   // pages with atleast 1 free record
  SLList<Page>::Head m_empty_pages; // Empty pages not in logical/physical map
  
694
  Uint32 m_lcp_scan_op;
695
  Uint32 m_lcp_keep_list;
696 697 698 699 700

  State fragStatus;
  Uint32 fragTableId;
  Uint32 fragmentId;
  Uint32 nextfreefrag;
701 702
  DLList<Page>::Head free_var_page_array[MAX_FREE_LIST];
  
703
  DLList<ScanOp>::Head m_scanList;
704

705 706
  enum { UC_LCP = 1, UC_CREATE = 2 };
  Uint32 m_undo_complete;
707 708 709
  Uint32 m_tablespace_id;
  Uint32 m_logfile_group_id;
  Disk_alloc_info m_disk_alloc_info;
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
710
  Uint32 m_var_page_chunks;
711 712 713 714 715
};
typedef Ptr<Fragrecord> FragrecordPtr;


struct Operationrec {
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
  /*
   * To handle Attrinfo signals and buffer them up we need to
   * a simple list with first and last and we also need to keep track
   * of how much we received for security check.
   * Will most likely disappear with introduction of long signals.
   * These variables are used before TUPKEYREQ is received and not
   * thereafter and is disposed with after calling copyAttrinfo
   * which is called before putting the operation into its lists.
   * Thus we can use union declarations for these variables.
   */

  /*
   * Used by scans to find the Attrinfo buffers.
   * This is only until returning from copyAttrinfo and
   * can thus reuse the same memory as needed by the
   * active operation list variables.
   */

  /*
   * Doubly linked list with anchor on tuple.
   * This is to handle multiple updates on the same tuple
   * by the same transaction.
   */
  union {
    Uint32 prevActiveOp;
    Uint32 storedProcedureId; //Used until copyAttrinfo
  };
  union {
    Uint32 nextActiveOp;
    Uint32 currentAttrinbufLen; //Used until copyAttrinfo
  };

748
  Operationrec() {}
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
  bool is_first_operation() const { return prevActiveOp == RNIL;}
  bool is_last_operation() const { return nextActiveOp == RNIL;}

  Uint32 m_undo_buffer_space; // In words
  union {
    Uint32 firstAttrinbufrec; //Used until copyAttrinfo
  };
  union {
    Uint32 lastAttrinbufrec; //Used until copyAttrinfo
    Uint32 nextPool;
  };
  Uint32 attrinbufLen; //only used during STORED_PROCDEF phase
  Uint32 storedProcPtr; //only used during STORED_PROCDEF phase
  
  /*
   * From fragment i-value we can find fragment and table record
   */
766
  Uint32 fragmentPtr;
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781

  /*
   * We need references to both the original tuple and the copy tuple.
   * We keep the page's real i-value and its index and from there we
   * can find out about the fragment page id and the page offset.
   */
  Local_key m_tuple_location;
  Local_key m_copy_tuple_location;

  /*
   * We keep the record linked to the operation record in LQH.
   * This is needed due to writing of REDO log must be performed
   * in correct order, which is the same order as the writes
   * occurred. LQH can receive the records in different order.
   */
782 783
  Uint32 userpointer;

784 785 786 787 788 789
  /*
   * When responding to queries in the same transaction they will see
   * a result from the save point id the query was started. Again
   * functionality for multi-updates of the same record in one
   * transaction.
   */
790
  union {
791 792 793 794 795 796 797
    Uint32 savepointId;
    Uint32 m_commit_disk_callback_page;
  };

  /*
   * We use 64 bits to save change mask for the most common cases.
   */
798
  Uint32 saved_change_mask[2];
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
  /*
   * State variables on connection.
   * State variable on tuple after multi-updates
   * Is operation undo logged or not
   * Is operation in fragment list
   * Is operation in multi-update list
   * Operation type (READ, UPDATE, etc)
   * Is record primary replica
   * Is delete or insert performed
   */
  struct OpBitFields {
    unsigned int trans_state : 3;
    unsigned int tuple_state : 2;
    unsigned int in_active_list : 1;

    unsigned int op_type : 3;
    unsigned int delete_insert_flag : 1;
    unsigned int primary_replica : 1;
    unsigned int change_mask_state : 2;
    unsigned int m_disk_preallocated : 1;
    unsigned int m_load_diskpage_on_commit : 1;
    unsigned int m_wait_log_buffer : 1;
  };
  union {
    OpBitFields op_struct;
    Uint16 op_bit_fields;
  };

  /*
   * TUX needs to know the tuple version of the tuple since it
   * keeps an entry for both the committed and all versions in
   * a transaction currently. So each update will create a new
   * version even if in the same transaction.
   */
  Uint16 tupVersion;
835
};
836
typedef Ptr<Operationrec> OperationrecPtr;
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

          /* ****************************** PAGE RANGE RECORD ************************** */
          /* PAGE RANGES AND BASE PAGE ID. EACH RANGE HAS A  CORRESPONDING BASE PAGE ID  */
          /* THAT IS USED TO  CALCULATE REAL PAGE ID FROM A FRAGMENT PAGE ID AND A TABLE */
          /* REFERENCE.                                                                  */
          /* THE PAGE RANGES ARE ORGANISED IN A B-TREE FASHION WHERE THE VARIABLE TYPE   */
          /* SPECIFIES IF A LEAF NODE HAS BEEN REACHED. IF A LEAF NODE HAS BEEN REACHED  */
          /* THEN BASE_PAGE_ID IS THE BASE_PAGE_ID OF THE SET OF PAGES THAT WAS          */
          /* ALLOCATED IN THAT RANGE. OTHERWISE BASE_PAGE_ID IS THE POINTER TO THE NEXT  */
          /* PAGE_RANGE RECORD.                                                          */
          /* *************************************************************************** */
struct PageRange {
  Uint32 startRange[4];                                  /* START OF RANGE                                   */
  Uint32 endRange[4];                                    /* END OF THIS RANGE                                */
  Uint32 basePageId[4];                                  /* BASE PAGE ID.                                    */
/*----               VARIABLE BASE_PAGE_ID2 (4) 8 DS NEEDED WHEN SUPPORTING 40 BIT PAGE ID           -------*/
  Uint8 type[4];                                        /* TYPE OF BASE PAGE ID                             */
  Uint32 nextFree;                                       /* NEXT FREE PAGE RANGE RECORD                      */
  Uint32 parentPtr;                                      /* THE PARENT TO THE PAGE RANGE REC IN THE B-TREE   */
  Uint8 currentIndexPos;
};
typedef Ptr<PageRange> PageRangePtr;


  /* ************* TRIGGER DATA ************* */
  /* THIS RECORD FORMS LISTS OF ACTIVE       */
  /* TRIGGERS FOR EACH TABLE.                 */
  /* THE RECORDS ARE MANAGED BY A TRIGGER     */
  /* POOL wHERE A TRIGGER RECORD IS SEIZED    */
  /* WHEN A TRIGGER IS ACTIVATED AND RELEASED */
  /* WHEN THE TRIGGER IS DEACTIVATED.         */
  /* **************************************** */
struct TupTriggerData {
870
  TupTriggerData() {}
871 872 873
  
  /**
   * Trigger id, used by DICT/TRIX to identify the trigger
874 875 876 877
   *
   * trigger Ids are unique per block for SUBSCRIPTION triggers.
   * This is so that BACKUP can use TUP triggers directly and delete them
   * properly.
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
   */
  Uint32 triggerId;

  /**
   * Index id is needed for ordered index.
   */
  Uint32 indexId;

  /**
   * Trigger type etc, defines what the trigger is used for
   */
  TriggerType::Value triggerType;
  TriggerActionTime::Value triggerActionTime;
  TriggerEvent::Value triggerEvent;
  /**
   * Receiver block
   */
  Uint32 m_receiverBlock;
  
  /**
   * Monitor all replicas, i.e. trigger will fire on all nodes where tuples
   * are stored
   */
  bool monitorReplicas;

  /**
   * Monitor all attributes, the trigger monitors all changes to attributes 
   * in the table
   */
  bool monitorAllAttributes;

  /**
   * Send only changed attributes at trigger firing time.
   */
  bool sendOnlyChangedAttributes;

  /**
   * Send also before values at trigger firing time.
   */
  bool sendBeforeValues;

  /**
   * Attribute mask, defines what attributes are to be monitored
   * Can be seen as a compact representation of SQL column name list
   */
  Bitmask<MAXNROFATTRIBUTESINWORDS> attributeMask;
  
  /**
   * Next ptr (used in pool/list)
   */
  union {
    Uint32 nextPool;
    Uint32 nextList;
  };
  
  /**
   * Prev pointer (used in list)
   */
  Uint32 prevList;

  inline void print(NdbOut & s) const { s << "[TriggerData = " << triggerId << "]"; };
};

typedef Ptr<TupTriggerData> TriggerPtr;
  
/**
 * Pool of trigger data record
 */
ArrayPool<TupTriggerData> c_triggerPool;

948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
  /* ************ TABLE RECORD ************ */
  /* THIS RECORD FORMS A LIST OF TABLE      */
  /* REFERENCE INFORMATION. ONE RECORD      */
  /* PER TABLE REFERENCE.                   */
  /* ************************************** */
  STATIC_CONST( MM = 0 );
  STATIC_CONST( DD = 1 );
  
  struct Tablerec {
    Tablerec(ArrayPool<TupTriggerData> & triggerPool) : 
      afterInsertTriggers(triggerPool),
      afterDeleteTriggers(triggerPool),
      afterUpdateTriggers(triggerPool),
      subscriptionInsertTriggers(triggerPool),
      subscriptionDeleteTriggers(triggerPool),
      subscriptionUpdateTriggers(triggerPool),
      constraintUpdateTriggers(triggerPool),
      tuxCustomTriggers(triggerPool)
      {}
    
    Bitmask<MAXNROFATTRIBUTESINWORDS> notNullAttributeMask;
969
    Bitmask<MAXNROFATTRIBUTESINWORDS> blobAttributeMask;
970 971 972 973 974 975 976 977 978
    
    ReadFunction* readFunctionArray;
    UpdateFunction* updateFunctionArray;
    CHARSET_INFO** charsetArray;
    
    Uint32 readKeyArray;
    Uint32 tabDescriptor;
    Uint32 m_real_order_descriptor;
    
979 980 981 982 983 984
    enum Bits
    {
      TR_Checksum = 0x1, // Need to be 1
      TR_RowGCI   = 0x2
    };
    Uint16 m_bits;
985 986 987 988 989 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 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
    Uint16 total_rec_size; // Max total size for entire tuple in words
    
    /**
     * Aggregates
     */
    Uint16 m_no_of_attributes;
    Uint16 m_no_of_disk_attributes;
    Uint16 noOfKeyAttr;
    Uint16 noOfCharsets;

    bool need_expand() const { 
      return m_no_of_attributes > m_attributes[MM].m_no_of_fixsize;
    }

    bool need_expand(bool disk) const { 
      return m_attributes[MM].m_no_of_varsize > 0 ||
	(disk && m_no_of_disk_attributes > 0);
    }
    
    bool need_shrink() const {
      return 
	m_attributes[MM].m_no_of_varsize > 0 ||
	m_attributes[DD].m_no_of_varsize > 0;
    }
    
    bool need_shrink(bool disk) const {
      return 
	m_attributes[MM].m_no_of_varsize > 0 ||
	(disk && m_attributes[DD].m_no_of_varsize > 0);
    }

    /**
     * Descriptors for MM and DD part
     */
    struct Tuple_offsets {
      Uint8 m_null_words;
      Uint8 m_null_offset;
      Uint16 m_disk_ref_offset; // In words relative m_data
      union {
	Uint16 m_varpart_offset;  // In words relative m_data
	Uint16 m_fix_header_size; // For fix size tuples= total rec size(part)
      };
      Uint16 m_max_var_offset;  // In bytes relative m_var_data.m_data_ptr
    } m_offsets[2];
    

    Uint32 get_check_offset(Uint32 mm) const {
      Uint32 cnt= m_attributes[mm].m_no_of_varsize;
      Uint32 off= m_offsets[mm].m_varpart_offset;
      return off - (cnt ? 0 : Tuple_header::HeaderSize);
    }

    struct {
      Uint16 m_no_of_fixsize;
      Uint16 m_no_of_varsize;
    } m_attributes[2];
    
    // Lists of trigger data for active triggers
1043 1044 1045 1046 1047 1048 1049
    DLList<TupTriggerData> afterInsertTriggers;
    DLList<TupTriggerData> afterDeleteTriggers;
    DLList<TupTriggerData> afterUpdateTriggers;
    DLList<TupTriggerData> subscriptionInsertTriggers;
    DLList<TupTriggerData> subscriptionDeleteTriggers;
    DLList<TupTriggerData> subscriptionUpdateTriggers;
    DLList<TupTriggerData> constraintUpdateTriggers;
1050 1051
    
    // List of ordered indexes
1052
    DLList<TupTriggerData> tuxCustomTriggers;
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
    
    Uint32 fragid[MAX_FRAG_PER_NODE];
    Uint32 fragrec[MAX_FRAG_PER_NODE];

    struct {
      Uint32 tabUserPtr;
      Uint32 tabUserRef;
    } m_dropTable;
    State tableStatus;
  };  

  struct Disk_undo 
  {
    enum 
    {
      UNDO_ALLOC = File_formats::Undofile::UNDO_TUP_ALLOC
      ,UNDO_UPDATE = File_formats::Undofile::UNDO_TUP_UPDATE
      ,UNDO_FREE = File_formats::Undofile::UNDO_TUP_FREE
      ,UNDO_CREATE = File_formats::Undofile::UNDO_TUP_CREATE
1072 1073 1074
      ,UNDO_DROP = File_formats::Undofile::UNDO_TUP_DROP
      ,UNDO_ALLOC_EXTENT = File_formats::Undofile::UNDO_TUP_ALLOC_EXTENT
      ,UNDO_FREE_EXTENT = File_formats::Undofile::UNDO_TUP_FREE_EXTENT
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106
    };
    
    struct Alloc 
    {
      Uint32 m_file_no_page_idx; // 16 bit file_no, 16 bit page_idx
      Uint32 m_page_no;
      Uint32 m_type_length; // 16 bit type, 16 bit length
    };
    
    struct Update
    {
      Uint32 m_file_no_page_idx; // 16 bit file_no, 16 bit page_idx
      Uint32 m_page_no;
      Uint32 m_gci;
      Uint32 m_data[1];
      Uint32 m_type_length; // 16 bit type, 16 bit length
    };
    
    struct Free
    {
      Uint32 m_file_no_page_idx; // 16 bit file_no, 16 bit page_idx
      Uint32 m_page_no;
      Uint32 m_gci;
      Uint32 m_data[1];
      Uint32 m_type_length; // 16 bit type, 16 bit length
    };
    
    struct Create
    {
      Uint32 m_table;
      Uint32 m_type_length; // 16 bit type, 16 bit length
    };
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130

    struct Drop
    {
      Uint32 m_table;
      Uint32 m_type_length; // 16 bit type, 16 bit length
    };

    struct AllocExtent
    {
      Uint32 m_table;
      Uint32 m_fragment;
      Uint32 m_page_no;
      Uint32 m_file_no;
      Uint32 m_type_length;
    };

    struct FreeExtent
    {
      Uint32 m_table;
      Uint32 m_fragment;
      Uint32 m_page_no;
      Uint32 m_file_no;
      Uint32 m_type_length;
    };
1131 1132
  };
  
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
1133 1134
  Extent_info_pool c_extent_pool;
  Extent_info_hash c_extent_hash;
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
1135
  Page_request_pool c_page_request_pool;
1136

1137
  typedef Ptr<Tablerec> TablerecPtr;
1138

1139 1140 1141 1142 1143 1144 1145
  struct storedProc {
    Uint32 storedLinkFirst;
    Uint32 storedLinkLast;
    Uint32 storedCounter;
    Uint32 nextPool;
    Uint16 storedCode;
    Uint16 storedProcLength;
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
};

typedef Ptr<storedProc> StoredProcPtr;

ArrayPool<storedProc> c_storedProcPool;

/* **************************** TABLE_DESCRIPTOR RECORD ******************************** */
/* THIS VARIABLE IS USED TO STORE TABLE DESCRIPTIONS. A TABLE DESCRIPTION IS STORED AS A */
/* CONTIGUOS ARRAY IN THIS VARIABLE. WHEN A NEW TABLE IS ADDED A CHUNK IS ALLOCATED IN   */
/* THIS RECORD. WHEN ATTRIBUTES ARE ADDED TO THE TABLE, A NEW CHUNK OF PROPER SIZE IS    */
/* ALLOCATED AND ALL DATA IS COPIED TO THIS NEW CHUNK AND THEN THE OLD CHUNK IS PUT IN   */
/* THE FREE LIST. EACH TABLE IS DESCRIBED BY A NUMBER OF TABLE DESCRIPTIVE ATTRIBUTES    */
/* AND A NUMBER OF ATTRIBUTE DESCRIPTORS AS SHOWN IN FIGURE BELOW                        */
/*                                                                                       */
/* WHEN ALLOCATING A TABLE DESCRIPTOR THE SIZE IS ALWAYS A MULTIPLE OF 16 WORDS.         */
/*                                                                                       */
/*               ----------------------------------------------                          */
/*               |    TRAILER USED FOR ALLOC/DEALLOC          |                          */
/*               ----------------------------------------------                          */
/*               |    TABLE DESCRIPTIVE ATTRIBUTES            |                          */
/*               ----------------------------------------------                          */
/*               |    ATTRIBUTE DESCRIPTION 1                 |                          */
/*               ----------------------------------------------                          */
/*               |    ATTRIBUTE DESCRIPTION 2                 |                          */
/*               ----------------------------------------------                          */
/*               |                                            |                          */
/*               |                                            |                          */
/*               |                                            |                          */
/*               ----------------------------------------------                          */
/*               |    ATTRIBUTE DESCRIPTION N                 |                          */
/*               ----------------------------------------------                          */
/*                                                                                       */
/* THE TABLE DESCRIPTIVE ATTRIBUTES CONTAINS THE FOLLOWING ATTRIBUTES:                   */
/*                                                                                       */
/*               ----------------------------------------------                          */
/*               |    HEADER (TYPE OF INFO)                   |                          */
/*               ----------------------------------------------                          */
/*               |    SIZE OF WHOLE CHUNK (INCL. TRAILER)     |                          */
/*               ----------------------------------------------                          */
/*               |    TABLE IDENTITY                          |                          */
/*               ----------------------------------------------                          */
/*               |    FRAGMENT IDENTITY                       |                          */
/*               ----------------------------------------------                          */
/*               |    NUMBER OF ATTRIBUTES                    |                          */
/*               ----------------------------------------------                          */
/*               |    SIZE OF FIXED ATTRIBUTES                |                          */
/*               ----------------------------------------------                          */
/*               |    NUMBER OF NULL FIELDS                   |                          */
/*               ----------------------------------------------                          */
/*               |    NOT USED                                |                          */
/*               ----------------------------------------------                          */
/*                                                                                       */
/* THESE ATTRIBUTES ARE ALL ONE R-VARIABLE IN THE RECORD.                                */
/* NORMALLY ONLY ONE TABLE DESCRIPTOR IS USED. DURING SCHEMA CHANGES THERE COULD         */
/* HOWEVER EXIST MORE THAN ONE TABLE DESCRIPTION SINCE THE SCHEMA CHANGE OF VARIOUS      */
/* FRAGMENTS ARE NOT SYNCHRONISED. THIS MEANS THAT ALTHOUGH THE SCHEMA HAS CHANGED       */
/* IN ALL FRAGMENTS, BUT THE FRAGMENTS HAVE NOT REMOVED THE ATTRIBUTES IN THE SAME       */
/* TIME-FRAME. THEREBY SOME ATTRIBUTE INFORMATION MIGHT DIFFER BETWEEN FRAGMENTS.        */
/* EXAMPLES OF ATTRIBUTES THAT MIGHT DIFFER ARE SIZE OF FIXED ATTRIBUTES, NUMBER OF      */
/* ATTRIBUTES, FIELD START WORD, START BIT.                                              */
/*                                                                                       */
/* AN ATTRIBUTE DESCRIPTION CONTAINS THE FOLLOWING ATTRIBUTES:                           */
/*                                                                                       */
/*               ----------------------------------------------                          */
/*               |    Field Type, 4 bits (LSB Bits)           |                          */
/*               ----------------------------------------------                          */
/*               |    Attribute Size, 4 bits                  |                          */
/*               ----------------------------------------------                          */
/*               |    NULL indicator 1 bit                    |                          */
/*               ----------------------------------------------                          */
/*               |    Indicator if TUP stores attr. 1 bit     |                          */
/*               ----------------------------------------------                          */
/*               |    Not used 6 bits                         |                          */
/*               ----------------------------------------------                          */
/*               |    No. of elements in fixed array 16 bits  |                          */
/*               ----------------------------------------------                          */
/*               ----------------------------------------------                          */
/*               |    Field Start Word, 21 bits (LSB Bits)    |                          */
/*               ----------------------------------------------                          */
/*               |    NULL Bit, 11 bits                       |                          */
/*               ----------------------------------------------                          */
/*                                                                                       */
/* THE ATTRIBUTE SIZE CAN BE 1,2,4,8,16,32,64 AND 128 BITS.                              */
/*                                                                                       */
/* THE UNUSED PARTS OF THE RECORDS ARE PUT IN A LINKED LIST OF FREE PARTS. EACH OF       */
/* THOSE FREE PARTS HAVE THREE RECORDS ASSIGNED AS SHOWN IN THIS STRUCTURE               */
/* ALL FREE PARTS ARE SET INTO A CHUNK LIST WHERE EACH CHUNK IS AT LEAST 16 WORDS        */
/*                                                                                       */
/*               ----------------------------------------------                          */
/*               |    HEADER = RNIL                           |                          */
/*               ----------------------------------------------                          */
/*               |    SIZE OF FREE AREA                       |                          */
/*               ----------------------------------------------                          */
/*               |    POINTER TO PREVIOUS FREE AREA           |                          */
/*               ----------------------------------------------                          */
/*               |    POINTER TO NEXT FREE AREA               |                          */
/*               ----------------------------------------------                          */
/*                                                                                       */
/* IF THE POINTER TO THE NEXT AREA IS RNIL THEN THIS IS THE LAST FREE AREA.              */
/*                                                                                       */
/*****************************************************************************************/
struct TableDescriptor {
  Uint32 tabDescr;
};
typedef Ptr<TableDescriptor> TableDescriptorPtr;

struct HostBuffer {
  bool  inPackedList;
  Uint32 packetLenTA;
  Uint32 noOfPacketsTA;
  Uint32 packetBufferTA[30];
};
typedef Ptr<HostBuffer> HostBufferPtr;

  /*
   * Build index operation record.
   */
  struct BuildIndexRec {
    // request cannot use signal class due to extra members
    Uint32 m_request[BuildIndxReq::SignalLength];
1266 1267
    Uint8  m_build_vs;          // varsize pages
    Uint32 m_indexId;           // the index
1268 1269
    Uint32 m_fragNo;            // fragment number under Tablerec
    Uint32 m_pageId;            // logical fragment page id
1270 1271
    Uint32 m_tupleNo;           // tuple number on page
    Uint32 m_buildRef;          // Where to send tuples
1272 1273 1274 1275 1276 1277 1278 1279 1280
    BuildIndxRef::ErrorCode m_errorCode;
    union {
      Uint32 nextPool;
      Uint32 nextList;
    };
    Uint32 prevList;
  };
  typedef Ptr<BuildIndexRec> BuildIndexPtr;
  ArrayPool<BuildIndexRec> c_buildIndexPool;
1281
  DLList<BuildIndexRec> c_buildIndexList;
1282 1283
  Uint32 c_noOfBuildIndexRec;

1284 1285 1286 1287 1288
  /**
   * Reference to variable part when a tuple is chained
   */
  struct Var_part_ref 
  {
1289
#if NDB_SIZEOF_CHARP == 4
1290
    Uint32 m_ref;
1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
    STATIC_CONST( SZ32 = 1 );

    void copyout(Local_key* dst) const {
      dst->m_page_no = m_ref >> MAX_TUPLES_BITS;
      dst->m_page_idx = m_ref & MAX_TUPLES_PER_PAGE;
    }

    void assign(const Local_key* src) {
      m_ref = (src->m_page_no << MAX_TUPLES_BITS) | src->m_page_idx;
    }
#else
    Uint32 m_page_no;
    Uint32 m_page_idx;
    STATIC_CONST( SZ32 = 2 );
1305

1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
    void copyout(Local_key* dst) const {
      dst->m_page_no = m_page_no;
      dst->m_page_idx = m_page_idx;
    }

    void assign(const Local_key* src) {
      m_page_no = src->m_page_no;
      m_page_idx = src->m_page_idx;
    }
#endif    
  };
  
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
  struct Tuple_header
  {
    union {
      Uint32 m_operation_ptr_i;  // OperationPtrI
      Uint32 m_base_record_ref;  // For disk tuple, ref to MM tuple
    };
    Uint32 m_header_bits;      // Header word
    union {
      Uint32 m_checksum;
      Uint32 m_data[1];
      Uint32 m_null_bits[1];
    };

    STATIC_CONST( HeaderSize = 2 );
    
    /**
     * header bits
     */
    STATIC_CONST( TUP_VERSION_MASK = 0xFFFF );
    STATIC_CONST( CHAINED_ROW = 0x00010000 ); // Is var part on different page
    STATIC_CONST( DISK_PART   = 0x00020000 ); // Is there a disk part
    STATIC_CONST( DISK_ALLOC  = 0x00040000 ); // Is disk part allocated
    STATIC_CONST( DISK_INLINE = 0x00080000 ); // Is disk inline
    STATIC_CONST( ALLOC       = 0x00100000 ); // Is record allocated now
    STATIC_CONST( MM_SHRINK   = 0x00200000 ); // Has MM part shrunk
    STATIC_CONST( MM_GROWN    = 0x00400000 ); // Has MM part grown
1344
    STATIC_CONST( FREED       = 0x00800000 ); // Is freed
1345
    STATIC_CONST( LCP_SKIP    = 0x01000000 ); // Should not be returned in LCP
1346 1347
    STATIC_CONST( LCP_KEEP    = 0x02000000 ); // Should be returned in LCP
    STATIC_CONST( FREE        = 0x02800000 ); // Is free
1348
    
1349
    Tuple_header() {}
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
    Uint32 get_tuple_version() const { 
      return m_header_bits & TUP_VERSION_MASK;
    }
    void set_tuple_version(Uint32 version) { 
      m_header_bits= 
	(m_header_bits & ~(Uint32)TUP_VERSION_MASK) | 
	(version & TUP_VERSION_MASK);
    }

    Uint32* get_null_bits(const Tablerec* tabPtrP) {
      return m_null_bits+tabPtrP->m_offsets[MM].m_null_offset;
    }

    Uint32* get_null_bits(const Tablerec* tabPtrP, Uint32 mm) {
      return m_null_bits+tabPtrP->m_offsets[mm].m_null_offset;
    }
    
    Uint32* get_var_part_ptr(const Tablerec* tabPtrP) {
      return m_data + tabPtrP->m_offsets[MM].m_varpart_offset;      
    }

    const Uint32* get_var_part_ptr(const Tablerec* tabPtrP) const {
      return m_data + tabPtrP->m_offsets[MM].m_varpart_offset;      
    }

    Uint32* get_disk_ref_ptr(const Tablerec* tabPtrP) {
      return m_data + tabPtrP->m_offsets[MM].m_disk_ref_offset;
    }

    const Uint32* get_disk_ref_ptr(const Tablerec* tabPtrP) const {
      return m_data + tabPtrP->m_offsets[MM].m_disk_ref_offset;
    }
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391

    Uint32 *get_mm_gci(const Tablerec* tabPtrP){
      assert(tabPtrP->m_bits & Tablerec::TR_RowGCI);
      return m_data + (tabPtrP->m_bits & Tablerec::TR_Checksum);
    }

    Uint32 *get_dd_gci(const Tablerec* tabPtrP, Uint32 mm){
      assert(tabPtrP->m_bits & Tablerec::TR_RowGCI);
      return m_data;
    }
1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432
  };
  
struct KeyReqStruct {
/**
 * These variables are used as temporary storage during execution of the
 * TUPKEYREQ signal.
 * The first set of variables defines a number of variables needed for
 * the fix part of the tuple.
 *
 * The second part defines a number of commonly used meta data variables.
 *
 * The third set of variables defines a set of variables needed for the
 * variable part.
 *
 * The fourth part is variables needed only for updates and inserts.
 *
 * The fifth part is a long array of real lengths which is is put last
 * for cache memory reasons. This is part of the variable part and
 * contains the real allocated lengths whereas the tuple contains
 * the length of attribute stored.
 */
  Tuple_header *m_tuple_ptr;

  Uint32 check_offset[2];

  TableDescriptor *attr_descr;
  Uint32          max_read;
  Uint32          out_buf_index;
  Uint32          in_buf_index;
  Uint32          in_buf_len;
  Uint32          attr_descriptor;
  bool            xfrm_flag;

  struct Var_data {
    char *m_data_ptr;
    Uint16 *m_offset_array_ptr;
    Uint16 m_var_len_offset;
    Uint16 m_max_var_offset;
  } m_var_data[2];

  Tuple_header *m_disk_ptr;
1433 1434
  PagePtr m_page_ptr;
  PagePtr m_varpart_page_ptr;    // could be same as m_page_ptr_p
1435
  PagePtr m_disk_page_ptr;       //
1436 1437
  Local_key m_row_id;
  
1438 1439 1440
  bool            dirty_op;
  bool            interpreted_exec;
  bool            last_row;
1441
  bool            m_use_rowid;
1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454

  Signal*         signal;
  Uint32 no_fired_triggers;
  Uint32 frag_page_id;
  Uint32 hash_value;
  Uint32 gci;
  Uint32 log_size;
  Uint32 read_length;
  Uint32 attrinfo_len;
  Uint32 tc_operation_ptr;
  Uint32 trans_id1;
  Uint32 trans_id2;
  Uint32 TC_index;
1455
  // next 2 apply only to attrids >= 64 (zero otherwise)
1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
  Uint32 max_attr_id_updated;
  Uint32 no_changed_attrs;
  BlockReference TC_ref;
  BlockReference rec_blockref;
  bool change_mask_calculated;
  /*
   * A bit mask where a bit set means that the update or insert
   * was updating this record.
   */
  Bitmask<MAXNROFATTRIBUTESINWORDS> changeMask;
  Uint16 var_pos_array[2*MAX_ATTRIBUTES_IN_TABLE + 1];
  OperationrecPtr prevOpPtr;
};

  friend class Undo_buffer;
  Undo_buffer c_undo_buffer;
  
/*
 No longer used:
 Implemented by shift instructions in subroutines instead
 
struct TupHeadInfo {
  struct BitPart {
    unsigned int disk_indicator : 1;
    unsigned int var_part_loc_ind : 1;
    unsigned int initialised : 1;
    unsigned int not_used_yet : 5;
    unsigned int no_var_sized : 8;
    unsigned int tuple_version : 16;
  };
  union {
    Uint32 all;
    BitPart bit_part;
  };
};
*/

// updateAttributes module
  Uint32          terrorCode;

1496
public:
1497
  Dbtup(Block_context&, Pgman*);
1498 1499
  virtual ~Dbtup();

1500 1501 1502 1503 1504
  /*
   * TUX uses logical tuple address when talking to ACC and LQH.
   */
  void tuxGetTupAddr(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32& tupAddr);

1505 1506
  /*
   * TUX index in TUP has single Uint32 array attribute which stores an
1507
   * index node.  TUX reads and writes the node directly via pointer.
1508 1509 1510 1511 1512
   */
  int tuxAllocNode(Signal* signal, Uint32 fragPtrI, Uint32& pageId, Uint32& pageOffset, Uint32*& node);
  void tuxFreeNode(Signal* signal, Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* node);
  void tuxGetNode(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32*& node);

1513
  /*
1514 1515 1516 1517 1518
   * TUX reads primary table attributes for index keys.  Tuple is
   * specified by location of original tuple and version number.  Input
   * is attribute ids in AttributeHeader format.  Output is attribute
   * data with headers.  Uses readAttributes with xfrm option set.
   * Returns number of words or negative (-terrorCode) on error.
1519
   */
1520
  int tuxReadAttrs(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32 tupVersion, const Uint32* attrIds, Uint32 numAttrs, Uint32* dataOut);
1521 1522

  /*
1523
   * TUX reads primary key without headers into an array of words.  Used
1524 1525
   * for md5 summing and when returning keyinfo.  Returns number of
   * words or negative (-terrorCode) on error.
1526
   */
1527
  int tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut, bool xfrmFlag);
1528

1529 1530 1531 1532 1533
  /*
   * ACC reads primary key without headers into an array of words.  At
   * this point in ACC deconstruction, ACC still uses logical references
   * to fragment and tuple.
   */
1534
  int accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut, bool xfrmFlag);
1535

1536 1537 1538 1539
  /*
   * TUX checks if tuple is visible to scan.
   */
  bool tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId);
1540

1541 1542 1543 1544 1545 1546
  int load_diskpage(Signal*, Uint32 opRec, Uint32 fragPtrI, 
		    Uint32 local_key, Uint32 flags);

  int load_diskpage_scan(Signal*, Uint32 opRec, Uint32 fragPtrI, 
			 Uint32 local_key, Uint32 flags);

1547 1548
  int alloc_page(Tablerec*, Fragrecord*, PagePtr*,Uint32 page_no);
  
1549 1550
  void start_restore_lcp(Uint32 tableId, Uint32 fragmentId);
  void complete_restore_lcp(Uint32 tableId, Uint32 fragmentId);
1551 1552 1553 1554 1555 1556

  int nr_read_pk(Uint32 fragPtr, const Local_key*, Uint32* dataOut, bool&copy);
  int nr_update_gci(Uint32 fragPtr, const Local_key*, Uint32 gci);
  int nr_delete(Signal*, Uint32, Uint32 fragPtr, const Local_key*, Uint32 gci);

  void nr_delete_page_callback(Signal*, Uint32 op, Uint32 page);
1557
  void nr_delete_log_buffer_callback(Signal*, Uint32 op, Uint32 page);
1558 1559 1560 1561 1562 1563 1564 1565
private:
  BLOCK_DEFINES(Dbtup);

  // Transit signals
  void execDEBUG_SIG(Signal* signal);
  void execCONTINUEB(Signal* signal);

  // Received signals
1566
  void execLCP_FRAG_ORD(Signal*signal);
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581
  void execDUMP_STATE_ORD(Signal* signal);
  void execSEND_PACKED(Signal* signal);
  void execSTTOR(Signal* signal);
  void execTUP_LCPREQ(Signal* signal);
  void execEND_LCPREQ(Signal* signal);
  void execSTART_RECREQ(Signal* signal);
  void execMEMCHECKREQ(Signal* signal);
  void execTUPSEIZEREQ(Signal* signal);
  void execTUPRELEASEREQ(Signal* signal);
  void execSTORED_PROCREQ(Signal* signal);
  void execTUPFRAGREQ(Signal* signal);
  void execTUP_ADD_ATTRREQ(Signal* signal);
  void execTUP_COMMITREQ(Signal* signal);
  void execTUP_ABORTREQ(Signal* signal);
  void execNDB_STTOR(Signal* signal);
1582
  void execREAD_CONFIG_REQ(Signal* signal);
1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
  void execDROP_TAB_REQ(Signal* signal);
  void execALTER_TAB_REQ(Signal* signal);
  void execTUP_DEALLOCREQ(Signal* signal);
  void execTUP_WRITELOG_REQ(Signal* signal);

  // Ordered index related
  void execBUILDINDXREQ(Signal* signal);
  void buildIndex(Signal* signal, Uint32 buildPtrI);
  void buildIndexReply(Signal* signal, const BuildIndexRec* buildRec);

1593 1594 1595 1596
  // Tup scan
  void execACC_SCANREQ(Signal* signal);
  void execNEXT_SCANREQ(Signal* signal);
  void execACC_CHECK_SCAN(Signal* signal);
1597 1598 1599
  void execACCKEYCONF(Signal* signal);
  void execACCKEYREF(Signal* signal);
  void execACC_ABORTCONF(Signal* signal);
1600

1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781
//------------------------------------------------------------------
//------------------------------------------------------------------
// Methods to handle execution of TUPKEYREQ + ATTRINFO.
//
// Module Execution Manager
//
// The TUPKEYREQ signal is central to this block. This signal is used
// by everybody that needs to read data residing in DBTUP. The data is
// read using an interpreter approach.
//
// Operations only needing to read execute a simplified version of the
// interpreter where the only instruction is read Attribute to send.
// Operations only needing to update the record (insert or update)
// execute a simplified version of the interpreter where the only
// instruction is write Attribute.
//
// Currently TUPKEYREQ is used in the following situations.
// 1) Normal transaction execution. Can be any of the types described
//    below.
// 2) Execution of fragment redo log during system restart.
//    In this situation there will only be normal updates, inserts
//    and deletes performed.
// 3) A special type of normal transaction execution is to write the
//    records arriving from the primary replica in the node restart
//    processing. This will always be normal write operations which
//    are translated to inserts or updates before arriving to TUP.
// 4) Scan processing. The scan processing will use normal reads or
//    interpreted reads in their execution. There will be one TUPKEYREQ
//    signal for each record processed.
// 5) Copy fragment processing. This is a special type of scan used in the
//    primary replica at system restart. It reads the entire reads and
//    converts those to writes to the starting node. In this special case
//    LQH acts as an API node and receives also the ATTRINFO sent in the
//    TRANSID_AI signals.
//
// Signal Diagram:
//
// In Signals:
// -----------
//
// Logically there is one request TUPKEYREQ which requests to read/write data
// of one tuple in the database. Since the definition of what to read and write
// can be bigger than the maximum signal size we segment the signal. The definition
// of what to read/write/interpreted program is sent before the TUPKEYREQ signal.
//
// ---> ATTRINFO
// ...
// ---> ATTRINFO
// ---> TUPKEYREQ
// The number of ATTRINFO signals can be anything between 0 and upwards.
// The total size of the ATTRINFO is not allowed to be more than 16384 words.
// There is always one and only one TUPKEYREQ.
//
// Response Signals (successful case):
//
// Simple/Dirty Read Operation
// ---------------------------
//
// <---- TRANSID_AI (to API)
// ...
// <---- TRANSID_AI (to API)
// <---- READCONF   (to API)
// <---- TUPKEYCONF (to LQH)
// There is always exactly one READCONF25 sent last. The number of
// TRANSID_AI is dependent on how much that was read. The maximum size
// of the ATTRINFO sent back is 16384 words. The signals are sent
// directly to the application with an address provided by the
// TUPKEYREQ signal.
// A positive response signal is also sent to LQH.
//
// Normal Read Operation
// ---------------------
//
// <---- TRANSID_AI (to API)
// ...
// <---- TRANSID_AI (to API)
// <---- TUPKEYCONF (to LQH)
// The number of TRANSID_AI is dependent on how much that was read.
// The maximum size of the ATTRINFO sent back is 16384 words. The
// signals are sent directly to the application with an address
// provided by the TUPKEYREQ signal.
// A positive response signal is also sent to LQH.
//
// Normal update/insert/delete operation
// -------------------------------------
//
// <---- TUPKEYCONF
// After successful updating of the tuple LQH is informed of this.
//
// Delete with read
// ----------------
//
// Will behave as a normal read although it also prepares the
// deletion of the tuple.
//
// Interpreted Update
// ------------------
//
// <---- TRANSID_AI (to API)
// ...
// <---- TRANSID_AI (to API)
// <---- TUP_ATTRINFO (to LQH)
// ...
// <---- TUP_ATTRINFO (to LQH)
// <---- TUPKEYCONF (to LQH)
//
// The interpreted Update contains five sections:
// The first section performs read Attribute operations
// that send results back to the API.
//
// The second section executes the interpreted program
// where data from attributes can be updated and it
// can also read attribute values into the registers.
//
// The third section performs unconditional updates of
// attributes.
//
// The fourth section can read the attributes to be sent to the
// API after updating the record.
//
// The fifth section contains subroutines used by the interpreter
// in the second section.
//
// All types of interpreted programs contains the same five sections.
// The only difference is that only interpreted updates can update
// attributes. Interpreted inserts are not allowed.
//
// Interpreted Updates have to send back the information about the
// attributes they have updated. This information will be shipped to
// the log and also to any other replicas. Thus interpreted updates
// are only performed in the primary replica. The fragment redo log
// in LQH will contain information so that normal update/inserts/deletes
// can be performed using TUPKEYREQ.
//
// Interpreted Read
// ----------------
//
// From a signalling point of view the Interpreted Read behaves as
// as a Normal Read. The interpreted Read is often used by Scan's.
//
// Interpreted Delete
// ------------------
//
// <---- TUPKEYCONF
// After successful prepartion to delete the tuple LQH is informed
// of this.
//
// Interpreted Delete with Read
// ----------------------------
//
// From a signalling point of view an interpreted delete with read
// behaves as a normal read.
//
// Continuation after successful case:
//
// After a read of any kind the operation record is ready to be used
// again by a new operation.
//
// Any updates, inserts or deletes waits for either of two messages.
// A commit specifying that the operation is to be performed for real
// or an abort specifying that the operation is to be rolled back and
// the record to be restored in its original format.
// 
// This is handled by the module Transaction Manager.
//
// Response Signals (unsuccessful case):
//
// <---- TUPKEYREF (to LQH)
// A signal is sent back to LQH informing about the unsuccessful
// operation. In this case TUP waits for an abort signal to arrive
// before the operation record is ready for the next operation.
// This is handled by the Transaction Manager.
//------------------------------------------------------------------
//------------------------------------------------------------------

// *****************************************************************
// Signal Reception methods.
// *****************************************************************
//------------------------------------------------------------------
//------------------------------------------------------------------
  void execTUPKEYREQ(Signal* signal);
1782 1783
  void disk_page_load_callback(Signal*, Uint32 op, Uint32 page);
  void disk_page_load_scan_callback(Signal*, Uint32 op, Uint32 page);
1784 1785 1786 1787

//------------------------------------------------------------------
//------------------------------------------------------------------
  void execATTRINFO(Signal* signal);
1788 1789 1790
public:
  void receive_attrinfo(Signal*, Uint32 op, const Uint32* data, Uint32 len);
private:
1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806

// Trigger signals
//------------------------------------------------------------------
//------------------------------------------------------------------
  void execCREATE_TRIG_REQ(Signal* signal);

//------------------------------------------------------------------
//------------------------------------------------------------------
  void execDROP_TRIG_REQ(Signal* signal);

// *****************************************************************
// Support methods for ATTRINFO.
// *****************************************************************
//------------------------------------------------------------------
//------------------------------------------------------------------
  void handleATTRINFOforTUPKEYREQ(Signal* signal,
1807
				  const Uint32* data,
1808
                                  Uint32 length,
1809
                                  Operationrec * regOperPtr);
1810 1811 1812 1813 1814 1815 1816

// *****************************************************************
// Setting up the environment for reads, inserts, updates and deletes.
// *****************************************************************
//------------------------------------------------------------------
//------------------------------------------------------------------
  int handleReadReq(Signal* signal,
1817 1818
                    Operationrec* regOperPtr,
                    Tablerec* regTabPtr,
1819
                    KeyReqStruct* req_struct);
1820 1821 1822 1823

//------------------------------------------------------------------
//------------------------------------------------------------------
  int handleUpdateReq(Signal* signal,
1824 1825 1826
                      Operationrec* regOperPtr,
                      Fragrecord* regFragPtr,
                      Tablerec* regTabPtr,
1827 1828
                      KeyReqStruct* req_struct,
		      bool disk);
1829 1830 1831 1832

//------------------------------------------------------------------
//------------------------------------------------------------------
  int handleInsertReq(Signal* signal,
1833 1834
                      Ptr<Operationrec> regOperPtr,
                      Ptr<Fragrecord>,
1835
                      Tablerec* regTabPtr,
1836
                      KeyReqStruct* req_struct);
1837 1838 1839 1840

//------------------------------------------------------------------
//------------------------------------------------------------------
  int handleDeleteReq(Signal* signal,
1841 1842 1843
                      Operationrec* regOperPtr,
                      Fragrecord* regFragPtr,
                      Tablerec* regTabPtr,
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
1844 1845
                      KeyReqStruct* req_struct,
		      bool disk);
1846 1847 1848 1849

//------------------------------------------------------------------
//------------------------------------------------------------------
  int  updateStartLab(Signal* signal,
1850 1851 1852
                      Operationrec* regOperPtr,
                      Fragrecord* regFragPtr,
                      Tablerec* regTabPtr,
1853
                      KeyReqStruct* req_struct);
1854 1855 1856 1857 1858 1859 1860 1861

// *****************************************************************
// Interpreter Handling methods.
// *****************************************************************

//------------------------------------------------------------------
//------------------------------------------------------------------
  int interpreterStartLab(Signal* signal,
1862
                          KeyReqStruct *req_struct);
1863 1864 1865 1866

//------------------------------------------------------------------
//------------------------------------------------------------------
  int interpreterNextLab(Signal* signal,
1867
                         KeyReqStruct *req_struct,
1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881
                         Uint32* logMemory,
                         Uint32* mainProgram,
                         Uint32 TmainProgLen,
                         Uint32* subroutineProg,
                         Uint32 TsubroutineLen,
			 Uint32 * tmpArea,
			 Uint32 tmpAreaSz);

// *****************************************************************
// Signal Sending methods.
// *****************************************************************
//------------------------------------------------------------------
//------------------------------------------------------------------
  void sendReadAttrinfo(Signal* signal,
1882
                        KeyReqStruct *req_struct,
1883
                        Uint32 TnoOfData,
1884
                        const Operationrec * regOperPtr);
1885 1886 1887 1888 1889

//------------------------------------------------------------------
//------------------------------------------------------------------
  void sendLogAttrinfo(Signal* signal,
                       Uint32 TlogSize,
1890
                       Operationrec * regOperPtr);
1891 1892 1893

//------------------------------------------------------------------
//------------------------------------------------------------------
1894 1895
  void sendTUPKEYCONF(Signal* signal,
                      KeyReqStruct *req_struct,
1896
                      Operationrec * regOperPtr); 
1897 1898 1899 1900 1901 1902 1903 1904 1905

//------------------------------------------------------------------
//------------------------------------------------------------------
// *****************************************************************
// The methods that perform the actual read and update of attributes
// in the tuple.
// *****************************************************************
//------------------------------------------------------------------
//------------------------------------------------------------------
1906
  int readAttributes(KeyReqStruct* req_struct,
1907
                     const Uint32*  inBuffer,
1908 1909
                     Uint32   inBufLen,
                     Uint32*  outBuffer,
1910 1911
                     Uint32   TmaxRead,
                     bool     xfrmFlag);
1912 1913 1914

//------------------------------------------------------------------
//------------------------------------------------------------------
1915
  int updateAttributes(KeyReqStruct *req_struct,
1916 1917 1918 1919 1920 1921
                       Uint32*     inBuffer,
                       Uint32      inBufLen);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool readFixedSizeTHOneWordNotNULL(Uint32* outBuffer,
1922
                                     KeyReqStruct *req_struct,
1923 1924 1925 1926 1927 1928
                                     AttributeHeader* ahOut,
                                     Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool updateFixedSizeTHOneWordNotNULL(Uint32* inBuffer,
1929
                                       KeyReqStruct *req_struct,
1930 1931 1932 1933 1934
                                       Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool readFixedSizeTHTwoWordNotNULL(Uint32* outBuffer,
1935
                                     KeyReqStruct *req_struct,
1936 1937 1938 1939 1940 1941
                                     AttributeHeader* ahOut,
                                     Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool updateFixedSizeTHTwoWordNotNULL(Uint32* inBuffer,
1942
                                       KeyReqStruct *req_struct,
1943 1944 1945 1946 1947
                                       Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool readFixedSizeTHManyWordNotNULL(Uint32* outBuffer,
1948
                                      KeyReqStruct *req_struct,
1949 1950 1951 1952 1953 1954
                                      AttributeHeader* ahOut,
                                      Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool updateFixedSizeTHManyWordNotNULL(Uint32* inBuffer,
1955
                                        KeyReqStruct *req_struct,
1956 1957 1958 1959 1960
                                        Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool readFixedSizeTHOneWordNULLable(Uint32* outBuffer,
1961
                                      KeyReqStruct *req_struct,
1962 1963 1964 1965 1966 1967
                                      AttributeHeader* ahOut,
                                      Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool updateFixedSizeTHOneWordNULLable(Uint32* inBuffer,
1968
                                        KeyReqStruct *req_struct,
1969 1970 1971 1972 1973
                                        Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool readFixedSizeTHTwoWordNULLable(Uint32* outBuffer,
1974
                                      KeyReqStruct *req_struct,
1975 1976 1977 1978 1979 1980
                                      AttributeHeader* ahOut,
                                      Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool updateFixedSizeTHTwoWordNULLable(Uint32* inBuffer,
1981
                                        KeyReqStruct *req_struct,
1982 1983 1984 1985 1986
                                        Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool readFixedSizeTHManyWordNULLable(Uint32* outBuffer,
1987
                                       KeyReqStruct *req_struct,
1988 1989 1990 1991 1992 1993
                                       AttributeHeader* ahOut,
                                       Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool readFixedSizeTHZeroWordNULLable(Uint32* outBuffer,
1994
                                       KeyReqStruct *req_struct,
1995 1996 1997 1998 1999
                                       AttributeHeader* ahOut,
                                       Uint32  attrDes2);
//------------------------------------------------------------------
//------------------------------------------------------------------
  bool updateFixedSizeTHManyWordNULLable(Uint32* inBuffer,
2000
                                         KeyReqStruct *req_struct,
2001 2002 2003 2004
                                         Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
2005 2006 2007 2008
  bool readVarSizeNotNULL(Uint32* outBuffer,
                          KeyReqStruct *req_struct,
                          AttributeHeader* ahOut,
                          Uint32  attrDes2);
2009 2010 2011

//------------------------------------------------------------------
//------------------------------------------------------------------
2012 2013 2014
  bool updateVarSizeNotNULL(Uint32* inBuffer,
                            KeyReqStruct *req_struct,
                            Uint32  attrDes2);
2015 2016 2017

//------------------------------------------------------------------
//------------------------------------------------------------------
2018 2019 2020 2021
  bool readVarSizeNULLable(Uint32* outBuffer,
                           KeyReqStruct *req_struct,
                           AttributeHeader* ahOut,
                           Uint32  attrDes2);
2022 2023 2024

//------------------------------------------------------------------
//------------------------------------------------------------------
2025 2026
  bool updateVarSizeNULLable(Uint32* inBuffer,
                             KeyReqStruct *req_struct,
2027 2028 2029 2030 2031
                             Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool readDynFixedSize(Uint32* outBuffer,
2032
                        KeyReqStruct *req_struct,
2033 2034 2035 2036 2037 2038
                        AttributeHeader* ahOut,
                        Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
  bool updateDynFixedSize(Uint32* inBuffer,
2039
                          KeyReqStruct *req_struct,
2040 2041 2042 2043
                          Uint32  attrDes2);

//------------------------------------------------------------------
//------------------------------------------------------------------
2044 2045 2046 2047
  bool readDynVarSize(Uint32* outBuffer,
                      KeyReqStruct *req_struct,
                      AttributeHeader* ahOut,
                      Uint32  attrDes2);
2048 2049 2050

//------------------------------------------------------------------
//------------------------------------------------------------------
2051 2052 2053
  bool updateDynVarSize(Uint32* inBuffer,
                        KeyReqStruct *req_struct,
                        Uint32  attrDes2);
2054

2055 2056 2057 2058
  bool readCharNotNULL(Uint32* outBuffer,
                       KeyReqStruct *req_struct,
                       AttributeHeader* ahOut,
                       Uint32  attrDes2);
2059

2060 2061 2062 2063
  bool readCharNULLable(Uint32* outBuffer,
                        KeyReqStruct *req_struct,
                        AttributeHeader* ahOut,
                        Uint32  attrDes2);
2064

2065 2066 2067 2068
  bool readBitsNULLable(Uint32* outBuffer, KeyReqStruct *req_struct, AttributeHeader*, Uint32);
  bool updateBitsNULLable(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
  bool readBitsNotNULL(Uint32* outBuffer, KeyReqStruct *req_struct, AttributeHeader*, Uint32);
  bool updateBitsNotNULL(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
2069

2070 2071
  bool updateFixedNULLable(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
  bool updateFixedNotNull(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
2072

2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098
  bool updateVarNULLable(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);
  bool updateVarNotNull(Uint32* inBuffer, KeyReqStruct *req_struct, Uint32);


  bool readDiskFixedSizeNotNULL(Uint32* outBuffer,
				KeyReqStruct *req_struct,
				AttributeHeader* ahOut,
				Uint32  attrDes2);
  
  bool readDiskFixedSizeNULLable(Uint32* outBuffer,
				 KeyReqStruct *req_struct,
				 AttributeHeader* ahOut,
				 Uint32  attrDes2);
  bool readDiskVarSizeNULLable(Uint32* outBuffer, KeyReqStruct *req_struct, AttributeHeader*, Uint32);
  bool readDiskVarSizeNotNULL(Uint32* outBuffer, KeyReqStruct *req_struct, AttributeHeader*, Uint32);

  bool updateDiskFixedSizeNULLable(Uint32*, KeyReqStruct*, Uint32);
  bool updateDiskFixedSizeNotNULL(Uint32*, KeyReqStruct*, Uint32);

  bool updateDiskVarSizeNULLable(Uint32*, KeyReqStruct *, Uint32);
  bool updateDiskVarSizeNotNULL(Uint32*, KeyReqStruct *, Uint32);
  
  bool readDiskBitsNULLable(Uint32*, KeyReqStruct*, AttributeHeader*, Uint32);
  bool readDiskBitsNotNULL(Uint32*, KeyReqStruct*, AttributeHeader*, Uint32);
  bool updateDiskBitsNULLable(Uint32*, KeyReqStruct*, Uint32);
  bool updateDiskBitsNotNULL(Uint32*, KeyReqStruct*, Uint32);
2099 2100


2101 2102
//------------------------------------------------------------------
//------------------------------------------------------------------
2103 2104 2105 2106 2107
  bool nullFlagCheck(KeyReqStruct *req_struct, Uint32  attrDes2);
  bool disk_nullFlagCheck(KeyReqStruct *req_struct, Uint32  attrDes2);
  Uint32 read_pseudo(Uint32 attrId,
                     KeyReqStruct *req_struct,
                     Uint32* outBuffer);
2108 2109 2110

//------------------------------------------------------------------
//------------------------------------------------------------------
2111
  void setUpQueryRoutines(Tablerec* regTabPtr);
2112 2113 2114 2115

// *****************************************************************
// Service methods.
// *****************************************************************
2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128
  TransState get_trans_state(Operationrec * const);
  void set_trans_state(Operationrec * const, TransState);
  TupleState get_tuple_state(Operationrec * const);
  void set_tuple_state(Operationrec * const, TupleState);
  Uint32 get_frag_page_id(Uint32 real_page_id);
  Uint32 get_fix_page_offset(Uint32 page_index, Uint32 tuple_size);

  Uint32 decr_tup_version(Uint32 tuple_version);
  void set_change_mask_state(Operationrec * const, ChangeMaskState);
  ChangeMaskState get_change_mask_state(Operationrec * const);
  void update_change_mask_info(KeyReqStruct * const, Operationrec * const);
  void set_change_mask_info(KeyReqStruct * const, Operationrec * const);

2129 2130
//------------------------------------------------------------------
//------------------------------------------------------------------
2131
  void copyAttrinfo(Operationrec * regOperPtr, Uint32*  inBuffer);
2132 2133 2134

//------------------------------------------------------------------
//------------------------------------------------------------------
2135
  void initOpConnection(Operationrec* regOperPtr);
2136 2137 2138 2139 2140 2141 2142

//------------------------------------------------------------------
//------------------------------------------------------------------
  void initOperationrec(Signal* signal);

//------------------------------------------------------------------
//------------------------------------------------------------------
2143
  int initStoredOperationrec(Operationrec* regOperPtr,
2144
                             KeyReqStruct* req_struct,
2145 2146 2147 2148
                             Uint32 storedId);

//------------------------------------------------------------------
//------------------------------------------------------------------
2149
  bool insertActiveOpList(OperationrecPtr, KeyReqStruct* req_struct);
2150 2151 2152 2153 2154 2155

//------------------------------------------------------------------
//------------------------------------------------------------------

//------------------------------------------------------------------
//------------------------------------------------------------------
joreland@mysql.com's avatar
joreland@mysql.com committed
2156
  void bufferTRANSID_AI(Signal* signal, BlockReference aRef, Uint32 Tlen);
2157 2158 2159 2160

//------------------------------------------------------------------
// Trigger handling routines
//------------------------------------------------------------------
2161
  DLList<TupTriggerData>*
2162 2163 2164 2165
  findTriggerList(Tablerec* table,
                  TriggerType::Value ttype,
                  TriggerActionTime::Value ttime,
                  TriggerEvent::Value tevent);
2166 2167 2168

  bool createTrigger(Tablerec* table, const CreateTrigReq* req);

2169 2170 2171
  Uint32 dropTrigger(Tablerec* table,
		     const DropTrigReq* req,
		     BlockNumber sender);
2172

2173 2174
  void
  checkImmediateTriggersAfterInsert(KeyReqStruct *req_struct,
2175 2176
                                    Operationrec* regOperPtr, 
                                    Tablerec* tablePtr);
2177

2178 2179
  void
  checkImmediateTriggersAfterUpdate(KeyReqStruct *req_struct,
2180 2181
                                    Operationrec* regOperPtr, 
                                    Tablerec* tablePtr);
2182

2183 2184
  void
  checkImmediateTriggersAfterDelete(KeyReqStruct *req_struct,
2185 2186
                                    Operationrec* regOperPtr, 
                                    Tablerec* tablePtr);
2187 2188 2189

#if 0
  void checkDeferredTriggers(Signal* signal, 
2190 2191
                             Operationrec* regOperPtr,
                             Tablerec* regTablePtr);
2192
#endif
2193
  void checkDetachedTriggers(KeyReqStruct *req_struct,
2194 2195
                             Operationrec* regOperPtr,
                             Tablerec* regTablePtr);
2196

2197
  void fireImmediateTriggers(KeyReqStruct *req_struct,
2198
                             DLList<TupTriggerData>& triggerList, 
2199
                             Operationrec* regOperPtr);
2200

2201
  void fireDeferredTriggers(KeyReqStruct *req_struct,
2202
                            DLList<TupTriggerData>& triggerList,
2203
                            Operationrec* regOperPtr);
2204

2205
  void fireDetachedTriggers(KeyReqStruct *req_struct,
2206
                            DLList<TupTriggerData>& triggerList,
2207
                            Operationrec* regOperPtr);
2208

2209
  void executeTriggers(KeyReqStruct *req_struct,
2210
                       DLList<TupTriggerData>& triggerList,
2211
                       Operationrec* regOperPtr);
2212

2213
  void executeTrigger(KeyReqStruct *req_struct,
2214 2215 2216 2217 2218 2219 2220 2221
                      TupTriggerData* trigPtr, 
                      Operationrec* regOperPtr);

  bool readTriggerInfo(TupTriggerData* trigPtr,
                       Operationrec* regOperPtr,
                       KeyReqStruct * req_struct,
                       Fragrecord* regFragPtr,
                       Uint32* keyBuffer,
2222
                       Uint32& noPrimKey,
2223
                       Uint32* afterBuffer,
2224
                       Uint32& noAfterWords,
2225
                       Uint32* beforeBuffer,
2226
                       Uint32& noBeforeWords);
2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238

  void sendTrigAttrInfo(Signal*        signal, 
                        Uint32*        data, 
                        Uint32         dataLen,
                        bool           executeDirect,
                        BlockReference receiverReference);

  Uint32 setAttrIds(Bitmask<MAXNROFATTRIBUTESINWORDS>& attributeMask, 
                    Uint32 noOfAttributes, 
                    Uint32* inBuffer);

  void sendFireTrigOrd(Signal* signal, 
2239
                       KeyReqStruct *req_struct,
2240 2241
                       Operationrec * regOperPtr,
                       TupTriggerData* trigPtr,
2242
		       Uint32 fragmentId,
2243 2244 2245 2246 2247 2248 2249 2250 2251
                       Uint32 noPrimKeySignals, 
                       Uint32 noBeforeSignals, 
                       Uint32 noAfterSignals);

  bool primaryKey(Tablerec* const, Uint32);

  // these set terrorCode and return non-zero on error

  int executeTuxInsertTriggers(Signal* signal, 
2252 2253 2254
                               Operationrec* regOperPtr,
                               Fragrecord* regFragPtr,
                               Tablerec* regTabPtr);
2255 2256

  int executeTuxUpdateTriggers(Signal* signal, 
2257 2258 2259
                               Operationrec* regOperPtr,
                               Fragrecord* regFragPtr,
                               Tablerec* regTabPtr);
2260 2261

  int executeTuxDeleteTriggers(Signal* signal, 
2262 2263 2264
                               Operationrec* regOperPtr,
                               Fragrecord* regFragPtr,
                               Tablerec* regTabPtr);
2265

pekka@mysql.com's avatar
pekka@mysql.com committed
2266 2267 2268 2269
  int addTuxEntries(Signal* signal,
                    Operationrec* regOperPtr,
                    Tablerec* regTabPtr);

2270 2271 2272 2273
  // these crash the node on error

  void executeTuxCommitTriggers(Signal* signal, 
                                Operationrec* regOperPtr,
2274 2275
                                Fragrecord* regFragPtr,
                                Tablerec* regTabPtr);
2276 2277 2278

  void executeTuxAbortTriggers(Signal* signal, 
                               Operationrec* regOperPtr,
2279 2280
                               Fragrecord* regFragPtr,
                               Tablerec* regTabPtr);
2281

pekka@mysql.com's avatar
pekka@mysql.com committed
2282 2283 2284
  void removeTuxEntries(Signal* signal,
                        Tablerec* regTabPtr);

2285 2286 2287 2288 2289 2290 2291 2292 2293 2294
// *****************************************************************
// Error Handling routines.
// *****************************************************************
//------------------------------------------------------------------
//------------------------------------------------------------------
  int TUPKEY_abort(Signal* signal, int error_type);

//------------------------------------------------------------------
//------------------------------------------------------------------
  void tupkeyErrorLab(Signal* signal);
2295
  void do_tup_abortreq(Signal*, Uint32 flags);
2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320

//------------------------------------------------------------------
//------------------------------------------------------------------
// Methods to handle execution of TUP_COMMITREQ + TUP_ABORTREQ.
//
// Module Transaction Manager
//
// The Transaction Manager module is responsible for the commit
// and abort of operations started by the Execution Manager.
//
// Commit Operation:
// ----------------
//
// Failures in commit processing is not allowed since that would
// leave the database in an unreliable state. Thus the only way
// to handle failures in commit processing is to crash the node.
//
// TUP_COMMITREQ can only be received in the wait state after a
// successful TUPKEYREQ which was not a read operation.
// 
// Commit of Delete:
// -----------------
//
// This will actually perform the deletion of the record unless
// other operations also are connected to the record. In this case
2321
// we will set the delete state on the record that becomes the ownerd
2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360
// of the record.
//
// Commit of Update:
// ----------------
//
// We will release the copy record where the original record was kept.
// Also here we will take special care if more operations are updating
// the record simultaneously.
//
// Commit of Insert:
// -----------------
//
// Will simply reset the state of the operation record.
//
// Signal Diagram:
// --->  TUP_COMMITREQ (from LQH)
// <---- TUP_COMMITCONF (to LQH)
//
//
// Abort Operation:
// ----------------
//
// Signal Diagram:
// --->  TUP_ABORTREQ (from LQH)
// <---- TUP_ABORTCONF (to LQH)
//
// Failures in abort processing is not allowed since that would
// leave the database in an unreliable state. Thus the only way
// to handle failures in abort processing is to crash the node.
//
// Abort messages can arrive at any time. It can arrive even before
// anything at all have arrived of the operation. It can arrive after
// receiving a number of ATTRINFO but before TUPKEYREQ has been received.
// It must arrive after that we sent TUPKEYREF in response to TUPKEYREQ
// and finally it can arrive after successfully performing the TUPKEYREQ
// in all cases including the read case.
//------------------------------------------------------------------
//------------------------------------------------------------------

2361
#if 0 
2362
  void checkPages(Fragrecord* regFragPtr);
2363
#endif
2364 2365 2366 2367 2368 2369 2370 2371 2372 2373
  Uint32 convert_byte_to_word_size(Uint32 byte_size)
  {
    return ((byte_size + 3) >> 2);
  }
  Uint32 convert_bit_to_word_size(Uint32 bit_size)
  {
    return ((bit_size + 31) >> 5);
  }

  void prepare_initial_insert(KeyReqStruct*, Operationrec*, Tablerec*);
2374
  void fix_disk_insert_no_mem_insert(KeyReqStruct*, Operationrec*, Tablerec*);
2375
  void setup_fixed_part(KeyReqStruct* req_struct,
2376 2377
			Operationrec* regOperPtr,
			Tablerec* regTabPtr);
2378 2379
  
  void send_TUPKEYREF(Signal* signal,
2380
                      Operationrec* regOperPtr);
2381
  void early_tupkey_error(Signal* signal);
2382

2383
  void printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit);
2384

2385 2386
  bool checkUpdateOfPrimaryKey(KeyReqStruct *req_struct,
                               Uint32* updateBuffer,
2387
                               Tablerec* regTabPtr);
2388

2389
  void setNullBits(Uint32*, Tablerec* regTabPtr);
2390 2391
  bool checkNullAttributes(KeyReqStruct * const, Tablerec* const);
  bool setup_read(KeyReqStruct* req_struct,
2392 2393 2394
		  Operationrec* regOperPtr,
		  Fragrecord* regFragPtr,
		  Tablerec* regTabPtr,
2395 2396
		  bool disk);
  
2397 2398
  Uint32 calculateChecksum(Tuple_header*, Tablerec* regTabPtr);
  void setChecksum(Tuple_header*, Tablerec* regTabPtr);
2399

2400 2401
  void complexTrigger(Signal* signal,
                      KeyReqStruct *req_struct,
2402 2403 2404
                      Operationrec* regOperPtr,
                      Fragrecord* regFragPtr,
                      Tablerec* regTabPtr);
2405

2406
  void setTupleStatesSetOpType(Operationrec* regOperPtr,
2407
                               KeyReqStruct *req_struct,
2408
                               Page* pagePtr,
2409 2410 2411 2412 2413 2414
                               Uint32& opType,
                               OperationrecPtr& firstOpPtr);

  void findBeforeValueOperation(OperationrecPtr& befOpPtr,
                                OperationrecPtr firstOpPtr);

2415 2416 2417
  void calculateChangeMask(Page* PagePtr,
                           Tablerec* regTabPtr,
                           KeyReqStruct * req_struct);
2418

2419
  void updateGcpId(KeyReqStruct *req_struct,
2420 2421 2422
                   Operationrec* regOperPtr,
                   Fragrecord* regFragPtr,
                   Tablerec* regTabPtr);
2423 2424 2425 2426 2427 2428

  void setTupleStateOnPreviousOps(Uint32 prevOpIndex);
  void copyMem(Signal* signal, Uint32 sourceIndex, Uint32 destIndex);

  void freeAllAttrBuffers(Operationrec*  const regOperPtr);
  void freeAttrinbufrec(Uint32 anAttrBufRec);
2429
  void removeActiveOpList(Operationrec*  const regOperPtr, Tuple_header*);
2430 2431 2432 2433

  void updatePackedList(Signal* signal, Uint16 ahostIndex);

  void setUpDescriptorReferences(Uint32 descriptorReference,
2434
                                 Tablerec* regTabPtr,
2435
                                 const Uint32* offset);
2436 2437 2438
  void setUpKeyArray(Tablerec* regTabPtr);
  bool addfragtotab(Tablerec* regTabPtr, Uint32 fragId, Uint32 fragIndex);
  void deleteFragTab(Tablerec* regTabPtr, Uint32 fragId);
2439
  void abortAddFragOp(Signal* signal);
2440 2441
  void releaseTabDescr(Tablerec* regTabPtr);
  void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* regTabPtr);
2442

2443
  void initialiseRecordsLab(Signal* signal, Uint32 switchData, Uint32, Uint32);
2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457
  void initializeAttrbufrec();
  void initializeCheckpointInfoRec();
  void initializeDiskBufferSegmentRecord();
  void initializeFragoperrec();
  void initializeFragrecord();
  void initializeHostBuffer();
  void initializeLocalLogInfo();
  void initializeOperationrec();
  void initializePendingFileOpenInfoRecord();
  void initializeRestartInfoRec();
  void initializeTablerec();
  void initializeTabDescr();
  void initializeUndoPage();

2458
  void initTab(Tablerec* regTabPtr);
2459 2460 2461 2462 2463 2464 2465 2466 2467

  void startphase3Lab(Signal* signal, Uint32 config1, Uint32 config2);

  void fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr);
  void fragrefuse1Lab(Signal* signal, FragoperrecPtr fragOperPtr);
  void fragrefuse2Lab(Signal* signal, FragoperrecPtr fragOperPtr, FragrecordPtr regFragPtr);
  void fragrefuse3Lab(Signal* signal,
                      FragoperrecPtr fragOperPtr,
                      FragrecordPtr regFragPtr,
2468
                      Tablerec* regTabPtr,
2469 2470 2471 2472
                      Uint32 fragId);
  void fragrefuse4Lab(Signal* signal,
                      FragoperrecPtr fragOperPtr,
                      FragrecordPtr regFragPtr,
2473
                      Tablerec* regTabPtr,
2474 2475 2476 2477
                      Uint32 fragId);
  void addattrrefuseLab(Signal* signal,
                        FragrecordPtr regFragPtr,
                        FragoperrecPtr fragOperPtr,
2478
                        Tablerec* regTabPtr,
2479 2480 2481
                        Uint32 fragId);


2482
  void releaseFragment(Signal* signal, Uint32 tableId, Uint32);
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2483
  void drop_fragment_free_var_pages(Signal*);
2484 2485
  void drop_fragment_free_extent(Signal*, TablerecPtr, FragrecordPtr, Uint32);
  void drop_fragment_free_extent_log_buffer_callback(Signal*, Uint32, Uint32);
2486 2487 2488
  void drop_fragment_unmap_pages(Signal*, TablerecPtr, FragrecordPtr, Uint32);
  void drop_fragment_unmap_page_callback(Signal* signal, Uint32, Uint32);
  
2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503
  // Initialisation
  void initData();
  void initRecords();

  void deleteScanProcedure(Signal* signal, Operationrec* regOperPtr);
  void copyProcedure(Signal* signal,
                     TablerecPtr regTabPtr,
                     Operationrec* regOperPtr);
  void scanProcedure(Signal* signal,
                     Operationrec* regOperPtr,
                     Uint32 lenAttrInfo);
  void storedSeizeAttrinbufrecErrorLab(Signal* signal,
                                       Operationrec* regOperPtr);
  bool storedProcedureAttrInfo(Signal* signal,
                               Operationrec* regOperPtr,
2504
			       const Uint32* data,
2505 2506 2507 2508 2509 2510 2511 2512
                               Uint32 length,
                               bool copyProc);

//-----------------------------------------------------------------------------
// Table Descriptor Memory Manager
//-----------------------------------------------------------------------------

// Public methods
2513 2514
  Uint32 getTabDescrOffsets(const Tablerec* regTabPtr, Uint32* offset);
  Uint32 allocTabDescr(const Tablerec* regTabPtr, Uint32* offset);
2515
  void freeTabDescr(Uint32 retRef, Uint32 retNo, bool normal = true);
2516 2517 2518 2519 2520 2521
  Uint32 getTabDescrWord(Uint32 index);
  void setTabDescrWord(Uint32 index, Uint32 word);

// Private methods
  Uint32 sizeOfReadFunction();
  void   removeTdArea(Uint32 tabDesRef, Uint32 list);
2522 2523 2524 2525 2526
  void   insertTdArea(Uint32 tabDesRef, Uint32 list);
  void   itdaMergeTabDescr(Uint32& retRef, Uint32& retNo, bool normal);
#ifdef VM_TRACE
  void verifytabdes();
#endif
2527

2528 2529 2530 2531 2532 2533
  void seizeOpRec(OperationrecPtr& regOperPtr);
  void seizeFragrecord(FragrecordPtr& regFragPtr);
  void seizeFragoperrec(FragoperrecPtr& fragOperPtr);
  void releaseFragoperrec(FragoperrecPtr fragOperPtr);
  void releaseFragrec(FragrecordPtr);
//----------------------------------------------------------------------------
2534
// Page Memory Manager
2535 2536
//----------------------------------------------------------------------------
  
2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559
// Public methods
  void allocConsPages(Uint32 noOfPagesToAllocate,
                      Uint32& noOfPagesAllocated,
                      Uint32& allocPageRef);
  void returnCommonArea(Uint32 retPageRef, Uint32 retNo);
  void initializePage();

// Private methods
  void removeCommonArea(Uint32 remPageRef, Uint32 list);
  void insertCommonArea(Uint32 insPageRef, Uint32 list);
  void findFreeLeftNeighbours(Uint32& allocPageRef, Uint32& noPagesAllocated, Uint32 noPagesToAllocate);
  void findFreeRightNeighbours(Uint32& allocPageRef, Uint32& noPagesAllocated, Uint32 noPagesToAllocate);
  Uint32 nextHigherTwoLog(Uint32 input);

// Private data
  Uint32 cfreepageList[16];

//------------------------------------------------------------------------------------------------------
// Page Mapper, convert logical page id's to physical page id's
// The page mapper also handles the pages allocated to the fragment.
//------------------------------------------------------------------------------------------------------
//
// Public methods
2560 2561
  Uint32 getRealpid(Fragrecord* regFragPtr, Uint32 logicalPageId);
  Uint32 getNoOfPages(Fragrecord* regFragPtr);
2562
  void initPageRangeSize(Uint32 size);
2563
  bool insertPageRangeTab(Fragrecord* regFragPtr,
2564 2565
                          Uint32 startPageId,
                          Uint32 noPages);
2566 2567
  void releaseFragPages(Fragrecord* regFragPtr);
  void initFragRange(Fragrecord* regFragPtr);
2568
  void initializePageRange();
2569 2570 2571 2572
  Uint32 getEmptyPage(Fragrecord* regFragPtr);
  Uint32 allocFragPages(Fragrecord* regFragPtr, Uint32 noOfPagesAllocated);
  Uint32 get_empty_var_page(Fragrecord* frag_ptr);
  
2573
// Private methods
2574
  Uint32 leafPageRangeFull(Fragrecord* regFragPtr, PageRangePtr currPageRangePtr);
2575 2576 2577
  void releasePagerange(PageRangePtr regPRPtr);
  void seizePagerange(PageRangePtr& regPageRangePtr);
  void errorHandler(Uint32 errorCode);
2578
  void allocMoreFragPages(Fragrecord* regFragPtr);
2579 2580 2581 2582 2583 2584 2585

// Private data
  Uint32 cfirstfreerange;
  PageRange *pageRange;
  Uint32 c_noOfFreePageRanges;
  Uint32 cnoOfPageRangeRec;

2586 2587
//---------------------------------------------------------------
// Variable Allocator
2588
// Allocates and deallocates tuples of fixed size on a fragment.
2589
//---------------------------------------------------------------
2590 2591
//
// Public methods
2592 2593

  void init_list_sizes(void);
2594 2595 2596

// Private methods

2597
  Uint32 get_alloc_page(Fragrecord* const, Uint32);
2598
  void update_free_page_list(Fragrecord* const, Ptr<Page>);
2599

2600 2601 2602 2603 2604
#if 0  
  Uint32 calc_free_list(const Tablerec* regTabPtr, Uint32 sz) const {
    return regTabPtr->m_disk_alloc_info.calc_page_free_bits(sz);
  }
#endif
2605

2606 2607 2608
  Uint32 calculate_free_list_impl(Uint32) const ;
  void remove_free_page(Fragrecord*, Var_page*, Uint32);
  void insert_free_page(Fragrecord*, Var_page*, Uint32);
2609

2610 2611 2612 2613 2614 2615
//---------------------------------------------------------------
// Fixed Allocator
// Allocates and deallocates tuples of fixed size on a fragment.
//---------------------------------------------------------------
//
// Public methods
2616 2617 2618 2619 2620
  Uint32* alloc_var_rec(Fragrecord*, Tablerec*, Uint32, Local_key*, Uint32*);
  void free_var_rec(Fragrecord*, Tablerec*, Local_key*, Ptr<Page>);
  Uint32* alloc_var_part(Fragrecord*, Tablerec*, Uint32, Local_key*);
  int realloc_var_part(Fragrecord*, Tablerec*, 
		       PagePtr, Var_part_ref*, Uint32, Uint32);
2621 2622 2623
  
  void validate_page(Tablerec*, Var_page* page);
  
2624 2625
  Uint32* alloc_fix_rec(Fragrecord*const, Tablerec*const, Local_key*,
                        Uint32*);
2626 2627
  void free_fix_rec(Fragrecord*, Tablerec*, Local_key*, Fix_page*);
  
2628 2629
  Uint32* alloc_fix_rowid(Fragrecord*, Tablerec*, Local_key*, Uint32 *);
  Uint32* alloc_var_rowid(Fragrecord*, Tablerec*, Uint32, Local_key*, Uint32*);
2630
// Private methods
2631 2632 2633
  void convertThPage(Fix_page* regPagePtr,
		     Tablerec*,
		     Uint32 mm);
2634 2635 2636 2637

  /**
   * Return offset
   */
2638 2639
  Uint32 alloc_tuple_from_page(Fragrecord* regFragPtr,
			       Fix_page* regPagePtr);
2640 2641 2642 2643 2644
  
//---------------------------------------------------------------
// Temporary variables used for storing commonly used variables
// in certain modules
//---------------------------------------------------------------
2645

2646
  Uint32 c_lcp_scan_op;
2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669
  FragrecordPtr   fragptr;
  OperationrecPtr operPtr;
  TablerecPtr     tabptr;

// readAttributes and updateAttributes module
//------------------------------------------------------------------------------------------------------
// Common stored variables. Variables that have a valid value always.
//------------------------------------------------------------------------------------------------------
  Attrbufrec *attrbufrec;
  Uint32 cfirstfreeAttrbufrec;
  Uint32 cnoOfAttrbufrec;
  Uint32 cnoFreeAttrbufrec;

  Fragoperrec *fragoperrec;
  Uint32 cfirstfreeFragopr;
  Uint32 cnoOfFragoprec;

  Fragrecord *fragrecord;
  Uint32 cfirstfreefrag;
  Uint32 cnoOfFragrec;

  HostBuffer *hostBuffer;

2670
  ArrayPool<Operationrec> c_operation_pool;
2671

2672
  ArrayPool<Page> c_page_pool;
2673 2674 2675 2676 2677 2678 2679
  Uint32 cnoOfAllocatedPages;
  
  Tablerec *tablerec;
  Uint32 cnoOfTablerec;

  TableDescriptor *tableDescriptor;
  Uint32 cnoOfTabDescrRec;
2680
  
2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702
  Uint32 cdata[32];
  Uint32 cdataPages[16];
  Uint32 cpackedListIndex;
  Uint32 cpackedList[MAX_NODES];
  Uint32 cfreeTdList[16];
  Uint32 clastBitMask;
  Uint32 clblPageCounter;
  Uint32 clblPagesPerTick;
  Uint32 clblPagesPerTickAfterSr;
  BlockReference clqhBlockref;
  Uint32 clqhUserpointer;
  Uint32 cminusOne;
  BlockReference cndbcntrRef;
  BlockReference cownref;
  Uint32 cownNodeId;
  Uint32 czero;

 // A little bit bigger to cover overwrites in copy algorithms (16384 real size).
#define ZATTR_BUFFER_SIZE 16384
  Uint32 clogMemBuffer[ZATTR_BUFFER_SIZE + 16];
  Uint32 coutBuffer[ZATTR_BUFFER_SIZE + 16];
  Uint32 cinBuffer[ZATTR_BUFFER_SIZE + 16];
2703 2704
  Uint32 ctemp_page[ZWORDS_ON_PAGE];
  Uint32 ctemp_var_record[ZWORDS_ON_PAGE];
2705 2706 2707 2708
  Uint32 totNoOfPagesAllocated;

  // Trigger variables
  Uint32 c_maxTriggersPerTable;
2709
  Uint32 c_memusage_report_frequency;
2710 2711

  Uint32 c_errorInsert4000TableId;
2712 2713
  Uint32 c_min_list_size[MAX_FREE_LIST + 1];
  Uint32 c_max_list_size[MAX_FREE_LIST + 1];
2714 2715 2716

  void initGlobalTemporaryVars();
  void reportMemoryUsage(Signal* signal, int incDec);
2717 2718

  
2719 2720 2721 2722 2723 2724 2725
#ifdef VM_TRACE
  struct Th {
    Uint32 data[1];
  };
  friend class NdbOut& operator<<(NdbOut&, const Operationrec&);
  friend class NdbOut& operator<<(NdbOut&, const Th&);
#endif
2726 2727 2728 2729 2730 2731 2732

  void expand_tuple(KeyReqStruct*, Uint32 sizes[4], Tuple_header*org, 
		    const Tablerec*, bool disk);
  void shrink_tuple(KeyReqStruct*, Uint32 sizes[2], const Tablerec*,
		    bool disk);
  
  Uint32* get_ptr(Var_part_ref);
2733
  Uint32* get_ptr(PagePtr*, Var_part_ref);
2734
  Uint32* get_ptr(PagePtr*, const Local_key*, const Tablerec*);
2735
  Uint32* get_dd_ptr(PagePtr*, const Local_key*, const Tablerec*);
2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758

  /**
   * prealloc space from disk
   *   key.m_file_no  contains file no
   *   key.m_page_no  contains disk page
   *   key.m_page_idx contains byte preallocated
   */
  int disk_page_prealloc(Signal*, Ptr<Fragrecord>, Local_key*, Uint32);
  void disk_page_prealloc_dirty_page(Disk_alloc_info&, 
				     Ptr<Page>, Uint32, Uint32);
  void disk_page_prealloc_transit_page(Disk_alloc_info&,
				       Ptr<Page_request>, Uint32, Uint32);
  
  void disk_page_abort_prealloc(Signal*, Fragrecord*,Local_key*, Uint32);
  void disk_page_abort_prealloc_callback(Signal*, Uint32, Uint32);
  void disk_page_abort_prealloc_callback_1(Signal*, Fragrecord*,
					   PagePtr, Uint32);
  
  void disk_page_prealloc_callback(Signal*, Uint32, Uint32);
  void disk_page_prealloc_initial_callback(Signal*, Uint32, Uint32);
  void disk_page_prealloc_callback_common(Signal*, 
					  Ptr<Page_request>, 
					  Ptr<Fragrecord>,
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2759
					  Ptr<Page>);
2760 2761 2762 2763 2764 2765 2766 2767 2768
  
  void disk_page_alloc(Signal*, 
		       Tablerec*, Fragrecord*, Local_key*, PagePtr, Uint32);
  void disk_page_free(Signal*, 
		      Tablerec*, Fragrecord*, Local_key*, PagePtr, Uint32);
  
  void disk_page_commit_callback(Signal*, Uint32 opPtrI, Uint32 page_id);  
  
  void disk_page_log_buffer_callback(Signal*, Uint32 opPtrI, Uint32); 
2769 2770 2771

  void disk_page_alloc_extent_log_buffer_callback(Signal*, Uint32, Uint32);
  void disk_page_free_extent_log_buffer_callback(Signal*, Uint32, Uint32);
2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784
  
  Uint64 disk_page_undo_alloc(Page*, const Local_key*,
			      Uint32 sz, Uint32 gci, Uint32 logfile_group_id);

  Uint64 disk_page_undo_update(Page*, const Local_key*,
			       const Uint32*, Uint32,
			       Uint32 gci, Uint32 logfile_group_id);
  
  Uint64 disk_page_undo_free(Page*, const Local_key*,
			     const Uint32*, Uint32 sz,
			     Uint32 gci, Uint32 logfile_group_id);

  void undo_createtable_callback(Signal* signal, Uint32 opPtrI, Uint32 unused);
jonas@eel.(none)'s avatar
jonas@eel.(none) committed
2785
  void undo_createtable_logsync_callback(Signal* signal, Uint32, Uint32);
2786

2787 2788 2789
  void drop_table_log_buffer_callback(Signal*, Uint32, Uint32);
  void drop_table_logsync_callback(Signal*, Uint32, Uint32);

jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2790
  void disk_page_set_dirty(Ptr<Page>);
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2791
  void restart_setup_page(Disk_alloc_info&, Ptr<Page>);
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2792 2793
  void update_extent_pos(Disk_alloc_info&, Ptr<Extent_info>);
  
2794 2795 2796 2797 2798
  /**
   * Disk restart code
   */
public:
  int disk_page_load_hook(Uint32 page_id);
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2799 2800
  
  void disk_page_unmap_callback(Uint32 page_id, Uint32 dirty_count);
2801 2802 2803 2804
  
  int disk_restart_alloc_extent(Uint32 tableId, Uint32 fragId, 
				const Local_key* key, Uint32 pages);
  void disk_restart_page_bits(Uint32 tableId, Uint32 fragId,
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2805
			      const Local_key*, Uint32 bits);
2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816
  void disk_restart_undo(Signal* signal, Uint64 lsn,
			 Uint32 type, const Uint32 * ptr, Uint32 len);

  struct Apply_undo 
  {
    Uint32 m_type, m_len;
    const Uint32* m_ptr;
    Uint64 m_lsn;
    Ptr<Tablerec> m_table_ptr;
    Ptr<Fragrecord> m_fragment_ptr;
    Ptr<Page> m_page_ptr;
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2817
    Ptr<Extent_info> m_extent_ptr;
2818 2819
    Local_key m_key;
  };
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2820 2821

  void disk_restart_mark_no_lcp(Uint32 table, Uint32 frag);
2822 2823 2824
  
private:
  void disk_restart_undo_next(Signal*);
2825
  void disk_restart_undo_lcp(Uint32, Uint32, Uint32 flag);
2826 2827 2828 2829
  void disk_restart_undo_callback(Signal* signal, Uint32, Uint32);
  void disk_restart_undo_alloc(Apply_undo*);
  void disk_restart_undo_update(Apply_undo*);
  void disk_restart_undo_free(Apply_undo*);
jonas@perch.ndb.mysql.com's avatar
jonas@perch.ndb.mysql.com committed
2830
  void disk_restart_undo_page_bits(Signal*, Apply_undo*);
2831 2832 2833 2834 2835 2836 2837 2838

#ifdef VM_TRACE
  void verify_page_lists(Disk_alloc_info&);
#else
  void verify_page_lists(Disk_alloc_info&) {}
#endif
  
  void fix_commit_order(OperationrecPtr);
2839
  void commit_operation(Signal*, Uint32, Tuple_header*, PagePtr,
2840 2841 2842 2843 2844 2845 2846 2847
			Operationrec*, Fragrecord*, Tablerec*);
  
  void dealloc_tuple(Signal* signal, Uint32, Page*, Tuple_header*, 
		     Operationrec*, Fragrecord*, Tablerec*);
  
  int handle_size_change_after_update(KeyReqStruct* req_struct,
				      Tuple_header* org,
				      Operationrec*,
2848 2849
				      Fragrecord* regFragPtr,
				      Tablerec* regTabPtr,
2850 2851 2852 2853 2854 2855 2856
				      Uint32 sizes[4]);

  /**
   * Setup all pointer on keyreqstruct to prepare for read
   *   req_struct->m_tuple_ptr is set to tuple to read
   */
  void prepare_read(KeyReqStruct*, Tablerec* const, bool disk);
2857 2858
};

2859
#if 0
2860
inline
2861 2862 2863 2864 2865 2866 2867 2868
Uint32
Dbtup::get_frag_page_id(Uint32 real_page_id)
{
  PagePtr real_page_ptr;
  real_page_ptr.i= real_page_id;
  ptrCheckGuard(real_page_ptr, cnoOfPage, cpage);
  return real_page_ptr.p->frag_page_id;
}
2869
#endif
2870 2871 2872

inline
Dbtup::TransState
2873
Dbtup::get_trans_state(Operationrec * regOperPtr)
2874 2875 2876 2877 2878 2879
{
  return (Dbtup::TransState)regOperPtr->op_struct.trans_state;
}

inline
void
2880
Dbtup::set_trans_state(Operationrec* regOperPtr,
2881 2882 2883 2884 2885 2886 2887
                       Dbtup::TransState trans_state)
{
  regOperPtr->op_struct.trans_state= (Uint32)trans_state;
}

inline
Dbtup::TupleState
2888
Dbtup::get_tuple_state(Operationrec * regOperPtr)
2889 2890 2891 2892 2893 2894
{
  return (Dbtup::TupleState)regOperPtr->op_struct.tuple_state;
}

inline
void
2895
Dbtup::set_tuple_state(Operationrec* regOperPtr,
2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910
                       Dbtup::TupleState tuple_state)
{
  regOperPtr->op_struct.tuple_state= (Uint32)tuple_state;
}


inline
Uint32
Dbtup::decr_tup_version(Uint32 tup_version)
{
  return (tup_version - 1) & ZTUP_VERSION_MASK;
}

inline
Dbtup::ChangeMaskState
2911
Dbtup::get_change_mask_state(Operationrec * regOperPtr)
2912
{
2913 2914
  return (Dbtup::ChangeMaskState)regOperPtr->op_struct.change_mask_state;
}
2915 2916

inline
2917
void
2918
Dbtup::set_change_mask_state(Operationrec * regOperPtr,
2919
                             ChangeMaskState new_state)
2920
{
2921 2922
  regOperPtr->op_struct.change_mask_state= (Uint32)new_state;
}
2923 2924

inline
2925
void
2926 2927
Dbtup::update_change_mask_info(KeyReqStruct * req_struct,
                               Operationrec * regOperPtr)
2928
{
2929
  if (req_struct->max_attr_id_updated == 0) {
2930 2931 2932 2933 2934
    if (get_change_mask_state(regOperPtr) == USE_SAVED_CHANGE_MASK) {
      // add new changes
      regOperPtr->saved_change_mask[0] |= req_struct->changeMask.getWord(0);
      regOperPtr->saved_change_mask[1] |= req_struct->changeMask.getWord(1);
    }
2935 2936 2937 2938 2939 2940 2941 2942
  } else {
    if (req_struct->no_changed_attrs < 16) {
      set_change_mask_state(regOperPtr, RECALCULATE_CHANGE_MASK);
    } else {
      set_change_mask_state(regOperPtr, SET_ALL_MASK);
    }
  }
}
2943 2944

inline
2945 2946
Uint32*
Dbtup::get_ptr(Var_part_ref ref)
2947
{
2948
  Ptr<Page> tmp;
2949 2950 2951 2952 2953
  return get_ptr(&tmp, ref);
}

inline
Uint32*
2954
Dbtup::get_ptr(Ptr<Page>* pagePtr, Var_part_ref ref)
2955 2956
{
  PagePtr tmp;
2957 2958 2959
  Local_key key;
  ref.copyout(&key);
  tmp.i = key.m_page_no;
2960
  
2961
  c_page_pool.getPtr(tmp);
2962
  memcpy(pagePtr, &tmp, sizeof(tmp));
2963
  return ((Var_page*)tmp.p)->get_ptr(key.m_page_idx);
2964 2965 2966 2967 2968 2969 2970 2971 2972
}

inline
Uint32*
Dbtup::get_ptr(PagePtr* pagePtr, 
	       const Local_key* key, const Tablerec* regTabPtr)
{
  PagePtr tmp;
  tmp.i= key->m_page_no;
2973
  c_page_pool.getPtr(tmp);
2974 2975
  memcpy(pagePtr, &tmp, sizeof(tmp));

2976 2977
  return ((Fix_page*)tmp.p)->
    get_ptr(key->m_page_idx, regTabPtr->m_offsets[MM].m_fix_header_size);
2978 2979 2980 2981
}

inline
Uint32*
2982 2983
Dbtup::get_dd_ptr(PagePtr* pagePtr, 
		  const Local_key* key, const Tablerec* regTabPtr)
2984 2985 2986
{
  PagePtr tmp;
  tmp.i= key->m_page_no;
2987
  tmp.p= (Page*)m_global_page_pool.getPtr(tmp.i);
2988 2989
  memcpy(pagePtr, &tmp, sizeof(tmp));
  
2990
  if(regTabPtr->m_attributes[DD].m_no_of_varsize)
2991 2992 2993
    return ((Var_page*)tmp.p)->get_ptr(key->m_page_idx);
  else
    return ((Fix_page*)tmp.p)->
2994
      get_ptr(key->m_page_idx, regTabPtr->m_offsets[DD].m_fix_header_size);
2995 2996 2997 2998
}

NdbOut&
operator<<(NdbOut&, const Dbtup::Tablerec&);
2999 3000

#endif