From 369bac8704527ccee22f8d843c203439cadfa6f3 Mon Sep 17 00:00:00 2001 From: James Ahlborn Date: Wed, 25 Apr 2007 20:09:52 +0000 Subject: [PATCH] add autosync option git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@141 f203690c-595d-4dc9-a70b-905162fa7fd2 --- .../jackcess/Database.java | 58 +++++++++++++++++-- .../jackcess/PageChannel.java | 11 +++- .../healthmarketscience/jackcess/Table.java | 2 +- 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/java/com/healthmarketscience/jackcess/Database.java b/src/java/com/healthmarketscience/jackcess/Database.java index 43bee10..3468b4f 100644 --- a/src/java/com/healthmarketscience/jackcess/Database.java +++ b/src/java/com/healthmarketscience/jackcess/Database.java @@ -74,6 +74,10 @@ public class Database 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; @@ -188,7 +192,8 @@ public class Database /** * 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 { @@ -198,6 +203,7 @@ public class Database /** * Open an existing Database. If the existing file is not writeable or the * readOnly flag is true, the file will be opened read-only. + * Auto-syncing is enabled for the returned Database. * @param mdbFile File containing the database * @param readOnly iff true, force opening file in read-only * mode @@ -205,11 +211,33 @@ public class Database 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 true, the file will be opened read-only. + * @param mdbFile File containing the database + * @param readOnly iff true, 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); } /** @@ -218,11 +246,30 @@ public class Database * already exists, it will be overwritten. */ 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. If this file + * already exists, it will be overwritten. + * @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) @@ -238,9 +285,10 @@ public class Database * 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(); } diff --git a/src/java/com/healthmarketscience/jackcess/PageChannel.java b/src/java/com/healthmarketscience/jackcess/PageChannel.java index 3865394..69b9206 100644 --- a/src/java/com/healthmarketscience/jackcess/PageChannel.java +++ b/src/java/com/healthmarketscience/jackcess/PageChannel.java @@ -57,14 +57,19 @@ public class PageChannel implements Channel { 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); @@ -100,7 +105,9 @@ public class PageChannel implements Channel { 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); + } } /** diff --git a/src/java/com/healthmarketscience/jackcess/Table.java b/src/java/com/healthmarketscience/jackcess/Table.java index a0ed9a6..9b60071 100644 --- a/src/java/com/healthmarketscience/jackcess/Table.java +++ b/src/java/com/healthmarketscience/jackcess/Table.java @@ -112,7 +112,7 @@ public class Table * Only used by unit tests */ Table() throws IOException { - _pageChannel = new PageChannel(null, JetFormat.VERSION_4); + _pageChannel = new PageChannel(null, JetFormat.VERSION_4, true); } /** -- 2.39.5