| /*- |
| * 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(); |
| } |
| } |