Browse Source

support reading inline usage maps with more than 512 pages

git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@218 f203690c-595d-4dc9-a70b-905162fa7fd2
tags/rel_1_1_11
James Ahlborn 16 years ago
parent
commit
94aa5f0252
2 changed files with 37 additions and 12 deletions
  1. 3
    0
      src/changes/changes.xml
  2. 34
    12
      src/java/com/healthmarketscience/jackcess/UsageMap.java

+ 3
- 0
src/changes/changes.xml View File

</properties> </properties>
<body> <body>
<release version="1.1.11" date="TBD"> <release version="1.1.11" date="TBD">
<action dev="jahlborn" type="fix">
Support reading inline usage maps with more than 512 pages.
</action>
<action dev="jahlborn" type="fix"> <action dev="jahlborn" type="fix">
Fix some problems with sporadic usage map corruption. Fix some problems with sporadic usage map corruption.
</action> </action>

+ 34
- 12
src/java/com/healthmarketscience/jackcess/UsageMap.java View File

/** Offset of the data page at which the usage map data starts */ /** Offset of the data page at which the usage map data starts */
private int _startOffset; private int _startOffset;
/** Offset of the data page at which the usage map declaration starts */ /** Offset of the data page at which the usage map declaration starts */
private short _rowStart;
private final short _rowStart;
/** First page that this usage map applies to */ /** First page that this usage map applies to */
private int _startPage; private int _startPage;
/** Last page that this usage map applies to */ /** Last page that this usage map applies to */
protected short getRowStart() { protected short getRowStart() {
return _rowStart; return _rowStart;
} }

protected int getRowEnd() {
return getTableBuffer().limit();
}

protected void setStartOffset(int startOffset) { protected void setStartOffset(int startOffset) {
_startOffset = startOffset; _startOffset = startOffset;
} }
_endPage = 0; _endPage = 0;
++_modCount; ++_modCount;
// clear out the table data
int tableStart = getRowStart() + getFormat().OFFSET_USAGE_MAP_START - 4;
int tableEnd = tableStart + getFormat().USAGE_MAP_TABLE_BYTE_LENGTH + 4;
// clear out the table data (everything except map type)
int tableStart = getRowStart() + 1;
int tableEnd = getRowEnd();
ByteUtil.clearRange(_tableBuffer, tableStart, tableEnd); ByteUtil.clearRange(_tableBuffer, tableStart, tableEnd);
} }
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
if ((b & (1 << i)) != 0) { if ((b & (1 << i)) != 0) {
int pageNumberOffset = (byteCount * 8 + i) + bufferStartPage; int pageNumberOffset = (byteCount * 8 + i) + bufferStartPage;
int pageNumber = bitIndexToPageNumber(
pageNumberOffset,
PageChannel.INVALID_PAGE_NUMBER);
if(!isPageWithinRange(pageNumber)) {
throw new IllegalStateException(
"found page number " + pageNumber
+ " in usage map outside of expected range " +
_startPage + " to " + _endPage);
}
_pageNumbers.set(pageNumberOffset); _pageNumbers.set(pageNumberOffset);
} }
} }


/** /**
* Usage map whose map is written inline in the same page. For Jet4, this * Usage map whose map is written inline in the same page. For Jet4, this
* type of map can contain a maximum of 512 pages. Free space maps are
* always inline, used space maps may be inline or reference. It has a
* type of map can usually contains a maximum of 512 pages. Free space maps
* are always inline, used space maps may be inline or reference. It has a
* start page, which all page numbers in its map are calculated as starting * start page, which all page numbers in its map are calculated as starting
* from. * from.
* @author Tim McCune * @author Tim McCune
private class InlineHandler extends Handler private class InlineHandler extends Handler
{ {
private final boolean _assumeOutOfRangeBitsOn; private final boolean _assumeOutOfRangeBitsOn;
private final int _maxInlinePages;
private InlineHandler(boolean assumeOutOfRangeBitsOn) private InlineHandler(boolean assumeOutOfRangeBitsOn)
throws IOException throws IOException
{ {
_assumeOutOfRangeBitsOn = assumeOutOfRangeBitsOn; _assumeOutOfRangeBitsOn = assumeOutOfRangeBitsOn;
_maxInlinePages = (getInlineDataEnd() - getInlineDataStart()) * 8;
int startPage = getTableBuffer().getInt(getRowStart() + 1); int startPage = getTableBuffer().getInt(getRowStart() + 1);
setInlinePageRange(startPage); setInlinePageRange(startPage);
processMap(getTableBuffer(), 0); processMap(getTableBuffer(), 0);
} }


private int getMaxInlinePages() { private int getMaxInlinePages() {
return(getFormat().USAGE_MAP_TABLE_BYTE_LENGTH * 8);
return _maxInlinePages;
}

private int getInlineDataStart() {
return getRowStart() + getFormat().OFFSET_USAGE_MAP_START;
}

private int getInlineDataEnd() {
return getRowEnd();
} }
/** /**
if(firstPage == PageChannel.INVALID_PAGE_NUMBER) { if(firstPage == PageChannel.INVALID_PAGE_NUMBER) {
// this is the common case where we left everything behind // this is the common case where we left everything behind
int tableStart = getRowStart() + getFormat().OFFSET_USAGE_MAP_START;
int tableEnd = tableStart + getFormat().USAGE_MAP_TABLE_BYTE_LENGTH;
ByteUtil.fillRange(_tableBuffer, tableStart, tableEnd);
ByteUtil.fillRange(_tableBuffer, getInlineDataStart(),
getInlineDataEnd());


// write out the updated table // write out the updated table
writeTable(); writeTable();
private ReferenceHandler() private ReferenceHandler()
throws IOException throws IOException
{ {
int numUsagePages = (getFormat().USAGE_MAP_TABLE_BYTE_LENGTH / 4) + 1;
int numUsagePages = (getRowEnd() - getRowStart() - 1) / 4;
setStartOffset(getFormat().OFFSET_USAGE_MAP_PAGE_DATA); setStartOffset(getFormat().OFFSET_USAGE_MAP_PAGE_DATA);
setPageRange(0, (numUsagePages * getMaxPagesPerUsagePage())); setPageRange(0, (numUsagePages * getMaxPagesPerUsagePage()));

Loading…
Cancel
Save