* deleting the FileSummaryLN. Iterate through all FileSummaryLNs and
* add them to the cache if their corresponding log file exists. But
* delete those records that have no corresponding log file.
*/
Long[] existingFiles = env.getFileManager().getAllFileNumbers();
Locker locker = null;
CursorImpl cursor = null;
try {
locker = BasicLocker.createBasicLocker(env, false /*noWait*/);
cursor = new CursorImpl(fileSummaryDb, locker);
/* Perform eviction in unsynchronized methods. */
cursor.setAllowEviction(true);
DatabaseEntry keyEntry = new DatabaseEntry();
DatabaseEntry dataEntry = new DatabaseEntry();
if (cursor.positionFirstOrLast(true)) {
/* Retrieve the first record. */
OperationStatus status = cursor.getCurrentAlreadyLatched
(keyEntry, dataEntry, LockType.NONE);
if (status != OperationStatus.SUCCESS) {
/* The record we're pointing at may be deleted. */
status = cursor.getNext
(keyEntry, dataEntry, LockType.NONE, true /*forward*/,
false /*alreadyLatched*/, null /*rangeConstraint*/);
}
while (status == OperationStatus.SUCCESS) {
counter.incNumRead();
/*
* Perform eviction once per operation. Pass false for
* backgroundIO because this is done during recovery and
* there is no reason to sleep.
*/
env.daemonEviction(false /*backgroundIO*/);
FileSummaryLN ln = (FileSummaryLN)
cursor.getCurrentLN(LockType.NONE);
if (ln == null) {
/* Advance past a cleaned record. */
status = cursor.getNext
(keyEntry, dataEntry, LockType.NONE,
true /*forward*/, false /*alreadyLatched*/,
null /*rangeConstraint*/);
continue;
}
byte[] keyBytes = keyEntry.getData();
boolean isOldVersion = ln.hasStringKey(keyBytes);
long fileNum = ln.getFileNumber(keyBytes);
Long fileNumLong = Long.valueOf(fileNum);
if (Arrays.binarySearch(existingFiles, fileNumLong) >= 0) {
counter.incNumProcessed();
/* File exists, cache the FileSummaryLN. */
FileSummary summary = ln.getBaseSummary();
fileSummaryMap.put(fileNumLong, summary);
/*
* Update old version records to the new version. A
* zero sequence number is used to distinguish the
* converted records and to ensure that later records
* will have a greater sequence number.
*/
if (isOldVersion && !env.isReadOnly()) {
insertFileSummary(ln, fileNum, 0);
cursor.delete(ReplicationContext.NO_REPLICATE);
} else {
/* Always evict after using a file summary LN. */
cursor.evict();
}
} else {
/*
* File does not exist, remove the summary from the map
* and delete all FileSummaryLN records.
*/
counter.incNumDeleted();
fileSummaryMap.remove(fileNumLong);
if (!env.isReadOnly()) {
removePerDbMetadata
(Collections.singleton(fileNumLong),
null /*databases*/);
if (isOldVersion) {
cursor.latchBIN();
cursor.delete(ReplicationContext.NO_REPLICATE);
} else {
deleteFileSummary(fileNumLong);
}
}
/*
* Do not evict after deleting since the compressor
* would have to fetch it again.
*/
}
/* Go on to the next entry. */
if (isOldVersion) {
/* Advance past the single old version record. */
status = cursor.getNext
(keyEntry, dataEntry, LockType.NONE,
true /*forward*/, false /*alreadyLatched*/,
null /*rangeConstraint*/);
} else {
/*
* Skip over other records for this file by adding one
* to the file number and doing a range search.
*/
if (!getFirstFSLN
(cursor,
fileNum + 1,
keyEntry, dataEntry,
LockType.NONE)) {
status = OperationStatus.NOTFOUND;
}
}
}
}
} finally {
if (cursor != null) {
/* positionFirstOrLast may leave BIN latched. */
cursor.close();
}
if (locker != null) {
locker.operationEnd();
}
int newMemorySize = fileSummaryMap.size() *
MemoryBudget.UTILIZATION_PROFILE_ENTRY;
MemoryBudget mb = env.getMemoryBudget();