00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #ifndef Fennel_BTreeKeyedNodeAccessor_Included
00025 #define Fennel_BTreeKeyedNodeAccessor_Included
00026 
00027 #include "fennel/btree/BTreeNodeAccessor.h"
00028 
00029 FENNEL_BEGIN_NAMESPACE
00030 
00031 
00032 
00038 template <class NodeAccessor,class KeyAccessor>
00039 class BTreeKeyedNodeAccessor : public NodeAccessor
00040 {
00041 public:
00042     KeyAccessor *pKeyAccessor;
00043 
00044     virtual void accessTupleInline(BTreeNode const &node,uint iEntry)
00045     {
00046         assert(iEntry < node.nEntries);
00047         NodeAccessor::tupleAccessor.setCurrentTupleBuf(
00048             NodeAccessor::getEntryForReadInline(node,iEntry));
00049     }
00050 
00051     virtual void accessTuple(BTreeNode const &node,uint iEntry)
00052     {
00053         return accessTupleInline(node,iEntry);
00054     }
00055 
00056     virtual void unmarshalKey(TupleData &keyData)
00057     {
00058         pKeyAccessor->unmarshal(keyData);
00059     }
00060 
00061     virtual uint binarySearch(
00062         BTreeNode const &node,
00063         TupleDescriptor const &keyDescriptor,
00064         TupleData const &searchKey,
00065         DuplicateSeek dupSeek,
00066         bool leastUpper,
00067         TupleData &scratchKey,
00068         bool &found)
00069     {
00070         uint probe = 0;
00071         uint base = probe;
00072         found = false;
00073         int nKeys = NodeAccessor::getKeyCount(node);
00074         while (nKeys > 0) {
00075             uint split = nKeys >> 1;
00076             probe = base + split;
00077             accessTupleInline(node,probe);
00078             pKeyAccessor->unmarshal(scratchKey);
00079             int j = keyDescriptor.compareTuples(
00080                 searchKey,scratchKey);
00081             if (j == 0) {
00082                 found = true;
00083                 switch (dupSeek) {
00084                 case DUP_SEEK_ANY:
00085                     return probe;
00086                 case DUP_SEEK_BEGIN:
00087                     j = -1;
00088                     break;
00089                 case DUP_SEEK_END:
00090                     j = 1;
00091                     break;
00092                 default:
00093                     permAssert(false);
00094                 }
00095             }
00096             if (j < 0) {
00097                 nKeys = split;
00098             } else {
00099                 base = probe + 1;
00100                 nKeys -= (split + 1);
00101             }
00102         }
00103         if (!found && !leastUpper && (base > 0)) {
00104             base--;
00105         }
00106         if (((base != probe) && (base < node.nEntries)) ||
00107             ((node.nEntries == 1) && (node.height != 0)))
00108         {
00109             
00110             accessTupleInline(node,base);
00111         }
00112         return base;
00113     }
00114 
00115     virtual int compareFirstKey(
00116         BTreeNode const &node,
00117         TupleDescriptor const &keyDescriptor,
00118         TupleData const &searchKey,
00119         TupleData &scratchKey)
00120     {
00121         int nKeys = NodeAccessor::getKeyCount(node);
00122         if (nKeys == 0) {
00123             return -1;
00124         }
00125         accessTupleInline(node, 0);
00126         pKeyAccessor->unmarshal(scratchKey);
00127         int compareResult = keyDescriptor.compareTuples(searchKey, scratchKey);
00128         return compareResult;
00129     }
00130 
00131     virtual PConstBuffer getEntryForRead(BTreeNode const &node,uint iEntry)
00132     {
00133         return NodeAccessor::getEntryForReadInline(node,iEntry);
00134     }
00135 };
00136 
00137 FENNEL_END_NAMESPACE
00138 
00139 #endif
00140 
00141