Package com.sleepycat.je.cleaner

Source Code of com.sleepycat.je.cleaner.RecoveryUtilizationTracker

/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002, 2011 Oracle and/or its affiliates.  All rights reserved.
*
*/

package com.sleepycat.je.cleaner;

import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;

import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.dbi.DatabaseId;
import com.sleepycat.je.dbi.DatabaseImpl;
import com.sleepycat.je.dbi.EnvironmentImpl;
import com.sleepycat.je.log.LogEntryType;
import com.sleepycat.je.tree.LN;
import com.sleepycat.je.utilint.DbLsn;

/**
* Accumulates changes to the utilization profile during recovery.
*
* <p>Per-database information is keyed by DatabaseId because the DatabaseImpl
* is not always available during recovery.  In fact this is the only reason
* that a "local" tracker is used during recovery -- to avoid requiring that
* the DatabaseImpl is available, which is necessary to use the "global"
* UtilizationTracker.  There is no requirement to accumulate totals locally,
* since recovery is single threaded.</p>
*
* <p>When finished with this object, its information should be added to the
* Environment's UtilizationTracker and DatabaseImpl objects by calling
* transferToUtilizationTracker.  This is done at the end of recovery, just
* prior to the checkpoint.  It does not have to be done under the log write
* latch, since recovery is single threaded.</p>
*/
public class RecoveryUtilizationTracker extends BaseLocalUtilizationTracker {

    /* File number -> LSN of FileSummaryLN */
    private final Map<Long, Long> fileSummaryLsns;
    /* DatabaseId  -> LSN of MapLN */
    private final Map<DatabaseId, Long> databaseLsns;

    public RecoveryUtilizationTracker(EnvironmentImpl env) {
        super(env, new HashMap<Object,DbFileSummaryMap>());
        fileSummaryLsns = new HashMap<Long, Long>();
        databaseLsns = new HashMap<DatabaseId, Long>();
    }

    /**
     * Saves the LSN of the last logged FileSummaryLN.
     */
    public void saveLastLoggedFileSummaryLN(long fileNum, long lsn) {
        fileSummaryLsns.put(Long.valueOf(fileNum), Long.valueOf(lsn));
    }

    /**
     * Saves the LSN of the last logged MapLN.
     */
    public void saveLastLoggedMapLN(DatabaseId dbId, long lsn) {
        databaseLsns.put(dbId, Long.valueOf(lsn));
    }

    /**
     * Counts the addition of all new log entries including LNs.
     */
    public void countNewLogEntry(long lsn,
                                 LogEntryType type,
                                 int size,
                                 DatabaseId dbId) {
        countNew(lsn, dbId, type, size);
    }

    /**
     * Counts the LSN of a node obsolete unconditionally.
     *
     * <p>Even when countExact is true, duplicate offsets are not checked (no
     * assertion is fired) because recovery is known to count the same LSN
     * offset twice in certain circumstances.</p>
     */
    public void countObsoleteUnconditional(long lsn,
                                           LogEntryType type,
                                           int size,
                                           DatabaseId dbId,
                                           boolean countExact) {
        countObsolete
            (lsn, dbId, type, size,
             true,       // countPerFile
             true,       // countPerDb
             countExact, // trackOffset
             false);     // checkDupOffsets
    }

    /**
     * Counts the oldLsn of a node obsolete if it has not already been counted
     * at the point of newLsn in the log.
     *
     * <p>Even when countExact is true, duplicate offsets are not checked (no
     * assertion is fired) because recovery is known to count the same LSN
     * offset twice in certain circumstances.</p>
     *
     * @return whether the file was previously uncounted.
     */
    public boolean countObsoleteIfUncounted(long oldLsn,
                                            long newLsn,
                                            LogEntryType type,
                                            int size,
                                            DatabaseId dbId,
                                            boolean countExact) {
        Long fileNum = Long.valueOf(DbLsn.getFileNumber(oldLsn));
        boolean fileUncounted = isFileUncounted(fileNum, newLsn);
        boolean dbUncounted = isDbUncounted(dbId, newLsn);
        countObsolete
            (oldLsn, dbId, type, size,
             fileUncounted, // countPerFile
             dbUncounted,   // countPerDb
             countExact,    // trackOffset
             false);        // checkDupOffsets
        return fileUncounted;
    }

    /**
     * Fetches the LN to get its size only if necessary and so configured.
     */
    public int fetchLNSize(int size, long lsn)
        throws DatabaseException {

        if (size == 0 && env.getCleaner().getFetchObsoleteSize()) {
            try {
                LN ln = (LN) env.getLogManager().getEntry(lsn);
                size = ln.getLastLoggedSize();
            } catch (FileNotFoundException e) {
                /* Ignore errors if the file was cleaned. */
            }
        }
        return size;
    }

    /**
     * Overrides this method for recovery and returns whether the FileSummaryLN
     * for the given file is prior to the given LSN.
     */
    @Override
    boolean isFileUncounted(Long fileNum, long lsn) {
        long fsLsn = DbLsn.longToLsn(fileSummaryLsns.get(fileNum));
        int cmpFsLsnToNewLsn = (fsLsn != DbLsn.NULL_LSN) ?
            DbLsn.compareTo(fsLsn, lsn) : -1;
        return cmpFsLsnToNewLsn < 0;
    }

    /**
     * Returns whether the MapLN for the given database ID is prior to the
     * given LSN.
     */
    private boolean isDbUncounted(DatabaseId dbId, long lsn) {
        long dbLsn = DbLsn.longToLsn(databaseLsns.get(dbId));
        int cmpDbLsnToLsn = (dbLsn != DbLsn.NULL_LSN) ?
            DbLsn.compareTo(dbLsn, lsn) : -1;
        return cmpDbLsnToLsn < 0;
    }

    /**
     * Clears all accmulated utilization info for the given file.
     */
    public void resetFileInfo(long fileNum) {
        TrackedFileSummary trackedSummary = getTrackedFile(fileNum);
        if (trackedSummary != null) {
            trackedSummary.reset();
        }
    }

    /**
     * Clears all accmulated utilization info for the given database.
     */
    public void resetDbInfo(DatabaseId dbId) {
        removeDbFileSummaries(dbId);
    }

    /**
     * Returns the DatabaseImpl from the database key, which in this case is
     * the DatabaseId.
     */
    @Override
    DatabaseImpl databaseKeyToDatabaseImpl(Object databaseKey)
        throws DatabaseException {

        DatabaseId dbId = (DatabaseId) databaseKey;
        return env.getDbTree().getDb(dbId);
    }

    /**
     * Must release the database, since DbTree.getDb was called by
     * databaseKeyToDatabaseImpl.
     */
    @Override
    void releaseDatabaseImpl(DatabaseImpl db) {
        env.getDbTree().releaseDb(db);
    }
}
TOP

Related Classes of com.sleepycat.je.cleaner.RecoveryUtilizationTracker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.