blob: edc55da471342f7945981bb0f3ce96b995cb4e0c [file] [log] [blame]
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.je.dbi;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
import com.sleepycat.je.cleaner.OffsetList;
import com.sleepycat.je.utilint.DbLsn;
/*
* The current set of LSNs of children which are not in-memory but are
* being accumulated, and will be subsequently sorted and processed. Once
* they have been accumulated, they will be sorted, fetched, and returned
* to the user.
*
* Represent this as a map from file number to OffsetList holding LSN
* offsets.
*/
abstract class LSNAccumulator {
/* File number -> OffsetList<LSN Offsets> */
private Map<Long, OffsetList> offsetsByFile;
private int nTotalEntries;
private long lsnAccMemoryUsage;
LSNAccumulator() {
init();
}
private void init() {
incInternalMemoryUsage(-lsnAccMemoryUsage);
offsetsByFile = new TreeMap<Long, OffsetList>();
nTotalEntries = 0;
incInternalMemoryUsage(MemoryBudget.TREEMAP_OVERHEAD);
}
void clear() {
offsetsByFile.clear();
nTotalEntries = 0;
incInternalMemoryUsage(-lsnAccMemoryUsage);
}
boolean isEmpty() {
return nTotalEntries == 0;
}
int getNTotalEntries() {
return nTotalEntries;
}
long getMemoryUsage() {
return lsnAccMemoryUsage;
}
abstract void noteMemUsage(long increment);
private void incInternalMemoryUsage(long increment) {
lsnAccMemoryUsage += increment;
noteMemUsage(increment);
}
void add(long lsn) {
long fileNumber = DbLsn.getFileNumber(lsn);
OffsetList offsetsForFile = offsetsByFile.get(fileNumber);
if (offsetsForFile == null) {
offsetsForFile = new OffsetList();
offsetsByFile.put(fileNumber, offsetsForFile);
incInternalMemoryUsage(MemoryBudget.TFS_LIST_INITIAL_OVERHEAD);
incInternalMemoryUsage(MemoryBudget.TREEMAP_ENTRY_OVERHEAD);
}
boolean newSegment =
offsetsForFile.add(DbLsn.getFileOffset(lsn), false);
if (newSegment) {
incInternalMemoryUsage(MemoryBudget.TFS_LIST_SEGMENT_OVERHEAD);
}
nTotalEntries += 1;
}
long[] getAndSortPendingLSNs() {
long[] currentLSNs = new long[nTotalEntries];
int curIdx = 0;
for (Map.Entry<Long, OffsetList> fileEntry :
offsetsByFile.entrySet()) {
long fileNumber = fileEntry.getKey();
for (long fileOffset : fileEntry.getValue().toArray()) {
currentLSNs[curIdx] = DbLsn.makeLsn(fileNumber, fileOffset);
curIdx += 1;
}
}
init();
Arrays.sort(currentLSNs);
return currentLSNs;
}
void getLSNs(long[] lsns, int nLsns) {
for (Map.Entry<Long, OffsetList> fileEntry :
offsetsByFile.entrySet()) {
long fileNumber = fileEntry.getKey();
for (long fileOffset : fileEntry.getValue().toArray()) {
lsns[nLsns] = DbLsn.makeLsn(fileNumber, fileOffset);
++nLsns;
}
}
init();
}
}