CircularSegment.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/segment/CircularSegment.cpp#8 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2005-2009 SQLstream, Inc.
00006 // Copyright (C) 2005-2009 LucidEra, Inc.
00007 // Portions Copyright (C) 1999-2009 John V. Sichi
00008 //
00009 // This program is free software; you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by the Free
00011 // Software Foundation; either version 2 of the License, or (at your option)
00012 // any later version approved by The Eigenbase Project.
00013 //
00014 // This program is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/segment/CircularSegment.h"
00026 #include "fennel/segment/CheckpointProvider.h"
00027 
00028 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/segment/CircularSegment.cpp#8 $");
00029 
00030 CircularSegment::CircularSegment(
00031     SharedSegment pDelegateSegment,
00032     SharedCheckpointProvider pCheckpointProviderInit,
00033     PageId oldestPageId,
00034     PageId newestPageId)
00035     : DelegatingSegment(pDelegateSegment),
00036       pCheckpointProvider(pCheckpointProviderInit)
00037 {
00038     assert(pDelegateSegment->getAllocationOrder() == LINEAR_ALLOCATION);
00039     nPages = DelegatingSegment::getAllocatedSizeInPages();
00040     if (oldestPageId == NULL_PAGE_ID) {
00041         assert(newestPageId == NULL_PAGE_ID);
00042         oldestPageNum = 0;
00043         nextPageNum = 0;
00044     } else {
00045         oldestPageNum = getLinearBlockNum(oldestPageId);
00046         if (newestPageId != NULL_PAGE_ID) {
00047             nextPageNum = getLinearBlockNum(newestPageId) + 1;
00048             assert(oldestPageNum < nextPageNum);
00049             assert((nextPageNum - oldestPageNum) <= nPages);
00050         } else {
00051             nextPageNum = oldestPageNum + nPages;
00052         }
00053     }
00054 
00055     // REVIEW:  parameterize this
00056     checkpointThreshold1 = nPages / 3;
00057     checkpointThreshold2 = 2*checkpointThreshold1;
00058 }
00059 
00060 CircularSegment::~CircularSegment()
00061 {
00062 }
00063 
00064 BlockNum CircularSegment::getAllocatedSizeInPages()
00065 {
00066     return (nextPageNum - oldestPageNum);
00067 }
00068 
00069 BlockId CircularSegment::translatePageId(PageId pageId)
00070 {
00071     assert(isPageIdAllocated(pageId));
00072     BlockNum pageNum = getLinearBlockNum(pageId);
00073     BlockNum blockNum = pageNum % nPages;
00074     return DelegatingSegment::translatePageId(
00075         Segment::getLinearPageId(blockNum));
00076 }
00077 
00078 PageId CircularSegment::translateBlockId(BlockId blockId)
00079 {
00080     assert(nextPageNum > oldestPageNum);
00081     PageId pageId = DelegatingSegment::translateBlockId(blockId);
00082     BlockNum blockNum = getLinearBlockNum(pageId);
00083     BlockNum nBlocks = nPages;
00084     assert(blockNum < nBlocks);
00085     BlockNum oldestBlockNum = oldestPageNum % nBlocks;
00086     BlockNum nextBlockNum = nextPageNum % nBlocks;
00087     BlockNum pageNum;
00088     if (nextBlockNum > oldestBlockNum) {
00089         assert(blockNum >= oldestBlockNum);
00090         assert(blockNum < nextBlockNum);
00091         pageNum = nextPageNum - (nextBlockNum - blockNum);
00092     } else {
00093         if (blockNum < nextBlockNum) {
00094             pageNum = nextPageNum - (nextBlockNum - blockNum);
00095         } else {
00096             assert(blockNum >= oldestBlockNum);
00097             pageNum = oldestPageNum + (blockNum - oldestBlockNum);
00098         }
00099     }
00100     return Segment::getLinearPageId(pageNum);
00101 }
00102 
00103 PageId CircularSegment::allocatePageId(PageOwnerId)
00104 {
00105     uint nAllocated = getAllocatedSizeInPages();
00106 
00107     // all full
00108     if (nAllocated >= nPages) {
00109         return NULL_PAGE_ID;
00110     }
00111 
00112     if ((nAllocated == checkpointThreshold1)
00113         || (nAllocated == checkpointThreshold2))
00114     {
00115         // getting low, try a checkpoint
00116         if (pCheckpointProvider) {
00117             pCheckpointProvider->requestCheckpoint(CHECKPOINT_FLUSH_FUZZY);
00118         }
00119     }
00120 
00121     // This wraparound should never be hit in practice.  If it is, a
00122     // restart which truncates logs should fix it.
00123     assert(!isMAXU(nextPageNum + 1));
00124 
00125     PageId pageId = Segment::getLinearPageId(nextPageNum);
00126     ++nextPageNum;
00127     return pageId;
00128 }
00129 
00130 void CircularSegment::deallocatePageRange(PageId startPageId,PageId endPageId)
00131 {
00132     assert(startPageId == NULL_PAGE_ID);
00133     if (endPageId == NULL_PAGE_ID) {
00134         oldestPageNum = nextPageNum;
00135     } else {
00136         assert(isPageIdAllocated(endPageId));
00137         BlockNum pageNum = getLinearBlockNum(endPageId);
00138         oldestPageNum = pageNum + 1;
00139     }
00140 }
00141 
00142 bool CircularSegment::isPageIdAllocated(PageId pageId)
00143 {
00144     BlockNum pageNum = getLinearBlockNum(pageId);
00145     return (pageNum >= oldestPageNum) && (pageNum < nextPageNum);
00146 }
00147 
00148 Segment::AllocationOrder CircularSegment::getAllocationOrder() const
00149 {
00150     return LINEAR_ALLOCATION;
00151 }
00152 
00153 PageId CircularSegment::getPageSuccessor(PageId pageId)
00154 {
00155     // Don't delegate this!
00156     return getLinearPageSuccessor(pageId);
00157 }
00158 
00159 void CircularSegment::setPageSuccessor(PageId pageId,PageId successorId)
00160 {
00161     // Don't delegate this!
00162     setLinearPageSuccessor(pageId,successorId);
00163 }
00164 
00165 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/segment/CircularSegment.cpp#8 $");
00166 
00167 // End CircularSegment.cpp

Generated on Mon Jun 22 04:00:20 2009 for Fennel by  doxygen 1.5.1