aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2008-01-17 19:14:22 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2008-01-17 19:14:22 +0000
commit94aa5f025245d8d9b9afaebcb7c59152507164d3 (patch)
tree1c9d4a589d184a29afc077732846c7d8964fd6b9
parent7190a46b85269da49437207cda5f6ca1af2e8205 (diff)
downloadjackcess-94aa5f025245d8d9b9afaebcb7c59152507164d3.tar.gz
jackcess-94aa5f025245d8d9b9afaebcb7c59152507164d3.zip
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
-rw-r--r--src/changes/changes.xml3
-rw-r--r--src/java/com/healthmarketscience/jackcess/UsageMap.java46
2 files changed, 37 insertions, 12 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 77d34a6..82c656d 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -7,6 +7,9 @@
<body>
<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">
Fix some problems with sporadic usage map corruption.
</action>
<action dev="jahlborn" type="update">
diff --git a/src/java/com/healthmarketscience/jackcess/UsageMap.java b/src/java/com/healthmarketscience/jackcess/UsageMap.java
index d5f0237..ac6b7a8 100644
--- a/src/java/com/healthmarketscience/jackcess/UsageMap.java
+++ b/src/java/com/healthmarketscience/jackcess/UsageMap.java
@@ -57,7 +57,7 @@ public class UsageMap
/** Offset of the data page at which the usage map data starts */
private int _startOffset;
/** 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 */
private int _startPage;
/** Last page that this usage map applies to */
@@ -150,7 +150,11 @@ public class UsageMap
protected short getRowStart() {
return _rowStart;
}
-
+
+ protected int getRowEnd() {
+ return getTableBuffer().limit();
+ }
+
protected void setStartOffset(int startOffset) {
_startOffset = startOffset;
}
@@ -240,9 +244,9 @@ public class UsageMap
_endPage = 0;
++_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);
}
@@ -265,6 +269,15 @@ public class UsageMap
for (int i = 0; i < 8; i++) {
if ((b & (1 << i)) != 0) {
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);
}
}
@@ -402,8 +415,8 @@ public class UsageMap
/**
* 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
* from.
* @author Tim McCune
@@ -411,18 +424,28 @@ public class UsageMap
private class InlineHandler extends Handler
{
private final boolean _assumeOutOfRangeBitsOn;
+ private final int _maxInlinePages;
private InlineHandler(boolean assumeOutOfRangeBitsOn)
throws IOException
{
_assumeOutOfRangeBitsOn = assumeOutOfRangeBitsOn;
+ _maxInlinePages = (getInlineDataEnd() - getInlineDataStart()) * 8;
int startPage = getTableBuffer().getInt(getRowStart() + 1);
setInlinePageRange(startPage);
processMap(getTableBuffer(), 0);
}
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();
}
/**
@@ -577,9 +600,8 @@ public class UsageMap
if(firstPage == PageChannel.INVALID_PAGE_NUMBER) {
// 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
writeTable();
@@ -616,7 +638,7 @@ public class UsageMap
private ReferenceHandler()
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);
setPageRange(0, (numUsagePages * getMaxPagesPerUsagePage()));