blob: 1c249f6d40b43ad7fca62d36e5ab7636051b862e [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;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Properties;
import com.sleepycat.je.config.ConfigParam;
import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.dbi.DbConfigManager;
import com.sleepycat.je.dbi.EnvironmentImpl;
/**
* Specifies the environment attributes that may be changed after the
* environment has been opened. EnvironmentMutableConfig is a parameter to
* {@link Environment#setMutableConfig} and is returned by {@link
* Environment#getMutableConfig}.
*
* <p>There are two types of mutable environment properties: per-environment
* handle properties, and environment wide properties.</p>
*
* <h3>Per-Environment Handle Properties</h3>
*
* <p>Per-environment handle properties apply only to a single Environment
* instance. For example, to change the default transaction commit behavior
* for a single environment handle, do this:</p>
*
* <blockquote><pre>
* // Specify no-sync behavior for a given handle.
* EnvironmentMutableConfig mutableConfig = env.getMutableConfig();
* mutableConfig.setDurability(Durability.COMMIT_NO_SYNC);
* env.setMutableConfig(mutableConfig);
* </pre></blockquote>
*
* <p>The per-environment handle properties are listed below. These properties
* are accessed using the setter and getter methods listed, as shown in the
* example above.</p>
*
* <ul>
* <li>{@link #setDurability}, {@link #getDurability}</li>
* <li>{@link #setTxnNoSync}, {@link #getTxnNoSync} <em>deprecated</em></li>
* <li>{@link #setTxnWriteNoSync}, {@link #getTxnWriteNoSync} <em>deprecated</em></li>
* </ul>
*
* <h4>Environment-Wide Mutable Properties</h4>
*
* <p>Environment-wide mutable properties are those that can be changed for an
* environment as a whole, irrespective of which environment instance (for the
* same physical environment) is used. For example, to stop the cleaner daemon
* thread, do this:</p>
*
* <blockquote><pre>
* // Stop the cleaner daemon threads for the environment.
* EnvironmentMutableConfig mutableConfig = env.getMutableConfig();
* mutableConfig.setConfigParam(EnvironmentConfig.ENV_RUN_CLEANER, "false");
* env.setMutableConfig(mutableConfig);
* </pre></blockquote>
*
* <p>The environment-wide mutable properties are documented as such for each
* EnvironmentConfig String constant.</p>
*
* <h4>Getting the Current Environment Properties</h4>
*
* To get the current "live" properties of an environment after constructing it
* or changing its properties, you must call {@link Environment#getConfig} or
* {@link Environment#getMutableConfig}. The original EnvironmentConfig or
* EnvironmentMutableConfig object used to set the properties is not kept up to
* date as properties are changed, and does not reflect property validation or
* properties that are computed.
*
* @see EnvironmentConfig
*/
public class EnvironmentMutableConfig implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
/*
* Change copyHandlePropsTo and Environment.copyToHandleConfig when adding
* fields here.
*/
private boolean txnNoSync = false;
private boolean txnWriteNoSync = false;
/**
* Cache size is a category of property that is calculated within the
* environment. It is only supplied when returning the cache size to the
* application and never used internally; internal code directly checks
* with the MemoryBudget class;
*/
private long cacheSize;
private long offHeapCacheSize;
/**
* Note that in the implementation we choose not to extend Properties in
* order to keep the configuration type safe.
*/
Properties props;
/**
* For unit testing, to prevent loading of je.properties.
*/
private transient boolean loadPropertyFile = true;
/**
* Internal boolean that says whether or not to validate params. Setting
* it to false means that parameter value validatation won't be performed
* during setVal() calls. Only should be set to false by unit tests using
* DbInternal.
*/
transient boolean validateParams = true;
private transient ExceptionListener exceptionListener = null;
private CacheMode cacheMode;
/**
* An instance created using the default constructor is initialized with
* the system's default settings.
*/
public EnvironmentMutableConfig() {
props = new Properties();
}
/**
* Used by EnvironmentConfig to construct from properties.
*/
EnvironmentMutableConfig(Properties properties)
throws IllegalArgumentException {
DbConfigManager.validateProperties(properties,
false, // isRepConfigInstance
getClass().getName());
/* For safety, copy the passed in properties. */
props = new Properties();
props.putAll(properties);
}
/**
* Configures the database environment for asynchronous transactions.
*
* @param noSync If true, do not write or synchronously flush the log on
* transaction commit. This means that transactions exhibit the ACI
* (Atomicity, Consistency, and Isolation) properties, but not D
* (Durability); that is, database integrity is maintained, but if the JVM
* or operating system fails, it is possible some number of the most
* recently committed transactions may be undone during recovery. The
* number of transactions at risk is governed by how many updates fit into
* a log buffer, how often the operating system flushes dirty buffers to
* disk, and how often the database environment is checkpointed.
*
* <p>This attribute is false by default for this class and for the
* database environment.</p>
*
* @deprecated replaced by {@link #setDurability}
*/
public EnvironmentMutableConfig setTxnNoSync(boolean noSync) {
setTxnNoSyncVoid(noSync);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setTxnNoSyncVoid(boolean noSync) {
TransactionConfig.checkMixedMode
(false, noSync, txnWriteNoSync, getDurability());
txnNoSync = noSync;
}
/**
* Returns true if the database environment is configured for asynchronous
* transactions.
*
* @return true if the database environment is configured for asynchronous
* transactions.
*
* @deprecated replaced by {@link #getDurability}
*/
public boolean getTxnNoSync() {
return txnNoSync;
}
/**
* Configures the database environment for transactions which write but do
* not flush the log.
*
* @param writeNoSync If true, write but do not synchronously flush the log
* on transaction commit. This means that transactions exhibit the ACI
* (Atomicity, Consistency, and Isolation) properties, but not D
* (Durability); that is, database integrity is maintained, but if the
* operating system fails, it is possible some number of the most recently
* committed transactions may be undone during recovery. The number of
* transactions at risk is governed by how often the operating system
* flushes dirty buffers to disk, and how often the database environment is
* checkpointed.
*
* <p>The motivation for this attribute is to provide a transaction that
* has more durability than asynchronous (nosync) transactions, but has
* higher performance than synchronous transactions.</p>
*
* <p>This attribute is false by default for this class and for the
* database environment.</p>
*
* @deprecated replaced by {@link #setDurability}
*/
public EnvironmentMutableConfig setTxnWriteNoSync(boolean writeNoSync) {
setTxnWriteNoSyncVoid(writeNoSync);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setTxnWriteNoSyncVoid(boolean writeNoSync) {
TransactionConfig.checkMixedMode
(false, txnNoSync, writeNoSync, getDurability());
txnWriteNoSync = writeNoSync;
}
/**
* Returns true if the database environment is configured for transactions
* which write but do not flush the log.
*
* @return true if the database environment is configured for transactions
* which write but do not flush the log.
*
* @deprecated replaced by {@link #getDurability}
*/
public boolean getTxnWriteNoSync() {
return txnWriteNoSync;
}
/**
* Convenience method for setting {@link EnvironmentConfig#TXN_DURABILITY}.
*
* @param durability the new durability definition
*
* @return this
*
* @see Durability
*/
public EnvironmentMutableConfig setDurability(Durability durability) {
setDurabilityVoid(durability);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setDurabilityVoid(Durability durability) {
TransactionConfig.checkMixedMode
(false, txnNoSync, txnWriteNoSync, durability);
if (durability == null) {
props.remove(EnvironmentParams.JE_DURABILITY);
} else {
DbConfigManager.setVal(props, EnvironmentParams.JE_DURABILITY,
durability.toString(),
validateParams);
}
}
/**
* Convenience method for setting {@link EnvironmentConfig#TXN_DURABILITY}.
*
* @return the durability setting currently associated with this config.
*/
public Durability getDurability() {
String value = DbConfigManager.getVal(props,
EnvironmentParams.JE_DURABILITY);
return Durability.parse(value);
}
/**
* A convenience method for setting {@link EnvironmentConfig#MAX_MEMORY}.
*
* @param totalBytes The memory available to the database system, in bytes.
*
* @throws IllegalArgumentException if an invalid parameter is specified.
*
* @return this
*
* @see EnvironmentConfig#MAX_MEMORY
*/
public EnvironmentMutableConfig setCacheSize(long totalBytes)
throws IllegalArgumentException {
setCacheSizeVoid(totalBytes);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setCacheSizeVoid(long totalBytes)
throws IllegalArgumentException {
DbConfigManager.setVal(props, EnvironmentParams.MAX_MEMORY,
Long.toString(totalBytes), validateParams);
}
/**
* Returns the memory available to the database system, in bytes. A valid
* value is only available if this EnvironmentConfig object has been
* returned from Environment.getConfig().
*
* @return The memory available to the database system, in bytes.
*/
public long getCacheSize() {
/*
* CacheSize is filled in from the EnvironmentImpl by way of
* fillInEnvironmentGeneratedProps.
*/
return cacheSize;
}
/**
* A convenience method for setting {@link
* EnvironmentConfig#MAX_MEMORY_PERCENT}.
*
* @param percent The percent of JVM memory to allocate to the JE cache.
*
* @throws IllegalArgumentException if an invalid parameter is specified.
*
* @return this
*
* @see EnvironmentConfig#MAX_MEMORY_PERCENT
*/
public EnvironmentMutableConfig setCachePercent(int percent)
throws IllegalArgumentException {
setCachePercentVoid(percent);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setCachePercentVoid(int percent)
throws IllegalArgumentException {
DbConfigManager.setIntVal(props, EnvironmentParams.MAX_MEMORY_PERCENT,
percent, validateParams);
}
/**
* A convenience method for getting {@link
* EnvironmentConfig#MAX_MEMORY_PERCENT}.
*
* @return the percentage value used in the JE cache size calculation.
*/
public int getCachePercent() {
return DbConfigManager.getIntVal(props,
EnvironmentParams.MAX_MEMORY_PERCENT);
}
/**
* A convenience method for setting
* {@link EnvironmentConfig#MAX_OFF_HEAP_MEMORY}.
*/
public EnvironmentMutableConfig setOffHeapCacheSize(long totalBytes)
throws IllegalArgumentException {
setOffHeapCacheSizeVoid(totalBytes);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setOffHeapCacheSizeVoid(long totalBytes)
throws IllegalArgumentException {
DbConfigManager.setVal(props, EnvironmentParams.MAX_OFF_HEAP_MEMORY,
Long.toString(totalBytes), validateParams);
}
/**
* A convenience method for getting
* {@link EnvironmentConfig#MAX_OFF_HEAP_MEMORY}.
*/
public long getOffHeapCacheSize() {
/*
* CacheSize is filled in from the EnvironmentImpl by way of
* fillInEnvironmentGeneratedProps.
*/
return offHeapCacheSize;
}
/**
* A convenience method for setting {@link EnvironmentConfig#MAX_DISK}.
*
* @param totalBytes is an upper limit on the number of bytes used for
* data storage, or zero if no limit is desired.
*
* @throws IllegalArgumentException if an invalid parameter is specified.
*
* @return this
*
* @see EnvironmentConfig#MAX_DISK
*/
public EnvironmentMutableConfig setMaxDisk(long totalBytes)
throws IllegalArgumentException {
setMaxDiskVoid(totalBytes);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setMaxDiskVoid(long totalBytes)
throws IllegalArgumentException {
DbConfigManager.setVal(props, EnvironmentParams.MAX_DISK,
Long.toString(totalBytes), validateParams);
}
/**
* A convenience method for getting {@link EnvironmentConfig#MAX_DISK}.
*
* @return the upper limit on the number of bytes used for data storage,
* or zero if no limit is set.
*
* @see EnvironmentConfig#MAX_DISK
*/
public long getMaxDisk() {
return DbConfigManager.getLongVal(props, EnvironmentParams.MAX_DISK);
}
/**
* Sets the exception listener for an Environment. The listener is called
* when a daemon thread throws an exception, in order to provide a
* notification mechanism for these otherwise asynchronous exceptions.
* Daemon thread exceptions are also printed through stderr.
* <p>
* Not all daemon exceptions are fatal, and the application bears
* responsibility for choosing how to respond to the notification. Since
* exceptions may repeat, the application should also choose how to handle
* a spate of exceptions. For example, the application may choose to act
* upon each notification, or it may choose to batch up its responses
* by implementing the listener so it stores exceptions, and only acts
* when a certain number have been received.
* @param exceptionListener the callback to be executed when an exception
* occurs.
*
* @return this
*/
public EnvironmentMutableConfig
setExceptionListener(ExceptionListener exceptionListener) {
setExceptionListenerVoid(exceptionListener);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setExceptionListenerVoid(ExceptionListener exceptionListener) {
this.exceptionListener = exceptionListener;
}
/**
* Returns the exception listener, if set.
*/
public ExceptionListener getExceptionListener() {
return exceptionListener;
}
/**
* Sets the default {@code CacheMode} used for operations performed in this
* environment. The default cache mode may be overridden on a per-database
* basis using {@link DatabaseConfig#setCacheMode}, and on a per-record or
* per-operation basis using {@link Cursor#setCacheMode}, {@link
* ReadOptions#setCacheMode(CacheMode)} or {@link
* WriteOptions#setCacheMode(CacheMode)}.
*
* @param cacheMode is the default {@code CacheMode} used for operations
* performed in this environment. If {@code null} is specified, {@link
* CacheMode#DEFAULT} will be used.
*
* @see CacheMode for further details.
*
* @since 4.0.97
*/
public EnvironmentMutableConfig setCacheMode(final CacheMode cacheMode) {
setCacheModeVoid(cacheMode);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setCacheModeVoid(final CacheMode cacheMode) {
this.cacheMode = cacheMode;
}
/**
* Returns the default {@code CacheMode} used for operations performed in
* this environment, or null if {@link CacheMode#DEFAULT} is used.
*
* @return the default {@code CacheMode} used for operations performed on
* this database, or null if {@link CacheMode#DEFAULT} is used.
*
* @see #setCacheMode
*
* @since 4.0.97
*/
public CacheMode getCacheMode() {
return cacheMode;
}
/**
* Set this configuration parameter. First validate the value specified for
* the configuration parameter; if it is valid, the value is set in the
* configuration.
*
* @param paramName the configuration parameter name, one of the String
* constants in this class
*
* @param value The configuration value
*
* @return this
*
* @throws IllegalArgumentException if the paramName or value is invalid.
*/
public EnvironmentMutableConfig setConfigParam(String paramName,
String value)
throws IllegalArgumentException {
DbConfigManager.setConfigParam(props,
paramName,
value,
true, /* require mutability. */
validateParams,
false /* forReplication */,
true /* verifyForReplication */);
return this;
}
/**
* Returns the value for this configuration parameter.
*
* @param paramName a valid configuration parameter, one of the String
* constants in this class.
* @return the configuration value.
* @throws IllegalArgumentException if the paramName is invalid.
*/
public String getConfigParam(String paramName)
throws IllegalArgumentException {
return DbConfigManager.getConfigParam(props, paramName);
}
/**
* @hidden
* For internal use only.
*/
public boolean isConfigParamSet(String paramName) {
return props.containsKey(paramName);
}
/*
* Helpers
*/
void setValidateParams(boolean validateParams) {
this.validateParams = validateParams;
}
/**
* @hidden
* Used by unit tests.
*/
boolean getValidateParams() {
return validateParams;
}
/**
* Checks that the immutable values in the environment config used to open
* an environment match those in the config object saved by the underlying
* shared EnvironmentImpl.
* @param handleConfigProps are the config property values that were
* specified by configuration object from the Environment.
*/
void checkImmutablePropsForEquality(Properties handleConfigProps)
throws IllegalArgumentException {
Iterator<String> iter =
EnvironmentParams.SUPPORTED_PARAMS.keySet().iterator();
while (iter.hasNext()) {
String paramName = iter.next();
ConfigParam param =
EnvironmentParams.SUPPORTED_PARAMS.get(paramName);
assert param != null;
if (!param.isMutable() && !param.isForReplication()) {
String paramVal = props.getProperty(paramName);
String useParamVal = handleConfigProps.getProperty(paramName);
if ((paramVal != null) ?
(!paramVal.equals(useParamVal)) :
(useParamVal != null)) {
throw new IllegalArgumentException
(paramName + " is set to " +
useParamVal +
" in the config parameter" +
" which is incompatible" +
" with the value of " +
paramVal + " in the" +
" underlying environment");
}
}
}
}
/**
* @hidden
* For internal use only.
* Overrides Object.clone() to clone all properties, used by this class and
* EnvironmentConfig.
*/
@Override
protected EnvironmentMutableConfig clone() {
try {
EnvironmentMutableConfig copy =
(EnvironmentMutableConfig) super.clone();
copy.props = (Properties) props.clone();
return copy;
} catch (CloneNotSupportedException willNeverOccur) {
return null;
}
}
/**
* Used by Environment to create a copy of the application supplied
* configuration. Done this way to provide non-public cloning.
*/
EnvironmentMutableConfig cloneMutableConfig() {
EnvironmentMutableConfig copy = (EnvironmentMutableConfig) clone();
/* Remove all immutable properties. */
copy.clearImmutableProps();
return copy;
}
/**
* Copies the per-handle properties of this object to the given config
* object.
*/
void copyHandlePropsTo(EnvironmentMutableConfig other) {
other.txnNoSync = txnNoSync;
other.txnWriteNoSync = txnWriteNoSync;
other.setDurability(getDurability());
}
/**
* Copies all mutable props to the given config object.
* Unchecked suppress here because Properties don't play well with
* generics in Java 1.5
*/
@SuppressWarnings("unchecked")
void copyMutablePropsTo(EnvironmentMutableConfig toConfig) {
Properties toProps = toConfig.props;
Enumeration propNames = props.propertyNames();
while (propNames.hasMoreElements()) {
String paramName = (String) propNames.nextElement();
ConfigParam param =
EnvironmentParams.SUPPORTED_PARAMS.get(paramName);
assert param != null;
if (param.isMutable()) {
String newVal = props.getProperty(paramName);
toProps.setProperty(paramName, newVal);
}
}
toConfig.exceptionListener = this.exceptionListener;
toConfig.cacheMode = this.cacheMode;
}
/**
* Fills in the properties calculated by the environment to the given
* config object.
*/
void fillInEnvironmentGeneratedProps(EnvironmentImpl envImpl) {
cacheSize = envImpl.getMemoryBudget().getMaxMemory();
offHeapCacheSize = envImpl.getOffHeapCache().getMaxMemory();
}
/**
* Removes all immutable props.
* Unchecked suppress here because Properties don't play well with
* generics in Java 1.5
*/
@SuppressWarnings("unchecked")
private void clearImmutableProps() {
Enumeration propNames = props.propertyNames();
while (propNames.hasMoreElements()) {
String paramName = (String) propNames.nextElement();
ConfigParam param =
EnvironmentParams.SUPPORTED_PARAMS.get(paramName);
assert param != null;
if (!param.isMutable()) {
props.remove(paramName);
}
}
}
Properties getProps() {
return props;
}
/**
* For unit testing, to prevent loading of je.properties.
*/
void setLoadPropertyFile(boolean loadPropertyFile) {
this.loadPropertyFile = loadPropertyFile;
}
/**
* For unit testing, to prevent loading of je.properties.
*/
boolean getLoadPropertyFile() {
return loadPropertyFile;
}
/**
* Testing support
* @hidden
*/
public int getNumExplicitlySetParams() {
return props.size();
}
/**
* Display configuration values.
*/
@Override
public String toString() {
return " cacheSize=" + cacheSize +
" offHeapCacheSize=" + offHeapCacheSize +
" cacheMode=" + cacheMode +
" txnNoSync=" + txnNoSync +
" txnWriteNoSync=" + txnWriteNoSync +
" exceptionListener=" + (exceptionListener != null) +
" map=" + props.toString();
}
}