* a random read during an update operation.
*
* Note that we checked for a deleted/cleaned LN above, so we know
* that fetchTarget will not return null.
*/
LN ln;
if (foundData != null ||
data.getPartial() ||
envImpl.getCleaner().getFetchObsoleteSize() ||
!dbType.mayCreateUpdatedLN()) {
/* Must fetch. */
ln = (LN) bin.fetchTarget(index);
} else {
/* If resident, use LN for obsolete size tracking. */
ln = (LN) bin.getTarget(index);
}
final byte[] oldKey = bin.getKey(index);
final byte[] foundDataBytes = (ln != null) ? ln.getData() : null;
final byte[] newData = data.getPartial() ?
LN.resolvePartialEntry(data, foundDataBytes) :
LN.copyEntryData(data);
/*
* If the key is changed (according to the comparator), we assume
* it is actually the data that has changed via putCurrent() for a
* duplicate's DB. It is not possible to change the key in a
* non-duplicates DB, because 1) putCurrent() is not passed the
* key, 2) for put() the key is used to perform the lookup.
*/
if (key != null &&
Key.compareKeys
(oldKey, key, databaseImpl.getKeyComparator()) != 0) {
throw new DuplicateDataException
("Can't replace a duplicate with data that is " +
"unequal according to the duplicate comparator.");
}
if (foundData != null) {
assert foundDataBytes != null;
LN.setEntry(foundData, foundDataBytes);
}
if (foundKey != null) {
LN.setEntry(foundKey, oldKey);
}
/*
* Update the existing LN, if resident, else create a new updated
* LN.
*/
final long oldLNMemSize;
if (ln != null) {
/* LN is already resident, modify its data. */
oldLNMemSize = ln.getMemorySizeIncludedByParent();
ln.modify(newData);
} else {
/* LN is not resident, create updated LN for logging. */
ln = dbType.createUpdatedLN(envImpl, newData);
/* Make updated LN resident. */
bin.updateNode(index, ln, null /*lnSlotKey*/);
oldLNMemSize = ln.getMemorySizeIncludedByParent();
}
/*
* Log the updated LN.
*
* Note that if the LN is not resident, the lastLoggedSize is
* unknown and not counted during utilization tracking.
*/
newLsn = ln.optionalLog
(envImpl, databaseImpl, (key != null) ? key : oldKey, oldKey,
oldLsn, locker, lockStanding.prepareForUpdate(), repContext);
/* Return a copy of resulting data, if requested. [#16932] */
if (returnNewData != null) {
ln.setEntry(returnNewData);
}
/*
* Update the parent BIN. Update the key, if changed. [#15704]
*/