00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/btree/BTreeBuildLevel.h"
00026 #include "fennel/btree/BTreeNodeAccessor.h"
00027 #include "fennel/btree/BTreeAccessBaseImpl.h"
00028 #include "fennel/segment/SegInputStream.h"
00029 #include "fennel/segment/SegOutputStream.h"
00030
00031 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/btree/BTreeBuildLevel.cpp#10 $");
00032
00033 BTreeBuildLevel::BTreeBuildLevel(
00034 BTreeBuilder &builderInit,
00035 BTreeNodeAccessor &nodeAccessorInit)
00036 : builder(builderInit), nodeAccessor(nodeAccessorInit)
00037 {
00038 iLevel = 0;
00039 nEntriesTotal = 0;
00040 cbReserved = 0;
00041 iNode = 0;
00042 nEntriesProcessed = 0;
00043 nEntriesPerNode = 0;
00044 pageLock.accessSegment(builder.treeDescriptor.segmentAccessor);
00045 }
00046
00047 BTreeBuildLevel::~BTreeBuildLevel()
00048 {
00049 }
00050
00051 bool BTreeBuildLevel::isFinished() const
00052 {
00053 return (pageLock.getNodeForRead().nEntries == nEntriesPerNode)
00054 && (nEntriesProcessed == nEntriesTotal);
00055 }
00056
00057 void BTreeBuildLevel::processInput(ByteInputStream &sortedInputStream)
00058 {
00059 BTreeNode *pNode = &(pageLock.getNodeForWrite());
00060
00061 for (;;) {
00062
00063 uint cbActual;
00064 PConstBuffer pCurrentTupleBuf =
00065 sortedInputStream.getReadPointer(1,&cbActual);
00066 if (!pCurrentTupleBuf) {
00067 break;
00068 }
00069 if (nEntriesTotal) {
00070 assert(nEntriesProcessed < nEntriesTotal);
00071 }
00072 nodeAccessor.tupleAccessor.setCurrentTupleBuf(pCurrentTupleBuf);
00073 uint cbTuple = nodeAccessor.tupleAccessor.getCurrentByteCount();
00074 assert(cbActual >= cbTuple);
00075
00076 builder.validateTupleSize(nodeAccessor.tupleAccessor);
00077
00078
00079 if (isNodeFull(*pNode,cbTuple)) {
00080 indexLastKey(false);
00081 pNode = allocateAndLinkNewNode();
00082 assert(!isNodeFull(*pNode,cbTuple));
00083
00084 nodeAccessor.tupleAccessor.setCurrentTupleBuf(pCurrentTupleBuf);
00085 }
00086
00087
00088 PBuffer pEntry = nodeAccessor.allocateEntry(
00089 *pNode,
00090 pNode->nEntries,
00091 cbTuple);
00092 memcpy(
00093 pEntry,
00094 pCurrentTupleBuf,
00095 cbTuple);
00096 ++nEntriesProcessed;
00097
00098
00099 sortedInputStream.consumeReadPointer(cbTuple);
00100 }
00101 }
00102
00103 void BTreeBuildLevel::indexLastChild()
00104 {
00105 assert(iLevel > 0);
00106 if (nEntriesTotal) {
00107 assert(nEntriesProcessed < nEntriesTotal);
00108 }
00109
00110 uint cbTuple = nodeAccessor.tupleAccessor.getByteCount(
00111 nodeAccessor.tupleData);
00112
00113 BTreeNode *pNode = &(pageLock.getNodeForWrite());
00114 if (isNodeFull(*pNode,cbTuple)) {
00115 indexLastKey(false);
00116 pNode = allocateAndLinkNewNode();
00117
00118
00119
00120 assert(!isNodeFull(*pNode,cbTuple));
00121
00122
00123 builder.getLevel(iLevel - 1).unmarshalLastKey();
00124 }
00125
00126
00127 nodeAccessor.tupleData.back().pData =
00128 reinterpret_cast<PConstBuffer>(&(builder.getLevel(iLevel-1).pageId));
00129 PBuffer pEntry = nodeAccessor.allocateEntry(
00130 *pNode,pNode->nEntries,cbTuple);
00131 nodeAccessor.tupleAccessor.marshal(nodeAccessor.tupleData,pEntry);
00132 ++nEntriesProcessed;
00133 }
00134
00135 void BTreeBuildLevel::unmarshalLastKey()
00136 {
00137 BTreeNode const &node = pageLock.getNodeForRead();
00138 nodeAccessor.accessTuple(node,node.nEntries - 1);
00139 nodeAccessor.unmarshalKey(builder.pNonLeafNodeAccessor->tupleData);
00140 }
00141
00142 BTreeNode *BTreeBuildLevel::allocateAndLinkNewNode()
00143 {
00144 PageId prevPageId = pageId;
00145
00146 BTreeNode &node = allocatePage();
00147
00148
00149
00150
00151 BTreePageLock prevPageLock;
00152 prevPageLock.accessSegment(builder.treeDescriptor.segmentAccessor);
00153 prevPageLock.lockExclusive(prevPageId);
00154 BTreeNode &prevNode = prevPageLock.getNodeForWrite();
00155 builder.setRightSibling(
00156 prevNode,
00157 prevPageId,
00158 pageId);
00159
00160
00161
00162 builder.getCacheAccessor()->nicePage(prevPageLock.getPage());
00163
00164 ++iNode;
00165 if (nEntriesPerNode) {
00166
00167 nEntriesPerNode = builder.calculateChildEntriesPerNode(
00168 builder.getLevel(iLevel + 1).nEntriesTotal,
00169 nEntriesTotal,
00170 iNode);
00171 }
00172 return &node;
00173 }
00174
00175 bool BTreeBuildLevel::isNodeFull(BTreeNode const &node,uint cbTuple)
00176 {
00177 return nodeAccessor.calculateCapacity(node,cbReserved + cbTuple)
00178 != BTreeNodeAccessor::CAN_FIT;
00179 }
00180
00181 BTreeNode &BTreeBuildLevel::allocatePage()
00182 {
00183 pageId = pageLock.allocatePage(builder.getPageOwnerId());
00184 BTreeNode &node = pageLock.getNodeForWrite();
00185 nodeAccessor.clearNode(
00186 node,builder.getSegment()->getUsablePageSize());
00187 node.height = iLevel;
00188 return node;
00189 }
00190
00191 FixedBuildLevel::FixedBuildLevel(
00192 BTreeBuilder &builderInit,
00193 BTreeNodeAccessor &nodeAccessorInit)
00194 : BTreeBuildLevel(builderInit,nodeAccessorInit)
00195 {
00196 }
00197
00198 void FixedBuildLevel::indexLastKey(bool finalize)
00199 {
00200 assert(pageLock.getNodeForRead().nEntries == nEntriesPerNode);
00201 if (iLevel == builder.getRootHeight()) {
00202 assert(finalize);
00203 return;
00204 }
00205 unmarshalLastKey();
00206 builder.getLevel(iLevel + 1).indexLastChild();
00207 }
00208
00209 bool FixedBuildLevel::isNodeFull(BTreeNode const &node,uint)
00210 {
00211 return (node.nEntries >= nEntriesPerNode);
00212 }
00213
00214 VariableBuildLevel::VariableBuildLevel(
00215 BTreeBuilder &builderInit,
00216 BTreeNodeAccessor &nodeAccessorInit)
00217 : BTreeBuildLevel(builderInit,nodeAccessorInit)
00218 {
00219 assert(builder.pTempSegment);
00220 SegmentAccessor tempSegmentAccessor(
00221 builder.pTempSegment,builder.getCacheAccessor());
00222 pParentKeyStream = SegOutputStream::newSegOutputStream(tempSegmentAccessor);
00223 }
00224
00225 VariableBuildLevel::~VariableBuildLevel()
00226 {
00227 if (!pParentKeyStream->isClosed()) {
00228
00229
00230 getParentKeyStream();
00231 }
00232 }
00233
00234 SharedSegInputStream VariableBuildLevel::getParentKeyStream()
00235 {
00236 PageId tempPageId = pParentKeyStream->getFirstPageId();
00237 pParentKeyStream->close();
00238 SegmentAccessor tempSegmentAccessor(
00239 builder.pTempSegment,builder.getCacheAccessor());
00240 SharedSegInputStream pParentInputStream =
00241 SegInputStream::newSegInputStream(
00242 tempSegmentAccessor,
00243 tempPageId);
00244
00245 pParentInputStream->setDeallocate(true);
00246 return pParentInputStream;
00247 }
00248
00249 void VariableBuildLevel::indexLastKey(bool)
00250 {
00251 unmarshalLastKey();
00252 BTreeNodeAccessor &nonLeafNodeAccessor = *builder.pNonLeafNodeAccessor;
00253
00254 nonLeafNodeAccessor.tupleData.back().pData =
00255 reinterpret_cast<PConstBuffer>(&pageId);
00256 uint cbTuple = nonLeafNodeAccessor.tupleAccessor.getByteCount(
00257 nonLeafNodeAccessor.tupleData);
00258 PBuffer pStreamBuf = pParentKeyStream->getWritePointer(cbTuple);
00259 nonLeafNodeAccessor.tupleAccessor.marshal(
00260 nonLeafNodeAccessor.tupleData,
00261 pStreamBuf);
00262 pParentKeyStream->consumeWritePointer(cbTuple);
00263 }
00264
00265 DynamicBuildLevel::DynamicBuildLevel(
00266 BTreeBuilder &builderInit,
00267 BTreeNodeAccessor &nodeAccessorInit)
00268 : BTreeBuildLevel(builderInit,nodeAccessorInit)
00269 {
00270 }
00271
00272 void DynamicBuildLevel::indexLastKey(bool finalize)
00273 {
00274 if (iLevel == builder.getRootHeight()) {
00275 if (finalize) {
00276 return;
00277 } else {
00278 builder.growTree();
00279 }
00280 }
00281 unmarshalLastKey();
00282 builder.getLevel(iLevel + 1).indexLastChild();
00283 }
00284
00285 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/btree/BTreeBuildLevel.cpp#10 $");
00286
00287