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/BTreeVerifier.h"
00026 #include "fennel/btree/BTreeAccessBaseImpl.h"
00027 
00028 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/btree/BTreeVerifier.cpp#15 $");
00029 
00030 
00031 
00032 BTreeVerifier::BTreeVerifier(BTreeDescriptor const &descriptor)
00033     : BTreeAccessBase(descriptor)
00034 {
00035     permAssert(getRootPageId() != NULL_PAGE_ID);
00036     keyData.compute(keyDescriptor);
00037     keyData2 = keyData;
00038 }
00039 
00040 BTreeVerifier::~BTreeVerifier()
00041 {
00042 }
00043 
00044 void BTreeVerifier::verify(bool strictInit, bool keysInit, bool leafInit)
00045 {
00046     strict = strictInit;
00047     keys = keysInit;
00048     leaf = leafInit;
00049     lowerBoundKey.clear();
00050     upperBoundKey.clear();
00051     stats.nLevels = MAXU;
00052     stats.nNonLeafNodes = 0;
00053     stats.nLeafNodes = 0;
00054     stats.nTuples = 0;
00055     stats.nUniqueKeys = 0;
00056     PageId pageId = getRootPageId();
00057     do {
00058         expectedRightSibling = NULL_PAGE_ID;
00059         if (isMAXU(stats.nLevels)) {
00060             expectedHeight = MAXU;
00061         } else {
00062             expectedHeight = stats.nLevels - 1;
00063         }
00064         pageId = verifyNode(pageId);
00065     } while (pageId != NULL_PAGE_ID);
00066 }
00067 
00068 
00069 
00070 PageId BTreeVerifier::verifyNode(
00071     PageId pageId)
00072 {
00073     BTreePageLock pageLock;
00074     pageLock.accessSegment(treeDescriptor.segmentAccessor);
00075     pageLock.lockShared(pageId);
00076     BTreeNode const &node = pageLock.getNodeForRead();
00077     PageId returnPageId = NULL_PAGE_ID;
00078 
00079     
00080     
00081     permAssert(node.magicNumber == BTreeNode::MAGIC_NUMBER);
00082 
00083     if (isMAXU(expectedHeight)) {
00084         stats.nLevels = node.height + 1;
00085     } else {
00086         permAssert(node.height == expectedHeight);
00087     }
00088 
00089     if (strict) {
00090         permAssert(node.rightSibling == getRightSibling(pageId));
00091         permAssert(node.rightSibling == expectedRightSibling);
00092     } else {
00093         if (node.rightSibling != expectedRightSibling) {
00094             permAssert(node.rightSibling != NULL_PAGE_ID);
00095             returnPageId = node.rightSibling;
00096         }
00097     }
00098 
00099     BTreeNodeAccessor &nodeAccessor = getNodeAccessor(node);
00100 
00101     
00102 
00103     
00104     if (keys) {
00105         bool countUniqueKeys = (node.height == 0);
00106         keyData = lowerBoundKey;
00107         uint nKeys = nodeAccessor.getKeyCount(node);
00108         for (uint i = 0; i < nKeys; ++i) {
00109             nodeAccessor.accessTuple(node,i);
00110             nodeAccessor.unmarshalKey(keyData2);
00111             if (keyData.size()) {
00112                 int c = keyDescriptor.compareTuples(keyData,keyData2);
00113 
00114                 
00115                 if (c > 0) {
00116                     nodeAccessor.dumpNode(std::cerr,node,pageId);
00117                 }
00118                 permAssert(c <= 0);
00119                 
00120 
00121                 if (countUniqueKeys && c == -1) {
00122                     
00123                     stats.nUniqueKeys++;
00124                 }
00125             } else if (countUniqueKeys) {
00126                 stats.nUniqueKeys++;
00127             }
00128             keyData = keyData2;
00129         }
00130     }
00131 
00132     
00133     if (keyData.size() && upperBoundKey.size()) {
00134         keyData2 = upperBoundKey;
00135         int c = keyDescriptor.compareTuples(keyData,keyData2);
00136         permAssert(c <= 0);
00137     }
00138     if (node.height) {
00139         stats.nNonLeafNodes++;
00140         verifyChildren(node);
00141     } else {
00142         stats.nLeafNodes++;
00143         stats.nTuples += node.nEntries;
00144     }
00145     return returnPageId;
00146 }
00147 
00148 void BTreeVerifier::verifyChildren(BTreeNode const &node)
00149 {
00150     
00151     if (node.height == 1 && !leaf) {
00152         stats.nLeafNodes += node.nEntries;
00153         return;
00154     }
00155 
00156     BTreeNodeAccessor &nodeAccessor = getNodeAccessor(node);
00157     for (uint i = 0; i < node.nEntries; ++i) {
00158         PageId nextChildPageId;
00159         if (i + 1 < node.nEntries) {
00160             nextChildPageId = getChild(node,i + 1);
00161         } else {
00162             nextChildPageId = getFirstChild(node.rightSibling);
00163         }
00164         PageId childPageId = getChild(node,i);
00165         do {
00166             expectedRightSibling = nextChildPageId;
00167             expectedHeight = node.height - 1;
00168             nodeAccessor.accessTuple(node,i);
00169             nodeAccessor.unmarshalKey(keyData);
00170             if (nextChildPageId == NULL_PAGE_ID) {
00171                 
00172                 upperBoundKey.clear();
00173             } else {
00174                 upperBoundKey = keyData;
00175             }
00176             childPageId = verifyNode(childPageId);
00177         } while (childPageId != NULL_PAGE_ID);
00178         nodeAccessor.accessTuple(node,i);
00179         nodeAccessor.unmarshalKey(keyData);
00180         lowerBoundKey = keyData;
00181     }
00182 }
00183 
00184 BTreeStatistics const &BTreeVerifier::getStatistics()
00185 {
00186     return stats;
00187 }
00188 
00189 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/btree/BTreeVerifier.cpp#15 $");
00190 
00191