]> source.dussan.org Git - jackcess.git/commitdiff
add autosync option
authorJames Ahlborn <jtahlborn@yahoo.com>
Wed, 25 Apr 2007 20:09:52 +0000 (20:09 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Wed, 25 Apr 2007 20:09:52 +0000 (20:09 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@141 f203690c-595d-4dc9-a70b-905162fa7fd2

src/java/com/healthmarketscience/jackcess/Database.java
src/java/com/healthmarketscience/jackcess/PageChannel.java
src/java/com/healthmarketscience/jackcess/Table.java

index 43bee10673fe9a38c4fcd4f36e832b615afe5196..3468b4fc96d5fc8340f264685fa88ec225654e7c 100644 (file)
@@ -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 <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
@@ -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 <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);
   }
   
   /**
@@ -218,11 +246,30 @@ public class Database
    *    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)
@@ -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();
   }
index 38653945e7cedf897ffc2c3570fc377d85e70b61..69b920631ebcac9864c953e61cd0817f69e75159 100644 (file)
@@ -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);
+    }
   }
   
   /**
index a0ed9a6256658d9471c9d817169b28fbb6963ff6..9b60071d58d7d6cbc59d34c9f4245675a61b20c0 100644 (file)
@@ -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);
   }
   
   /**