DbtupFixAlloc.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #define DBTUP_C
  14. #include "Dbtup.hpp"
  15. #include <RefConvert.hpp>
  16. #include <ndb_limits.h>
  17. #include <pc.hpp>
  18. #define ljam() { jamLine(6000 + __LINE__); }
  19. #define ljamEntry() { jamEntryLine(6000 + __LINE__); }
  20. //
  21. // Fixed Allocator
  22. // This module is used to allocate and free fixed size tuples from the
  23. // set of pages attached to a fragment. The fixed size is preset per
  24. // fragment and their can only be one such value per fragment in the
  25. // current implementation.
  26. // 
  27. // Public methods
  28. // bool allocTh(Fragrecord* const regFragPtr, # In
  29. //              Tablerec* const regTabPtr,    # In
  30. //              Uint32 pageType,              # In
  31. //              Signal* signal,               # In
  32. //              Uint32& pageOffset,           # Out
  33. //              PagePtr& pagePtr)             # In/Out
  34. // This method allocates a fixed size and the pagePtr is a reference
  35. // to the page and pageOffset is the offset in the page of the tuple.
  36. //
  37. // freeTh()
  38. // This method is used to free a tuple header in normal transaction
  39. // handling.
  40. //
  41. // freeThSr()
  42. // This method is used to free a tuple as part of executing the undo
  43. // log records.
  44. //
  45. // getThAtPageSr()
  46. // This method is used to allocate a tuple on a set page as part of
  47. // undo log execution.
  48. //
  49. //
  50. // Private methods
  51. // getThAtPage()
  52. // This method gets a tuple from a page with free tuples.
  53. //
  54. // convertThPage()
  55. // Convert an empty page into a page of free tuples in a linked list.
  56. //
  57. // getEmptyPageThCopy()
  58. // A page recently taken from set of empty pages on fragment is made
  59. // part of the copy pages.
  60. //
  61. // getEmptyPageTh()
  62. // A page recently taken from the set of empty pages on the fragment is
  63. // is made part of the set of free pages with fixed size tuples in the
  64. // fragment.
  65. // 
  66. bool Dbtup::allocTh(Fragrecord* const regFragPtr,
  67.                     Tablerec* const regTabPtr,
  68.                     Uint32 pageType,
  69.                     Signal* signal,
  70.                     Uint32& pageOffset,
  71.                     PagePtr& pagePtr) 
  72. {
  73.   if (pageType == SAME_PAGE) {
  74.     ljam();
  75.     ptrCheckGuard(pagePtr, cnoOfPage, page);
  76.     if (pagePtr.p->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FREE) {
  77.       ljam();
  78.       getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
  79.       return true;
  80.     }//if
  81.     pageType = NORMAL_PAGE;
  82.   }//if
  83.   if (pageType == COPY_PAGE) {
  84. /* ---------------------------------------------------------------- */
  85. // Allocate a tuple header for the copy of the tuple header
  86. /* ---------------------------------------------------------------- */
  87.     if (regFragPtr->thFreeCopyFirst == RNIL) {
  88. /* ---------------------------------------------------------------- */
  89. // No page in list with free tuple header exists
  90. /* ---------------------------------------------------------------- */
  91.       if (regFragPtr->noCopyPagesAlloc < ZMAX_NO_COPY_PAGES) {
  92.         ljam();
  93. /* ---------------------------------------------------------------- */
  94. // We have not yet allocated the maximum number of copy pages for
  95. // this fragment.
  96. /* ---------------------------------------------------------------- */
  97.         pagePtr.i = getEmptyPage(regFragPtr);
  98.         if (pagePtr.i != RNIL) {
  99.           ljam();
  100. /* ---------------------------------------------------------------- */
  101. // We have empty pages already allocated to this fragment. Allocate
  102. // one of those as copy page.
  103. /* ---------------------------------------------------------------- */
  104.           ptrCheckGuard(pagePtr, cnoOfPage, page);
  105.           getEmptyPageThCopy(regFragPtr, signal, pagePtr.p);
  106. /* ---------------------------------------------------------------- */
  107. // Convert page into a tuple header page.
  108. /* ---------------------------------------------------------------- */
  109.           convertThPage(regTabPtr->tupheadsize, pagePtr.p);
  110.           getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
  111.           return true;
  112.         }//if
  113.       }//if
  114.     } else {
  115.       ljam();
  116. /* ---------------------------------------------------------------- */
  117. /*       NORMAL PATH WHEN COPY PAGE REQUESTED, GET PAGE POINTER     */
  118. /*       AND THEN GOTO COMMON HANDLING OF GET TUPLE HEADER AT PAGE. */
  119. /* ---------------------------------------------------------------- */
  120.       pagePtr.i = getRealpid(regFragPtr, regFragPtr->thFreeCopyFirst);
  121.       ptrCheckGuard(pagePtr, cnoOfPage, page);
  122.       getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
  123.       return true;
  124.     }//if
  125.   }//if
  126. /* ---------------------------------------------------------------- */
  127. /*       EITHER NORMAL PAGE REQUESTED OR ALLOCATION FROM COPY PAGE  */
  128. /*       FAILED. TRY ALLOCATING FROM NORMAL PAGE.                   */
  129. /* ---------------------------------------------------------------- */
  130.   Uint32 fragPageId = regFragPtr->thFreeFirst;
  131.   if (fragPageId == RNIL) {
  132. /* ---------------------------------------------------------------- */
  133. // No prepared tuple header page with free entries exists.
  134. /* ---------------------------------------------------------------- */
  135.     pagePtr.i = getEmptyPage(regFragPtr);
  136.     if (pagePtr.i != RNIL) {
  137.       ljam();
  138. /* ---------------------------------------------------------------- */
  139. // We found empty pages on the fragment. Allocate an empty page and
  140. // convert it into a tuple header page and put it in thFreeFirst-list.
  141. /* ---------------------------------------------------------------- */
  142.       ptrCheckGuard(pagePtr, cnoOfPage, page);
  143.       getEmptyPageTh(regFragPtr, signal, pagePtr.p);
  144.       convertThPage(regTabPtr->tupheadsize, pagePtr.p);
  145.       getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
  146.       return true;
  147.     } else {
  148.       ljam();
  149. /* ---------------------------------------------------------------- */
  150. /*       THERE ARE NO EMPTY PAGES. MEMORY CAN NOT BE ALLOCATED.     */
  151. /* ---------------------------------------------------------------- */
  152.       terrorCode = ZMEM_NOMEM_ERROR;
  153.       return false;
  154.     }//if
  155.   } else {
  156.     ljam();
  157. /* ---------------------------------------------------------------- */
  158. /*       THIS SHOULD BE THE COMMON PATH THROUGH THE CODE, FREE      */
  159. /*       COPY PAGE EXISTED.                                         */
  160. /* ---------------------------------------------------------------- */
  161.     pagePtr.i = getRealpid(regFragPtr, fragPageId);
  162.     ptrCheckGuard(pagePtr, cnoOfPage, page);
  163.     getThAtPage(regFragPtr, pagePtr.p, signal, pageOffset);
  164.     return true;
  165.   }//if
  166.   ndbrequire(false); // Dead code
  167.   return false;
  168. }//Dbtup::allocTh()
  169. void Dbtup::convertThPage(Uint32 Tupheadsize,
  170.                           Page*  const regPagePtr) 
  171. {
  172.   Uint32 ctpConstant = Tupheadsize << 16;
  173.   Uint32 nextTuple = ZPAGE_HEADER_SIZE + Tupheadsize;
  174.   Uint32 endOfList;
  175.   /*
  176.   ASSUMES AT LEAST ONE TUPLE HEADER FITS AND THEREFORE NO HANDLING
  177.   OF ZERO AS EXTREME CASE
  178.   */
  179.   do {
  180.     ljam();
  181.     endOfList = nextTuple - Tupheadsize;
  182.     regPagePtr->pageWord[endOfList] = ctpConstant + nextTuple;
  183.     nextTuple += Tupheadsize;
  184.   } while (nextTuple <= ZWORDS_ON_PAGE);
  185.   regPagePtr->pageWord[endOfList] = ctpConstant;
  186.   Uint32 startOfList = ZPAGE_HEADER_SIZE;
  187.   regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (startOfList << 16) + endOfList;
  188. }//Dbtup::convertThPage()
  189. void Dbtup::getEmptyPageTh(Fragrecord* const regFragPtr,
  190.                            Signal* signal,
  191.                            Page* const regPagePtr) 
  192. {
  193.   if (isUndoLoggingNeeded(regFragPtr, regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS])) {
  194.     cprAddUndoLogPageHeader(signal,
  195.                             regPagePtr,
  196.                             regFragPtr);
  197.   }//if
  198.   regPagePtr->pageWord[ZPAGE_NEXT_POS] = regFragPtr->thFreeFirst;
  199.   regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FREE;
  200.   regFragPtr->thFreeFirst = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
  201. ndbrequire(regFragPtr->thFreeFirst != (RNIL -1));
  202. }//Dbtup::getEmptyPageTh()
  203. void Dbtup::getEmptyPageThCopy(Fragrecord* const regFragPtr,
  204.                                Signal* signal,
  205.                                Page* const regPagePtr) 
  206. {
  207.   if (isUndoLoggingNeeded(regFragPtr, regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS])) {
  208.     cprAddUndoLogPageHeader(signal,
  209.                             regPagePtr,
  210.                             regFragPtr);
  211.   }//if
  212.   regPagePtr->pageWord[ZPAGE_NEXT_POS] = regFragPtr->thFreeCopyFirst;
  213.   regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FREE_COPY;
  214.   regFragPtr->thFreeCopyFirst = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
  215.   regFragPtr->noCopyPagesAlloc++;
  216. }//Dbtup::getEmptyPageThCopy()
  217. void Dbtup::getThAtPage(Fragrecord* const regFragPtr,
  218.                         Page* const regPagePtr,
  219.                         Signal* signal,
  220.                         Uint32& pageOffset) 
  221. {
  222.   Uint32 freeListHeader = regPagePtr->pageWord[ZFREELIST_HEADER_POS];
  223.   Uint32 startTuple = freeListHeader >> 16;
  224.   Uint32 endTuple = freeListHeader & 0xffff;
  225.   pageOffset = startTuple; /* START IS THE ONE ALLOCATED */
  226.   if (startTuple > 0) {
  227.    if (startTuple != endTuple) {
  228. /* ---------------------------------------------------------------- */
  229. /*       NOT THE LAST, SIMPLY RESHUFFLE POINTERS.                   */
  230. /* ---------------------------------------------------------------- */
  231.      ndbrequire(startTuple < ZWORDS_ON_PAGE);
  232.      startTuple = regPagePtr->pageWord[startTuple] & 0xffff;
  233.      regPagePtr->pageWord[ZFREELIST_HEADER_POS] = endTuple +
  234.                                                   (startTuple << 16);
  235.      return;
  236.    } else {
  237. /* ---------------------------------------------------------------- */
  238. /*       THIS WAS THE LAST TUPLE HEADER IN THIS PAGE. REMOVE IT FROM*/
  239. /*       THE TUPLE HEADER FREE LIST OR TH COPY FREE LIST. ALSO SET  */
  240. /*       A PROPER PAGE STATE.                                       */
  241. /*                                                                  */
  242. /*       WE ALSO HAVE TO INSERT AN UNDO LOG ENTRY TO ENSURE PAGE    */
  243. /*       ARE MAINTAINED EVEN AFTER A SYSTEM CRASH.                  */
  244. /* ---------------------------------------------------------------- */
  245.      if (isUndoLoggingNeeded(regFragPtr,
  246.                              regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS])) {
  247.        cprAddUndoLogPageHeader(signal,
  248.                                regPagePtr,
  249.                                regFragPtr);
  250.      }//if
  251.      if (regPagePtr->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FREE) {
  252.        ljam();
  253.        regFragPtr->thFreeFirst = regPagePtr->pageWord[ZPAGE_NEXT_POS];
  254.        regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FULL;
  255.      } else if (regPagePtr->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FREE_COPY) {
  256.        ljam();
  257.        regFragPtr->thFreeCopyFirst = regPagePtr->pageWord[ZPAGE_NEXT_POS];
  258.        regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FULL_COPY;
  259.      } else {
  260.        ndbrequire(false);
  261.      }//if
  262.      regPagePtr->pageWord[ZFREELIST_HEADER_POS] = 0;
  263.      regPagePtr->pageWord[ZPAGE_NEXT_POS] = RNIL;
  264.    }//if
  265.   } else {
  266.     ndbrequire(false);
  267.   }//if
  268.   return;
  269. }//Dbtup::getThAtPage()
  270. void Dbtup::getThAtPageSr(Page* const regPagePtr,
  271.                           Uint32& pageOffset) 
  272. {
  273.   Uint32 freeListHeader = regPagePtr->pageWord[ZFREELIST_HEADER_POS];
  274.   Uint32 startTuple = freeListHeader >> 16;
  275.   Uint32 endTuple = freeListHeader & 0xffff;
  276.   ndbrequire(startTuple > 0);
  277.   pageOffset = startTuple; /* START IS THE ONE ALLOCATED */
  278.   if (startTuple == endTuple) {
  279.     ljam();
  280. /* ---------------------------------------------------------------- */
  281. /*       THIS WAS THE LAST TUPLE HEADER IN THIS PAGE. SINCE WE ARE  */
  282. /*       UNDOING PAGE UPDATES WE SHALL NOT DO ANYTHING ABOUT THE    */
  283. /*       PAGE HEADER. THIS IS DONE BY SEPARATE LOG RECORDS.         */
  284. /* ---------------------------------------------------------------- */
  285.     regPagePtr->pageWord[ZFREELIST_HEADER_POS] = 0;
  286.   } else {
  287.     ljam();
  288. /* ---------------------------------------------------------------- */
  289. /*       NOT THE LAST, SIMPLY RESHUFFLE POINTERS.                   */
  290. /* ---------------------------------------------------------------- */
  291.     ndbrequire(startTuple < ZWORDS_ON_PAGE);
  292.     startTuple = regPagePtr->pageWord[startTuple] & 0xffff; /* GET NEXT POINTER */
  293.     regPagePtr->pageWord[ZFREELIST_HEADER_POS] = endTuple + (startTuple << 16);
  294.   }//if
  295. }//Dbtup::getThAtPageSr()
  296. void Dbtup::freeTh(Fragrecord*  const regFragPtr,
  297.                    Tablerec* const regTabPtr,
  298.                    Signal* signal,
  299.                    Page*  const regPagePtr,
  300.                    Uint32 freePageOffset) 
  301. {
  302.   Uint32 startOfList = regPagePtr->pageWord[ZFREELIST_HEADER_POS] >> 16;
  303.   Uint32 endOfList = regPagePtr->pageWord[ZFREELIST_HEADER_POS] & 0xffff;
  304. /* LINK THE NOW FREE TUPLE SPACE INTO BEGINNING OF FREE LIST OF OF THE PAGE */
  305. /* SET THE SIZE OF THE NEW FREE SPACE AND LINK TO THE OLD START OF FREELIST */
  306.   ndbrequire(freePageOffset < ZWORDS_ON_PAGE);
  307.   regPagePtr->pageWord[freePageOffset] = (regTabPtr->tupheadsize << 16) +
  308.                                           startOfList;
  309.   if (endOfList == 0) {
  310.     ljam();
  311.     ndbrequire(startOfList == 0);
  312. /* ---------------------------------------------------------------- */
  313. /*       THE PAGE WAS PREVIOUSLY FULL, NO EMPTY SPACE AT ALL.       */
  314. /*       THIS ENTRY WILL THEN BE BOTH THE START AND THE END OF THE  */
  315. /*       LIST. IT WILL ALSO BE PUT ON THE PROPER FREE LIST.         */
  316. /*                                                                  */
  317. /*       UPDATE OF NEXT POINTER AND PAGE STATE MUST BE LOGGED TO    */
  318. /*       THE UNDO LOG TO ENSURE THAT FREE LISTS ARE OK AFTER A      */
  319. /*       SYSTEM RESTART.                                            */
  320. /* ---------------------------------------------------------------- */
  321.     if (isUndoLoggingNeeded(regFragPtr, regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS])) {
  322.       cprAddUndoLogPageHeader(signal,
  323.                               regPagePtr,
  324.                               regFragPtr);
  325.     }//if
  326.     regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (freePageOffset << 16) + freePageOffset;
  327.     if (regPagePtr->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FULL) {
  328.       ljam();
  329.       regPagePtr->pageWord[ZPAGE_NEXT_POS] = regFragPtr->thFreeFirst;
  330.       regFragPtr->thFreeFirst = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
  331.       regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FREE;
  332.     } else {
  333.       ndbrequire(regPagePtr->pageWord[ZPAGE_STATE_POS] == ZTH_MM_FULL_COPY);
  334.       ljam();
  335.       regPagePtr->pageWord[ZPAGE_NEXT_POS] = regFragPtr->thFreeCopyFirst;
  336.       regFragPtr->thFreeCopyFirst = regPagePtr->pageWord[ZPAGE_FRAG_PAGE_ID_POS];
  337.       regPagePtr->pageWord[ZPAGE_STATE_POS] = ZTH_MM_FREE_COPY;
  338.     }//if
  339.   } else {
  340.     ljam();
  341.     regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (freePageOffset << 16) + endOfList;
  342.   }//if
  343. }//Dbtup::freeTh()
  344. void Dbtup::freeThSr(Tablerec* const regTabPtr,
  345.                      Page*  const regPagePtr,
  346.                      Uint32 freePageOffset) 
  347. {
  348. /* ------------------------------------------------------------------------ */
  349. /* LINK THE NOW FREE TUPLE SPACE INTO BEGINNING OF FREE LIST OF OF THE PAGE */
  350. /* SET THE SIZE OF THE NEW FREE SPACE AND LINK TO THE OLD START OF FREELIST */
  351. /* ------------------------------------------------------------------------ */
  352.   Uint32 startOfList = regPagePtr->pageWord[ZFREELIST_HEADER_POS] >> 16;
  353.   Uint32 endOfList = regPagePtr->pageWord[ZFREELIST_HEADER_POS] & 0xffff;
  354.   ndbrequire(freePageOffset < ZWORDS_ON_PAGE);
  355.   regPagePtr->pageWord[freePageOffset] = (regTabPtr->tupheadsize << 16) + startOfList;
  356.   if (endOfList == 0) {
  357.     ljam();
  358.     ndbrequire(startOfList == 0);
  359. /* ---------------------------------------------------------------- */
  360. /*       THE PAGE WAS PREVIOUSLY FULL, NO EMPTY SPACE AT ALL.       */
  361. /*       THIS ENTRY WILL THEN BE BOTH THE START AND THE END OF THE  */
  362. /*       LIST. IT WILL ALSO BE PUT ON THE PROPER FREE LIST.         */
  363. /* ---------------------------------------------------------------- */
  364.     regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (freePageOffset << 16) + freePageOffset;
  365.   } else {
  366.     ljam();
  367.     regPagePtr->pageWord[ZFREELIST_HEADER_POS] = (freePageOffset << 16) + endOfList;
  368.   }//if
  369. }//Dbtup::freeThSr()