aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2019-08-06 21:20:51 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2019-08-06 21:20:51 +0000
commit5329ce15298859aff24512986c07305cf08a137f (patch)
treeb9db533a6ff76292e07e01adf1e3b540f80d8f3f /src
parentff9e16462ef5b3e720b676f9d11670e0d6a8d0b2 (diff)
downloadjackcess-5329ce15298859aff24512986c07305cf08a137f.tar.gz
jackcess-5329ce15298859aff24512986c07305cf08a137f.zip
add separate method for reading root db page
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/a97_indexes@1306 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java26
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java81
3 files changed, 66 insertions, 45 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
index bc3cf80..e00c82b 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java
@@ -942,7 +942,7 @@ public class DatabaseImpl implements Database, DateTimeContext
private void initRootPageInfo() throws IOException {
ByteBuffer buffer = takeSharedBuffer();
try {
- _pageChannel.readPage(buffer, 0);
+ _pageChannel.readRootPage(buffer);
_defaultSortOrder = ColumnImpl.readSortOrder(
buffer, _format.OFFSET_SORT_ORDER, _format);
_defaultCodePage = buffer.getShort(_format.OFFSET_CODE_PAGE);
@@ -1586,7 +1586,7 @@ public class DatabaseImpl implements Database, DateTimeContext
{
ByteBuffer buffer = takeSharedBuffer();
try {
- _pageChannel.readPage(buffer, 0);
+ _pageChannel.readRootPage(buffer);
byte[] pwdBytes = new byte[_format.SIZE_PASSWORD];
buffer.position(_format.OFFSET_PASSWORD);
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java b/src/main/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java
index 11854e7..87e6ec8 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java
@@ -30,15 +30,15 @@ import java.nio.charset.Charset;
public class DefaultCodecProvider implements CodecProvider
{
/** common instance of DefaultCodecProvider */
- public static final CodecProvider INSTANCE =
+ public static final CodecProvider INSTANCE =
new DefaultCodecProvider();
/** common instance of {@link DummyHandler} */
- public static final CodecHandler DUMMY_HANDLER =
+ public static final CodecHandler DUMMY_HANDLER =
new DummyHandler();
/** common instance of {@link UnsupportedHandler} */
- public static final CodecHandler UNSUPPORTED_HANDLER =
+ public static final CodecHandler UNSUPPORTED_HANDLER =
new UnsupportedHandler();
@@ -62,7 +62,7 @@ public class DefaultCodecProvider implements CodecProvider
case OFFICE:
// check for an encode key. if 0, not encoded
ByteBuffer bb = channel.createPageBuffer();
- channel.readPage(bb, 0);
+ channel.readRootPage(bb);
int codecKey = bb.getInt(format.OFFSET_ENCODING_KEY);
return((codecKey == 0) ? DUMMY_HANDLER : UNSUPPORTED_HANDLER);
@@ -93,15 +93,15 @@ public class DefaultCodecProvider implements CodecProvider
@Override
public void decodePage(ByteBuffer inPage, ByteBuffer outPage,
- int pageNumber)
- throws IOException
+ int pageNumber)
+ throws IOException
{
// does nothing
}
@Override
- public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
- int pageOffset)
+ public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
+ int pageOffset)
throws IOException
{
// does nothing
@@ -127,16 +127,16 @@ public class DefaultCodecProvider implements CodecProvider
}
@Override
- public void decodePage(ByteBuffer inPage, ByteBuffer outPage,
- int pageNumber)
- throws IOException
+ 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.");
}
@Override
- public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
- int pageOffset)
+ public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
+ int pageOffset)
throws IOException
{
throw new UnsupportedCodecException("Encoding not supported. Please choose a CodecProvider which supports writing the current database encoding.");
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java b/src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java
index 41c164c..101a3e0 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java
@@ -29,22 +29,22 @@ import java.nio.channels.FileChannel;
* @author Tim McCune
*/
public class PageChannel implements Channel, Flushable {
-
+
static final int INVALID_PAGE_NUMBER = -1;
static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
-
+
/** invalid page header, used when deallocating old pages. data pages
generally have 4 interesting bytes at the beginning which we want to
reset. */
private static final byte[] INVALID_PAGE_BYTE_HEADER =
new byte[]{PageTypes.INVALID, (byte)0, (byte)0, (byte)0};
-
+
/** Global usage map always lives on page 1 */
static final int PAGE_GLOBAL_USAGE_MAP = 1;
/** Global usage map always lives at row 0 */
static final int ROW_GLOBAL_USAGE_MAP = 0;
-
+
/** Channel containing the database */
private final FileChannel _channel;
/** whether or not the _channel should be closed by this class */
@@ -67,7 +67,7 @@ public class PageChannel implements Channel, Flushable {
private TempPageHolder _fullPageEncodeBufferH;
private TempBufferHolder _tempDecodeBufferH;
private int _writeCount;
-
+
/**
* Only used by unit tests
*/
@@ -117,7 +117,7 @@ public class PageChannel implements Channel, Flushable {
_globalUsageMap = UsageMap.read(database, PAGE_GLOBAL_USAGE_MAP,
ROW_GLOBAL_USAGE_MAP, true);
}
-
+
public JetFormat getFormat() {
return _format;
}
@@ -177,7 +177,7 @@ public class PageChannel implements Channel, Flushable {
throw new IllegalStateException("No write operation in progress");
}
}
-
+
/**
* Returns the next page number based on the given file size.
*/
@@ -191,7 +191,7 @@ public class PageChannel implements Channel, Flushable {
private long getPageOffset(int pageNumber) {
return((long) pageNumber * (long) getFormat().PAGE_SIZE);
}
-
+
/**
* Validates that the given pageNumber is valid for this database.
*/
@@ -203,7 +203,7 @@ public class PageChannel implements Channel, Flushable {
throw new IllegalStateException("invalid page number " + pageNumber);
}
}
-
+
/**
* @param buffer Buffer to read the page into
* @param pageNumber Number of the page to read in (starting at 0)
@@ -211,11 +211,16 @@ public class PageChannel implements Channel, Flushable {
public void readPage(ByteBuffer buffer, int pageNumber)
throws IOException
{
+ if(pageNumber == 0) {
+ readRootPage(buffer);
+ return;
+ }
+
validatePageNumber(pageNumber);
ByteBuffer inPage = buffer;
ByteBuffer outPage = buffer;
- if((pageNumber != 0) && !_codecHandler.canDecodeInline()) {
+ if(!_codecHandler.canDecodeInline()) {
inPage = _tempDecodeBufferH.getPageBuffer(this);
outPage.clear();
}
@@ -230,14 +235,30 @@ public class PageChannel implements Channel, Flushable {
pageNumber + ", only read " + bytesRead);
}
- if(pageNumber == 0) {
- // de-mask header (note, page 0 never has additional encoding)
- applyHeaderMask(buffer);
- } else {
- _codecHandler.decodePage(inPage, outPage, pageNumber);
+ _codecHandler.decodePage(inPage, outPage, pageNumber);
+ }
+
+ /**
+ * @param buffer Buffer to read the root page into
+ */
+ public void readRootPage(ByteBuffer buffer)
+ throws IOException
+ {
+ // special method for reading root page, can be done before PageChannel is
+ // fully initialized
+ buffer.clear();
+ int bytesRead = _channel.read(buffer, 0L);
+ buffer.flip();
+ if(bytesRead != getFormat().PAGE_SIZE) {
+ throw new IOException("Failed attempting to read " +
+ getFormat().PAGE_SIZE + " bytes from page " +
+ 0 + ", only read " + bytesRead);
}
+
+ // de-mask header (note, page 0 never has additional encoding)
+ applyHeaderMask(buffer);
}
-
+
/**
* Write a page to disk
* @param page Page to write
@@ -246,7 +267,7 @@ public class PageChannel implements Channel, Flushable {
public void writePage(ByteBuffer page, int pageNumber) throws IOException {
writePage(page, pageNumber, 0);
}
-
+
/**
* Write a page (or part of a page) to disk
* @param page Page to write
@@ -259,7 +280,7 @@ public class PageChannel implements Channel, Flushable {
{
assertWriting();
validatePageNumber(pageNumber);
-
+
page.rewind().position(pageOffset);
int writeLen = page.remaining();
@@ -267,7 +288,7 @@ public class PageChannel implements Channel, Flushable {
throw new IllegalArgumentException(
"Page buffer is too large, size " + (writeLen + pageOffset));
}
-
+
ByteBuffer encodedPage = page;
if(pageNumber == 0) {
// re-mask header
@@ -315,7 +336,7 @@ public class PageChannel implements Channel, Flushable {
}
}
}
-
+
/**
* Allocates a new page in the database. Data in the page is undefined
* until it is written in a call to {@link #writePage(ByteBuffer,int)}.
@@ -334,9 +355,9 @@ public class PageChannel implements Channel, Flushable {
" is not multiple of page size " +
getFormat().PAGE_SIZE);
}
-
+
_forceBytes.rewind();
-
+
// push the buffer to the end of the page, so that a full page's worth of
// data is written
int pageOffset = (getFormat().PAGE_SIZE - _forceBytes.remaining());
@@ -358,15 +379,15 @@ public class PageChannel implements Channel, Flushable {
assertWriting();
validatePageNumber(pageNumber);
-
+
// don't write the whole page, just wipe out the header (which should be
// enough to let us know if we accidentally try to use an invalid page)
_invalidPageBytes.rewind();
_channel.write(_invalidPageBytes, getPageOffset(pageNumber));
-
+
_globalUsageMap.addPageNumber(pageNumber); //force is done here
}
-
+
/**
* @return A newly-allocated buffer that can be passed to readPage
*/
@@ -381,19 +402,19 @@ public class PageChannel implements Channel, Flushable {
public static ByteBuffer createBuffer(int size) {
return createBuffer(size, DEFAULT_BYTE_ORDER);
}
-
+
/**
* @return A newly-allocated buffer of the given size and byte order
*/
public static ByteBuffer createBuffer(int size, ByteOrder order) {
return ByteBuffer.allocate(size).order(order);
}
-
+
@Override
public void flush() throws IOException {
_channel.force(true);
}
-
+
@Override
public void close() throws IOException {
flush();
@@ -401,7 +422,7 @@ public class PageChannel implements Channel, Flushable {
_channel.close();
}
}
-
+
@Override
public boolean isOpen() {
return _channel.isOpen();
@@ -419,7 +440,7 @@ public class PageChannel implements Channel, Flushable {
buffer.put(pos, b);
}
}
-
+
/**
* @return a duplicate of the current buffer narrowed to the given position
* and limit. mark will be set at the current position.