]> source.dussan.org Git - jackcess.git/commitdiff
enhance CodecHandler to better support impls which cannot decode pages inline
authorJames Ahlborn <jtahlborn@yahoo.com>
Sat, 27 Jul 2013 03:02:06 +0000 (03:02 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Sat, 27 Jul 2013 03:02:06 +0000 (03:02 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/jackcess-2@753 f203690c-595d-4dc9-a70b-905162fa7fd2

src/java/com/healthmarketscience/jackcess/impl/CodecHandler.java
src/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java
src/java/com/healthmarketscience/jackcess/impl/PageChannel.java
test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java

index fd71f5d29bee846b194e093fc99117c8a349878e..944ac08367a7f1d2c00fb0b6e05b012c0c731b5f 100644 (file)
@@ -39,14 +39,24 @@ public interface CodecHandler
   public boolean canEncodePartialPage();
 
   /**
-   * Decodes the given page buffer inline.
+   * Returns {@code true} if this handler can decode a page inline,
+   * {@code false} otherwise.  If this method returns {@code false}, the
+   * {@link #decodePage} method will always be called with separate buffers.
+   */
+  public boolean canDecodeInline();
+
+  /**
+   * Decodes the given page buffer.
    *
-   * @param page the page to be decoded
+   * @param inPage the page to be decoded
+   * @param outPage the decoded page.  if {@link #canDecodeInline} is {@code
+   *                true}, this will be the same buffer as inPage.
    * @param pageNumber the page number of the given page
    * 
    * @throws IOException if an exception occurs during decoding
    */
-  public void decodePage(ByteBuffer page, int pageNumber) throws IOException;
+  public void decodePage(ByteBuffer inPage, ByteBuffer outPage, int pageNumber) 
+    throws IOException;
 
   /**
    * Encodes the given page buffer into a new page buffer and returns it.  The
index 1c08687f78f926b6cb4f76000227051ab9aa4171..0e1de8f22f0e7cce7097c711cb9e1d0af26fbadb 100644 (file)
@@ -87,7 +87,14 @@ public class DefaultCodecProvider implements CodecProvider
       return true;
     }
 
-    public void decodePage(ByteBuffer page, int pageNumber) throws IOException {
+    public boolean canDecodeInline() {
+      return true;
+    }
+
+    public void decodePage(ByteBuffer inPage, ByteBuffer outPage,
+                           int pageNumber) 
+      throws IOException 
+    {
       // does nothing
     }
 
@@ -111,7 +118,14 @@ public class DefaultCodecProvider implements CodecProvider
       return true;
     }
 
-    public void decodePage(ByteBuffer page, int pageNumber) throws IOException {
+    public boolean canDecodeInline() {
+      return true;
+    }
+
+    public void decodePage(ByteBuffer inPage, ByteBuffer outPage, 
+                           int pageNumber) 
+      throws IOException 
+    {
       throw new UnsupportedCodecException("Decoding not supported.  Please choose a CodecProvider which supports reading the current database encoding.");
     }
 
index 2ea9d275999d05591a2999a990688e652f1377ad..89e952dc6e962f3212878583c3b1d9a716eadd95 100644 (file)
@@ -79,8 +79,8 @@ public class PageChannel implements Channel, Flushable {
   /** handler for the current database encoding type */
   private CodecHandler _codecHandler = DefaultCodecProvider.DUMMY_HANDLER;
   /** temp page buffer used when pages cannot be partially encoded */
-  private final TempPageHolder _fullPageEncodeBufferH =
-    TempPageHolder.newHolder(TempBufferHolder.Type.SOFT);
+  private TempPageHolder _fullPageEncodeBufferH;
+  private TempBufferHolder _tempDecodeBufferH;
   private int _writeCount;
   
   /**
@@ -118,6 +118,14 @@ public class PageChannel implements Channel, Flushable {
   {
     // initialize page en/decoding support
     _codecHandler = codecProvider.createHandler(this, database.getCharset());
+    if(!_codecHandler.canEncodePartialPage()) {
+      _fullPageEncodeBufferH =
+        TempPageHolder.newHolder(TempBufferHolder.Type.SOFT);
+    }
+    if(!_codecHandler.canDecodeInline()) {
+      _tempDecodeBufferH = TempBufferHolder.newHolder(
+          TempBufferHolder.Type.SOFT, true);
+    }
 
     // note the global usage map is a special map where any page outside of
     // the current range is assumed to be "on"
@@ -206,10 +214,18 @@ public class PageChannel implements Channel, Flushable {
     throws IOException
   {
     validatePageNumber(pageNumber);
-    buffer.clear();
+
+    ByteBuffer inPage = buffer;
+    ByteBuffer outPage = buffer;
+    if((pageNumber != 0) && !_codecHandler.canDecodeInline()) {
+      inPage = _tempDecodeBufferH.getPageBuffer(this);
+      outPage.clear();
+    }
+
+    inPage.clear();
     int bytesRead = _channel.read(
-        buffer, (long) pageNumber * (long) getFormat().PAGE_SIZE);
-    buffer.flip();
+        inPage, (long) pageNumber * (long) getFormat().PAGE_SIZE);
+    inPage.flip();
     if(bytesRead != getFormat().PAGE_SIZE) {
       throw new IOException("Failed attempting to read " +
                             getFormat().PAGE_SIZE + " bytes from page " +
@@ -220,7 +236,7 @@ public class PageChannel implements Channel, Flushable {
       // de-mask header (note, page 0 never has additional encoding)
       applyHeaderMask(buffer);
     } else {
-      _codecHandler.decodePage(buffer, pageNumber);
+      _codecHandler.decodePage(inPage, outPage, pageNumber);
     }
   }
   
index e3cf49919428df7bf465fa83311c05aa20c0029f..47a832af3c7bd2c969b5be4c1e6ee71b1e20fbe9 100644 (file)
@@ -236,9 +236,16 @@ public class CodecHandlerTest extends TestCase
     public boolean canEncodePartialPage() {
       return true;
     }
+
+    public boolean canDecodeInline() {
+      return true;
+    }
     
-    public void decodePage(ByteBuffer page, int pageNumber) throws IOException {
-      byte[] arr = page.array();
+    public void decodePage(ByteBuffer inPage, ByteBuffer outPage,
+                           int pageNumber) 
+      throws IOException 
+    {
+      byte[] arr = inPage.array();
       simpleDecode(arr, arr, pageNumber);
     }
 
@@ -267,9 +274,16 @@ public class CodecHandlerTest extends TestCase
     public boolean canEncodePartialPage() {
       return false;
     }
+
+    public boolean canDecodeInline() {
+      return true;
+    }
     
-    public void decodePage(ByteBuffer page, int pageNumber) throws IOException {
-      byte[] arr = page.array();
+    public void decodePage(ByteBuffer inPage, ByteBuffer outPage, 
+                           int pageNumber) 
+      throws IOException 
+    {
+      byte[] arr = inPage.array();
       fullDecode(arr, arr, pageNumber);
     }