SID[1] = (byte) 0x33;
}
+ /** default value for the auto-sync value ({@code true}). this is slower,
+ but leaves more chance of a useable database in the face of failures. */
+ public static final boolean DEFAULT_AUTO_SYNC = true;
+
/** Batch commit size for copying other result sets into this database */
private static final int COPY_TABLE_BATCH_SIZE = 200;
/**
* Open an existing Database. If the existing file is not writeable, the
- * file will be opened read-only.
+ * file will be opened read-only. Auto-syncing is enabled for the returned
+ * Database.
* @param mdbFile File containing the database
*/
public static Database open(File mdbFile) throws IOException {
/**
* Open an existing Database. If the existing file is not writeable or the
* readOnly flag is <code>true</code>, the file will be opened read-only.
+ * Auto-syncing is enabled for the returned Database.
* @param mdbFile File containing the database
* @param readOnly iff <code>true</code>, force opening file in read-only
* mode
public static Database open(File mdbFile, boolean readOnly)
throws IOException
{
+ return open(mdbFile, readOnly, DEFAULT_AUTO_SYNC);
+ }
+
+ /**
+ * Open an existing Database. If the existing file is not writeable or the
+ * readOnly flag is <code>true</code>, the file will be opened read-only.
+ * @param mdbFile File containing the database
+ * @param readOnly iff <code>true</code>, force opening file in read-only
+ * mode
+ * @param autoSync whether or not to enable auto-syncing on write. if
+ * {@code true}, writes will be immediately flushed to disk.
+ * This leaves the database in a (fairly) consistent state
+ * on each write, but can be very inefficient for many
+ * updates. if {@code false}, flushing to disk happens at
+ * the jvm's leisure, which can be much faster, but may
+ * leave the database in an inconsistent state if failures
+ * are encountered during writing.
+ */
+ public static Database open(File mdbFile, boolean readOnly, boolean autoSync)
+ throws IOException
+ {
if(!mdbFile.exists() || !mdbFile.canRead()) {
throw new FileNotFoundException("given file does not exist: " + mdbFile);
}
return new Database(openChannel(mdbFile,
- (!mdbFile.canWrite() || readOnly)));
+ (!mdbFile.canWrite() || readOnly)),
+ autoSync);
}
/**
* already exists, it will be overwritten.</b>
*/
public static Database create(File mdbFile) throws IOException {
+ return create(mdbFile, DEFAULT_AUTO_SYNC);
+ }
+
+ /**
+ * Create a new Database
+ * @param mdbFile Location to write the new database to. <b>If this file
+ * already exists, it will be overwritten.</b>
+ * @param autoSync whether or not to enable auto-syncing on write. if
+ * {@code true}, writes will be immediately flushed to disk.
+ * This leaves the database in a (fairly) consistent state
+ * on each write, but can be very inefficient for many
+ * updates. if {@code false}, flushing to disk happens at
+ * the jvm's leisure, which can be much faster, but may
+ * leave the database in an inconsistent state if failures
+ * are encountered during writing.
+ */
+ public static Database create(File mdbFile, boolean autoSync)
+ throws IOException
+ {
FileChannel channel = openChannel(mdbFile, false);
channel.transferFrom(Channels.newChannel(
Thread.currentThread().getContextClassLoader().getResourceAsStream(
EMPTY_MDB)), 0, (long) Integer.MAX_VALUE);
- return new Database(channel);
+ return new Database(channel, autoSync);
}
private static FileChannel openChannel(File mdbFile, boolean readOnly)
* FileChannel instead of a ReadableByteChannel because we need to
* randomly jump around to various points in the file.
*/
- protected Database(FileChannel channel) throws IOException {
+ protected Database(FileChannel channel, boolean autoSync) throws IOException
+ {
_format = JetFormat.getFormat(channel);
- _pageChannel = new PageChannel(channel, _format);
+ _pageChannel = new PageChannel(channel, _format, autoSync);
_buffer = _pageChannel.createPageBuffer();
readSystemCatalog();
}
private JetFormat _format;
/** Tracks free pages in the database. */
private UsageMap _globalUsageMap;
+ /** whether or not to force all writes to disk immediately */
+ private boolean _autoSync;
/**
* @param channel Channel containing the database
* @param format Format of the database in the channel
*/
- public PageChannel(FileChannel channel, JetFormat format) throws IOException {
+ public PageChannel(FileChannel channel, JetFormat format, boolean autoSync)
+ throws IOException
+ {
_channel = channel;
_format = format;
+ _autoSync = autoSync;
//Null check only exists for unit tests. Channel should never normally be null.
if (channel != null) {
_globalUsageMap = UsageMap.read(this, PAGE_GLOBAL_USAGE_MAP, (byte) 0, format);
public void writePage(ByteBuffer page, int pageNumber) throws IOException {
page.rewind();
_channel.write(page, (long) pageNumber * (long) _format.PAGE_SIZE);
- _channel.force(true);
+ if(_autoSync) {
+ _channel.force(true);
+ }
}
/**