superpool.cpp

来自「MySQL数据库开发源码 值得一看哦」· C++ 代码 · 共 443 行

CPP
443
字号
/* Copyright (C) 2003 MySQL AB   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <ndb_global.h>#include "SuperPool.hpp"// SuperPoolSuperPool::SuperPool(Uint32 pageSize, Uint32 pageBits) :  m_pageSize(SP_ALIGN_SIZE(pageSize, SP_ALIGN)),  m_pageBits(pageBits),  m_memRoot(0),  m_pageEnt(0),  m_typeCheck(0),  m_typeSeq(0),  m_pageList(),  m_totalSize(0),  m_initSize(0),  m_incrSize(0),  m_maxSize(0){  assert(5 <= pageBits <= 30);}boolSuperPool::init(){  return true;}SuperPool::~SuperPool(){}SuperPool::PageEnt::PageEnt() :  m_pageType(0),  m_freeRecI(RNIL),  m_useCount(0),  m_nextPageI(RNIL),  m_prevPageI(RNIL){}SuperPool::PageList::PageList() :  m_headPageI(RNIL),  m_tailPageI(RNIL),  m_pageCount(0){}SuperPool::PageList::PageList(PtrI pageI) :  m_headPageI(pageI),  m_tailPageI(pageI),  m_pageCount(1){}SuperPool::RecInfo::RecInfo(Uint32 recType, Uint32 recSize) :  m_recType(recType),  m_recSize(recSize),  m_maxUseCount(0),  m_currPageI(RNIL),  m_currFreeRecI(RNIL),  m_currUseCount(0),  m_totalUseCount(0),  m_totalRecCount(0),  m_freeList(),  m_activeList(),  m_fullList(){}SuperPool::PtrISuperPool::getPageI(void* pageP){  const Uint32 pageSize = m_pageSize;  const Uint32 pageBits = m_pageBits;  const Uint32 recBits = 32 - pageBits;  void* const memRoot = m_memRoot;  assert(pageP == SP_ALIGN_PTR(pageP, memRoot, pageSize));  my_ptrdiff_t ipL = ((Uint8*)pageP - (Uint8*)memRoot) / pageSize;  Int32 ip = (Int32)ipL;  Int32 lim = 1 << (pageBits - 1);  assert(ip == ipL && -lim <= ip && ip < lim && ip != -1);  PtrI pageI = ip << recBits;  assert(pageP == getPageP(pageI));  return pageI;}voidSuperPool::movePages(PageList& pl1, PageList& pl2){  const Uint32 recBits = 32 - m_pageBits;  if (pl1.m_pageCount != 0) {    if (pl2.m_pageCount != 0) {      PtrI pageI1 = pl1.m_tailPageI;      PtrI pageI2 = pl2.m_headPageI;      PageEnt& pe1 = getPageEnt(pageI1);      PageEnt& pe2 = getPageEnt(pageI2);      pe1.m_nextPageI = pageI2;      pe2.m_prevPageI = pageI1;      pl1.m_pageCount += pl2.m_pageCount;    }  } else {    pl1 = pl2;  }  pl2.m_headPageI = pl2.m_tailPageI = RNIL;  pl2.m_pageCount = 0;}voidSuperPool::addHeadPage(PageList& pl, PtrI pageI){  PageList pl2(pageI);  movePages(pl2, pl);  pl = pl2;}voidSuperPool::addTailPage(PageList& pl, PtrI pageI){  PageList pl2(pageI);  movePages(pl, pl2);}voidSuperPool::removePage(PageList& pl, PtrI pageI){  PageEnt& pe = getPageEnt(pageI);  PtrI pageI1 = pe.m_prevPageI;  PtrI pageI2 = pe.m_nextPageI;  if (pageI1 != RNIL) {    PageEnt& pe1 = getPageEnt(pageI1);    pe1.m_nextPageI = pageI2;    if (pageI2 != RNIL) {      PageEnt& pe2 = getPageEnt(pageI2);      pe2.m_prevPageI = pageI1;    } else {      pl.m_tailPageI = pageI1;    }  } else {    if (pageI2 != RNIL) {      PageEnt& pe2 = getPageEnt(pageI2);      pe2.m_prevPageI = pageI1;      pl.m_headPageI = pageI2;    } else {      pl.m_headPageI = pl.m_tailPageI = RNIL;    }  }  pe.m_prevPageI = pe.m_nextPageI = RNIL;  assert(pl.m_pageCount != 0);  pl.m_pageCount--;}voidSuperPool::setCurrPage(RecInfo& ri, PtrI newPageI){  PtrI oldPageI = ri.m_currPageI;  if (oldPageI != RNIL) {    // copy from cache    PageEnt& pe = getPageEnt(oldPageI);    pe.m_freeRecI = ri.m_currFreeRecI;    pe.m_useCount = ri.m_currUseCount;    // add to right list according to "pp2" policy    if (pe.m_useCount == 0) {      pe.m_pageType = 0;      addHeadPage(m_pageList, oldPageI);      ri.m_totalRecCount -= ri.m_maxUseCount;    } else if (pe.m_useCount < ri.m_maxUseCount) {      addHeadPage(ri.m_activeList, oldPageI);    } else {      addHeadPage(ri.m_fullList, oldPageI);    }  }  if (newPageI != RNIL) {    PageEnt& pe = getPageEnt(newPageI);    // copy to cache    ri.m_currPageI = newPageI;    ri.m_currFreeRecI = pe.m_freeRecI;    ri.m_currUseCount = pe.m_useCount;    // remove from right list    if (pe.m_useCount == 0) {      removePage(ri.m_freeList, newPageI);    } else if (pe.m_useCount < ri.m_maxUseCount) {      removePage(ri.m_activeList, newPageI);    } else {      removePage(ri.m_fullList, newPageI);    }  } else {    ri.m_currPageI = RNIL;    ri.m_currFreeRecI = RNIL;    ri.m_currUseCount = 0;  }}boolSuperPool::getAvailPage(RecInfo& ri){  PtrI pageI;  if ((pageI = ri.m_activeList.m_headPageI) != RNIL ||      (pageI = ri.m_freeList.m_headPageI) != RNIL ||      (pageI = getFreePage(ri)) != RNIL) {    setCurrPage(ri, pageI);    return true;  }  return false;}SuperPool::PtrISuperPool::getFreePage(RecInfo& ri){  PtrI pageI;  if (m_pageList.m_pageCount != 0) {    pageI = m_pageList.m_headPageI;    removePage(m_pageList, pageI);  } else {    pageI = getNewPage();    if (pageI == RNIL)      return RNIL;  }  void* pageP = getPageP(pageI);  // set up free record list  Uint32 maxUseCount = ri.m_maxUseCount;  Uint32 recSize = ri.m_recSize;  void* recP = (Uint8*)pageP;  Uint32 irNext = 1;  while (irNext < maxUseCount) {    *(Uint32*)recP = pageI | irNext;    recP = (Uint8*)recP + recSize;    irNext++;  }  *(Uint32*)recP = RNIL;  // add to total record count  ri.m_totalRecCount += maxUseCount;  // set up new page entry  PageEnt& pe = getPageEnt(pageI);  new (&pe) PageEnt();  pe.m_pageType = ri.m_recType;  pe.m_freeRecI = pageI | 0;  pe.m_useCount = 0;  // set type check bits  setCheckBits(pageI, ri.m_recType);  // add to record pool free list  addHeadPage(ri.m_freeList, pageI);  return pageI;}voidSuperPool::setSizes(size_t initSize, size_t incrSize, size_t maxSize){  const Uint32 pageSize = m_pageSize;  m_initSize = SP_ALIGN_SIZE(initSize, pageSize);  m_incrSize = SP_ALIGN_SIZE(incrSize, pageSize);  m_maxSize = SP_ALIGN_SIZE(maxSize, pageSize);}voidSuperPool::verify(RecInfo& ri){  PageList* plList[3] = { &ri.m_freeList, &ri.m_activeList, &ri.m_fullList };  for (int i = 0; i < 3; i++) {    PageList& pl = *plList[i];    unsigned count = 0;    PtrI pageI = pl.m_headPageI;    while (pageI != RNIL) {      PageEnt& pe = getPageEnt(pageI);      PtrI pageI1 = pe.m_prevPageI;      PtrI pageI2 = pe.m_nextPageI;      if (count == 0) {        assert(pageI1 == RNIL);      } else {        assert(pageI1 != RNIL);        PageEnt& pe1 = getPageEnt(pageI1);        assert(pe1.m_nextPageI == pageI);        if (pageI2 != RNIL) {          PageEnt& pe2 = getPageEnt(pageI2);          assert(pe2.m_prevPageI == pageI);        }      }      pageI = pageI2;      count++;    }    assert(pl.m_pageCount == count);  }}// HeapPoolHeapPool::HeapPool(Uint32 pageSize, Uint32 pageBits) :  SuperPool(pageSize, pageBits),  m_areaHead(),  m_currArea(&m_areaHead),  m_lastArea(&m_areaHead),  m_mallocPart(4){}boolHeapPool::init(){  const Uint32 pageBits = m_pageBits;  if (! SuperPool::init())    return false;;  // allocate page entry array  Uint32 peBytes = (1 << pageBits) * sizeof(PageEnt);  m_pageEnt = static_cast<PageEnt*>(malloc(peBytes));  if (m_pageEnt == 0)    return false;  memset(m_pageEnt, 0, peBytes);  // allocate type check array  Uint32 tcWords = 1 << (pageBits - (5 - SP_CHECK_LOG2));  m_typeCheck = static_cast<Uint32*>(malloc(tcWords << 2));  if (m_typeCheck == 0)    return false;  memset(m_typeCheck, 0, tcWords << 2);  // allocate initial data  assert(m_totalSize == 0);  if (! allocMoreData(m_initSize))    return false;  return true;}HeapPool::~HeapPool(){  free(m_pageEnt);  free(m_typeCheck);  Area* ap;  while ((ap = m_areaHead.m_nextArea) != 0) {    m_areaHead.m_nextArea = ap->m_nextArea;    free(ap->m_memory);    free(ap);  }}HeapPool::Area::Area() :  m_nextArea(0),  m_firstPageI(RNIL),  m_currPage(0),  m_numPages(0),  m_memory(0){}SuperPool::PtrIHeapPool::getNewPage(){  const Uint32 pageSize = m_pageSize;  const Uint32 pageBits = m_pageBits;  const Uint32 recBits= 32 - pageBits;  Area* ap = m_currArea;  if (ap->m_currPage == ap->m_numPages) {    // area is used up    if (ap->m_nextArea == 0) {      // todo dynamic increase      assert(m_incrSize == 0);      return RNIL;    }    ap = m_currArea = ap->m_nextArea;  }  assert(ap->m_currPage < ap->m_numPages);  PtrI pageI = ap->m_firstPageI;  Int32 ip = (Int32)pageI >> recBits;  ip += ap->m_currPage;  pageI = ip << recBits;  ap->m_currPage++;  return pageI;}boolHeapPool::allocMoreData(size_t size){  const Uint32 pageSize = m_pageSize;  const Uint32 pageBits = m_pageBits;  const Uint32 recBits = 32 - pageBits;  const Uint32 incrSize = m_incrSize;  const Uint32 incrPages = incrSize / pageSize;  const Uint32 mallocPart = m_mallocPart;  size = SP_ALIGN_SIZE(size, pageSize);  if (incrSize != 0)    size = SP_ALIGN_SIZE(size, incrSize);  Uint32 needPages = size / pageSize;  while (needPages != 0) {    Uint32 wantPages = needPages;    if (incrPages != 0 && wantPages > incrPages)      wantPages = incrPages;    Uint32 tryPages = 0;    void* p1 = 0;    for (Uint32 i = mallocPart; i > 0 && p1 == 0; i--) {      // one page is usually wasted due to alignment to memory root      tryPages = ((wantPages + 1) * i) / mallocPart;      if (tryPages < 2)        break;      p1 = malloc(pageSize * tryPages);    }    if (p1 == 0)      return false;    if (m_memRoot == 0) {      // set memory root at first "big" alloc      // assume malloc header makes later ip = -1 impossible      m_memRoot = p1;    }    void* p2 = SP_ALIGN_PTR(p1, m_memRoot, pageSize);    Uint32 numPages = tryPages - (p1 != p2);    my_ptrdiff_t ipL = ((Uint8*)p2 - (Uint8*)m_memRoot) / pageSize;    Int32 ip = (Int32)ipL;    Int32 lim = 1 << (pageBits - 1);    if (! (ip == ipL && -lim <= ip && ip + numPages < lim)) {      free(p1);      return false;    }    assert(ip != -1);    PtrI pageI = ip << recBits;    needPages = (needPages >= numPages ? needPages - numPages : 0);    m_totalSize += numPages * pageSize;    // allocate new area    Area* ap = static_cast<Area*>(malloc(sizeof(Area)));    if (ap == 0) {      free(p1);      return false;    }    new (ap) Area();    ap->m_firstPageI = pageI;    ap->m_numPages = numPages;    ap->m_memory = p1;    m_lastArea->m_nextArea = ap;    m_lastArea = ap;  }  return true;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?