Parcourir la 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 il y a 4 ans
Parent
révision
5329ce1529

+ 2
- 2
src/main/java/com/healthmarketscience/jackcess/impl/DatabaseImpl.java Voir le fichier

private void initRootPageInfo() throws IOException { private void initRootPageInfo() throws IOException {
ByteBuffer buffer = takeSharedBuffer(); ByteBuffer buffer = takeSharedBuffer();
try { try {
_pageChannel.readPage(buffer, 0);
_pageChannel.readRootPage(buffer);
_defaultSortOrder = ColumnImpl.readSortOrder( _defaultSortOrder = ColumnImpl.readSortOrder(
buffer, _format.OFFSET_SORT_ORDER, _format); buffer, _format.OFFSET_SORT_ORDER, _format);
_defaultCodePage = buffer.getShort(_format.OFFSET_CODE_PAGE); _defaultCodePage = buffer.getShort(_format.OFFSET_CODE_PAGE);
{ {
ByteBuffer buffer = takeSharedBuffer(); ByteBuffer buffer = takeSharedBuffer();
try { try {
_pageChannel.readPage(buffer, 0);
_pageChannel.readRootPage(buffer);


byte[] pwdBytes = new byte[_format.SIZE_PASSWORD]; byte[] pwdBytes = new byte[_format.SIZE_PASSWORD];
buffer.position(_format.OFFSET_PASSWORD); buffer.position(_format.OFFSET_PASSWORD);

+ 13
- 13
src/main/java/com/healthmarketscience/jackcess/impl/DefaultCodecProvider.java Voir le fichier

public class DefaultCodecProvider implements CodecProvider public class DefaultCodecProvider implements CodecProvider
{ {
/** common instance of DefaultCodecProvider */ /** common instance of DefaultCodecProvider */
public static final CodecProvider INSTANCE =
public static final CodecProvider INSTANCE =
new DefaultCodecProvider(); new DefaultCodecProvider();


/** common instance of {@link DummyHandler} */ /** common instance of {@link DummyHandler} */
public static final CodecHandler DUMMY_HANDLER =
public static final CodecHandler DUMMY_HANDLER =
new DummyHandler(); new DummyHandler();


/** common instance of {@link UnsupportedHandler} */ /** common instance of {@link UnsupportedHandler} */
public static final CodecHandler UNSUPPORTED_HANDLER =
public static final CodecHandler UNSUPPORTED_HANDLER =
new UnsupportedHandler(); new UnsupportedHandler();




case OFFICE: case OFFICE:
// check for an encode key. if 0, not encoded // check for an encode key. if 0, not encoded
ByteBuffer bb = channel.createPageBuffer(); ByteBuffer bb = channel.createPageBuffer();
channel.readPage(bb, 0);
channel.readRootPage(bb);
int codecKey = bb.getInt(format.OFFSET_ENCODING_KEY); int codecKey = bb.getInt(format.OFFSET_ENCODING_KEY);
return((codecKey == 0) ? DUMMY_HANDLER : UNSUPPORTED_HANDLER); return((codecKey == 0) ? DUMMY_HANDLER : UNSUPPORTED_HANDLER);




@Override @Override
public void decodePage(ByteBuffer inPage, ByteBuffer outPage, public void decodePage(ByteBuffer inPage, ByteBuffer outPage,
int pageNumber)
throws IOException
int pageNumber)
throws IOException
{ {
// does nothing // does nothing
} }


@Override @Override
public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
int pageOffset)
public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
int pageOffset)
throws IOException throws IOException
{ {
// does nothing // does nothing
} }


@Override @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."); throw new UnsupportedCodecException("Decoding not supported. Please choose a CodecProvider which supports reading the current database encoding.");
} }


@Override @Override
public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
int pageOffset)
public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
int pageOffset)
throws IOException throws IOException
{ {
throw new UnsupportedCodecException("Encoding not supported. Please choose a CodecProvider which supports writing the current database encoding."); 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 Voir le fichier

* @author Tim McCune * @author Tim McCune
*/ */
public class PageChannel implements Channel, Flushable { public class PageChannel implements Channel, Flushable {
static final int INVALID_PAGE_NUMBER = -1; static final int INVALID_PAGE_NUMBER = -1;


static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.LITTLE_ENDIAN; static final ByteOrder DEFAULT_BYTE_ORDER = ByteOrder.LITTLE_ENDIAN;
/** invalid page header, used when deallocating old pages. data pages /** invalid page header, used when deallocating old pages. data pages
generally have 4 interesting bytes at the beginning which we want to generally have 4 interesting bytes at the beginning which we want to
reset. */ reset. */
private static final byte[] INVALID_PAGE_BYTE_HEADER = private static final byte[] INVALID_PAGE_BYTE_HEADER =
new byte[]{PageTypes.INVALID, (byte)0, (byte)0, (byte)0}; new byte[]{PageTypes.INVALID, (byte)0, (byte)0, (byte)0};
/** Global usage map always lives on page 1 */ /** Global usage map always lives on page 1 */
static final int PAGE_GLOBAL_USAGE_MAP = 1; static final int PAGE_GLOBAL_USAGE_MAP = 1;
/** Global usage map always lives at row 0 */ /** Global usage map always lives at row 0 */
static final int ROW_GLOBAL_USAGE_MAP = 0; static final int ROW_GLOBAL_USAGE_MAP = 0;
/** Channel containing the database */ /** Channel containing the database */
private final FileChannel _channel; private final FileChannel _channel;
/** whether or not the _channel should be closed by this class */ /** whether or not the _channel should be closed by this class */
private TempPageHolder _fullPageEncodeBufferH; private TempPageHolder _fullPageEncodeBufferH;
private TempBufferHolder _tempDecodeBufferH; private TempBufferHolder _tempDecodeBufferH;
private int _writeCount; private int _writeCount;
/** /**
* Only used by unit tests * Only used by unit tests
*/ */
_globalUsageMap = UsageMap.read(database, PAGE_GLOBAL_USAGE_MAP, _globalUsageMap = UsageMap.read(database, PAGE_GLOBAL_USAGE_MAP,
ROW_GLOBAL_USAGE_MAP, true); ROW_GLOBAL_USAGE_MAP, true);
} }
public JetFormat getFormat() { public JetFormat getFormat() {
return _format; return _format;
} }
throw new IllegalStateException("No write operation in progress"); throw new IllegalStateException("No write operation in progress");
} }
} }
/** /**
* Returns the next page number based on the given file size. * Returns the next page number based on the given file size.
*/ */
private long getPageOffset(int pageNumber) { private long getPageOffset(int pageNumber) {
return((long) pageNumber * (long) getFormat().PAGE_SIZE); return((long) pageNumber * (long) getFormat().PAGE_SIZE);
} }
/** /**
* Validates that the given pageNumber is valid for this database. * Validates that the given pageNumber is valid for this database.
*/ */
throw new IllegalStateException("invalid page number " + pageNumber); throw new IllegalStateException("invalid page number " + pageNumber);
} }
} }
/** /**
* @param buffer Buffer to read the page into * @param buffer Buffer to read the page into
* @param pageNumber Number of the page to read in (starting at 0) * @param pageNumber Number of the page to read in (starting at 0)
public void readPage(ByteBuffer buffer, int pageNumber) public void readPage(ByteBuffer buffer, int pageNumber)
throws IOException throws IOException
{ {
if(pageNumber == 0) {
readRootPage(buffer);
return;
}

validatePageNumber(pageNumber); validatePageNumber(pageNumber);


ByteBuffer inPage = buffer; ByteBuffer inPage = buffer;
ByteBuffer outPage = buffer; ByteBuffer outPage = buffer;
if((pageNumber != 0) && !_codecHandler.canDecodeInline()) {
if(!_codecHandler.canDecodeInline()) {
inPage = _tempDecodeBufferH.getPageBuffer(this); inPage = _tempDecodeBufferH.getPageBuffer(this);
outPage.clear(); outPage.clear();
} }
pageNumber + ", only read " + bytesRead); 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 * Write a page to disk
* @param page Page to write * @param page Page to write
public void writePage(ByteBuffer page, int pageNumber) throws IOException { public void writePage(ByteBuffer page, int pageNumber) throws IOException {
writePage(page, pageNumber, 0); writePage(page, pageNumber, 0);
} }
/** /**
* Write a page (or part of a page) to disk * Write a page (or part of a page) to disk
* @param page Page to write * @param page Page to write
{ {
assertWriting(); assertWriting();
validatePageNumber(pageNumber); validatePageNumber(pageNumber);
page.rewind().position(pageOffset); page.rewind().position(pageOffset);


int writeLen = page.remaining(); int writeLen = page.remaining();
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Page buffer is too large, size " + (writeLen + pageOffset)); "Page buffer is too large, size " + (writeLen + pageOffset));
} }
ByteBuffer encodedPage = page; ByteBuffer encodedPage = page;
if(pageNumber == 0) { if(pageNumber == 0) {
// re-mask header // re-mask header
} }
} }
} }
/** /**
* Allocates a new page in the database. Data in the page is undefined * 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)}. * until it is written in a call to {@link #writePage(ByteBuffer,int)}.
" is not multiple of page size " + " is not multiple of page size " +
getFormat().PAGE_SIZE); getFormat().PAGE_SIZE);
} }
_forceBytes.rewind(); _forceBytes.rewind();
// push the buffer to the end of the page, so that a full page's worth of // push the buffer to the end of the page, so that a full page's worth of
// data is written // data is written
int pageOffset = (getFormat().PAGE_SIZE - _forceBytes.remaining()); int pageOffset = (getFormat().PAGE_SIZE - _forceBytes.remaining());
assertWriting(); assertWriting();


validatePageNumber(pageNumber); validatePageNumber(pageNumber);
// don't write the whole page, just wipe out the header (which should be // 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) // enough to let us know if we accidentally try to use an invalid page)
_invalidPageBytes.rewind(); _invalidPageBytes.rewind();
_channel.write(_invalidPageBytes, getPageOffset(pageNumber)); _channel.write(_invalidPageBytes, getPageOffset(pageNumber));
_globalUsageMap.addPageNumber(pageNumber); //force is done here _globalUsageMap.addPageNumber(pageNumber); //force is done here
} }
/** /**
* @return A newly-allocated buffer that can be passed to readPage * @return A newly-allocated buffer that can be passed to readPage
*/ */
public static ByteBuffer createBuffer(int size) { public static ByteBuffer createBuffer(int size) {
return createBuffer(size, DEFAULT_BYTE_ORDER); return createBuffer(size, DEFAULT_BYTE_ORDER);
} }
/** /**
* @return A newly-allocated buffer of the given size and byte order * @return A newly-allocated buffer of the given size and byte order
*/ */
public static ByteBuffer createBuffer(int size, ByteOrder order) { public static ByteBuffer createBuffer(int size, ByteOrder order) {
return ByteBuffer.allocate(size).order(order); return ByteBuffer.allocate(size).order(order);
} }
@Override @Override
public void flush() throws IOException { public void flush() throws IOException {
_channel.force(true); _channel.force(true);
} }
@Override @Override
public void close() throws IOException { public void close() throws IOException {
flush(); flush();
_channel.close(); _channel.close();
} }
} }
@Override @Override
public boolean isOpen() { public boolean isOpen() {
return _channel.isOpen(); return _channel.isOpen();
buffer.put(pos, b); buffer.put(pos, b);
} }
} }
/** /**
* @return a duplicate of the current buffer narrowed to the given position * @return a duplicate of the current buffer narrowed to the given position
* and limit. mark will be set at the current position. * and limit. mark will be set at the current position.

Chargement…
Annuler
Enregistrer