/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2002-2005 * Sleepycat Software. All rights reserved. * * $Id: DatabaseConfig.java,v 12.2 2005/06/16 20:22:59 bostic Exp $ */ package com.sleepycat.db; import com.sleepycat.db.internal.Db; import com.sleepycat.db.internal.DbConstants; import com.sleepycat.db.internal.DbEnv; import com.sleepycat.db.internal.DbTxn; import com.sleepycat.db.internal.DbUtil; public class DatabaseConfig implements Cloneable { /* * For internal use, final to allow null as a valid value for * the config parameter. */ public static final DatabaseConfig DEFAULT = new DatabaseConfig(); /* package */ static DatabaseConfig checkNull(DatabaseConfig config) { return (config == null) ? DEFAULT : config; } /* Parameters */ private DatabaseType type = DatabaseType.UNKNOWN; private int mode = 0644; private int btMinKey = 0; private int byteOrder = 0; private long cacheSize = 0L; private int cacheCount = 0; private java.io.OutputStream errorStream = null; private String errorPrefix = null; private int hashFillFactor = 0; private int hashNumElements = 0; private java.io.OutputStream messageStream = null; private int pageSize = 0; private String password = null; private int queueExtentSize = 0; private int recordDelimiter = 0; private int recordLength = 0; private int recordPad = -1; // Zero is a valid, non-default value. private java.io.File recordSource = null; /* Flags */ private boolean allowCreate = false; private boolean btreeRecordNumbers = false; private boolean checksum = false; private boolean readUncommitted = false; private boolean encrypted = false; private boolean exclusiveCreate = false; private boolean noMMap = false; private boolean queueInOrder = false; private boolean readOnly = false; private boolean renumbering = false; private boolean reverseSplitOff = false; private boolean sortedDuplicates = false; private boolean snapshot = false; private boolean unsortedDuplicates = false; private boolean transactional = false; private boolean transactionNotDurable = false; private boolean truncate = false; private boolean xaCreate = false; private java.util.Comparator btreeComparator = null; private BtreePrefixCalculator btreePrefixCalculator = null; private java.util.Comparator duplicateComparator = null; private FeedbackHandler feedbackHandler = null; private ErrorHandler errorHandler = null; private MessageHandler messageHandler = null; private Hasher hasher = null; private RecordNumberAppender recnoAppender = null; private PanicHandler panicHandler = null; public DatabaseConfig() { } public void setAllowCreate(final boolean allowCreate) { this.allowCreate = allowCreate; } public boolean getAllowCreate() { return allowCreate; } public void setBtreeComparator(final java.util.Comparator btreeComparator) { this.btreeComparator = btreeComparator; } public java.util.Comparator getBtreeComparator() { return btreeComparator; } public void setBtreeMinKey(final int btMinKey) { this.btMinKey = btMinKey; } public int getBtreeMinKey() { return btMinKey; } public void setByteOrder(final int byteOrder) { this.byteOrder = byteOrder; } public int getByteOrder() { return byteOrder; } public boolean getByteSwapped() { return byteOrder != 0 && byteOrder != DbUtil.default_lorder(); } public void setBtreePrefixCalculator( final BtreePrefixCalculator btreePrefixCalculator) { this.btreePrefixCalculator = btreePrefixCalculator; } public BtreePrefixCalculator getBtreePrefixCalculator() { return btreePrefixCalculator; } public void setCacheSize(final long cacheSize) { this.cacheSize = cacheSize; } public long getCacheSize() { return cacheSize; } public void setCacheCount(final int cacheCount) { this.cacheCount = cacheCount; } public int getCacheCount() { return cacheCount; } public void setChecksum(final boolean checksum) { this.checksum = checksum; } public boolean getChecksum() { return checksum; } public void setReadUncommitted(final boolean readUncommitted) { this.readUncommitted = readUncommitted; } public boolean getReadUncommitted() { return readUncommitted; } /** @deprecated */ public void setDirtyRead(final boolean dirtyRead) { setReadUncommitted(dirtyRead); } /** @deprecated */ public boolean getDirtyRead() { return getReadUncommitted(); } public void setDuplicateComparator(final java.util.Comparator duplicateComparator) { this.duplicateComparator = duplicateComparator; } public java.util.Comparator getDuplicateComparator() { return duplicateComparator; } public void setEncrypted(final String password) { this.password = password; } public boolean getEncrypted() { return (password != null); } public void setErrorHandler(final ErrorHandler errorHandler) { this.errorHandler = errorHandler; } public ErrorHandler getErrorHandler() { return errorHandler; } public void setErrorPrefix(final String errorPrefix) { this.errorPrefix = errorPrefix; } public String getErrorPrefix() { return errorPrefix; } public void setErrorStream(final java.io.OutputStream errorStream) { this.errorStream = errorStream; } public java.io.OutputStream getErrorStream() { return errorStream; } public void setExclusiveCreate(final boolean exclusiveCreate) { this.exclusiveCreate = exclusiveCreate; } public boolean getExclusiveCreate() { return exclusiveCreate; } public void setFeedbackHandler(final FeedbackHandler feedbackHandler) { this.feedbackHandler = feedbackHandler; } public FeedbackHandler getFeedbackHandler() { return feedbackHandler; } public void setHashFillFactor(final int hashFillFactor) { this.hashFillFactor = hashFillFactor; } public int getHashFillFactor() { return hashFillFactor; } public void setHasher(final Hasher hasher) { this.hasher = hasher; } public Hasher getHasher() { return hasher; } public void setHashNumElements(final int hashNumElements) { this.hashNumElements = hashNumElements; } public int getHashNumElements() { return hashNumElements; } public void setMessageHandler(final MessageHandler messageHandler) { this.messageHandler = messageHandler; } public MessageHandler getMessageHandler() { return messageHandler; } public void setMessageStream(final java.io.OutputStream messageStream) { this.messageStream = messageStream; } public java.io.OutputStream getMessageStream() { return messageStream; } public void setMode(final int mode) { this.mode = mode; } public long getMode() { return mode; } public void setNoMMap(final boolean noMMap) { this.noMMap = noMMap; } public boolean getNoMMap() { return noMMap; } public void setPageSize(final int pageSize) { this.pageSize = pageSize; } public int getPageSize() { return pageSize; } public void setPanicHandler(final PanicHandler panicHandler) { this.panicHandler = panicHandler; } public PanicHandler getPanicHandler() { return panicHandler; } public void setQueueExtentSize(final int queueExtentSize) { this.queueExtentSize = queueExtentSize; } public int getQueueExtentSize() { return queueExtentSize; } public void setQueueInOrder(final boolean queueInOrder) { this.queueInOrder = queueInOrder; } public boolean getQueueInOrder() { return queueInOrder; } public void setReadOnly(final boolean readOnly) { this.readOnly = readOnly; } public boolean getReadOnly() { return readOnly; } public void setRecordNumberAppender(final RecordNumberAppender recnoAppender) { this.recnoAppender = recnoAppender; } public RecordNumberAppender getRecordNumberAppender() { return recnoAppender; } public void setRecordDelimiter(final int recordDelimiter) { this.recordDelimiter = recordDelimiter; } public int getRecordDelimiter() { return recordDelimiter; } public void setRecordLength(final int recordLength) { this.recordLength = recordLength; } public int getRecordLength() { return recordLength; } public void setBtreeRecordNumbers(final boolean btreeRecordNumbers) { this.btreeRecordNumbers = btreeRecordNumbers; } public boolean getBtreeRecordNumbers() { return btreeRecordNumbers; } public void setRecordPad(final int recordPad) { this.recordPad = recordPad; } public int getRecordPad() { return recordPad; } public void setRecordSource(final java.io.File recordSource) { this.recordSource = recordSource; } public java.io.File getRecordSource() { return recordSource; } public void setRenumbering(final boolean renumbering) { this.renumbering = renumbering; } public boolean getRenumbering() { return renumbering; } public void setReverseSplitOff(final boolean reverseSplitOff) { this.reverseSplitOff = reverseSplitOff; } public boolean getReverseSplitOff() { return reverseSplitOff; } public void setSortedDuplicates(final boolean sortedDuplicates) { this.sortedDuplicates = sortedDuplicates; } public boolean getSortedDuplicates() { return sortedDuplicates; } public void setUnsortedDuplicates(final boolean unsortedDuplicates) { this.unsortedDuplicates = unsortedDuplicates; } public boolean getUnsortedDuplicates() { return unsortedDuplicates; } public void setSnapshot(final boolean snapshot) { this.snapshot = snapshot; } public boolean getSnapshot() { return snapshot; } public boolean getTransactional() { return transactional; } public void setTransactional(final boolean transactional) { this.transactional = transactional; } public void setTransactionNotDurable(final boolean transactionNotDurable) { this.transactionNotDurable = transactionNotDurable; } public boolean getTransactionNotDurable() { return transactionNotDurable; } public void setTruncate(final boolean truncate) { this.truncate = truncate; } public boolean getTruncate() { return truncate; } public void setType(final DatabaseType type) { this.type = type; } public DatabaseType getType() { return type; } public void setXACreate(final boolean xaCreate) { this.xaCreate = xaCreate; } public boolean getXACreate() { return xaCreate; } /* package */ Db createDatabase(final DbEnv dbenv) throws DatabaseException { int createFlags = 0; createFlags |= xaCreate ? DbConstants.DB_XA_CREATE : 0; return new Db(dbenv, createFlags); } /* package */ Db openDatabase(final DbEnv dbenv, final DbTxn txn, final String fileName, final String databaseName) throws DatabaseException, java.io.FileNotFoundException { final Db db = createDatabase(dbenv); // The DB_THREAD flag is inherited from the environment // (defaulting to ON if no environment handle is supplied). boolean threaded = (dbenv == null || (dbenv.get_open_flags() & DbConstants.DB_THREAD) != 0); int openFlags = 0; openFlags |= allowCreate ? DbConstants.DB_CREATE : 0; openFlags |= readUncommitted ? DbConstants.DB_READ_UNCOMMITTED : 0; openFlags |= exclusiveCreate ? DbConstants.DB_EXCL : 0; openFlags |= noMMap ? DbConstants.DB_NOMMAP : 0; openFlags |= readOnly ? DbConstants.DB_RDONLY : 0; openFlags |= threaded ? DbConstants.DB_THREAD : 0; openFlags |= truncate ? DbConstants.DB_TRUNCATE : 0; if (transactional && txn == null) openFlags |= DbConstants.DB_AUTO_COMMIT; boolean succeeded = false; try { configureDatabase(db, DEFAULT); db.open(txn, fileName, databaseName, type.getId(), openFlags, mode); succeeded = true; return db; } finally { if (!succeeded) try { db.close(0); } catch (Throwable t) { // Ignore it -- an exception is already in flight. } } } /* package */ void configureDatabase(final Db db, final DatabaseConfig oldConfig) throws DatabaseException { int dbFlags = 0; dbFlags |= checksum ? DbConstants.DB_CHKSUM : 0; dbFlags |= (password != null) ? DbConstants.DB_ENCRYPT : 0; dbFlags |= btreeRecordNumbers ? DbConstants.DB_RECNUM : 0; dbFlags |= queueInOrder ? DbConstants.DB_INORDER : 0; dbFlags |= renumbering ? DbConstants.DB_RENUMBER : 0; dbFlags |= reverseSplitOff ? DbConstants.DB_REVSPLITOFF : 0; dbFlags |= sortedDuplicates ? DbConstants.DB_DUPSORT : 0; dbFlags |= snapshot ? DbConstants.DB_SNAPSHOT : 0; dbFlags |= unsortedDuplicates ? DbConstants.DB_DUP : 0; dbFlags |= transactionNotDurable ? DbConstants.DB_TXN_NOT_DURABLE : 0; if (dbFlags != 0) db.set_flags(dbFlags); if (btMinKey != oldConfig.btMinKey) db.set_bt_minkey(btMinKey); if (byteOrder != oldConfig.byteOrder) db.set_lorder(byteOrder); if (cacheSize != oldConfig.cacheSize || cacheCount != oldConfig.cacheCount) db.set_cachesize(cacheSize, cacheCount); if (errorStream != oldConfig.errorStream) db.set_error_stream(errorStream); if (errorPrefix != oldConfig.errorPrefix) db.set_errpfx(errorPrefix); if (hashFillFactor != oldConfig.hashFillFactor) db.set_h_ffactor(hashFillFactor); if (hashNumElements != oldConfig.hashNumElements) db.set_h_nelem(hashNumElements); if (messageStream != oldConfig.messageStream) db.set_message_stream(messageStream); if (pageSize != oldConfig.pageSize) db.set_pagesize(pageSize); if (password != oldConfig.password) db.set_encrypt(password, DbConstants.DB_ENCRYPT_AES); if (queueExtentSize != oldConfig.queueExtentSize) db.set_q_extentsize(queueExtentSize); if (recordDelimiter != oldConfig.recordDelimiter) db.set_re_delim(recordDelimiter); if (recordLength != oldConfig.recordLength) db.set_re_len(recordLength); if (recordPad != oldConfig.recordPad) db.set_re_pad(recordPad); if (recordSource != oldConfig.recordSource) db.set_re_source( (recordSource == null) ? null : recordSource.toString()); if (btreeComparator != oldConfig.btreeComparator) db.set_bt_compare(btreeComparator); if (btreePrefixCalculator != oldConfig.btreePrefixCalculator) db.set_bt_prefix(btreePrefixCalculator); if (duplicateComparator != oldConfig.duplicateComparator) db.set_dup_compare(duplicateComparator); if (feedbackHandler != oldConfig.feedbackHandler) db.set_feedback(feedbackHandler); if (errorHandler != oldConfig.errorHandler) db.set_errcall(errorHandler); if (hasher != oldConfig.hasher) db.set_h_hash(hasher); if (messageHandler != oldConfig.messageHandler) db.set_msgcall(messageHandler); if (recnoAppender != oldConfig.recnoAppender) db.set_append_recno(recnoAppender); if (panicHandler != oldConfig.panicHandler) db.set_paniccall(panicHandler); } /* package */ DatabaseConfig(final Db db) throws DatabaseException { type = DatabaseType.fromInt(db.get_type()); final int openFlags = db.get_open_flags(); allowCreate = (openFlags & DbConstants.DB_CREATE) != 0; readUncommitted = (openFlags & DbConstants.DB_READ_UNCOMMITTED) != 0; exclusiveCreate = (openFlags & DbConstants.DB_EXCL) != 0; noMMap = (openFlags & DbConstants.DB_NOMMAP) != 0; readOnly = (openFlags & DbConstants.DB_RDONLY) != 0; truncate = (openFlags & DbConstants.DB_TRUNCATE) != 0; final int dbFlags = db.get_flags(); checksum = (dbFlags & DbConstants.DB_CHKSUM) != 0; btreeRecordNumbers = (dbFlags & DbConstants.DB_RECNUM) != 0; queueInOrder = (dbFlags & DbConstants.DB_INORDER) != 0; renumbering = (dbFlags & DbConstants.DB_RENUMBER) != 0; reverseSplitOff = (dbFlags & DbConstants.DB_REVSPLITOFF) != 0; sortedDuplicates = (dbFlags & DbConstants.DB_DUPSORT) != 0; snapshot = (dbFlags & DbConstants.DB_SNAPSHOT) != 0; unsortedDuplicates = (dbFlags & DbConstants.DB_DUP) != 0; transactionNotDurable = (dbFlags & DbConstants.DB_TXN_NOT_DURABLE) != 0; if (type == DatabaseType.BTREE) { btMinKey = db.get_bt_minkey(); } byteOrder = db.get_lorder(); // Call get_cachesize* on the DbEnv to avoid this error: // DB->get_cachesize: method not permitted in shared environment cacheSize = db.get_env().get_cachesize(); cacheCount = db.get_env().get_cachesize_ncache(); errorStream = db.get_error_stream(); errorPrefix = db.get_errpfx(); if (type == DatabaseType.HASH) { hashFillFactor = db.get_h_ffactor(); hashNumElements = db.get_h_nelem(); } messageStream = db.get_message_stream(); // Not available by design password = ((dbFlags & DbConstants.DB_ENCRYPT) != 0) ? "" : null; if (type == DatabaseType.QUEUE) { queueExtentSize = db.get_q_extentsize(); } if (type == DatabaseType.QUEUE || type == DatabaseType.RECNO) { recordLength = db.get_re_len(); recordPad = db.get_re_pad(); } if (type == DatabaseType.RECNO) { recordDelimiter = db.get_re_delim(); recordSource = (db.get_re_source() == null) ? null : new java.io.File(db.get_re_source()); } transactional = db.get_transactional(); btreeComparator = db.get_bt_compare(); btreePrefixCalculator = db.get_bt_prefix(); duplicateComparator = db.get_dup_compare(); feedbackHandler = db.get_feedback(); errorHandler = db.get_errcall(); hasher = db.get_h_hash(); messageHandler = db.get_msgcall(); recnoAppender = db.get_append_recno(); panicHandler = db.get_paniccall(); } }