00001 /* 00002 // $Id: //open/dev/fennel/segment/LinearDeviceSegment.cpp#11 $ 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/LinearDeviceSegment.h" 00026 #include "fennel/device/RandomAccessDevice.h" 00027 #include "fennel/cache/Cache.h" 00028 00029 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/segment/LinearDeviceSegment.cpp#11 $"); 00030 00031 LinearDeviceSegmentParams::LinearDeviceSegmentParams() 00032 { 00033 firstBlockId = NULL_BLOCK_ID; 00034 nPagesMin = 0; 00035 nPagesAllocated = 0; 00036 nPagesIncrement = 1; 00037 nPagesMax = MAXU; 00038 } 00039 00040 BlockNum LinearDeviceSegment::getAvailableDevicePages() const 00041 { 00042 return pDevice->getSizeInBytes() / getFullPageSize() - 00043 CompoundId::getBlockNum(firstBlockId); 00044 } 00045 00046 LinearDeviceSegment::LinearDeviceSegment( 00047 SharedCache cache, 00048 LinearDeviceSegmentParams const ¶ms) 00049 : Segment(cache), 00050 pDevice( 00051 cache->getDevice(CompoundId::getDeviceId(params.firstBlockId))) 00052 { 00053 firstBlockId = params.firstBlockId; 00054 nPagesMax = params.nPagesMax; 00055 nPagesAllocated = params.nPagesAllocated; 00056 nPagesIncrement = params.nPagesIncrement; 00057 nPagesExtended = 0; 00058 BlockNum nPagesActual = getAvailableDevicePages(); 00059 if (nPagesActual < params.nPagesMin) { 00060 pDevice->setSizeInBytes( 00061 pDevice->getSizeInBytes() + 00062 (params.nPagesMin - nPagesActual)*getFullPageSize()); 00063 nPagesActual = params.nPagesMin; 00064 } 00065 if (isMAXU(nPagesAllocated)) { 00066 nPagesAllocated = nPagesActual; 00067 } else { 00068 assert(nPagesAllocated <= nPagesActual); 00069 } 00070 } 00071 00072 LinearDeviceSegment::~LinearDeviceSegment() 00073 { 00074 } 00075 00076 BlockId LinearDeviceSegment::translatePageId(PageId pageId) 00077 { 00078 assert(isPageIdAllocated(pageId)); 00079 BlockId blockId = firstBlockId; 00080 CompoundId::setBlockNum( 00081 blockId, 00082 CompoundId::getBlockNum(firstBlockId) 00083 + getLinearBlockNum(pageId)); 00084 return blockId; 00085 } 00086 00087 PageId LinearDeviceSegment::translateBlockId(BlockId blockId) 00088 { 00089 return getLinearPageId( 00090 CompoundId::getBlockNum(blockId) 00091 - CompoundId::getBlockNum(firstBlockId)); 00092 } 00093 00094 BlockNum LinearDeviceSegment::getAllocatedSizeInPages() 00095 { 00096 return nPagesAllocated; 00097 } 00098 00099 BlockNum LinearDeviceSegment::getNumPagesOccupiedHighWater() 00100 { 00101 return getAllocatedSizeInPages(); 00102 } 00103 00104 BlockNum LinearDeviceSegment::getNumPagesExtended() 00105 { 00106 return nPagesExtended; 00107 } 00108 00109 PageId LinearDeviceSegment::allocatePageId(PageOwnerId) 00110 { 00111 // nothing to do with PageOwnerId 00112 00113 BlockNum newBlockNum = nPagesAllocated; 00114 00115 if (!ensureAllocatedSize(nPagesAllocated + 1)) { 00116 return NULL_PAGE_ID; 00117 } 00118 00119 return getLinearPageId(newBlockNum); 00120 } 00121 00122 void LinearDeviceSegment::deallocatePageRange( 00123 PageId startPageId,PageId endPageId) 00124 { 00125 if (endPageId != NULL_PAGE_ID) { 00126 // REVIEW: Technically, this should assert; instead, we let it slip so 00127 // that LinearDeviceSegments can be used as really stupid logs in 00128 // tests. Should probably fix the tests and tighten this up. 00129 return; 00130 } 00131 if (startPageId == NULL_PAGE_ID) { 00132 nPagesAllocated = 0; 00133 } else { 00134 nPagesAllocated = getLinearBlockNum(startPageId); 00135 } 00136 } 00137 00138 bool LinearDeviceSegment::isPageIdAllocated(PageId pageId) 00139 { 00140 return isLinearPageIdAllocated(pageId); 00141 } 00142 00143 PageId LinearDeviceSegment::getPageSuccessor(PageId pageId) 00144 { 00145 return getLinearPageSuccessor(pageId); 00146 } 00147 00148 void LinearDeviceSegment::setPageSuccessor(PageId pageId,PageId successorId) 00149 { 00150 setLinearPageSuccessor(pageId,successorId); 00151 } 00152 00153 Segment::AllocationOrder LinearDeviceSegment::getAllocationOrder() const 00154 { 00155 return LINEAR_ALLOCATION; 00156 } 00157 00158 DeviceId LinearDeviceSegment::getDeviceId() const 00159 { 00160 return CompoundId::getDeviceId(firstBlockId); 00161 } 00162 00163 bool LinearDeviceSegment::ensureAllocatedSize(BlockNum nPages) 00164 { 00165 if (nPages > nPagesMax) { 00166 return false; 00167 } 00168 if (nPages <= nPagesAllocated) { 00169 return true; 00170 } 00171 BlockNum nPagesAvailable = getAvailableDevicePages(); 00172 assert(nPagesAllocated <= nPagesAvailable); 00173 if (nPages > nPagesAvailable) { 00174 if (!nPagesIncrement) { 00175 return false; 00176 } 00177 BlockNum nNewPages = std::max(nPagesIncrement,nPages - nPagesAvailable); 00178 if (!isMAXU(nPagesMax) && (nPagesAvailable + nNewPages > nPagesMax)) { 00179 nNewPages = nPagesMax - nPagesAvailable; 00180 } 00181 assert(nNewPages); 00182 nPagesExtended += nNewPages; 00183 pDevice->setSizeInBytes( 00184 pDevice->getSizeInBytes() + nNewPages*getFullPageSize()); 00185 } 00186 nPagesAllocated = nPages; 00187 return true; 00188 } 00189 00190 void LinearDeviceSegment::delegatedCheckpoint( 00191 Segment &delegatingSegment, 00192 CheckpointType checkpointType) 00193 { 00194 Segment::delegatedCheckpoint(delegatingSegment,checkpointType); 00195 if (checkpointType != CHECKPOINT_DISCARD) { 00196 pDevice->flush(); 00197 } 00198 } 00199 00200 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/segment/LinearDeviceSegment.cpp#11 $"); 00201 00202 // End LinearDeviceSegment.cpp