* as a unit. Recovery skips provisional entries, so the changed
* children are only used if the parent makes it out to the log.
*/
EnvironmentImpl env = databaseImpl.getDbEnvironment();
LogManager logManager = env.getLogManager();
INList inMemoryINs = env.getInMemoryINs();
long newSiblingLsn =
newSibling.optionalLogProvisional(logManager, parent);
long myNewLsn = optionalLogProvisional(logManager, parent);
/*
* When we update the parent entry, we use updateEntryCompareKey so
* that we don't replace the parent's key that points at 'this'
* with a key that is > than the existing one. Replacing the
* parent's key with something > would effectively render a piece
* of the subtree inaccessible. So only replace the parent key
* with something <= the existing one. See tree/SplitTest.java for
* more details on the scenario.
*/
if (low == 0) {
/*
* Change the original entry to point to the new child and add
* an entry to point to the newly logged version of this
* existing child.
*/
if (childIndex == 0) {
parent.updateEntryCompareKey(childIndex, newSibling,
newSiblingLsn, newIdKey);
} else {
parent.updateNode(childIndex, newSibling, newSiblingLsn,
null /*lnSlotKey*/);
}
byte[] ourKey = getKey(0);
boolean insertOk = parent.insertEntry
(new ChildReference(this, ourKey, myNewLsn));
assert insertOk;
} else {
/*
* Update the existing child's LSN to reflect the newly logged
* version and insert new child into parent.
*/
if (childIndex == 0) {
/*
* this's idkey may be < the parent's entry 0 so we need to
* update parent's entry 0 with the key for 'this'.
*/
parent.updateEntryCompareKey
(childIndex, this, myNewLsn, getKey(0));
} else {
parent.updateNode(childIndex, this, myNewLsn,
null /*lnSlotKey*/);
}
boolean insertOk = parent.insertEntry
(new ChildReference(newSibling, newIdKey, newSiblingLsn));
assert insertOk;
}
/*
* If this node has no key prefix, calculate it now that it has
* been split.
*/
byte[] newKeyPrefix = computeKeyPrefix(-1);
recalcSuffixes(newKeyPrefix, null, -1);
/* Only recalc if there are multiple entries in newSibling. */
if (newSibling.getNEntries() > 1) {
byte[] newSiblingPrefix = newSibling.getKeyPrefix();
newSiblingPrefix = newSibling.computeKeyPrefix(-1);
newSibling.recalcSuffixes(newSiblingPrefix, null, -1);
newSibling.initMemorySize();
}
parentLsn = parent.optionalLog(logManager);
/*
* Maintain dirtiness if this is the root, so this parent will be
* checkpointed. Other parents who are not roots are logged as part
* of the propagation of splits upwards.
*/
if (parent.isRoot()) {
parent.setDirty(true);
}
/*
* Update size. newSibling and parent are correct, but this IN has
* had its entries shifted and is not correct.
*/
long newSize = computeMemorySize();
updateMemorySize(oldMemorySize, newSize);
inMemoryINs.add(newSibling);
/* Debug log this information. */
traceSplit(Level.FINE, parent,
newSibling, parentLsn, myNewLsn,
newSiblingLsn, splitIndex, idKeyIndex, childIndex);