]> source.dussan.org Git - jackcess.git/commitdiff
support reading inline usage maps with more than 512 pages
authorJames Ahlborn <jtahlborn@yahoo.com>
Thu, 17 Jan 2008 19:14:22 +0000 (19:14 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Thu, 17 Jan 2008 19:14:22 +0000 (19:14 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@218 f203690c-595d-4dc9-a70b-905162fa7fd2

src/changes/changes.xml
src/java/com/healthmarketscience/jackcess/UsageMap.java

index 77d34a6da1dba2c1707722599ac151b6b9b3d4de..82c656d3db68bece4096fa6d1753a9d867386cb9 100644 (file)
@@ -6,6 +6,9 @@
   </properties>
   <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>
index d5f0237cb71a44087bb302f6f15c1cf271ef92b0..ac6b7a8ba5334a406f569ba4586320c0ac17ebc7 100644 (file)
@@ -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()));