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