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