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

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(16000 + __LINE__); }
  19. #define ljamEntry() { jamEntryLine(16000 + __LINE__); }
  20. /* ---------------------------------------------------------------- */
  21. // 4) Page Memory Manager (buddy algorithm)
  22. //
  23. // The following data structures in Dbtup is used by the Page Memory
  24. // Manager.
  25. //
  26. // cfreepageList[16]
  27. // Pages with a header
  28. //
  29. // The cfreepageList is 16 free lists. Free list 0 contains chunks of
  30. // pages with 2^0 (=1) pages in each chunk. Free list 1 chunks of 2^1
  31. // (=2) pages in each chunk and so forth upto free list 15 which
  32. // contains chunks of 2^15 (=32768) pages in each chunk.
  33. // The cfreepageList array contains the pointer to the first chunk
  34. // in each of those lists. The lists are doubly linked where the
  35. // first page in each chunk contains the next and previous references
  36. // in position ZPAGE_NEXT_CLUST_POS and ZPAGE_PREV_CLUST_POS in the
  37. // page header.
  38. // In addition the leading page and the last page in each chunk is marked
  39. // with a state (=ZFREE_COMMON) in position ZPAGE_STATE_POS in page
  40. // header. This state indicates that the page is the leading or last page
  41. // in a chunk of free pages. Furthermore the leading and last page is
  42. // also marked with a reference to the leading (=ZPAGE_FIRST_CLUST_POS)
  43. // and the last page (=ZPAGE_LAST_CLUST_POS) in the chunk.
  44. //
  45. // The aim of these data structures is to enable a free area handling of
  46. // free pages based on a buddy algorithm. When allocating pages it is
  47. // performed in chunks of pages and the algorithm tries to make the
  48. // chunks as large as possible.
  49. // This manager is invoked when fragments lack internal page space to
  50. // accomodate all the data they are requested to store. It is also
  51. // invoked when fragments deallocate page space back to the free area.
  52. //
  53. // The following routines are part of the external interface:
  54. // void
  55. // allocConsPages(Uint32  noOfPagesToAllocate, #In
  56. //                Uint32& noOfPagesAllocated,  #Out
  57. //                Uint32& retPageRef)          #Out
  58. // void
  59. // returnCommonArea(Uint32 retPageRef,         #In
  60. //                  Uint32 retNoPages)         #In
  61. //
  62. // allocConsPages tries to allocate noOfPagesToAllocate pages in one chunk.
  63. // If this fails it delivers a chunk as large as possible. It returns the
  64. // i-value of the first page in the chunk delivered, if zero pages returned
  65. // this i-value is undefined. It also returns the size of the chunk actually
  66. // delivered.
  67. // 
  68. // returnCommonArea is used when somebody is returning pages to the free area.
  69. // It is used both from internal routines and external routines.
  70. //
  71. // The following routines are private routines used to support the
  72. // above external interface:
  73. // removeCommonArea()
  74. // insertCommonArea()
  75. // findFreeLeftNeighbours()
  76. // findFreeRightNeighbours()
  77. // Uint32
  78. // nextHigherTwoLog(Uint32 input)
  79. //
  80. // nextHigherTwoLog is a support routine which is a mathematical function with
  81. // an integer as input and an integer as output. It calculates the 2-log of
  82. // (input + 1). If the 2-log of (input + 1) is larger than 15 then the routine
  83. // will return 15. It is part of the external interface since it is also used
  84. // by other similar memory management algorithms.
  85. //
  86. // External dependencies:
  87. // None.
  88. //
  89. // Side Effects:
  90. // Apart from the above mentioned data structures there are no more
  91. // side effects other than through the subroutine parameters in the
  92. // external interface.
  93. //
  94. /* ---------------------------------------------------------------- */
  95. /* ---------------------------------------------------------------- */
  96. /* CALCULATE THE 2-LOG + 1 OF TMP AND PUT RESULT INTO TBITS         */
  97. /* ---------------------------------------------------------------- */
  98. Uint32 Dbtup::nextHigherTwoLog(Uint32 input) 
  99. {
  100.   input = input | (input >> 8);
  101.   input = input | (input >> 4);
  102.   input = input | (input >> 2);
  103.   input = input | (input >> 1);
  104.   Uint32 output = (input & 0x5555) + ((input >> 1) & 0x5555);
  105.   output = (output & 0x3333) + ((output >> 2) & 0x3333);
  106.   output = output + (output >> 4);
  107.   output = (output & 0xf) + ((output >> 8) & 0xf);
  108.   return output;
  109. }//nextHigherTwoLog()
  110. void Dbtup::initializePage() 
  111. {
  112.   for (Uint32 i = 0; i < 16; i++) {
  113.     cfreepageList[i] = RNIL;
  114.   }//for
  115.   PagePtr pagePtr;
  116.   for (pagePtr.i = 0; pagePtr.i < cnoOfPage; pagePtr.i++) {
  117.     ljam();
  118.     refresh_watch_dog();
  119.     ptrAss(pagePtr, page);
  120.     pagePtr.p->pageWord[ZPAGE_PHYSICAL_INDEX] = pagePtr.i;
  121.     pagePtr.p->pageWord[ZPAGE_NEXT_POS] = pagePtr.i + 1;
  122.     pagePtr.p->pageWord[ZPAGE_NEXT_CLUST_POS] = RNIL;
  123.     pagePtr.p->pageWord[ZPAGE_LAST_CLUST_POS] = RNIL;
  124.     pagePtr.p->pageWord[ZPAGE_PREV_POS] = RNIL;
  125.     pagePtr.p->pageWord[ZPAGE_STATE_POS] = ZFREE_COMMON;
  126.   }//for
  127.   pagePtr.i = cnoOfPage - 1;
  128.   ptrAss(pagePtr, page);
  129.   pagePtr.p->pageWord[ZPAGE_NEXT_POS] = RNIL;
  130.   
  131.   pagePtr.i = 0;
  132.   ptrAss(pagePtr, page);
  133.   pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON;
  134.   for(size_t j = 0; j<MAX_PARALLELL_TUP_SRREQ; j++){
  135.     pagePtr.i = 1+j;
  136.     ptrAss(pagePtr, page);
  137.     pagePtr.p->pageWord[ZPAGE_STATE_POS] = ~ZFREE_COMMON;
  138.   }
  139.   
  140.   Uint32 tmp = 1 + MAX_PARALLELL_TUP_SRREQ;
  141.   returnCommonArea(tmp, cnoOfPage - tmp);
  142.   cnoOfAllocatedPages = tmp; // Is updated by returnCommonArea
  143.   c_sr_free_page_0 = ~0;
  144. }//Dbtup::initializePage()
  145. void Dbtup::allocConsPages(Uint32 noOfPagesToAllocate,
  146.                            Uint32& noOfPagesAllocated,
  147.                            Uint32& allocPageRef)
  148. {
  149.   if (noOfPagesToAllocate == 0){ 
  150.     ljam();
  151.     noOfPagesAllocated = 0;
  152.     return;
  153.   }//if
  154.   Uint32 firstListToCheck = nextHigherTwoLog(noOfPagesToAllocate - 1);
  155.   for (Uint32 i = firstListToCheck; i < 16; i++) {
  156.     ljam();
  157.     if (cfreepageList[i] != RNIL) {
  158.       ljam();
  159. /* ---------------------------------------------------------------- */
  160. /*       PROPER AMOUNT OF PAGES WERE FOUND. NOW SPLIT THE FOUND     */
  161. /*       AREA AND RETURN THE PART NOT NEEDED.                       */
  162. /* ---------------------------------------------------------------- */
  163.       noOfPagesAllocated = noOfPagesToAllocate;
  164.       allocPageRef = cfreepageList[i];
  165.       removeCommonArea(allocPageRef, i);
  166.       Uint32 retNo = (1 << i) - noOfPagesToAllocate;
  167.       Uint32 retPageRef = allocPageRef + noOfPagesToAllocate;
  168.       returnCommonArea(retPageRef, retNo);
  169.       return;
  170.     }//if
  171.   }//for
  172. /* ---------------------------------------------------------------- */
  173. /*       PROPER AMOUNT OF PAGES WERE NOT FOUND. FIND AS MUCH AS     */
  174. /*       POSSIBLE.                                                  */
  175. /* ---------------------------------------------------------------- */
  176.   for (Uint32 j = firstListToCheck; (Uint32)~j; j--) {
  177.     ljam();
  178.     if (cfreepageList[j] != RNIL) {
  179.       ljam();
  180. /* ---------------------------------------------------------------- */
  181. /*       SOME AREA WAS FOUND, ALLOCATE ALL OF IT.                   */
  182. /* ---------------------------------------------------------------- */
  183.       allocPageRef = cfreepageList[j];
  184.       removeCommonArea(allocPageRef, j);
  185.       noOfPagesAllocated = 1 << j;
  186.       findFreeLeftNeighbours(allocPageRef, noOfPagesAllocated, 
  187.      noOfPagesToAllocate);
  188.       findFreeRightNeighbours(allocPageRef, noOfPagesAllocated, 
  189.       noOfPagesToAllocate);
  190.       return;
  191.     }//if
  192.   }//for
  193. /* ---------------------------------------------------------------- */
  194. /*       NO FREE AREA AT ALL EXISTED. RETURN ZERO PAGES             */
  195. /* ---------------------------------------------------------------- */
  196.   noOfPagesAllocated = 0;
  197.   return;
  198. }//allocConsPages()
  199. void Dbtup::returnCommonArea(Uint32 retPageRef, Uint32 retNo) 
  200. {
  201.   do {
  202.     ljam();
  203.     if (retNo == 0) {
  204.       ljam();
  205.       return;
  206.     }//if
  207.     Uint32 list = nextHigherTwoLog(retNo) - 1;
  208.     retNo -= (1 << list);
  209.     insertCommonArea(retPageRef, list);
  210.     retPageRef += (1 << list);
  211.   } while (1);
  212. }//Dbtup::returnCommonArea()
  213. void Dbtup::findFreeLeftNeighbours(Uint32& allocPageRef,
  214.                                    Uint32& noPagesAllocated,
  215.                                    Uint32  noOfPagesToAllocate)
  216. {
  217.   PagePtr pageFirstPtr, pageLastPtr;
  218.   Uint32 remainAllocate = noOfPagesToAllocate - noPagesAllocated;
  219.   while (allocPageRef > 0) {
  220.     ljam();
  221.     pageLastPtr.i = allocPageRef - 1;
  222.     ptrCheckGuard(pageLastPtr, cnoOfPage, page);
  223.     if (pageLastPtr.p->pageWord[ZPAGE_STATE_POS] != ZFREE_COMMON) {
  224.       ljam();
  225.       return;
  226.     } else {
  227.       ljam();
  228.       pageFirstPtr.i = pageLastPtr.p->pageWord[ZPAGE_FIRST_CLUST_POS];
  229.       ndbrequire(pageFirstPtr.i != RNIL);
  230.       Uint32 list = nextHigherTwoLog(pageLastPtr.i - pageFirstPtr.i);
  231.       removeCommonArea(pageFirstPtr.i, list);
  232.       Uint32 listSize = 1 << list;
  233.       if (listSize > remainAllocate) {
  234.         ljam();
  235.         Uint32 retNo = listSize - remainAllocate;
  236.         returnCommonArea(pageFirstPtr.i, retNo);
  237.         allocPageRef = pageFirstPtr.i + retNo;
  238.         noPagesAllocated = noOfPagesToAllocate;
  239.         return;
  240.       } else {
  241.         ljam();
  242.         allocPageRef = pageFirstPtr.i;
  243.         noPagesAllocated += listSize;
  244.         remainAllocate -= listSize;
  245.       }//if
  246.     }//if
  247.   }//while
  248. }//Dbtup::findFreeLeftNeighbours()
  249. void Dbtup::findFreeRightNeighbours(Uint32& allocPageRef,
  250.                                     Uint32& noPagesAllocated,
  251.                                     Uint32  noOfPagesToAllocate)
  252. {
  253.   PagePtr pageFirstPtr, pageLastPtr;
  254.   Uint32 remainAllocate = noOfPagesToAllocate - noPagesAllocated;
  255.   if (remainAllocate == 0) {
  256.     ljam();
  257.     return;
  258.   }//if
  259.   while ((allocPageRef + noPagesAllocated) < cnoOfPage) {
  260.     ljam();
  261.     pageFirstPtr.i = allocPageRef + noPagesAllocated;
  262.     ptrCheckGuard(pageFirstPtr, cnoOfPage, page);
  263.     if (pageFirstPtr.p->pageWord[ZPAGE_STATE_POS] != ZFREE_COMMON) {
  264.       ljam();
  265.       return;
  266.     } else {
  267.       ljam();
  268.       pageLastPtr.i = pageFirstPtr.p->pageWord[ZPAGE_LAST_CLUST_POS];
  269.       ndbrequire(pageLastPtr.i != RNIL);
  270.       Uint32 list = nextHigherTwoLog(pageLastPtr.i - pageFirstPtr.i);
  271.       removeCommonArea(pageFirstPtr.i, list);
  272.       Uint32 listSize = 1 << list;
  273.       if (listSize > remainAllocate) {
  274.         ljam();
  275.         Uint32 retPageRef = pageFirstPtr.i + remainAllocate;
  276.         Uint32 retNo = listSize - remainAllocate;
  277.         returnCommonArea(retPageRef, retNo);
  278.         noPagesAllocated += remainAllocate;
  279.         return;
  280.       } else {
  281.         ljam();
  282.         noPagesAllocated += listSize;
  283.         remainAllocate -= listSize;
  284.       }//if
  285.     }//if
  286.   }//while
  287. }//Dbtup::findFreeRightNeighbours()
  288. void Dbtup::insertCommonArea(Uint32 insPageRef, Uint32 insList) 
  289. {
  290.   cnoOfAllocatedPages -= (1 << insList);
  291.   PagePtr pageLastPtr, pageInsPtr;
  292.   pageInsPtr.i = insPageRef;
  293.   ptrCheckGuard(pageInsPtr, cnoOfPage, page);
  294.   ndbrequire(insList < 16);
  295.   pageLastPtr.i = (pageInsPtr.i + (1 << insList)) - 1;
  296.   pageInsPtr.p->pageWord[ZPAGE_NEXT_CLUST_POS] = cfreepageList[insList];
  297.   pageInsPtr.p->pageWord[ZPAGE_PREV_CLUST_POS] = RNIL;
  298.   pageInsPtr.p->pageWord[ZPAGE_LAST_CLUST_POS] = pageLastPtr.i;
  299.   cfreepageList[insList] = pageInsPtr.i;
  300.   ptrCheckGuard(pageLastPtr, cnoOfPage, page);
  301.   pageLastPtr.p->pageWord[ZPAGE_FIRST_CLUST_POS] = pageInsPtr.i;
  302.   pageLastPtr.p->pageWord[ZPAGE_NEXT_POS] = RNIL;
  303. }//Dbtup::insertCommonArea()
  304. void Dbtup::removeCommonArea(Uint32 remPageRef, Uint32 list) 
  305. {
  306.   cnoOfAllocatedPages += (1 << list);  
  307.   PagePtr pagePrevPtr, pageNextPtr, pageLastPtr, pageSearchPtr, remPagePtr;
  308.   remPagePtr.i = remPageRef;
  309.   ptrCheckGuard(remPagePtr, cnoOfPage, page);
  310.   ndbrequire(list < 16);
  311.   if (cfreepageList[list] == remPagePtr.i) {
  312.     ljam();
  313.     cfreepageList[list] = remPagePtr.p->pageWord[ZPAGE_NEXT_CLUST_POS];
  314.     pageNextPtr.i = cfreepageList[list];
  315.     if (pageNextPtr.i != RNIL) {
  316.       ljam();
  317.       ptrCheckGuard(pageNextPtr, cnoOfPage, page);
  318.       pageNextPtr.p->pageWord[ZPAGE_PREV_CLUST_POS] = RNIL;
  319.     }//if
  320.   } else {
  321.     pageSearchPtr.i = cfreepageList[list];
  322.     while (true) {
  323.       ljam();
  324.       ptrCheckGuard(pageSearchPtr, cnoOfPage, page);
  325.       pagePrevPtr = pageSearchPtr;
  326.       pageSearchPtr.i = pageSearchPtr.p->pageWord[ZPAGE_NEXT_CLUST_POS];
  327.       if (pageSearchPtr.i == remPagePtr.i) {
  328.         ljam();
  329.         break;
  330.       }//if
  331.     }//while
  332.     pageNextPtr.i = remPagePtr.p->pageWord[ZPAGE_NEXT_CLUST_POS];
  333.     pagePrevPtr.p->pageWord[ZPAGE_NEXT_CLUST_POS] = pageNextPtr.i;
  334.     if (pageNextPtr.i != RNIL) {
  335.       ljam();
  336.       ptrCheckGuard(pageNextPtr, cnoOfPage, page);
  337.       pageNextPtr.p->pageWord[ZPAGE_PREV_CLUST_POS] = pagePrevPtr.i;
  338.     }//if
  339.   }//if
  340.   remPagePtr.p->pageWord[ZPAGE_NEXT_CLUST_POS] = RNIL;
  341.   remPagePtr.p->pageWord[ZPAGE_LAST_CLUST_POS] = RNIL;
  342.   remPagePtr.p->pageWord[ZPAGE_PREV_CLUST_POS] = RNIL;
  343.   pageLastPtr.i = (remPagePtr.i + (1 << list)) - 1;
  344.   ptrCheckGuard(pageLastPtr, cnoOfPage, page);
  345.   pageLastPtr.p->pageWord[ZPAGE_FIRST_CLUST_POS] = RNIL;
  346. }//Dbtup::removeCommonArea()