00001 /* 00002 // $Id: //open/dev/fennel/segment/VersionedRandomAllocationSegmentImpl.h#9 $ 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 #ifndef Fennel_VersionedRandomAllocationSegmentImpl_Included 00025 #define Fennel_VersionedRandomAllocationSegmentImpl_Included 00026 00027 #include "fennel/segment/VersionedRandomAllocationSegment.h" 00028 #include "fennel/segment/SegPageLock.h" 00029 00030 #include <boost/shared_ptr.hpp> 00031 00032 FENNEL_BEGIN_NAMESPACE 00033 00034 // NOTE: read comments on struct StoredNode before modifying 00035 // the structs below 00036 00041 struct FENNEL_SEGMENT_EXPORT VersionedExtentAllocationNode 00042 : public StoredNode 00043 { 00044 static const MagicNumber MAGIC_NUMBER = 0xbfc76ee9882a1be6LL; 00045 00046 VersionedPageEntry &getPageEntry(uint i) 00047 { 00048 return reinterpret_cast<VersionedPageEntry *>(this+1)[i]; 00049 } 00050 00051 VersionedPageEntry const &getPageEntry(uint i) const 00052 { 00053 return reinterpret_cast<VersionedPageEntry const *>(this+1)[i]; 00054 } 00055 }; 00056 00057 typedef SegNodeLock<VersionedExtentAllocationNode> VersionedExtentAllocLock; 00058 00063 struct FENNEL_SEGMENT_EXPORT ModifiedAllocationNode 00064 { 00068 bool isSegAllocNode; 00069 00073 uint updateCount; 00074 00078 PageId tempPageId; 00079 }; 00080 00081 template <class AllocationLockT> 00082 PageId VersionedRandomAllocationSegment::getTempAllocNodePage( 00083 PageId origNodePageId, 00084 bool isSegAllocNode) 00085 { 00086 SXMutexExclusiveGuard mapGuard(mapMutex); 00087 00088 PageId tempNodePageId; 00089 SharedModifiedAllocationNode pModAllocNode; 00090 00091 // If we've already previously modified the allocation node, it 00092 // will be in our map. Otherwise, this is the first time we're modifying 00093 // the node. In that case, allocate a new page in our temp segment 00094 // corresponding to the node. 00095 NodeMapConstIter iter = allocationNodeMap.find(origNodePageId); 00096 if (iter == allocationNodeMap.end()) { 00097 // Allocate a new page and copy the contents of the original page on to 00098 // the new one. 00099 SegmentAccessor tempAccessor(pTempSegment, pCache); 00100 AllocationLockT tempAllocLock(tempAccessor); 00101 tempNodePageId = tempAllocLock.allocatePage(); 00102 00103 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00104 AllocationLockT allocLock(selfAccessor); 00105 allocLock.lockShared(origNodePageId); 00106 00107 memcpy( 00108 tempAllocLock.getPage().getWritableData(), 00109 allocLock.getPage().getReadableData(), 00110 pTempSegment->getUsablePageSize()); 00111 00112 // Allocate a new map entry 00113 pModAllocNode = 00114 SharedModifiedAllocationNode(new ModifiedAllocationNode()); 00115 pModAllocNode->tempPageId = tempNodePageId; 00116 pModAllocNode->updateCount = 0; 00117 pModAllocNode->isSegAllocNode = isSegAllocNode; 00118 } else { 00119 pModAllocNode = iter->second; 00120 tempNodePageId = pModAllocNode->tempPageId; 00121 } 00122 00123 // Update the map 00124 pModAllocNode->updateCount++; 00125 00126 if (iter == allocationNodeMap.end()) { 00127 allocationNodeMap.insert( 00128 ModifiedAllocationNodeMap::value_type( 00129 origNodePageId, 00130 pModAllocNode)); 00131 } 00132 00133 return tempNodePageId; 00134 } 00135 00136 inline PageOwnerId VersionedRandomAllocationSegment::makeDeallocatedPageOwnerId( 00137 TxnId txnId) 00138 { 00139 assert(VALID_PAGE_OWNER_ID(txnId)); 00140 return PageOwnerId(DEALLOCATED_PAGE_OWNER_ID_MASK | opaqueToInt(txnId)); 00141 } 00142 00143 inline bool VersionedRandomAllocationSegment::isDeallocatedPageOwnerId( 00144 PageOwnerId pageOwnerId) 00145 { 00146 return 00147 (pageOwnerId != ANON_PAGE_OWNER_ID && 00148 (opaqueToInt(pageOwnerId) & DEALLOCATED_PAGE_OWNER_ID_MASK)); 00149 } 00150 00151 inline TxnId VersionedRandomAllocationSegment::getDeallocatedTxnId( 00152 PageOwnerId pageOwnerId) 00153 { 00154 assert(isDeallocatedPageOwnerId(pageOwnerId)); 00155 return TxnId(opaqueToInt(pageOwnerId) & ~DEALLOCATED_PAGE_OWNER_ID_MASK); 00156 } 00157 00158 FENNEL_END_NAMESPACE 00159 00160 #endif 00161 00162 // End VersionedRandomAllocationSegmentImpl.h