Browse Source

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
tags/jackcess-3.5.0
James Ahlborn 4 years ago
parent
commit
5329ce1529

+ 2
- 2
src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java View File

@@ -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);

+ 13
- 13
src/main/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java View File

@@ -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.");

+ 51
- 30
src/main/java/com/healthmarketscience/jackcess/impl/PageChannel.java View File

@@ -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.

Loading…
Cancel
Save