All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sleepycat.je.cleaner.DbCache Maven / Gradle / Ivy

Go to download

Berkeley DB Java Edition is a open source, transactional storage solution for Java applications. The Direct Persistence Layer (DPL) API is faster and easier to develop, deploy, and manage than serialized object files or ORM-based Java persistence solutions. The Collections API enhances the standard java.util.collections classes allowing them to be persisted to a local file system and accessed concurrently while protected by ACID transactions. Data is stored by serializing objects and managing class and instance data separately so as not to waste space. Berkeley DB Java Edition is the reliable drop-in solution for complex, fast, and scalable storage. Source for this release is in 'je-4.0.92-sources.jar', the Javadoc is located at 'http://download.oracle.com/berkeley-db/docs/je/4.0.92/'.

There is a newer version: 5.0.73
Show newest version
/*-
 * 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.cleaner;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.dbi.DatabaseId;
import com.sleepycat.je.dbi.DatabaseImpl;
import com.sleepycat.je.dbi.EnvironmentImpl;

import org.checkerframework.checker.nullness.qual.NonNull;

class DbCache implements Iterable> {

    private final EnvironmentImpl envImpl;
    private final Cleaner cleaner;
    private final long timoutMs;
    private long lastClearTime;
    private int lookups;
    private final Map cache = new HashMap<>();

    DbCache(final EnvironmentImpl envImpl, final Cleaner cleaner) {
        this.envImpl = envImpl;
        this.cleaner = cleaner;

        timoutMs = envImpl.getConfigManager().getDuration(
            EnvironmentParams.ENV_DB_CACHE_TIMEOUT);

        lastClearTime = System.currentTimeMillis();
    }

    /**
     * Used to cache DatabaseImpl and some relatively static info about it.
     * The static info can be used for determining obsolescence without doing
     * an expensive DbTree lookup.This reduces the negative performance impact
     * of periodically clearing the cache via {@link #releaseDbImpls}. The
     * static info can be obtained with a single DbTree lookup per DB for each
     * file cleaned.
     */
    static class DbInfo {

        /**
         * The dbImpl field is non-null if it is cached, but set to null
         * periodically by calling {@link #releaseDbImpls}.
         */
        DatabaseImpl dbImpl;

        /*
         * The following fields are available even when dbImpl is null. When
         * the cache is cleared, dbImpl is set to null but these fields are
         * left in place. For the most part they can be used for determining
         * obsolescence even when they are stale, with some caveats below.
         */

        /**
         * The following fields are truly immutable.
         */
        boolean dups;
        boolean internal;
        boolean isLNImmediatelyObsolete;

        /**
         * The name field can change, but in all cases the old name can be
         * used, either as debug output or to pass to the extinction filter.
         */
        String name;

        /**
         * If true, the deleted field is immutable and dbImpl will be null.
         * If false, the deleting field can be used to determine whether a
         * deletion is in progress. If both fields are false, the current
         * dbImpl must be consulted to determine whether the DB is deleted.
         * @see #getDbImpl
         */
        boolean deleted;

        /**
         * If true, the DB will definitely be deleted, so the only possible
         * state transition is from [deleting=true,deleted=false] to
         * [deleting=false,deleted=true].
         * @see #getDbImpl
         */
        boolean deleting;
    }

    /**
     * Returns the possibly-stale info for a given DB ID. Does not call
     * DbTree.getDb if the DB ID has been previously cached.
     *
     * DbInfo.dbImpl is not guaranteed to be non-null even if DbInfo.deleted
     * is false. If DbInfo.dbImpl is null, the DB has been released and may be
     * deleted by another thread.
     */
    DbInfo getDbInfo(final DatabaseId dbId) {
        final DbInfo info = cache.get(dbId);
        if (info != null) {
            return info;
        }
        return getDbImpl(dbId);
    }

    /**
     * Returns the up-to-date info for a given DB ID, returning a non-null
     * DbInfo.dbImpl when the DB is not deleted or deleting.
     *
     * If the DB was previously found to be deleted or deleting, this method
     * does not call DbTree.getDb again (this case is optimized).
     */
    DbInfo getDbImpl(final DatabaseId id) {
        DbInfo info = cache.get(id);
        if (info == null) {
            info = new DbInfo();
            cache.put(id, info);
        }
        if (info.dbImpl == null && !info.deleted && !info.deleting) {
            final DatabaseImpl db =
                envImpl.getDbTree().getDb(id, cleaner.lockTimeout);
            if (db == null) {
                info.deleted = true;
            } else {
                info.dbImpl = db;
                info.dups = db.getSortedDuplicates();
                info.internal = db.getDbType().isInternal();
                info.isLNImmediatelyObsolete = db.isLNImmediatelyObsolete();
                info.name = db.getName();
                info.deleting = db.isDeleting();
            }
            lookups++;
        }
        return info;
    }

    /**
     * Returns an iterator over the cached entries.
     */
    @Override
    @NonNull
    public Iterator> iterator() {
        return cache.entrySet().iterator();
    }

    /**
     * Returns the number of calls to DbTree.getDb during the cleaner run.
     */
    int getLookups() {
        return lookups;
    }

    /**
     * Releases all non-null DbInfo.dbImpl objects in the cache and sets this
     * field to null.
     */
    void releaseDbImpls() {
        for (final DbInfo info : cache.values()) {
            releaseDbImpl(info);
        }
    }

    /**
     * Releases DbInfo.dbImpl if non-null and sets this field to null.
     */
    void releaseDbImpl(final DbInfo info) {
        if (info.dbImpl != null) {
            envImpl.getDbTree().releaseDb(info.dbImpl);
            info.dbImpl = null;
        }
    }

    /**
     * Release cached dbImpls periodically to prevent starving other threads
     * that need exclusive access to the MapLN (for example,
     * DbTree.deleteMapLN). [#21015]
     */
    void clearCachePeriodically() {

        final long now = System.currentTimeMillis();

        if (now >= lastClearTime + timoutMs) {
            releaseDbImpls();
            lastClearTime = now;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy