]> source.dussan.org Git - jackcess.git/commitdiff
change references between major data types; share common utility classes from common...
authorJames Ahlborn <jtahlborn@yahoo.com>
Mon, 19 Nov 2007 03:26:40 +0000 (03:26 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Mon, 19 Nov 2007 03:26:40 +0000 (03:26 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@175 f203690c-595d-4dc9-a70b-905162fa7fd2

src/java/com/healthmarketscience/jackcess/Column.java
src/java/com/healthmarketscience/jackcess/Database.java
src/java/com/healthmarketscience/jackcess/Index.java
src/java/com/healthmarketscience/jackcess/PageChannel.java
src/java/com/healthmarketscience/jackcess/Table.java
src/java/com/healthmarketscience/jackcess/UsageMap.java
test/src/java/com/healthmarketscience/jackcess/TableTest.java

index 20a26ae1670d0455ce0b33d89db6f468b7539dce..3cfd4feffe3cbc9502cf94edd314b50a9cebda80 100644 (file)
@@ -96,6 +96,8 @@ public class Column implements Comparable<Column> {
   
   private static final Pattern GUID_PATTERN = Pattern.compile("\\s*[{]([\\p{XDigit}]{8})-([\\p{XDigit}]{4})-([\\p{XDigit}]{4})-([\\p{XDigit}]{4})-([\\p{XDigit}]{12})[}]\\s*");
 
+  /** owning table */
+  private final Table _table;
   /** For text columns, whether or not they are compressed */ 
   private boolean _compressedUnicode = false;
   /** Whether or not the column is of variable length */
@@ -108,10 +110,6 @@ public class Column implements Comparable<Column> {
   private byte _scale;
   /** Data type */
   private DataType _type;
-  /** Format that the containing database is in */
-  private JetFormat _format;
-  /** Used to read in LVAL pages */
-  private PageChannel _pageChannel;
   /** Maximum column length */
   private short _columnLength;
   /** 0-based column number */
@@ -130,7 +128,7 @@ public class Column implements Comparable<Column> {
   }
   
   public Column(JetFormat format) {
-    _format = format;
+    _table = null;
   }
 
   /**
@@ -140,43 +138,54 @@ public class Column implements Comparable<Column> {
     if(!testing) {
       throw new IllegalArgumentException();
     }
-    _format = JetFormat.VERSION_4;
-    _pageChannel = new PageChannel(testing);
+    _table = null;
   }
     
   /**
    * Read a column definition in from a buffer
+   * @param table owning table
    * @param buffer Buffer containing column definition
    * @param offset Offset in the buffer at which the column definition starts
    * @param format Format that the containing database is in
    */
-  public Column(ByteBuffer buffer, int offset, PageChannel pageChannel, JetFormat format)
-  throws IOException
+  public Column(Table table, ByteBuffer buffer, int offset)
+    throws IOException
   {
+    _table = table;
     if (LOG.isDebugEnabled()) {
       LOG.debug("Column def block:\n" + ByteUtil.toHexString(buffer, offset, 25));
     }
-    _pageChannel = pageChannel;
-    _format = format;
-    setType(DataType.fromByte(buffer.get(offset + format.OFFSET_COLUMN_TYPE)));
-    _columnNumber = buffer.getShort(offset + format.OFFSET_COLUMN_NUMBER);
-    _columnLength = buffer.getShort(offset + format.OFFSET_COLUMN_LENGTH);
+    setType(DataType.fromByte(buffer.get(offset + getFormat().OFFSET_COLUMN_TYPE)));
+    _columnNumber = buffer.getShort(offset + getFormat().OFFSET_COLUMN_NUMBER);
+    _columnLength = buffer.getShort(offset + getFormat().OFFSET_COLUMN_LENGTH);
     if (_type.getHasScalePrecision()) {
-      _precision = buffer.get(offset + format.OFFSET_COLUMN_PRECISION);
-      _scale = buffer.get(offset + format.OFFSET_COLUMN_SCALE);
+      _precision = buffer.get(offset + getFormat().OFFSET_COLUMN_PRECISION);
+      _scale = buffer.get(offset + getFormat().OFFSET_COLUMN_SCALE);
     }
-    byte flags = buffer.get(offset + format.OFFSET_COLUMN_FLAGS);
+    byte flags = buffer.get(offset + getFormat().OFFSET_COLUMN_FLAGS);
     _variableLength = ((flags & FIXED_LEN_FLAG_MASK) == 0);
     _autoNumber = ((flags & AUTO_NUMBER_FLAG_MASK) != 0);
     _compressedUnicode = ((buffer.get(offset +
-        format.OFFSET_COLUMN_COMPRESSED_UNICODE) & 1) == 1);
+        getFormat().OFFSET_COLUMN_COMPRESSED_UNICODE) & 1) == 1);
 
     if(_variableLength) {
-      _varLenTableIndex = buffer.getShort(offset + format.OFFSET_COLUMN_VARIABLE_TABLE_INDEX);
+      _varLenTableIndex = buffer.getShort(offset + getFormat().OFFSET_COLUMN_VARIABLE_TABLE_INDEX);
     } else {
-      _fixedDataOffset = buffer.getShort(offset + format.OFFSET_COLUMN_FIXED_DATA_OFFSET);
+      _fixedDataOffset = buffer.getShort(offset + getFormat().OFFSET_COLUMN_FIXED_DATA_OFFSET);
     }
   }
+
+  public Table getTable() {
+    return _table;
+  }
+  
+  public JetFormat getFormat() {
+    return getTable().getFormat();
+  }
+
+  public PageChannel getPageChannel() {
+    return getTable().getPageChannel();
+  }
   
   public String getName() {
     return _name;
@@ -307,10 +316,6 @@ public class Column implements Comparable<Column> {
    * @throws IllegalArgumentException if this column definition is invalid.
    */
   public void validate(JetFormat format) {
-    if(_format != format) {
-      throw new IllegalArgumentException("format must be " + format +
-                                         " but is " + _format);
-    }
     if(getType() == null) {
       throw new IllegalArgumentException("must have type");
     }
@@ -441,23 +446,23 @@ public class Column implements Comparable<Column> {
     } else {
 
       // long value on other page(s)
-      if (lvalDefinition.length != _format.SIZE_LONG_VALUE_DEF) {
-        throw new IOException("Expected " + _format.SIZE_LONG_VALUE_DEF +
+      if (lvalDefinition.length != getFormat().SIZE_LONG_VALUE_DEF) {
+        throw new IOException("Expected " + getFormat().SIZE_LONG_VALUE_DEF +
                               " bytes in long value definition, but found " +
                               lvalDefinition.length);
       }
 
       byte rowNum = def.get();
       int pageNum = ByteUtil.get3ByteInt(def, def.position());
-      ByteBuffer lvalPage = _pageChannel.createPageBuffer();
+      ByteBuffer lvalPage = getPageChannel().createPageBuffer();
       
       switch (type) {
       case LONG_VALUE_TYPE_OTHER_PAGE:
         {
-          _pageChannel.readPage(lvalPage, pageNum);
+          getPageChannel().readPage(lvalPage, pageNum);
 
-          short rowStart = Table.findRowStart(lvalPage, rowNum, _format);
-          short rowEnd = Table.findRowEnd(lvalPage, rowNum, _format);
+          short rowStart = Table.findRowStart(lvalPage, rowNum, getFormat());
+          short rowEnd = Table.findRowEnd(lvalPage, rowNum, getFormat());
 
           if((rowEnd - rowStart) != length) {
             throw new IOException("Unexpected lval row length");
@@ -474,10 +479,10 @@ public class Column implements Comparable<Column> {
         int remainingLen = length;
         while(remainingLen > 0) {
           lvalPage.clear();
-          _pageChannel.readPage(lvalPage, pageNum);
+          getPageChannel().readPage(lvalPage, pageNum);
 
-          short rowStart = Table.findRowStart(lvalPage, rowNum, _format);
-          short rowEnd = Table.findRowEnd(lvalPage, rowNum, _format);
+          short rowStart = Table.findRowStart(lvalPage, rowNum, getFormat());
+          short rowEnd = Table.findRowEnd(lvalPage, rowNum, getFormat());
           
           // read next page information
           lvalPage.position(rowStart);
@@ -726,19 +731,19 @@ public class Column implements Comparable<Column> {
 
     // determine which type to write
     byte type = 0;
-    int lvalDefLen = _format.SIZE_LONG_VALUE_DEF;
-    if((_format.SIZE_LONG_VALUE_DEF + value.length) <= remainingRowLength) {
+    int lvalDefLen = getFormat().SIZE_LONG_VALUE_DEF;
+    if((getFormat().SIZE_LONG_VALUE_DEF + value.length) <= remainingRowLength) {
       type = LONG_VALUE_TYPE_THIS_PAGE;
       lvalDefLen += value.length;
-    } else if(Table.getRowSpaceUsage(value.length, _format) <=
-              _format.MAX_ROW_SIZE)
+    } else if(Table.getRowSpaceUsage(value.length, getFormat()) <=
+              getFormat().MAX_ROW_SIZE)
     {
       type = LONG_VALUE_TYPE_OTHER_PAGE;
     } else {
       type = LONG_VALUE_TYPE_OTHER_PAGES;
     }
 
-    ByteBuffer def = _pageChannel.createBuffer(lvalDefLen);
+    ByteBuffer def = getPageChannel().createBuffer(lvalDefLen);
     ByteUtil.put3ByteInt(def, value.length);
     def.put(type);
 
@@ -752,7 +757,7 @@ public class Column implements Comparable<Column> {
       int firstLvalPageNum = PageChannel.INVALID_PAGE_NUMBER;
       byte firstLvalRow = 0;
 
-      ByteBuffer lvalPage = _pageChannel.createPageBuffer();
+      ByteBuffer lvalPage = getPageChannel().createPageBuffer();
       
       // write other page(s)
       switch(type) {
@@ -760,9 +765,9 @@ public class Column implements Comparable<Column> {
         writeLongValueHeader(lvalPage);
         firstLvalRow = (byte)Table.addDataPageRow(lvalPage,
                                                   value.length,
-                                                  _format);
+                                                  getFormat());
         lvalPage.put(value);
-        firstLvalPageNum = _pageChannel.writeNewPage(lvalPage);
+        firstLvalPageNum = getPageChannel().writeNewPage(lvalPage);
         break;
 
       case LONG_VALUE_TYPE_OTHER_PAGES:
@@ -770,7 +775,7 @@ public class Column implements Comparable<Column> {
         ByteBuffer buffer = ByteBuffer.wrap(value);
         int remainingLen = buffer.remaining();
         buffer.limit(0);
-        int lvalPageNum = _pageChannel.allocateNewPage();
+        int lvalPageNum = getPageChannel().allocateNewPage();
         byte lvalRow = 0;
         int nextLvalPageNum = 0;
         while(remainingLen > 0) {
@@ -778,14 +783,14 @@ public class Column implements Comparable<Column> {
           writeLongValueHeader(lvalPage);
 
           // figure out how much we will put in this page
-          int chunkLength = Math.min(_format.MAX_ROW_SIZE - 4,
+          int chunkLength = Math.min(getFormat().MAX_ROW_SIZE - 4,
                                      remainingLen);
           nextLvalPageNum = ((chunkLength < remainingLen) ?
-                             _pageChannel.allocateNewPage() : 0);
+                             getPageChannel().allocateNewPage() : 0);
 
           // add row to this page
           lvalRow = (byte)Table.addDataPageRow(lvalPage, chunkLength + 4,
-                                               _format);
+                                               getFormat());
           
           // write next page info (we'll always be writing into row 0 for
           // newly created pages)
@@ -798,7 +803,7 @@ public class Column implements Comparable<Column> {
           remainingLen -= chunkLength;
 
           // write new page to database
-          _pageChannel.writePage(lvalPage, lvalPageNum);
+          getPageChannel().writePage(lvalPage, lvalPageNum);
           
           // hang onto first page info
           if(firstLvalPageNum == PageChannel.INVALID_PAGE_NUMBER) {
@@ -833,8 +838,8 @@ public class Column implements Comparable<Column> {
   {
     lvalPage.put(PageTypes.DATA); //Page type
     lvalPage.put((byte) 1); //Unknown
-    lvalPage.putShort((short) (_format.PAGE_SIZE -
-                               _format.OFFSET_ROW_START)); //Free space
+    lvalPage.putShort((short) (getFormat().PAGE_SIZE -
+                               getFormat().OFFSET_ROW_START)); //Free space
     lvalPage.put((byte) 'L');
     lvalPage.put((byte) 'V');
     lvalPage.put((byte) 'A');
@@ -874,7 +879,7 @@ public class Column implements Comparable<Column> {
       switch(getType()) {
       case NUMERIC:
         // don't ask me why numerics are "var length" columns...
-        ByteBuffer buffer = _pageChannel.createBuffer(getLength(), order);
+        ByteBuffer buffer = getPageChannel().createBuffer(getLength(), order);
         writeNumericValue(buffer, obj);
         buffer.flip();
         return buffer;
@@ -931,7 +936,7 @@ public class Column implements Comparable<Column> {
     int size = getType().getFixedSize();
 
     // create buffer for data
-    ByteBuffer buffer = _pageChannel.createBuffer(size, order);
+    ByteBuffer buffer = getPageChannel().createBuffer(size, order);
 
     obj = booleanToInteger(obj);
 
@@ -1064,7 +1069,7 @@ public class Column implements Comparable<Column> {
    * @return A buffer with the text encoded
    */
   private ByteBuffer encodeUncompressedText(CharSequence text) {
-    return _format.CHARSET.encode(CharBuffer.wrap(text));
+    return getFormat().CHARSET.encode(CharBuffer.wrap(text));
   }
 
   /**
@@ -1081,7 +1086,7 @@ public class Column implements Comparable<Column> {
    */
   private CharBuffer decodeUncompressedText(byte[] textBytes, int startPost,
                                             int length) {
-    return _format.CHARSET.decode(ByteBuffer.wrap(textBytes, startPost,
+    return getFormat().CHARSET.decode(ByteBuffer.wrap(textBytes, startPost,
                                                   length));
   }  
 
index d161d4eb0a88732e0e3491a52af9bb5d45eec792..7c62843073f79d3738ee21afe4514e4753360475 100644 (file)
@@ -172,7 +172,7 @@ public class Database
   /** ID of the Tables system object */
   private Integer _tableParentId;
   /** Format that the containing database is in */
-  private JetFormat _format;
+  private final JetFormat _format;
   /**
    * Map of UPPERCASE table names to page numbers containing their definition
    * and their stored table name.
@@ -182,7 +182,7 @@ public class Database
   /** set of table names as stored in the mdb file, created on demand */
   private Set<String> _tableNames;
   /** Reads and writes database pages */
-  private PageChannel _pageChannel;
+  private final PageChannel _pageChannel;
   /** System catalog table */
   private Table _systemCatalog;
   /** System access control entries table */
@@ -287,6 +287,10 @@ public class Database
   {
     _format = JetFormat.getFormat(channel);
     _pageChannel = new PageChannel(channel, _format, autoSync);
+    // note, it's slighly sketchy to pass ourselves along partially
+    // constructed, but only our _format and _pageChannel refs should be
+    // needed
+    _pageChannel.initialize(this);
     _buffer = _pageChannel.createPageBuffer();
     readSystemCatalog();
   }
@@ -294,6 +298,10 @@ public class Database
   public PageChannel getPageChannel() {
     return _pageChannel;
   }
+
+  public JetFormat getFormat() {
+    return _format;
+  }
   
   /**
    * @return The system catalog table
@@ -316,7 +324,8 @@ public class Database
       throw new IOException("Looking for system catalog at page " +
           PAGE_SYSTEM_CATALOG + ", but page type is " + pageType);
     }
-    _systemCatalog = new Table(_buffer, _pageChannel, _format, PAGE_SYSTEM_CATALOG, "System Catalog");
+    _systemCatalog = new Table(this, _buffer, PAGE_SYSTEM_CATALOG,
+                               "System Catalog");
     Map<String,Object> row;
     while ( (row = _systemCatalog.getNextRow(SYSTEM_CATALOG_COLUMNS)) != null)
     {
@@ -349,7 +358,8 @@ public class Database
       throw new IOException("Looking for MSysACEs at page " + pageNum +
           ", but page type is " + pageType);
     }
-    _accessControlEntries = new Table(buffer, _pageChannel, _format, pageNum, "Access Control Entries");
+    _accessControlEntries = new Table(this, buffer, pageNum,
+                                      "Access Control Entries");
   }
   
   /**
@@ -390,8 +400,7 @@ public class Database
     
     int pageNumber = tableInfo.pageNumber.intValue();
     _pageChannel.readPage(_buffer, pageNumber);
-    return new Table(_buffer, _pageChannel, _format, pageNumber,
-                     tableInfo.tableName);
+    return new Table(this, _buffer, pageNumber, tableInfo.tableName);
   }
   
   /**
index 073ce578d8be08a7cb923b1b9c52d9298c87f2bd..3dba5ef0a9c67d242491782ec325deea6620c948 100644 (file)
@@ -184,19 +184,18 @@ public class Index implements Comparable<Index> {
     CODES_EXT.put('\'', new byte[]{(byte)6, (byte)128});
     CODES_EXT.put('-', new byte[]{(byte)6, (byte)130});
   }
-  
+
+  /** owning table */
+  private final Table _table;
   /** Page number of the index data */
   private int _pageNumber;
-  private int _parentPageNumber;
   /** Number of rows in the index
       NOTE: this does not actually seem to be the row count, unclear what the
       value means*/
   private int _rowCount;
-  private JetFormat _format;
   private SortedSet<Entry> _entries;
   /** Map of columns to flags */
   private Map<Column, Byte> _columns = new LinkedHashMap<Column, Byte>();
-  private PageChannel _pageChannel;
   /** 0-based index number */
   private int _indexNumber;
   /** Index name */
@@ -209,12 +208,22 @@ public class Index implements Comparable<Index> {
   /** FIXME, for now, we can't write multi-page indexes or indexes using the funky primary key compression scheme */
   boolean _readOnly;
   
-  public Index(int parentPageNumber, PageChannel channel, JetFormat format) {
-    _parentPageNumber = parentPageNumber;
-    _pageChannel = channel;
-    _format = format;
+  public Index(Table table) {
+    _table  = table;
+  }
+
+  public Table getTable() {
+    return _table;
   }
   
+  public JetFormat getFormat() {
+    return getTable().getFormat();
+  }
+
+  public PageChannel getPageChannel() {
+    return getTable().getPageChannel();
+  }
+
   public void setIndexNumber(int indexNumber) {
     _indexNumber = indexNumber;
   }
@@ -304,18 +313,18 @@ public class Index implements Comparable<Index> {
       throw new UnsupportedOperationException(
           "FIXME cannot write indexes of this type yet");
     }
-    _pageChannel.writePage(write(), _pageNumber);
+    getPageChannel().writePage(write(), _pageNumber);
   }
 
   /**
    * Write this index out to a buffer
    */
   private ByteBuffer write() throws IOException {
-    ByteBuffer buffer = _pageChannel.createPageBuffer();
+    ByteBuffer buffer = getPageChannel().createPageBuffer();
     buffer.put((byte) 0x04);  //Page type
     buffer.put((byte) 0x01);  //Unknown
     buffer.putShort((short) 0); //Free space
-    buffer.putInt(_parentPageNumber);
+    buffer.putInt(getTable().getTableDefPageNumber());
     buffer.putInt(0); //Prev page
     buffer.putInt(0); //Next page
     buffer.putInt(0); //Leaf page
@@ -323,7 +332,7 @@ public class Index implements Comparable<Index> {
     buffer.put((byte) 0); // compressed byte count
     buffer.put((byte) 0); //Unknown
     buffer.put((byte) 0); //Unknown
-    byte[] entryMask = new byte[_format.SIZE_INDEX_ENTRY_MASK];
+    byte[] entryMask = new byte[getFormat().SIZE_INDEX_ENTRY_MASK];
     int totalSize = 0;
     for(Entry entry : _entries) {
       int size = entry.size();
@@ -339,7 +348,7 @@ public class Index implements Comparable<Index> {
     for(Entry entry : _entries) {
       entry.write(buffer);
     }
-    buffer.putShort(2, (short) (_format.PAGE_SIZE - buffer.position()));
+    buffer.putShort(2, (short) (getFormat().PAGE_SIZE - buffer.position()));
     return buffer;
   }
   
@@ -371,12 +380,12 @@ public class Index implements Comparable<Index> {
   {
     _entries = new TreeSet<Entry>();
     
-    ByteBuffer indexPage = _pageChannel.createPageBuffer();
+    ByteBuffer indexPage = getPageChannel().createPageBuffer();
 
     // find first leaf page
     int leafPageNumber = _pageNumber;
     while(true) {
-      _pageChannel.readPage(indexPage, leafPageNumber);
+      getPageChannel().readPage(indexPage, leafPageNumber);
 
       if(indexPage.get(0) == INDEX_NODE_PAGE_TYPE) {
         // FIXME we can't modify this index at this point in time
@@ -400,7 +409,7 @@ public class Index implements Comparable<Index> {
         _readOnly = true;
         
         // found another one 
-        _pageChannel.readPage(indexPage, leafPageNumber);
+        getPageChannel().readPage(indexPage, leafPageNumber);
         
       } else {
         // all done
@@ -444,7 +453,7 @@ public class Index implements Comparable<Index> {
     // note, "header" data is in LITTLE_ENDIAN format, entry data is in
     // BIG_ENDIAN format
 
-    int nextLeafPage = leafPage.getInt(_format.OFFSET_NEXT_INDEX_LEAF_PAGE);
+    int nextLeafPage = leafPage.getInt(getFormat().OFFSET_NEXT_INDEX_LEAF_PAGE);
     readIndexPage(leafPage, true, _entries, null);
 
     return nextLeafPage;
@@ -462,10 +471,10 @@ public class Index implements Comparable<Index> {
     // note, "header" data is in LITTLE_ENDIAN format, entry data is in
     // BIG_ENDIAN format
     int numCompressedBytes = indexPage.get(
-        _format.OFFSET_INDEX_COMPRESSED_BYTE_COUNT);
-    int entryMaskLength = _format.SIZE_INDEX_ENTRY_MASK;
-    int entryMaskPos = _format.OFFSET_INDEX_ENTRY_MASK;
-    int entryPos = entryMaskPos + _format.SIZE_INDEX_ENTRY_MASK;
+        getFormat().OFFSET_INDEX_COMPRESSED_BYTE_COUNT);
+    int entryMaskLength = getFormat().SIZE_INDEX_ENTRY_MASK;
+    int entryMaskPos = getFormat().OFFSET_INDEX_ENTRY_MASK;
+    int entryPos = entryMaskPos + getFormat().SIZE_INDEX_ENTRY_MASK;
     int lastStart = 0;
     byte[] valuePrefix = null;
     boolean firstEntry = true;
index 0c823c8620b57714aca14774871a0cfd66a590a5..e5c3fed83aef8088baa2818e8fb8486439cb50ce 100644 (file)
@@ -54,13 +54,13 @@ public class PageChannel implements Channel, Flushable {
   private static final int PAGE_GLOBAL_USAGE_MAP = 1;
   
   /** Channel containing the database */
-  private FileChannel _channel;
+  private final FileChannel _channel;
   /** Format of the database in the channel */
-  private JetFormat _format;
+  private final JetFormat _format;
+  /** whether or not to force all writes to disk immediately */
+  private final  boolean _autoSync;
   /** Tracks free pages in the database. */
   private UsageMap _globalUsageMap;
-  /** whether or not to force all writes to disk immediately */
-  private boolean _autoSync;
   
   /**
    * @param channel Channel containing the database
@@ -72,15 +72,20 @@ public class PageChannel implements Channel, Flushable {
     _channel = channel;
     _format = format;
     _autoSync = autoSync;
-    //Null check only exists for unit tests.  Channel should never normally be null.
-    if (channel != null) {
-      // note the global usage map is a special map where any page outside of
-      // the current range is assumed to be "on"
-      _globalUsageMap = UsageMap.read(this, PAGE_GLOBAL_USAGE_MAP, (byte) 0,
-                                      format, true);
-    }
   }
 
+  /**
+   * Does second-stage initialization, must be called after construction.
+   */
+  public void initialize(Database database)
+    throws IOException
+  {
+    // note the global usage map is a special map where any page outside of
+    // the current range is assumed to be "on"
+    _globalUsageMap = UsageMap.read(database, PAGE_GLOBAL_USAGE_MAP, (byte) 0,
+                                    true);
+  }
+  
   /**
    * Only used by unit tests
    */
@@ -92,6 +97,10 @@ public class PageChannel implements Channel, Flushable {
     _format = JetFormat.VERSION_4;
     _autoSync = false;
   }
+
+  public JetFormat getFormat() {
+    return _format;
+  }
   
   /**
    * @param buffer Buffer to read the page into
@@ -109,7 +118,7 @@ public class PageChannel implements Channel, Flushable {
       LOG.debug("Reading in page " + Integer.toHexString(pageNumber));
     }
     buffer.clear();
-    boolean rtn = _channel.read(buffer, (long) pageNumber * (long) _format.PAGE_SIZE) != -1;
+    boolean rtn = _channel.read(buffer, (long) pageNumber * (long) getFormat().PAGE_SIZE) != -1;
     buffer.flip();
     return rtn;
   }
@@ -136,7 +145,7 @@ public class PageChannel implements Channel, Flushable {
   {
     page.rewind();
     page.position(pageOffset);
-    _channel.write(page, (((long) pageNumber * (long) _format.PAGE_SIZE) +
+    _channel.write(page, (((long) pageNumber * (long) getFormat().PAGE_SIZE) +
                           (long) pageOffset));
     if(_autoSync) {
       flush();
@@ -155,9 +164,9 @@ public class PageChannel implements Channel, Flushable {
     // push the buffer to the end of the page, so that a full page's worth of
     // data is written regardless of the incoming buffer size (we use a tiny
     // buffer in allocateNewPage)
-    long offset = size + (_format.PAGE_SIZE - page.remaining());
+    long offset = size + (getFormat().PAGE_SIZE - page.remaining());
     _channel.write(page, offset);
-    int pageNumber = (int) (size / _format.PAGE_SIZE);
+    int pageNumber = (int) (size / getFormat().PAGE_SIZE);
     _globalUsageMap.removePageNumber(pageNumber);  //force is done here
     return pageNumber;
   }
@@ -175,7 +184,7 @@ public class PageChannel implements Channel, Flushable {
    * @return A newly-allocated buffer that can be passed to readPage
    */
   public ByteBuffer createPageBuffer() {
-    return createBuffer(_format.PAGE_SIZE);
+    return createBuffer(getFormat().PAGE_SIZE);
   }
 
   /**
index 6acab8dd7595b1ef0540da03997abca38bcd9349..9fdc5c5af3115f75213cfa1397da4c049d1413f6 100644 (file)
@@ -76,7 +76,9 @@ public class Table
                  0));
       }
     };
-  
+
+  /** owning database */
+  private final Database _database;
   /** State used for reading the table rows */
   private RowState _rowState;
   /** Type of the table (either TYPE_SYSTEM or TYPE_USER) */
@@ -92,25 +94,21 @@ public class Table
   /** last auto number for the table */
   private int _lastAutoNumber;
   /** page number of the definition of this table */
-  private int _tableDefPageNumber;
+  private final int _tableDefPageNumber;
   /** Number of rows left to be read on the current page */
   private short _rowsLeftOnPage = 0;
   /** max Number of columns in the table (includes previous deletions) */
   private short _maxColumnCount;
   /** max Number of variable columns in the table */
   private short _maxVarColumnCount;
-  /** Format of the database that contains this table */
-  private JetFormat _format;
   /** List of columns in this table, ordered by column number */
   private List<Column> _columns = new ArrayList<Column>();
   /** List of variable length columns in this table, ordered by offset */
   private List<Column> _varColumns = new ArrayList<Column>();
   /** List of indexes on this table */
   private List<Index> _indexes = new ArrayList<Index>();
-  /** Used to read in pages */
-  private PageChannel _pageChannel;
   /** Table name as stored in Database */
-  private String _name;
+  private final String _name;
   /** Usage map of pages that this table owns */
   private UsageMap _ownedPages;
   /** Iterator over the pages that this table owns */
@@ -121,11 +119,14 @@ public class Table
   /**
    * Only used by unit tests
    */
-  Table(boolean testing) throws IOException {
+  Table(boolean testing, List<Column> columns) throws IOException {
     if(!testing) {
       throw new IllegalArgumentException();
     }
-    _pageChannel = new PageChannel(testing);
+    _database = null;
+    _tableDefPageNumber = PageChannel.INVALID_PAGE_NUMBER;
+    _name = null;
+    setColumns(columns);
   }
   
   /**
@@ -135,27 +136,25 @@ public class Table
    * @param pageNumber Page number of the table definition
         * @param name Table name
    */
-  protected Table(ByteBuffer tableBuffer, PageChannel pageChannel,
-                  JetFormat format, int pageNumber, String name)
+  protected Table(Database database, ByteBuffer tableBuffer,
+                  int pageNumber, String name)
   throws IOException
   {
-    _pageChannel = pageChannel;
-    _format = format;
+    _database = database;
     _tableDefPageNumber = pageNumber;
     _name = name;
-    int nextPage;
+    int nextPage = tableBuffer.getInt(getFormat().OFFSET_NEXT_TABLE_DEF_PAGE);
     ByteBuffer nextPageBuffer = null;
-    nextPage = tableBuffer.getInt(_format.OFFSET_NEXT_TABLE_DEF_PAGE);
     while (nextPage != 0) {
       if (nextPageBuffer == null) {
-        nextPageBuffer = _pageChannel.createPageBuffer();
+        nextPageBuffer = getPageChannel().createPageBuffer();
       }
-      _pageChannel.readPage(nextPageBuffer, nextPage);
-      nextPage = nextPageBuffer.getInt(_format.OFFSET_NEXT_TABLE_DEF_PAGE);
-      ByteBuffer newBuffer = _pageChannel.createBuffer(
-          tableBuffer.capacity() + format.PAGE_SIZE - 8);
+      getPageChannel().readPage(nextPageBuffer, nextPage);
+      nextPage = nextPageBuffer.getInt(getFormat().OFFSET_NEXT_TABLE_DEF_PAGE);
+      ByteBuffer newBuffer = getPageChannel().createBuffer(
+          tableBuffer.capacity() + getFormat().PAGE_SIZE - 8);
       newBuffer.put(tableBuffer);
-      newBuffer.put(nextPageBuffer.array(), 8, format.PAGE_SIZE - 8);
+      newBuffer.put(nextPageBuffer.array(), 8, getFormat().PAGE_SIZE - 8);
       tableBuffer = newBuffer;
       tableBuffer.flip();
     }
@@ -171,6 +170,22 @@ public class Table
   public String getName() {
     return _name;
   }
+
+  public Database getDatabase() {
+    return _database;
+  }
+  
+  public JetFormat getFormat() {
+    return getDatabase().getFormat();
+  }
+
+  public PageChannel getPageChannel() {
+    return getDatabase().getPageChannel();
+  }
+
+  protected int getTableDefPageNumber() {
+    return _tableDefPageNumber;
+  }
   
   /**
    * @return All of the columns in this table (unmodifiable List)
@@ -182,7 +197,7 @@ public class Table
   /**
    * Only called by unit tests
    */
-  void setColumns(List<Column> columns) {
+  private void setColumns(List<Column> columns) {
     _columns = columns;
     int colIdx = 0;
     int varLenIdx = 0;
@@ -243,9 +258,9 @@ public class Table
     }
     
     // delete flag always gets set in the "root" page (even if overflow row)
-    ByteBuffer rowBuffer = _rowState.getPage(_pageChannel);
+    ByteBuffer rowBuffer = _rowState.getPage(getPageChannel());
     int pageNumber = _rowState.getPageNumber();
-    int rowIndex = getRowStartOffset(_currentRowInPage, _format);
+    int rowIndex = getRowStartOffset(_currentRowInPage, getFormat());
     rowBuffer.putShort(rowIndex, (short)(rowBuffer.getShort(rowIndex)
                                       | DELETED_ROW_MASK | OVERFLOW_ROW_MASK));
     writeDataPage(rowBuffer, pageNumber);
@@ -456,13 +471,13 @@ public class Table
         }
 
         // load new page
-        ByteBuffer rowBuffer = _rowState.setPage(_pageChannel, nextPageNumber);
+        ByteBuffer rowBuffer = _rowState.setPage(getPageChannel(), nextPageNumber);
         if(rowBuffer.get() != PageTypes.DATA) {
           //Only interested in data pages
           continue;
         }
 
-        _rowsLeftOnPage = rowBuffer.getShort(_format.OFFSET_NUM_ROWS_ON_DATA_PAGE);
+        _rowsLeftOnPage = rowBuffer.getShort(getFormat().OFFSET_NUM_ROWS_ON_DATA_PAGE);
         if(_rowsLeftOnPage == 0) {
           // no rows on this page?
           continue;
@@ -475,7 +490,7 @@ public class Table
       _rowsLeftOnPage--;
 
       ByteBuffer rowBuffer =
-        positionAtRow(_rowState, _currentRowInPage, _pageChannel, _format);
+        positionAtRow(_rowState, _currentRowInPage, getPageChannel(), getFormat());
       if(rowBuffer != null) {
         // we found a non-deleted row, return it
         return rowBuffer;
@@ -862,40 +877,38 @@ public class Table
     if (LOG.isDebugEnabled()) {
       tableBuffer.rewind();
       LOG.debug("Table def block:\n" + ByteUtil.toHexString(tableBuffer,
-          _format.SIZE_TDEF_HEADER));
+          getFormat().SIZE_TDEF_HEADER));
     }
-    _rowCount = tableBuffer.getInt(_format.OFFSET_NUM_ROWS);
-    _lastAutoNumber = tableBuffer.getInt(_format.OFFSET_NEXT_AUTO_NUMBER);
-    _tableType = tableBuffer.get(_format.OFFSET_TABLE_TYPE);
-    _maxColumnCount = tableBuffer.getShort(_format.OFFSET_MAX_COLS);
-    _maxVarColumnCount = tableBuffer.getShort(_format.OFFSET_NUM_VAR_COLS);
-    short columnCount = tableBuffer.getShort(_format.OFFSET_NUM_COLS);
-    _indexSlotCount = tableBuffer.getInt(_format.OFFSET_NUM_INDEX_SLOTS);
-    _indexCount = tableBuffer.getInt(_format.OFFSET_NUM_INDEXES);
+    _rowCount = tableBuffer.getInt(getFormat().OFFSET_NUM_ROWS);
+    _lastAutoNumber = tableBuffer.getInt(getFormat().OFFSET_NEXT_AUTO_NUMBER);
+    _tableType = tableBuffer.get(getFormat().OFFSET_TABLE_TYPE);
+    _maxColumnCount = tableBuffer.getShort(getFormat().OFFSET_MAX_COLS);
+    _maxVarColumnCount = tableBuffer.getShort(getFormat().OFFSET_NUM_VAR_COLS);
+    short columnCount = tableBuffer.getShort(getFormat().OFFSET_NUM_COLS);
+    _indexSlotCount = tableBuffer.getInt(getFormat().OFFSET_NUM_INDEX_SLOTS);
+    _indexCount = tableBuffer.getInt(getFormat().OFFSET_NUM_INDEXES);
     
-    byte rowNum = tableBuffer.get(_format.OFFSET_OWNED_PAGES);
-    int pageNum = ByteUtil.get3ByteInt(tableBuffer, _format.OFFSET_OWNED_PAGES + 1);
-    _ownedPages = UsageMap.read(_pageChannel, pageNum, rowNum, _format,
-                                false);
+    byte rowNum = tableBuffer.get(getFormat().OFFSET_OWNED_PAGES);
+    int pageNum = ByteUtil.get3ByteInt(tableBuffer, getFormat().OFFSET_OWNED_PAGES + 1);
+    _ownedPages = UsageMap.read(getDatabase(), pageNum, rowNum, false);
     _ownedPagesIterator = _ownedPages.iterator();
-    rowNum = tableBuffer.get(_format.OFFSET_FREE_SPACE_PAGES);
-    pageNum = ByteUtil.get3ByteInt(tableBuffer, _format.OFFSET_FREE_SPACE_PAGES + 1);
-    _freeSpacePages = UsageMap.read(_pageChannel, pageNum, rowNum, _format,
-                                    false);
+    rowNum = tableBuffer.get(getFormat().OFFSET_FREE_SPACE_PAGES);
+    pageNum = ByteUtil.get3ByteInt(tableBuffer, getFormat().OFFSET_FREE_SPACE_PAGES + 1);
+    _freeSpacePages = UsageMap.read(getDatabase(), pageNum, rowNum, false);
     
     for (int i = 0; i < _indexCount; i++) {
-      Index index = new Index(_tableDefPageNumber, _pageChannel, _format);
+      Index index = new Index(this);
       _indexes.add(index);
-      index.setRowCount(tableBuffer.getInt(_format.OFFSET_INDEX_DEF_BLOCK +
-          i * _format.SIZE_INDEX_DEFINITION + 4));
+      index.setRowCount(tableBuffer.getInt(getFormat().OFFSET_INDEX_DEF_BLOCK +
+          i * getFormat().SIZE_INDEX_DEFINITION + 4));
     }
     
-    int offset = _format.OFFSET_INDEX_DEF_BLOCK +
-        _indexCount * _format.SIZE_INDEX_DEFINITION;
+    int offset = getFormat().OFFSET_INDEX_DEF_BLOCK +
+        _indexCount * getFormat().SIZE_INDEX_DEFINITION;
     Column column;
     for (int i = 0; i < columnCount; i++) {
-      column = new Column(tableBuffer,
-          offset + i * _format.SIZE_COLUMN_HEADER, _pageChannel, _format);
+      column = new Column(this, tableBuffer,
+          offset + i * getFormat().SIZE_COLUMN_HEADER);
       _columns.add(column);
       if(column.isVariableLength()) {
         // also shove it in the variable columns list, which is ordered
@@ -903,7 +916,7 @@ public class Table
         _varColumns.add(column);
       }
     }
-    offset += columnCount * _format.SIZE_COLUMN_HEADER;
+    offset += columnCount * getFormat().SIZE_COLUMN_HEADER;
     for (int i = 0; i < columnCount; i++) {
       column = (Column) _columns.get(i);
       short nameLength = tableBuffer.getShort(offset);
@@ -911,7 +924,7 @@ public class Table
       byte[] nameBytes = new byte[nameLength];
       tableBuffer.position(offset);
       tableBuffer.get(nameBytes, 0, (int) nameLength);
-      column.setName(_format.CHARSET.decode(ByteBuffer.wrap(nameBytes)).toString());
+      column.setName(getFormat().CHARSET.decode(ByteBuffer.wrap(nameBytes)).toString());
       offset += nameLength;
     }
     Collections.sort(_columns);
@@ -928,7 +941,7 @@ public class Table
     
     int idxOffset = tableBuffer.position();
     tableBuffer.position(idxOffset +
-                     (_format.OFFSET_INDEX_NUMBER_BLOCK * _indexCount));
+                     (getFormat().OFFSET_INDEX_NUMBER_BLOCK * _indexCount));
 
     // there are _indexSlotCount blocks here, we ignore any slot with an index
     // number greater than the number of actual indexes
@@ -960,7 +973,7 @@ public class Table
     for (int i = 0; i < _indexCount; i++) {
       byte[] nameBytes = new byte[tableBuffer.getShort()];
       tableBuffer.get(nameBytes);
-      _indexes.get(i).setName(_format.CHARSET.decode(ByteBuffer.wrap(
+      _indexes.get(i).setName(getFormat().CHARSET.decode(ByteBuffer.wrap(
           nameBytes)).toString());
     }
     int idxEndOffset = tableBuffer.position();
@@ -986,7 +999,7 @@ public class Table
     throws IOException
   {
     // write the page data
-    _pageChannel.writePage(pageBuffer, pageNumber);
+    getPageChannel().writePage(pageBuffer, pageNumber);
 
     // if the overflow buffer is this page, invalidate it
     _rowState.possiblyInvalidate(pageNumber, pageBuffer);
@@ -1006,12 +1019,12 @@ public class Table
    * @param rows List of Object[] row values
    */
   public void addRows(List<? extends Object[]> rows) throws IOException {
-    ByteBuffer dataPage = _pageChannel.createPageBuffer();
+    ByteBuffer dataPage = getPageChannel().createPageBuffer();
     ByteBuffer[] rowData = new ByteBuffer[rows.size()];
     Iterator<? extends Object[]> iter = rows.iterator();
     for (int i = 0; iter.hasNext(); i++) {
-      rowData[i] = createRow(iter.next(), _format.MAX_ROW_SIZE);
-      if (rowData[i].limit() > _format.MAX_ROW_SIZE) {
+      rowData[i] = createRow(iter.next(), getFormat().MAX_ROW_SIZE);
+      if (rowData[i].limit() > getFormat().MAX_ROW_SIZE) {
         throw new IOException("Row size " + rowData[i].limit() +
                               " is too large");
       }
@@ -1026,7 +1039,7 @@ public class Table
         revPageIter.hasNextPage(); )
     {
       int tmpPageNumber = revPageIter.getNextPage();
-      _pageChannel.readPage(dataPage, tmpPageNumber);
+      getPageChannel().readPage(dataPage, tmpPageNumber);
       if(dataPage.get() == PageTypes.DATA) {
         // found last data page
         pageNumber = tmpPageNumber;
@@ -1041,8 +1054,8 @@ public class Table
     
     for (int i = 0; i < rowData.length; i++) {
       rowSize = rowData[i].remaining();
-      int rowSpaceUsage = getRowSpaceUsage(rowSize, _format);
-      short freeSpaceInPage = dataPage.getShort(_format.OFFSET_FREE_SPACE);
+      int rowSpaceUsage = getRowSpaceUsage(rowSize, getFormat());
+      short freeSpaceInPage = dataPage.getShort(getFormat().OFFSET_FREE_SPACE);
       if (freeSpaceInPage < rowSpaceUsage) {
 
         //Last data page is full.  Create a new one.
@@ -1051,11 +1064,11 @@ public class Table
         _freeSpacePages.removePageNumber(pageNumber);
 
         pageNumber = newDataPage(dataPage);
-        freeSpaceInPage = dataPage.getShort(_format.OFFSET_FREE_SPACE);
+        freeSpaceInPage = dataPage.getShort(getFormat().OFFSET_FREE_SPACE);
       }
 
       // write out the row data
-      int rowNum = addDataPageRow(dataPage, rowSize, _format);
+      int rowNum = addDataPageRow(dataPage, rowSize, getFormat());
       dataPage.put(rowData[i]);
 
       // update the indexes
@@ -1076,24 +1089,24 @@ public class Table
   private void updateTableDefinition() throws IOException
   {
     // load table definition
-    ByteBuffer tdefPage = _pageChannel.createPageBuffer();
-    _pageChannel.readPage(tdefPage, _tableDefPageNumber);
+    ByteBuffer tdefPage = getPageChannel().createPageBuffer();
+    getPageChannel().readPage(tdefPage, _tableDefPageNumber);
     
     // make sure rowcount and autonumber are up-to-date
-    tdefPage.putInt(_format.OFFSET_NUM_ROWS, _rowCount);
-    tdefPage.putInt(_format.OFFSET_NEXT_AUTO_NUMBER, _lastAutoNumber);
+    tdefPage.putInt(getFormat().OFFSET_NUM_ROWS, _rowCount);
+    tdefPage.putInt(getFormat().OFFSET_NEXT_AUTO_NUMBER, _lastAutoNumber);
 
     // write any index changes
     Iterator<Index> indIter = _indexes.iterator();
     for (int i = 0; i < _indexes.size(); i++) {
-      tdefPage.putInt(_format.OFFSET_INDEX_DEF_BLOCK +
-          (i * _format.SIZE_INDEX_DEFINITION) + 4, _rowCount);
+      tdefPage.putInt(getFormat().OFFSET_INDEX_DEF_BLOCK +
+          (i * getFormat().SIZE_INDEX_DEFINITION) + 4, _rowCount);
       Index index = indIter.next();
       index.update();
     }
 
     // write modified table definition
-    _pageChannel.writePage(tdefPage, _tableDefPageNumber);
+    getPageChannel().writePage(tdefPage, _tableDefPageNumber);
   }
   
   /**
@@ -1106,12 +1119,12 @@ public class Table
     }
     dataPage.put(PageTypes.DATA); //Page type
     dataPage.put((byte) 1); //Unknown
-    dataPage.putShort((short)getRowSpaceUsage(_format.MAX_ROW_SIZE,
-                                              _format)); //Free space in this page
+    dataPage.putShort((short)getRowSpaceUsage(getFormat().MAX_ROW_SIZE,
+                                              getFormat())); //Free space in this page
     dataPage.putInt(_tableDefPageNumber); //Page pointer to table definition
     dataPage.putInt(0); //Unknown
     dataPage.putInt(0); //Number of records on this page
-    int pageNumber = _pageChannel.writeNewPage(dataPage);
+    int pageNumber = getPageChannel().writeNewPage(dataPage);
     _ownedPages.addPageNumber(pageNumber);
     _freeSpacePages.addPageNumber(pageNumber);
     return pageNumber;
@@ -1121,7 +1134,7 @@ public class Table
    * Serialize a row of Objects into a byte buffer
    */
   ByteBuffer createRow(Object[] rowArray, int maxRowSize) throws IOException {
-    ByteBuffer buffer = _pageChannel.createPageBuffer();
+    ByteBuffer buffer = getPageChannel().createPageBuffer();
     buffer.putShort((short) _maxColumnCount);
     NullMask nullMask = new NullMask(_maxColumnCount);
     
index ec3bc36120022dc82d41a0963eb0b3a1345990d2..3305f114d2944b175b156cb81075abf9b70f06a6 100644 (file)
@@ -48,15 +48,15 @@ public class UsageMap
   public static final byte MAP_TYPE_INLINE = 0x0;
   /** Reference map type, for maps that are too large to fit inline */
   public static final byte MAP_TYPE_REFERENCE = 0x1;
-  
+
+  /** owning database */
+  private final Database _database;
   /** Page number of the map table declaration */
-  private int _tablePageNum;
+  private final int _tablePageNum;
   /** 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;
-  /** Format of the database that contains this usage map */
-  private JetFormat _format;
   /** First page that this usage map applies to */
   private int _startPage;
   /** Last page that this usage map applies to */
@@ -64,9 +64,7 @@ public class UsageMap
   /** bits representing page numbers used, offset from _startPage */
   private BitSet _pageNumbers = new BitSet();
   /** Buffer that contains the usage map table declaration page */
-  private ByteBuffer _tableBuffer;
-  /** Used to read in pages */
-  private PageChannel _pageChannel;
+  private final ByteBuffer _tableBuffer;
   /** modification count on the usage map, used to keep the iterators in
       sync */
   private int _modCount = 0;
@@ -75,22 +73,20 @@ public class UsageMap
   private Handler _handler;
   
   /**
-   * @param pageChannel Used to read in pages
+   * @param database database that contains this usage map
    * @param tableBuffer Buffer that contains this map's declaration
    * @param pageNum Page number that this usage map is contained in
-   * @param format Format of the database that contains this usage map
    * @param rowStart Offset at which the declaration starts in the buffer
    */
-  private UsageMap(PageChannel pageChannel, ByteBuffer tableBuffer,
-                   int pageNum, JetFormat format, short rowStart)
+  private UsageMap(Database database, ByteBuffer tableBuffer,
+                   int pageNum, short rowStart)
   throws IOException
   {
-    _pageChannel = pageChannel;
+    _database = database;
     _tableBuffer = tableBuffer;
     _tablePageNum = pageNum;
-    _format = format;
     _rowStart = rowStart;
-    _tableBuffer.position((int) _rowStart + format.OFFSET_USAGE_MAP_START);
+    _tableBuffer.position((int) _rowStart + getFormat().OFFSET_USAGE_MAP_START);
     _startOffset = _tableBuffer.position();
     if (LOG.isDebugEnabled()) {
       LOG.debug("Usage map block:\n" + ByteUtil.toHexString(_tableBuffer, _rowStart,
@@ -98,27 +94,38 @@ public class UsageMap
     }
   }
 
+  public Database getDatabase() {
+    return _database;
+  }
+  
+  public JetFormat getFormat() {
+    return getDatabase().getFormat();
+  }
+
+  public PageChannel getPageChannel() {
+    return getDatabase().getPageChannel();
+  }
+  
   /**
-   * @param pageChannel Used to read in pages
+   * @param database database that contains this usage map
    * @param pageNum Page number that this usage map is contained in
    * @param rowNum Number of the row on the page that contains this usage map
-   * @param format Format of the database that contains this usage map
    * @return Either an InlineUsageMap or a ReferenceUsageMap, depending on
    *         which type of map is found
    */
-  public static UsageMap read(PageChannel pageChannel, int pageNum,
-                              byte rowNum, JetFormat format,
-                              boolean assumeOutOfRangeBitsOn)
+  public static UsageMap read(Database database, int pageNum,
+                              byte rowNum, boolean assumeOutOfRangeBitsOn)
     throws IOException
   {
+    JetFormat format = database.getFormat();
+    PageChannel pageChannel = database.getPageChannel();
     ByteBuffer tableBuffer = pageChannel.createPageBuffer();
     pageChannel.readPage(tableBuffer, pageNum);
     short rowStart = Table.findRowStart(tableBuffer, rowNum, format);
     int rowEnd = Table.findRowEnd(tableBuffer, rowNum, format);
     tableBuffer.limit(rowEnd);    
     byte mapType = tableBuffer.get(rowStart);
-    UsageMap rtn = new UsageMap(pageChannel, tableBuffer, pageNum, format,
-                                rowStart);
+    UsageMap rtn = new UsageMap(database, tableBuffer, pageNum, rowStart);
     rtn.initHandler(mapType, assumeOutOfRangeBitsOn);
     return rtn;
   }
@@ -163,14 +170,6 @@ public class UsageMap
     return _tablePageNum;
   }
   
-  protected PageChannel getPageChannel() {
-    return _pageChannel;
-  }
-  
-  protected JetFormat getFormat() {
-    return _format;
-  }
-
   protected int getStartPage() {
     return _startPage;
   }
@@ -251,7 +250,7 @@ public class UsageMap
     throws IOException
   {
     // note, we only want to write the row data with which we are working
-    _pageChannel.writePage(_tableBuffer, _tablePageNum, _rowStart);
+    getPageChannel().writePage(_tableBuffer, _tablePageNum, _rowStart);
   }
   
   /**
index 041600a6a5dbda664b748cffd42620d8c7de9812..5b22db0f371d89617399fbd49ccea82eabf24f26 100644 (file)
@@ -18,19 +18,24 @@ public class TableTest extends TestCase {
   }
   
   public void testCreateRow() throws Exception {
-    JetFormat format = JetFormat.VERSION_4;
-    Table table = new Table(true);
+    final JetFormat format = JetFormat.VERSION_4;
+    final PageChannel pageChannel = new PageChannel(true);
     List<Column> columns = new ArrayList<Column>();
-    Column col = new Column(true);
+    Column col = newTestColumn(pageChannel);
     col.setType(DataType.INT);
     columns.add(col);
-    col = new Column(true);
+    col = newTestColumn(pageChannel);
     col.setType(DataType.TEXT);
     columns.add(col);
-    col = new Column(true);
+    col = newTestColumn(pageChannel);
     col.setType(DataType.TEXT);
     columns.add(col);
-    table.setColumns(columns);
+    Table table = new Table(true, columns) {
+        @Override
+        public PageChannel getPageChannel() {
+          return pageChannel;
+        }
+      };
     int colCount = 3;
     Object[] row = new Object[colCount];
     row[0] = new Short((short) 9);
@@ -46,5 +51,18 @@ public class TableTest extends TestCase {
     assertEquals((short) 2, buffer.getShort(28));
     assertEquals((byte) 7, buffer.get(30));
   }
+
+  private static Column newTestColumn(final PageChannel pageChannel) {
+    return new Column(true) {
+        @Override
+        public PageChannel getPageChannel() {
+          return pageChannel;
+        }
+        @Override
+        public JetFormat getFormat() {
+          return JetFormat.VERSION_4;
+        }
+      };
+  }
   
 }