final byte[] keyBytes = new byte[(nodeAvg <= 0xFF) ? 1 : 2];
final DatabaseEntry keyEntry = new DatabaseEntry();
final DatabaseEntry dataEntry = new DatabaseEntry();
/* Insert nodeAvg records into a single BIN. */
final Database db = openDatabase(env, true);
for (int i = 0; i < nodeAvg; i += 1) {
if (keyBytes.length == 1) {
keyBytes[0] = (byte) i;
} else {
assert keyBytes.length == 2;
keyBytes[0] = (byte) (i >> 8);
keyBytes[1] = (byte) i;
}
setKeyData(keyBytes, keyPrefix, keyEntry, dataEntry);
final OperationStatus status;
if (duplicates) {
status = db.putNoDupData(null, keyEntry, dataEntry);
} else {
status = db.putNoOverwrite(null, keyEntry, dataEntry);
}
if (status != OperationStatus.SUCCESS) {
throw new IllegalStateException(status.toString());
}
}
/* Position a cursor to the first record. */
final Cursor cursor = db.openCursor(null, null);
OperationStatus status = cursor.getFirst(keyEntry, dataEntry, null);
assert status == OperationStatus.SUCCESS;
/*
* Calculate BIN size including LNs/data. The recalcKeyPrefix and
* compactMemory methods are called to simulate normal operation.
* Normally prefixes are recalculated when a IN is split, and
* compactMemory is called after fetching a IN or evicting an LN.
*/
final BIN bin = DbInternal.getCursorImpl(cursor).getBIN();
bin.recalcKeyPrefix();
bin.compactMemory();
minBinSizeWithData = bin.getInMemorySize();
/* Evict all LNs. */
for (int i = 0; i < nodeAvg; i += 1) {
assert status == OperationStatus.SUCCESS;
final CursorImpl cursorImpl = DbInternal.getCursorImpl(cursor);
assert bin == cursorImpl.getBIN();
assert duplicates ?
(bin.getTarget(i) == null) :
(bin.getTarget(i) != null);
if (!duplicates) {
cursorImpl.evict();
}
status = cursor.getNext(keyEntry, dataEntry, null);
}
assert status == OperationStatus.NOTFOUND;
cursor.close();
/*
* Calculate BIN size without LNs/data. The clearLsnCompaction method
* is called to artificially remove LSN compaction savings. The amount
* saved by LSN compaction is currently the only difference between the
* min and max memory sizes.
*/
bin.compactMemory();
minBinSize = bin.getInMemorySize();
bin.clearLsnCompaction();
maxBinSize = bin.getInMemorySize();
final long lsnSavings = maxBinSize - minBinSize;
maxBinSizeWithData = minBinSizeWithData + lsnSavings;
/*
* To calculate IN size, get parent/root IN and artificially fill the
* slots with nodeAvg entries.
*/
final IN in = DbInternal.getDatabaseImpl(db).
getTree().
getRootINLatchedExclusive(CacheMode.DEFAULT);
assert bin == in.getTarget(0);
for (int i = 1; i < nodeAvg; i += 1) {
final ChildReference child =
new ChildReference(bin, bin.getKey(i), bin.getLsn(i));
final int result = in.insertEntry1(child);
assert (result & IN.INSERT_SUCCESS) != 0;
assert i == (result & ~IN.INSERT_SUCCESS);
}
in.recalcKeyPrefix();
in.compactMemory();
in.releaseLatch();
minInSize = in.getInMemorySize();
maxInSize = minInSize + lsnSavings;
db.close();
}