blob: 70152f51b55639028e1d89f04c2beec6fc5b993f [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;
/**
* Modes that can be specified for control over caching of records in the JE
* in-memory cache. When a record is stored or retrieved, the cache mode
* determines how long the record is subsequently retained in the JE in-memory
* cache, relative to other records in the cache.
*
* <p>When the cache overflows, JE must evict some records from the cache. By
* default, JE uses a Least Recently Used (LRU) algorithm for determining which
* records to evict. With the LRU algorithm, JE makes a best effort to evict
* the "coldest" (least recently used or accessed) records and to retain the
* "hottest" records in the cache for as long as possible.</p>
*
* <p>When an {@link EnvironmentMutableConfig#setOffHeapCacheSize off-heap
* cache} is configured, records evicted from the main cache are placed in
* the off-heap cache, and a separate LRU is used to determine when to evict
* a record from the off-heap cache.</p>
*
* <p>JE uses an approximate LRU approach with some exceptions and special
* cases.</p>
* <ul>
* <li>
* Individual records (LNs or Leaf Nodes) do not appear on the LRU
* list, i.e., their "hotness" is not explicitly tracked. Instead,
* their containing Btree node (BIN or bottom internal node) appears on
* the LRU list. Each BIN contains roughly 100 LNs
* (see {@link com.sleepycat.je.EnvironmentConfig#NODE_MAX_ENTRIES}).
* When an LN is accessed, its BIN is moved to the hot end of the LRU
* list, implying that all other LNs in the same BIN also are treated
* as if they are hot. The same applies if the BIN is moved to the cold
* end of the LRU list. The above statement applies to the off-heap
* cache also, when one is configured.
* </li>
* <li>
* When a BIN contains LNs and the BIN reaches the cold end of the LRU
* list, if memory can be reclaimed by deleting space for expired LNs
* or evicting resident LNs, then eviction of the BIN is deferred.
* The empty BIN is moved to the hot end of the LRU list. When an
* off-heap cache is configured, the eviction of LNs in this manner
* occurs independently in both caches.
* </li>
* <li>
* When a BIN contains no LNs, it may be evicted entirely. When the
* BINs parent node becomes empty, it may also be evicted, and so on.
* The BINs and INs are evicted on the basis of an LRU, but with two
* exceptions:
* <p>
* 1) Dirty BINs and INs are evicted only after eviction of all
* non-dirty BINs and INs. This is important to reduce logging and
* associated cleaning costs. When an off-heap cache is configured,
* BINs and INs are evicted from the main cache without regard to
* whether they are dirty. Dirty BINs and INs are evicted last, as
* just described, only from the off-heap cache.
* <p>
* 2) A BIN may be mutated to a BIN-delta to reclaim memory, rather
* then being evicted entirely. A BIN-delta contains only the dirty
* entries (for LNs recently logged). A BIN-delta is used when its
* size relative to the full BIN will be small enough so that it will
* be more efficient, both on disk and in memory, to store the delta
* rather than the full BIN.
* (see {@link com.sleepycat.je.EnvironmentConfig#TREE_BIN_DELTA}).
* The advantage of keeping a BIN-delta in cache is that some
* operations, particularly record insertions, can be performed using
* the delta without having the complete BIN in cache. When a BIN is
* mutated to a BIN-delta to reclaim memory, it is placed at the hot
* end of the LRU list. When an off-heap cache is configured, BINs are
* not mutated to BIN-deltas in the main cache, but rather this is done
* only in the off-heap cache.
* </li>
* <li>
* To reduce contention among threads on the LRU list, multiple LRU
* lists may be configured. See
* {@link com.sleepycat.je.EnvironmentConfig#EVICTOR_N_LRU_LISTS}.
* As described in the javadoc for this parameter, there is a trade-off
* between thread contention and the accuracy of the LRU. This
* parameter determines the number of main cache LRU lists as well as
* the number of off-heap cache LRU lists, when an off-heap cache is
* configured.
* </li>
* <li>
* A non-default cache mode may be explicitly specified to override
* the LRU behavior. See the CacheMode enumeration values for details.
* the normal LRU behavior described above. See the CacheMode
* enumeration values for details. The behavior of each CacheMode
* when an off-heap cache is configured is also described.
* </li>
* </ul>
*
* <p>When no cache mode is explicitly specified, the default cache mode is
* {@link #DEFAULT}. The default mode causes the normal LRU algorithm to be
* used.</p>
*
* <p>An explicit cache mode may be specified as an {@link
* EnvironmentConfig#setCacheMode Environment property}, a {@link
* DatabaseConfig#setCacheMode Database property}, a {@link
* Cursor#setCacheMode Cursor property}, or on a per-operation basis using
* {@link ReadOptions#setCacheMode(CacheMode)} or {@link
* WriteOptions#setCacheMode(CacheMode)}. If none are specified, {@link
* #DEFAULT} is used. If more than one non-null property is specified, the
* Cursor property overrides the Database and Environment properties, and the
* Database property overrides the Environment property.</p>
*
* <p>When all records in a given Database, or all Databases, should be treated
* the same with respect to caching, using the Database and/or Environment
* cache mode properties is sufficient. For applications that need finer
* grained control, the Cursor cache mode property can be used to provide a
* specific cache mode for individual records or operations. The Cursor cache
* mode property can be changed at any time, and the cache mode specified will
* apply to subsequent operations performed with that Cursor.</p>
*
* <p>In a Replicated Environment where a non-default cache mode is desired,
* the cache mode can be configured on the Master node as described above.
* However, it is important to configure the cache mode on the Replica nodes
* using an Environment property. That way, the cache mode will apply to
* <em>write</em> operations that are replayed on the Replica for all
* Databases, even if the Databases are not open by the application on the
* Replica. Since all nodes may be Replicas at some point in their life cycle,
* it is recommended to configure the desired cache mode as an Environment
* property on all nodes in a Replicated Environment.</p>
*
* <p>On a Replica, per-Database control over the cache mode for <em>write</em>
* operations is possible by opening the Database on the Replica and
* configuring the cache mode. Per-Cursor control (meaning per-record or
* per-operation) control of the cache mode is not possible on a Replica for
* <em>write</em> operations. For <em>read</em> operations, both per-Database
* and per-Cursor control is possible on the Replica, as described above.</p>
* <p>
* The cache related stats in {@link EnvironmentStats} can provide some measure
* of the effectiveness of the cache mode choice.
*
* @see <a href="EnvironmentStats.html#cacheSizing">Cache Statistics:
* Sizing</a>
*/
public enum CacheMode {
/**
* The record's hotness is changed to "most recently used" by the
* operation.
*
* <p>This cache mode is used when the application does not need explicit
* control over the cache and a standard LRU approach is sufficient.</p>
*
* <p>Note that {@code null} may be specified to use the {@code DEFAULT}
* mode.</p>
*
* <p>Specifically:
* <ul>
* <li>The BIN containing the record's LN will remain in the main
* cache, and it is moved to the hot end of its LRU list.</li>
*
* <li>When an off-heap cache is configured, the record's LN and BIN
* will be loaded into the main cache only. They will be removed from
* the off-heap cache, if they were present there. However, if other
* LNs belonging to this BIN were present in the off-heap cache, they
* will remain there.</li>
* </ul>
*/
DEFAULT,
/**
* @deprecated please use {@link #DEFAULT} instead. As of JE 4.0, this mode
* functions exactly as if {@link #DEFAULT} were specified.
*/
KEEP_HOT,
/**
* The record's hotness or coldness is unchanged by the operation where
* this cache mode is specified.
*
* <p>This cache mode is normally used when the application prefers that
* the operation should not perturb the cache, for example, when scanning
* over all records in a database.</p>
*
* <p>Specifically:
* <ul>
* <li>A record's LN and BIN must be loaded into the main cache in
* order to perform the operation. However, they may be removed from
* the main cache after the operation, to avoid a net change to the
* cache, according to the rules below.</li>
*
* <li>If the record's LN was not present in the main cache prior to
* the operation, then the LN will be evicted from the main cache
* after the operation. The LN will not be added to, or removed from,
* the off-heap cache.</li>
*
* <li>When the LN is to be evicted from the main cache (according to
* the above rules) and the operation is not performed via a cursor,
* the LN is evicted when the operation is complete. When a cursor is
* used, the LN is evicted when the cursor is moved to a different
* record or closed.</li>
*
* <li>If the record's BIN was not present in the main cache prior to
* the operation, the action taken depends on whether the BIN is dirty
* and whether an off-heap cache is configured.
* <ul>
* <li>When the BIN is not dirty, the BIN (and LN) will be evicted
* from the main cache after the operation. The BIN (and LN) will
* not be added to, or removed from, the off-heap cache.</li>
*
* <li>When the BIN is dirty and an off-heap cache is
* <em>not</em> configured, the BIN will not be evicted from the
* main cache and will be moved to the hot end of its main cache
* LRU list. This is done to reduce logging.</li>
*
* <li>When the BIN is dirty and an off-heap cache <em>is</em>
* configured, we evict the BIN from the main cache even when it
* is dirty because the BIN (and LN) will be stored in the off-heap
* cache and the BIN will not be logged. The BIN will be placed at
* the hot end of its off-heap LRU list.</li>
*
* <li>Note that when this operation loaded the BIN and the BIN
* becomes dirty, it is normally because this operation is a write
* operation. However, other concurrent threads can also dirty the
* BIN.</li>
* </ul>
*
* <li>When the BIN is to be evicted from the main cache (according
* to the above rules) and the operation is not performed via a
* cursor, the BIN is evicted when the operation is complete. When a
* cursor is used, the BIN is evicted only when the cursor moves to a
* different BIN or is closed. Because of the way BINs are evicted,
* when multiple operations are performed using a single cursor and
* not perturbing the cache is desired, it is important to use this
* cache mode for all of the operations.</li>
*
* <li>When the BIN was present in the main cache prior to the
* operation, its position in the LRU list will not be changed. Its
* position in the off-heap LRU list, if it is present in the off-heap
* cache, will also not be changed.</li>
* </ul>
*/
UNCHANGED,
/**
* @deprecated please use {@link #UNCHANGED} instead. As of JE 4.0, this
* mode functions exactly as if {@link #UNCHANGED} were specified.
*/
MAKE_COLD,
/**
* The record's LN is evicted after the operation, and the containing
* BIN is moved to the hot end of the LRU list.
*
* <p>This cache mode is normally used when not all LNs will fit into the
* main cache, and the application prefers to read the LN from the log file
* or load it from the off-heap cache when the record is accessed again,
* rather than have it take up space in the main cache and potentially
* cause expensive Java GC. By using this mode, the file system cache or
* off-heap cache can be relied on for holding LNs, which complements the
* use of the JE cache to hold BINs and INs.</p>
*
* <p>Note that using this mode for all operations will prevent the cache
* from filling, if all internal nodes fit in cache.</p>
*
* <p>Specifically:
* <ul>
* <li>The record's LN will be evicted from the main cache after the
* operation. The LN will be added to the off-heap cache, if it is not
* already present and an off-heap cache is configured.</li>
*
* <li>When the operation is not performed via a cursor, the LN is
* evicted when the operation is complete. When a cursor is used, the
* LN is evicted when the cursor is moved to a different record or
* closed.</li>
* </ul>
*
* @since 3.3.98
*/
EVICT_LN,
/**
* The record's BIN (and its LNs) are evicted after the operation.
*
* <p>This cache mode is normally used when not all BINs will fit into the
* main cache, and the application prefers to read the LN and BIN from the
* log file or load it from the off-heap cache when the record is accessed
* again, rather than have them take up space in the JE cache and
* potentially cause expensive Java GC.</p>
*
* <p>Because this mode evicts all LNs in the BIN, even if they are "hot"
* from the perspective of a different accessor, this mode should be used
* with caution. One valid use case is where all accessors use this mode;
* in this case the cache mode might be set on a per-Database or
* per-Environment basis.</p>
*
* <p>Note that using this mode for all operations will prevent the cache
* from filling, if all upper internal nodes fit in cache.</p>
*
* <p>Specifically:
* <ul>
* <li>The record's LN will be evicted from the main cache after the
* operation. The LN will be added to the off-heap cache, if it is not
* already present and an off-heap cache is configured.</li>
*
* <li>When the operation is not performed via a cursor, the LN is
* evicted when the operation is complete. When a cursor is used, the
* LN is evicted when the cursor is moved to a different record or
* closed.</li>
*
* <li>Whether the BIN is evicted depends on whether the BIN is dirty
* and whether an off-heap cache is configured.
* <ul>
* <li>When the BIN is not dirty, the BIN (and LN) will be evicted
* from the main cache after the operation. The BIN (and LN) will
* be added to the off-heap cache, if they are not already present
* and an off-heap cache is configured. The BIN will be placed at
* the hot end of its off-heap LRU list.</li>
*
* <li>When the BIN is dirty and an off-heap cache is
* <em>not</em> configured, the BIN will not be evicted from the
* main cache and will be moved to the hot end of its main cache
* LRU list. This is done to reduce logging.</li>
*
* <li>When the BIN is dirty and an off-heap cache <em>is</em>
* configured, we evict the BIN from the main cache even when it
* is dirty because the BIN (and LN) will be stored in the off-heap
* cache and the BIN will not be logged. The BIN will be placed at
* the hot end of its off-heap LRU list.</li>
*
* <li>Note that BIN may have been dirtied by this operation, if
* it is a write operation, or by earlier write operations.</li>
* </ul>
*
* <li>When the BIN is to be evicted from the main cache (according
* to the above rules) and the operation is not performed via a
* cursor, the BIN is evicted when the operation is complete. When a
* cursor is used, the BIN is evicted only when the cursor moves to a
* different BIN or is closed. Because of the way BINs are evicted,
* when multiple operations are performed using a single cursor and
* not perturbing the cache is desired, it is important to use this
* cache mode for all of the operations.</li>
* </ul>
*
* @since 4.0.97
*/
EVICT_BIN,
/**
* @hidden
* For internal use only.
* Placeholder to avoid DPL class evolution errors. Never actually used.
* @since 4.0.97
*/
DYNAMIC
}