diff options
author | James Ahlborn <jtahlborn@yahoo.com> | 2013-07-27 03:02:06 +0000 |
---|---|---|
committer | James Ahlborn <jtahlborn@yahoo.com> | 2013-07-27 03:02:06 +0000 |
commit | 286c6b06b5965daf1a33db2d0cf4e22c6c2cc758 (patch) | |
tree | 4afaa71e40e29226a4097d4033c24938249039af | |
parent | 77daac9f4b313c2f7c9617549f04a95786d59daf (diff) | |
download | jackcess-286c6b06b5965daf1a33db2d0cf4e22c6c2cc758.tar.gz jackcess-286c6b06b5965daf1a33db2d0cf4e22c6c2cc758.zip |
enhance CodecHandler to better support impls which cannot decode pages inline
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/jackcess-2@753 f203690c-595d-4dc9-a70b-905162fa7fd2
4 files changed, 69 insertions, 15 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/impl/CodecHandler.java b/src/java/com/healthmarketscience/jackcess/impl/CodecHandler.java index fd71f5d..944ac08 100644 --- a/src/java/com/healthmarketscience/jackcess/impl/CodecHandler.java +++ b/src/java/com/healthmarketscience/jackcess/impl/CodecHandler.java @@ -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 diff --git a/src/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java b/src/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java index 1c08687..0e1de8f 100644 --- a/src/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java +++ b/src/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java @@ -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."); } diff --git a/src/java/com/healthmarketscience/jackcess/impl/PageChannel.java b/src/java/com/healthmarketscience/jackcess/impl/PageChannel.java index 2ea9d27..89e952d 100644 --- a/src/java/com/healthmarketscience/jackcess/impl/PageChannel.java +++ b/src/java/com/healthmarketscience/jackcess/impl/PageChannel.java @@ -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); } } diff --git a/test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java b/test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java index e3cf499..47a832a 100644 --- a/test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java +++ b/test/src/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java @@ -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); } |