00001 /* 00002 // $Id: //open/dev/fennel/lucidera/bitmap/LbmUnionWorkspace.cpp#7 $ 00003 // Fennel is a library of data storage and processing components. 00004 // Copyright (C) 2005-2009 LucidEra, Inc. 00005 // Copyright (C) 2005-2009 The Eigenbase Project 00006 // 00007 // This program is free software; you can redistribute it and/or modify it 00008 // under the terms of the GNU General Public License as published by the Free 00009 // Software Foundation; either version 2 of the License, or (at your option) 00010 // any later version approved by The Eigenbase Project. 00011 // 00012 // This program is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with this program; if not, write to the Free Software 00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 */ 00021 00022 #include "fennel/common/CommonPreamble.h" 00023 #include "fennel/lucidera/bitmap/LbmUnionWorkspace.h" 00024 00025 #include "boost/format.hpp" 00026 00027 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/lucidera/bitmap/LbmUnionWorkspace.cpp#7 $"); 00028 00029 void LbmUnionWorkspace::init(SharedByteBuffer pBuffer, uint maxSegmentSize) 00030 { 00031 mergeArea.init(pBuffer); 00032 this->maxSegmentSize = maxSegmentSize; 00033 reset(); 00034 } 00035 00036 void LbmUnionWorkspace::reset() 00037 { 00038 mergeArea.reset(); 00039 segment.reset(); 00040 limited = true; 00041 productionLimitByte = (LbmByteNumber) 0; 00042 } 00043 00044 void LbmUnionWorkspace::advanceToSrid(LcsRid requestedSrid) 00045 { 00046 advanceToByteNum(ridToByteNumber(requestedSrid)); 00047 } 00048 00049 void LbmUnionWorkspace::advanceToByteNum(LbmByteNumber requestedByteNum) 00050 { 00051 if (opaqueToInt(requestedByteNum) > mergeArea.getStart()) { 00052 mergeArea.advance(opaqueToInt(requestedByteNum)); 00053 } 00054 } 00055 00056 void LbmUnionWorkspace::advancePastSegment() 00057 { 00058 LbmByteNumber endByteNum = segment.byteNum + segment.len; 00059 advanceToByteNum(endByteNum); 00060 } 00061 00062 void LbmUnionWorkspace::setProductionLimit(LcsRid productionLimitRid) 00063 { 00064 productionLimitByte = ridToByteNumber(productionLimitRid); 00065 limited = true; 00066 } 00067 00068 void LbmUnionWorkspace::removeLimit() 00069 { 00070 limited = false; 00071 } 00072 00073 bool LbmUnionWorkspace::isEmpty() const 00074 { 00075 LbmByteNumberPrimitive i; 00076 for (i = mergeArea.getStart(); i < mergeArea.getEnd(); i++) { 00077 if (mergeArea.getByte(i) != 0) { 00078 return false; 00079 } 00080 } 00081 return true; 00082 } 00083 00084 bool LbmUnionWorkspace::canProduce() 00085 { 00086 return (! getSegment().isNull()); 00087 } 00088 00089 const LbmByteSegment &LbmUnionWorkspace::getSegment() 00090 { 00091 // limit for the beginning of a segment; we don't begin a segment 00092 // unless it has had time to mature (grow to maximum size) 00093 LbmByteNumberPrimitive startLimit; 00094 00095 // limit for reading; we can read to the production limit, but not 00096 // past the end 00097 LbmByteNumberPrimitive readLimit; 00098 00099 // if production limit is past end of current data, then it can all 00100 // be written out due to the gap in data 00101 LbmByteNumberPrimitive productionLimit = opaqueToInt(productionLimitByte); 00102 if (!limited || (productionLimit > mergeArea.getEnd())) { 00103 startLimit = readLimit = mergeArea.getEnd(); 00104 } else { 00105 readLimit = productionLimit; 00106 startLimit = (productionLimit > maxSegmentSize) 00107 ? (productionLimit - maxSegmentSize) : 0; 00108 } 00109 00110 // begin with a null segment 00111 segment.reset(); 00112 00113 // skip past whitespace 00114 LbmByteNumberPrimitive i = mergeArea.getStart(); 00115 while (i < readLimit && mergeArea.getByte(i) == 0) { 00116 i++; 00117 } 00118 mergeArea.advance(i); 00119 LbmByteNumberPrimitive start = i; 00120 00121 if (start > startLimit) { 00122 return segment; 00123 } 00124 00125 // find length of segment (only use the contiguous part) 00126 uint len = 0; 00127 while (i < readLimit && mergeArea.getByte(i) != 0) { 00128 i++; 00129 len++; 00130 if (len == maxSegmentSize) { 00131 break; 00132 } 00133 } 00134 uint contigLen; 00135 PBuffer mem = mergeArea.getMem(start, contigLen); 00136 len = std::min(len, contigLen); 00137 00138 if (len > 0) { 00139 segment.byteNum = LbmByteNumber(start); 00140 segment.byteSeg = mem; 00141 segment.len = len; 00142 } 00143 return segment; 00144 } 00145 00146 bool LbmUnionWorkspace::addSegment(const LbmByteSegment &segmentIn) 00147 { 00148 LbmByteSegment segment = segmentIn; 00149 00150 // return false if segment cannot fit into merge area 00151 if (opaqueToInt(segment.getEnd()) > mergeArea.getLimit()) { 00152 return false; 00153 } 00154 00155 // return true if merge area is already advanced beyond segment 00156 if (opaqueToInt(segment.getEnd()) < mergeArea.getStart()) { 00157 return true; 00158 } 00159 00160 segment.advanceToByteNum(LbmByteNumber(mergeArea.getStart())); 00161 if (! segment.isNull()) { 00162 LbmByteNumberPrimitive next = opaqueToInt(segment.byteNum); 00163 LbmByteNumberPrimitive last = next + segment.len; 00164 PBuffer read = segment.byteSeg; 00165 while (next < last) { 00166 mergeArea.mergeByte(next++, *read--); 00167 } 00168 } 00169 return true; 00170 } 00171 00172 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/lucidera/bitmap/LbmUnionWorkspace.cpp#7 $"); 00173 00174 // End LbmUnionWorkspace.cpp