SegPageEntryIterImpl.h

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/segment/SegPageEntryIterImpl.h#5 $
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_SegPageEntryIterImpl_Included
00025 #define Fennel_SegPageEntryIterImpl_Included
00026 
00027 #include "fennel/segment/SegPageEntryIter.h"
00028 #include "fennel/segment/SegPageEntryIterSource.h"
00029 
00030 FENNEL_BEGIN_NAMESPACE
00031 
00032 template <class EntryT>
00033 SegPageEntryIter<EntryT>::SegPageEntryIter()
00034 {
00035     init();
00036 }
00037 
00038 template <class EntryT>
00039 SegPageEntryIter<EntryT>::SegPageEntryIter(uint nEntriesInit)
00040     : entryQueue(nEntriesInit)
00041 {
00042     init();
00043 }
00044 
00045 template <class EntryT>
00046 void SegPageEntryIter<EntryT>::init()
00047 {
00048     pPrefetchSource = NULL;
00049 }
00050 
00051 template <class EntryT>
00052 void SegPageEntryIter<EntryT>::resize(uint nEntries)
00053 {
00054     entryQueue.resize(nEntries);
00055 }
00056 
00057 template <class EntryT>
00058 void SegPageEntryIter<EntryT>::setPrefetchSource(
00059     SegPageEntryIterSource<EntryT> &prefetchSource)
00060 {
00061     assert(entryQueue.size() > 0);
00062     pPrefetchSource = &prefetchSource;
00063     for (uint i = 0; i < entryQueue.size(); i++) {
00064         pPrefetchSource->initPrefetchEntry(entryQueue[i].second);
00065     }
00066 }
00067 
00068 template <class EntryT>
00069 void SegPageEntryIter<EntryT>::mapRange(
00070     SegmentAccessor const &segmentAccessorInit,
00071     PageId beginPageIdInit,
00072     PageId endPageIdInit)
00073 {
00074     assert(segmentAccessorInit.pSegment);
00075     assert(segmentAccessorInit.pCacheAccessor);
00076     assert(beginPageIdInit == NULL_PAGE_ID);
00077     segmentAccessor = segmentAccessorInit;
00078     endPageId = endPageIdInit;
00079     initPrefetchQueue();
00080     entryQueue.clear();
00081 
00082     // Pre-populate the queues
00083     prefetchPages(NULL_PAGE_ID, false);
00084 }
00085 
00086 template <class EntryT>
00087 void SegPageEntryIter<EntryT>::prefetchPages(PageId prevPageId, bool oneIter)
00088 {
00089     if (!entryQueue.empty()) {
00090         prevPageId = entryQueue.reference_back().first;
00091     }
00092 
00093     // Continue retrieving pageIds while we have available space in
00094     // the prefetch queue
00095     while (nFreePageSlots != 0 || oneIter) {
00096         // But make sure we have space in the entryQueue
00097         if (!entryQueue.spaceAvailable()) {
00098             break;
00099         }
00100 
00101         std::pair<PageId, EntryT> &entryPair =
00102             entryQueue[entryQueue.getLastPos() + 1];
00103         bool found;
00104         entryPair.first =
00105             pPrefetchSource->getNextPageForPrefetch(entryPair.second, found);
00106         if (!found) {
00107             break;
00108         }
00109         entryQueue.push_back(entryPair);
00110 
00111         if (entryPair.first == endPageId) {
00112             atEnd = 1;
00113         }
00114 
00115         if (atEnd || entryPair.first != prevPageId) {
00116             prefetchPage(entryPair.first);
00117         }
00118 
00119         if (atEnd || oneIter) {
00120             break;
00121         }
00122 
00123         prevPageId = entryPair.first;
00124     }
00125 }
00126 
00127 template <class EntryT>
00128 void SegPageEntryIter<EntryT>::operator ++ ()
00129 {
00130     assert(!isSingular());
00131     std::pair<PageId, EntryT> &entryPair = entryQueue.reference_front();
00132     PageId currPageId = entryPair.first;
00133     assert(currPageId != endPageId);
00134 
00135     entryQueue.pop_front();
00136 
00137     // If the queue is empty, we have to try and pre-fetch some more entries.
00138     // Worst case, we'll hit the ending page.  The queueSize == 1 case needs
00139     // special handling because:
00140     // 1) There are currently no free slots in the prefetch queue.  The one
00141     //    slot is occupied by the last page pre-fetched.
00142     // 2) We can only replace that slot with a new page if it's different
00143     //    from that last pre-fetched page.
00144     // Therefore, we can't assume that the current page will always be
00145     // replaced by a new one.
00146     if (entryQueue.empty()) {
00147         prefetchPages(currPageId, (queueSize == 1));
00148     }
00149 
00150     PageId nextPageId = entryQueue.reference_front().first;
00151     // Bump up the prefetch queue only if we've moved on to a new page
00152     if (nextPageId != currPageId) {
00153         iFetch = (iFetch + 1) % queueSize;
00154         nFreePageSlots++;
00155     }
00156 
00157     // Re-populate the queues if there's available space
00158     if (!atEnd) {
00159         prefetchPages(NULL_PAGE_ID, false);
00160     }
00161 }
00162 
00163 FENNEL_END_NAMESPACE
00164 
00165 #endif
00166 
00167 // End SegPageEntryIterImpl.h

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