#At file:///home/lb200670/mysql/checkin/ based on revid:christopher.powers@stripped
2766 lars-erik.bjork@stripped 2009-08-13
This is a fix for bug #46083 - falcon_pagesize2K fails in
IndexRootPage::addIndexEntry() during recovery
This is the reason for the bug:
We try to add a node in IndexRootPage::addIndexEntry:
<snip>
/* If the node fits on page, we're done */
AddNodeResult result;
for (;;)
{
result = page->addNode(dbb, key, recordNumber);
<snip>
The node does not fit on the page, and we are told to split the page
at the middle.
In IndexPage::splitIndexPageMiddle, we search for a node to split
on. We want to chose a node where the prefix compression is poor.
<snip>
for (; node.node < pageEnd; node.getNext(bucketEnd))
{
//int l =
node.expandKey(key);
if (node.offset || node.length)
{
if (node.nextNode > midpoint)
break;
chain = node.node;
}
}
<snip>
Then we check to make sure that this is not the last node on the page,
and if it is, we split on the previous node (prevNode)
<snip>
// The split node should never be the last node on the page
if ((UCHAR*) node.nextNode > (UCHAR*) this + length)
node = prevNode;
<snip>
What I have seen in the debugger is that (UCHAR*) node.nextNode == (UCHAR*)
this + length (note *equal*). To my understanding, this *is* the last
node on the page, and the condition should have been '>=' instead of
just '>'. This means that we in this case split on the last node
instead of the second to last node. On the next iteration we will
navigate to this page once again, and try to insert into it. This page
is still full (same length as the last time, we split on the
END_BUCKET node I assume), and we will split it again. This repeats.
In this fix I change the condition from '>' to '>=' and also actually
update prevNode in the loop showed earlier, so that it does not refer
to the first node on the page.
modified file 'storage/falcon/IndexPage.cpp'
* Changed the condition, and updated prevNode.
* Removed unused and confusing 'chain' from ::splitIndexPageMiddle and
::splitIndexPageEnd
modified:
storage/falcon/IndexPage.cpp
=== modified file 'storage/falcon/IndexPage.cpp'
--- a/storage/falcon/IndexPage.cpp 2009-04-02 22:36:19 +0000
+++ b/storage/falcon/IndexPage.cpp 2009-08-13 07:51:37 +0000
@@ -332,7 +332,6 @@ Bdb* IndexPage::splitIndexPageMiddle(Dbb
IndexNode node (this);
IndexNode prevNode = node;
- Btn *chain = node.node;
Btn *bucketEnd = getEnd();
for (; node.node < pageEnd; node.getNext(bucketEnd))
@@ -345,13 +344,15 @@ Bdb* IndexPage::splitIndexPageMiddle(Dbb
if (node.nextNode > midpoint)
break;
- chain = node.node;
}
+
+ prevNode = node;
+
}
// The split node should never be the last node on the page
- if ((UCHAR*) node.nextNode > (UCHAR*) this + length)
+ if ((UCHAR*) node.nextNode >= (UCHAR*) this + length)
node = prevNode;
int tailLength = (int) (((UCHAR*) this + length) - (UCHAR*) node.nextNode);
@@ -1074,7 +1075,6 @@ Bdb* IndexPage::splitIndexPageEnd(Dbb *d
Btn *pageEnd = getEnd();
IndexNode node (this);
- Btn *chain = node.node;
uint priorLength = 0;
IndexKey tempKey(insertKey->index);
Btn *priorNode = NULL;
@@ -1087,10 +1087,8 @@ Bdb* IndexPage::splitIndexPageEnd(Dbb *d
node.expandKey (&tempKey);
if (node.offset != priorLength || node.length)
- {
- chain = node.node;
priorLength = node.length;
- }
+
}
// Allocate and format new page. Link forward and backward to siblings.
@@ -1649,4 +1647,4 @@ void IndexPage::initRootPage(Bdb *bdb)
IndexNode node;
node.insert(page->nodes, 0, 0, dummy.key, END_LEVEL);
page->length += IndexNode::nodeLength(0, 0, END_LEVEL);
-}
\ No newline at end of file
+}