BTreeNodeAccessor.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/btree/BTreeNodeAccessor.cpp#12 $
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/btree/BTreeNodeAccessor.h"
00026 #include "fennel/tuple/TuplePrinter.h"
00027 
00028 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/btree/BTreeNodeAccessor.cpp#12 $");
00029 
00030 BTreeNodeAccessor::~BTreeNodeAccessor()
00031 {
00032 }
00033 
00034 void BTreeNodeAccessor::clearNode(BTreeNode &node,uint cbPage)
00035 {
00036     node.rightSibling = NULL_PAGE_ID;
00037     node.nEntries = 0;
00038     node.height = 0;
00039     node.cbTotalFree = cbPage - sizeof(BTreeNode);
00040     node.cbCompactFree = MAXU;
00041 }
00042 
00043 void BTreeNodeAccessor::onInit()
00044 {
00045     tupleAccessor.compute(tupleDescriptor);
00046     tupleData.compute(tupleDescriptor);
00047 }
00048 
00049 void BTreeNodeAccessor::dumpNode(
00050     std::ostream &os,BTreeNode const &node,PageId pageId)
00051 {
00052     os << "PageId:  " << pageId << std::endl;
00053     if (node.rightSibling == NULL_PAGE_ID) {
00054         os << "rightSibling:  <null>" << std::endl;
00055     } else {
00056         os << "rightSibling:  " << node.rightSibling << std::endl;
00057     }
00058     os << "nEntries:  " << node.nEntries << std::endl;
00059     os << "height:  " << node.height << std::endl;
00060     os << "cbTotalFree:  " << node.cbTotalFree << std::endl;
00061     if (!isMAXU(node.cbCompactFree)) {
00062         os << "cbCompactFree:  " << node.cbCompactFree << std::endl;
00063     }
00064     os << std::endl;
00065     TuplePrinter tuplePrinter;
00066     // TODO:  print "+infinity" for last key on right fringe
00067     for (uint i = 0; i < node.nEntries; ++i) {
00068         PConstBuffer pEntry = getEntryForRead(node,i);
00069         os << "offset = "
00070            << pEntry - reinterpret_cast<PConstBuffer>(&node) << std::endl;
00071         tupleAccessor.setCurrentTupleBuf(pEntry);
00072         tupleAccessor.unmarshal(tupleData);
00073         tuplePrinter.print(os,tupleDescriptor,tupleData);
00074         os << std::endl;
00075     }
00076     os << std::endl;
00077 }
00078 
00079 // TODO:  warning about usage of tupleAccessor
00080 // TODO:  override with a more efficient BTreeHeapNodeAccessor::compactNode
00081 // (eliminate virtual calls and reduce pointer arithmetic)
00082 void BTreeNodeAccessor::compactNode(BTreeNode &node,BTreeNode &scratchNode)
00083 {
00084     assert(!scratchNode.nEntries);
00085     for (uint i = 0; i < node.nEntries; ++i) {
00086         accessTuple(node,i);
00087         uint cbTuple = tupleAccessor.getCurrentByteCount();
00088         PBuffer pBuffer = allocateEntry(scratchNode,i,cbTuple);
00089         memcpy(pBuffer,tupleAccessor.getCurrentTupleBuf(),cbTuple);
00090     }
00091 
00092     if (!isMAXU(node.cbCompactFree)) {
00093         node.cbCompactFree = node.cbTotalFree;
00094     }
00095     memcpy(&scratchNode,&node,sizeof(BTreeNode));
00096 }
00097 
00098 // REVIEW:  to maximize the allowed tuple length, I think the split algorithm
00099 // below needs to use the index of the new tuple
00100 
00101 // TODO:  override with a more efficient BTreeCompactNodeAccessor::splitNode
00102 // (memcpy everything at once) and BTreeHeapNodeAccessor::splitNode (eliminate
00103 // virtual calls and reduce pointer arithmetic)
00104 void BTreeNodeAccessor::splitNode(
00105     BTreeNode &node,BTreeNode &newNode,
00106     uint cbNewTuple,
00107     bool monotonic)
00108 {
00109     assert(!newNode.nEntries);
00110     assert(node.nEntries > 1);
00111     newNode.height = node.height; // split should be of the same height
00112 
00113     // if monotonic, for leaf page,
00114     // don't actually split the page; leave the left
00115     // page as is and force all inserts to go into the new page
00116     // on the right
00117     // for internal node,
00118     // put the last entry to the right page.
00119     if (monotonic && node.height == 0) {
00120         return;
00121     }
00122 
00123     // Calculate the balance point in bytes
00124     uint cbNeeded = getEntryByteCount(cbNewTuple);
00125     uint cbBalance = cbNeeded;
00126     if (!monotonic) {
00127         cbBalance = (node.cbTotalFree + newNode.cbTotalFree - cbNeeded) / 2;
00128         cbBalance = std::max(cbNeeded,cbBalance);
00129     }
00130 
00131     // Calculate the corresponding split point in terms of tuples
00132     uint cbFreeAfterSplit = node.cbTotalFree;
00133     uint iSplitTuple = node.nEntries;
00134     while (cbFreeAfterSplit < cbBalance) {
00135         --iSplitTuple;
00136         accessTuple(node,iSplitTuple);
00137         uint cbTuple = tupleAccessor.getCurrentByteCount();
00138         cbFreeAfterSplit += getEntryByteCount(cbTuple);
00139     }
00140 
00141     // Copy tuples accordingly.
00142     for (uint i = iSplitTuple; i < node.nEntries; ++i) {
00143         accessTuple(node,i);
00144         uint cbTuple = tupleAccessor.getCurrentByteCount();
00145         PBuffer pNewEntry = allocateEntry(newNode,newNode.nEntries,cbTuple);
00146         memcpy(pNewEntry,tupleAccessor.getCurrentTupleBuf(),cbTuple);
00147     }
00148 
00149     // Truncate old node.  NOTE: This isn't kosher, since it assumes too much
00150     // about data layout, but this whole method is going to go away soon
00151     // anyway.
00152     node.nEntries = iSplitTuple;
00153     node.cbTotalFree = cbFreeAfterSplit;
00154 }
00155 
00156 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/btree/BTreeNodeAccessor.cpp#12 $");
00157 
00158 // End BTreeNodeAccessor.cpp

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