column.getName());
}
}
-
- //We are creating a new page at the end of the db for the tdef.
- int pageNumber = _pageChannel.getPageCount();
-
+
+ // first, create the usage map page
+ int usageMapPageNumber = _pageChannel.writeNewPage(
+ createUsageMapDefinitionBuffer());
+
+ // now, create the table definition
ByteBuffer buffer = _pageChannel.createPageBuffer();
-
- writeTableDefinition(buffer, columns, pageNumber);
-
+ writeTableDefinition(buffer, columns, usageMapPageNumber);
writeColumnDefinitions(buffer, columns);
//End of tabledef
buffer.putShort(2, (short)(_format.PAGE_SIZE - tableDefLen - 8)); // overwrite page free space
buffer.putInt(8, tableDefLen); //Overwrite length of data for this page
- //Write the tdef and usage map pages to disk.
- _pageChannel.writeNewPage(buffer);
- _pageChannel.writeNewPage(createUsageMapDefinitionBuffer(pageNumber));
- _pageChannel.writeNewPage(createUsageMapDataBuffer()); //Usage map
+ //Write the tdef page to disk.
+ int tdefPageNumber = _pageChannel.writeNewPage(buffer);
//Add this table to our internal list.
- addTable(name, new Integer(pageNumber));
+ addTable(name, new Integer(tdefPageNumber));
//Add this table to system tables
- addToSystemCatalog(name, pageNumber);
- addToAccessControlEntries(pageNumber);
+ addToSystemCatalog(name, tdefPageNumber);
+ addToAccessControlEntries(tdefPageNumber);
}
/**
* @param pageNumber Page number that this table definition will be written to
*/
private void writeTableDefinition(ByteBuffer buffer, List<Column> columns,
- int pageNumber)
+ int usageMapPageNumber)
throws IOException {
//Start writing the tdef
buffer.put(PageTypes.TABLE_DEF); //Page type
buffer.putInt(0); //Number of indexes in table
buffer.putInt(0); //Number of indexes in table
buffer.put((byte) 0); //Usage map row number
- int usageMapPage = pageNumber + 1;
- ByteUtil.put3ByteInt(buffer, usageMapPage); //Usage map page number
+ ByteUtil.put3ByteInt(buffer, usageMapPageNumber); //Usage map page number
buffer.put((byte) 1); //Free map row number
- ByteUtil.put3ByteInt(buffer, usageMapPage); //Free map page number
+ ByteUtil.put3ByteInt(buffer, usageMapPageNumber); //Free map page number
if (LOG.isDebugEnabled()) {
int position = buffer.position();
buffer.rewind();
}
/**
- * Create the usage map definition page buffer. It will be stored on the page
- * immediately after the tdef page.
- * @param pageNumber Page number that the corresponding table definition will
- * be written to
+ * Create the usage map definition page buffer.
*/
- private ByteBuffer createUsageMapDefinitionBuffer(int pageNumber) throws IOException {
+ private ByteBuffer createUsageMapDefinitionBuffer() throws IOException
+ {
ByteBuffer rtn = _pageChannel.createPageBuffer();
rtn.put(PageTypes.DATA);
rtn.put((byte) 0x1); //Unknown
rtn.putShort((short) _format.OFFSET_FREE_PAGES_USAGE_MAP_DEF); //Second location
rtn.position(_format.OFFSET_USED_PAGES_USAGE_MAP_DEF);
rtn.put((byte) UsageMap.MAP_TYPE_REFERENCE);
- rtn.putInt(pageNumber + 2); //First referenced page number
rtn.position(_format.OFFSET_FREE_PAGES_USAGE_MAP_DEF);
rtn.put((byte) UsageMap.MAP_TYPE_INLINE);
return rtn;
}
- /**
- * Create a usage map data page buffer.
- */
- private ByteBuffer createUsageMapDataBuffer() throws IOException {
- ByteBuffer rtn = _pageChannel.createPageBuffer();
- rtn.put(PageTypes.USAGE_MAP);
- rtn.put((byte) 0x01); //Unknown
- rtn.putShort((short) 0); //Unknown
- return rtn;
- }
-
/**
* Add a new table to the system catalog
* @param name Table name
+++ /dev/null
-/*
-Copyright (c) 2005 Health Market Science, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
-
-You can contact Health Market Science at info@healthmarketscience.com
-or at the following address:
-
-Health Market Science
-2700 Horizon Drive
-Suite 200
-King of Prussia, PA 19406
-*/
-
-package com.healthmarketscience.jackcess;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * Usage map whose map is written inline in the same page. This type of map
- * can contain a maximum of 512 pages, and is always used for free space maps.
- * It has a start page, which all page numbers in its map are calculated as
- * starting from.
- * @author Tim McCune
- */
-public class InlineUsageMap extends UsageMap {
-
- /** Size in bytes of the map */
- private static final int MAP_SIZE = 64;
-
- /**
- * @param pageChannel Used to read in pages
- * @param dataBuffer 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
- */
- public InlineUsageMap(PageChannel pageChannel, ByteBuffer dataBuffer,
- int pageNum, JetFormat format, short rowStart)
- throws IOException
- {
- super(pageChannel, dataBuffer, pageNum, format, rowStart);
- int startPage = dataBuffer.getInt(rowStart + 1);
- processMap(dataBuffer, 0, startPage);
- }
-
- //Javadoc copied from UsageMap
- protected void addOrRemovePageNumber(final int pageNumber, boolean add)
- throws IOException
- {
- int startPage = getStartPage();
- if (add && pageNumber < startPage) {
- throw new IOException("Can't add page number " + pageNumber +
- " because it is less than start page " + startPage);
- }
- int relativePageNumber = pageNumber - startPage;
- ByteBuffer buffer = getDataBuffer();
- if ((!add && !getPageNumbers().get(relativePageNumber)) ||
- (add && (relativePageNumber > MAP_SIZE * 8 - 1)))
- {
- //Increase the start page to the current page and clear out the map.
- startPage = pageNumber;
- setStartPage(startPage);
- buffer.position(getRowStart() + 1);
- buffer.putInt(startPage);
- getPageNumbers().clear();
- if (!add) {
- for (int j = 0; j < MAP_SIZE; j++) {
- buffer.put((byte) 0xff); //Fill bitmap with 1s
- }
- getPageNumbers().set(0, (MAP_SIZE * 8)); //Fill our list with page numbers
- }
- getPageChannel().writePage(buffer, getDataPageNumber());
- relativePageNumber = pageNumber - startPage;
- }
- updateMap(pageNumber, relativePageNumber, 1 << (relativePageNumber % 8), buffer, add);
- //Write the updated map back to disk
- getPageChannel().writePage(buffer, getDataPageNumber());
- }
-
-}
package com.healthmarketscience.jackcess;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public final int SIZE_INDEX_ENTRY_MASK;
public final int PAGES_PER_USAGE_MAP_PAGE;
+ public final int USAGE_MAP_TABLE_BYTE_LENGTH;
public final Charset CHARSET;
SIZE_INDEX_ENTRY_MASK = defineSizeIndexEntryMask();
PAGES_PER_USAGE_MAP_PAGE = definePagesPerUsageMapPage();
+ USAGE_MAP_TABLE_BYTE_LENGTH = defineUsageMapTableByteLength();
CHARSET = defineCharset();
}
protected abstract int defineSizeIndexEntryMask();
protected abstract int definePagesPerUsageMapPage();
+ protected abstract int defineUsageMapTableByteLength();
protected abstract Charset defineCharset();
protected int defineSizeIndexEntryMask() { return 453; }
protected int definePagesPerUsageMapPage() { return 4092 * 8; }
+ protected int defineUsageMapTableByteLength() { return 64; }
protected Charset defineCharset() { return Charset.forName("UTF-16LE"); }
}
return pageNumber;
}
- /**
- * @return Number of pages in the database
- */
- public int getPageCount() throws IOException {
- return (int) (_channel.size() / _format.PAGE_SIZE);
- }
-
/**
* @return A newly-allocated buffer that can be passed to readPage
*/
+++ /dev/null
-/*
-Copyright (c) 2005 Health Market Science, Inc.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-USA
-
-You can contact Health Market Science at info@healthmarketscience.com
-or at the following address:
-
-Health Market Science
-2700 Horizon Drive
-Suite 200
-King of Prussia, PA 19406
-*/
-
-package com.healthmarketscience.jackcess;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * Usage map whose map is written across one or more entire separate pages of
- * page type USAGE_MAP. This type of map can contain 32736 pages per reference
- * page, and a maximum of 16 reference map pages for a total maximum of 523776
- * pages (2 GB).
- * @author Tim McCune
- */
-public class ReferenceUsageMap extends UsageMap {
-
- /** Buffer that contains the current reference map page */
- private final TempPageHolder _mapPageHolder =
- TempPageHolder.newHolder(false);
-
- /**
- * @param pageChannel Used to read in pages
- * @param dataBuffer 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
- */
- public ReferenceUsageMap(PageChannel pageChannel, ByteBuffer dataBuffer,
- int pageNum, JetFormat format, short rowStart)
- throws IOException
- {
- super(pageChannel, dataBuffer, pageNum, format, rowStart);
- for (int i = 0; i < 17; i++) {
- int mapPageNum = dataBuffer.getInt(getRowStart() +
- format.OFFSET_REFERENCE_MAP_PAGE_NUMBERS + (4 * i));
- if (mapPageNum > 0) {
- ByteBuffer mapPageBuffer =
- _mapPageHolder.setPage(pageChannel, mapPageNum);
- byte pageType = mapPageBuffer.get();
- if (pageType != PageTypes.USAGE_MAP) {
- throw new IOException("Looking for usage map at page " + mapPageNum +
- ", but page type is " + pageType);
- }
- mapPageBuffer.position(format.OFFSET_USAGE_MAP_PAGE_DATA);
- setStartOffset(mapPageBuffer.position());
- processMap(mapPageBuffer, i, 0);
- }
- }
- }
-
- //Javadoc copied from UsageMap
- protected void addOrRemovePageNumber(final int pageNumber, boolean add)
- throws IOException
- {
- int pageIndex = (int) Math.floor(pageNumber / getFormat().PAGES_PER_USAGE_MAP_PAGE);
- int mapPageNum = getDataBuffer().getInt(calculateMapPagePointerOffset(pageIndex));
- if(mapPageNum <= 0) {
- //Need to create a new usage map page
- mapPageNum = createNewUsageMapPage(pageIndex);
- }
- ByteBuffer mapPageBuffer = _mapPageHolder.setPage(getPageChannel(),
- mapPageNum);
- updateMap(pageNumber, pageNumber - (getFormat().PAGES_PER_USAGE_MAP_PAGE * pageIndex),
- 1 << ((pageNumber - (getFormat().PAGES_PER_USAGE_MAP_PAGE * pageIndex)) % 8),
- mapPageBuffer, add);
- getPageChannel().writePage(mapPageBuffer, mapPageNum);
- }
-
- /**
- * Create a new usage map page and update the map declaration with a pointer
- * to it.
- * @param pageIndex Index of the page reference within the map declaration
- */
- private int createNewUsageMapPage(int pageIndex) throws IOException {
- ByteBuffer mapPageBuffer = _mapPageHolder.startNewPage(getPageChannel());
- mapPageBuffer.put(PageTypes.USAGE_MAP);
- mapPageBuffer.put((byte) 0x01); //Unknown
- mapPageBuffer.putShort((short) 0); //Unknown
- int mapPageNum = getPageChannel().writeNewPage(mapPageBuffer);
- _mapPageHolder.finishNewPage(mapPageNum);
- getDataBuffer().putInt(calculateMapPagePointerOffset(pageIndex),
- mapPageNum);
- getPageChannel().writePage(getDataBuffer(), getDataPageNumber());
- return mapPageNum;
- }
-
- private int calculateMapPagePointerOffset(int pageIndex) {
- return getRowStart() + getFormat().OFFSET_REFERENCE_MAP_PAGE_NUMBERS + (pageIndex * 4);
- }
-
-}
* the PageChannel as a new page and assigned a number.
*/
public void finishNewPage(int pageNumber)
+ throws IOException
{
if(_pageNumber != PageChannel.INVALID_PAGE_NUMBER) {
- throw new IllegalStateException("page number should not be set");
+ throw new IOException("page number should not be set");
}
_pageNumber = pageNumber;
}
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
+import java.util.logging.Handler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
* Describes which database pages a particular table uses
* @author Tim McCune
*/
-public abstract class UsageMap {
+public class UsageMap
+{
private static final Log LOG = LogFactory.getLog(UsageMap.class);
/** modification count on the usage map, used to keep the iterators in
sync */
private int _modCount = 0;
-
- /**
- * @param pageChannel Used to read in pages
- * @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)
- throws IOException
- {
- ByteBuffer dataBuffer = pageChannel.createPageBuffer();
- pageChannel.readPage(dataBuffer, pageNum);
- short rowStart = Table.findRowStart(dataBuffer, rowNum, format);
- int rowEnd = Table.findRowEnd(dataBuffer, rowNum, format);
- dataBuffer.limit(rowEnd);
- byte mapType = dataBuffer.get(rowStart);
- UsageMap rtn;
- if (mapType == MAP_TYPE_INLINE) {
- rtn = new InlineUsageMap(pageChannel, dataBuffer, pageNum, format, rowStart);
- } else if (mapType == MAP_TYPE_REFERENCE) {
- rtn = new ReferenceUsageMap(pageChannel, dataBuffer, pageNum, format, rowStart);
- } else {
- throw new IOException("Unrecognized map type: " + mapType);
- }
- return rtn;
- }
+ /** the current handler implementation for reading/writing the specific
+ usage map type. note, this may change over time. */
+ private Handler _handler;
/**
* @param pageChannel Used to read in pages
* @param format Format of the database that contains this usage map
* @param rowStart Offset at which the declaration starts in the buffer
*/
- protected UsageMap(PageChannel pageChannel, ByteBuffer dataBuffer,
- int pageNum, JetFormat format, short rowStart)
+ private UsageMap(PageChannel pageChannel, ByteBuffer dataBuffer,
+ int pageNum, JetFormat format, short rowStart)
throws IOException
{
_pageChannel = pageChannel;
}
}
+ /**
+ * @param pageChannel Used to read in pages
+ * @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)
+ throws IOException
+ {
+ ByteBuffer dataBuffer = pageChannel.createPageBuffer();
+ pageChannel.readPage(dataBuffer, pageNum);
+ short rowStart = Table.findRowStart(dataBuffer, rowNum, format);
+ int rowEnd = Table.findRowEnd(dataBuffer, rowNum, format);
+ dataBuffer.limit(rowEnd);
+ byte mapType = dataBuffer.get(rowStart);
+ UsageMap rtn = new UsageMap(pageChannel, dataBuffer, pageNum, format,
+ rowStart);
+ rtn.initHandler(mapType);
+ return rtn;
+ }
+
+ private void initHandler(byte mapType)
+ throws IOException
+ {
+ if (mapType == MAP_TYPE_INLINE) {
+ _handler = new InlineHandler();
+ } else if (mapType == MAP_TYPE_REFERENCE) {
+ _handler = new ReferenceHandler();
+ } else {
+ throw new IOException("Unrecognized map type: " + mapType);
+ }
+ }
+
public PageIterator iterator() {
return new ForwardPageIterator();
}
_startPage = startPage;
while (buffer.hasRemaining()) {
byte b = buffer.get();
- for (int i = 0; i < 8; i++) {
- if ((b & (1 << i)) != 0) {
- int pageNumberOffset = (byteCount * 8 + i) +
- (pageIndex * _format.PAGES_PER_USAGE_MAP_PAGE);
- _pageNumbers.set(pageNumberOffset);
+ if(b != (byte)0) {
+ for (int i = 0; i < 8; i++) {
+ if ((b & (1 << i)) != 0) {
+ int pageNumberOffset = (byteCount * 8 + i) +
+ (pageIndex * _format.PAGES_PER_USAGE_MAP_PAGE);
+ _pageNumbers.set(pageNumberOffset);
+ }
}
}
byteCount++;
}
}
++_modCount;
- addOrRemovePageNumber(pageNumber, true);
+ _handler.addOrRemovePageNumber(pageNumber, true);
}
/**
*/
public void removePageNumber(int pageNumber) throws IOException {
++_modCount;
- addOrRemovePageNumber(pageNumber, false);
+ _handler.addOrRemovePageNumber(pageNumber, false);
}
protected void updateMap(int absolutePageNumber, int relativePageNumber,
buffer.put(_startOffset + offset, b);
}
+ private void promoteInlineHandlerToReferenceHandler(int pageNumber)
+ throws IOException
+ {
+ // FIXME writeme
+// int startPage = _startPage;
+// BitSet curPageNumbers = (BitSet)_pageNumbers.clone();
+// _pageNumbers.clear();
+// _startPage = 0;
+
+ }
+
public String toString() {
StringBuilder builder = new StringBuilder("page numbers: [");
for(PageIterator iter = iterator(); iter.hasNextPage(); ) {
return builder.toString();
}
+ private abstract class Handler
+ {
+ protected Handler() {
+ }
+
+ /**
+ * @param pageNumber Page number to add or remove from this map
+ * @param add True to add it, false to remove it
+ */
+ public abstract void addOrRemovePageNumber(int pageNumber, boolean add)
+ throws IOException;
+ }
+
/**
- * @param pageNumber Page number to add or remove from this map
- * @param add True to add it, false to remove it
+ * Usage map whose map is written inline in the same page. This type of map
+ * can contain a maximum of 512 pages, and is always used for free space
+ * maps. It has a start page, which all page numbers in its map are
+ * calculated as starting from.
+ * @author Tim McCune
*/
- protected abstract void addOrRemovePageNumber(int pageNumber, boolean add) throws IOException;
+ private class InlineHandler extends Handler
+ {
+ private InlineHandler()
+ throws IOException
+ {
+ int startPage = getDataBuffer().getInt(getRowStart() + 1);
+ processMap(getDataBuffer(), 0, startPage);
+ }
+
+ @Override
+ public void addOrRemovePageNumber(int pageNumber, boolean add)
+ throws IOException
+ {
+ int startPage = getStartPage();
+ if (add && pageNumber < startPage) {
+ throw new IOException("Can't add page number " + pageNumber +
+ " because it is less than start page " + startPage);
+ }
+ int relativePageNumber = pageNumber - startPage;
+ ByteBuffer buffer = getDataBuffer();
+ if ((!add && !getPageNumbers().get(relativePageNumber)) ||
+ (add && (relativePageNumber >
+ (getFormat().USAGE_MAP_TABLE_BYTE_LENGTH * 8 - 1))))
+ {
+ // FIXME writeme
+// if(add) {
+// promoteInlineHandlerToReferenceHandler(pageNumber);
+// return;
+// }
+ //Increase the start page to the current page and clear out the map.
+ startPage = pageNumber;
+ setStartPage(startPage);
+ buffer.position(getRowStart() + 1);
+ buffer.putInt(startPage);
+ getPageNumbers().clear();
+ if (!add) {
+ for (int j = 0; j < getFormat().USAGE_MAP_TABLE_BYTE_LENGTH; j++) {
+ buffer.put((byte) 0xff); //Fill bitmap with 1s
+ }
+ getPageNumbers().set(0, (getFormat().USAGE_MAP_TABLE_BYTE_LENGTH * 8)); //Fill our list with page numbers
+ }
+ getPageChannel().writePage(buffer, getDataPageNumber());
+ relativePageNumber = pageNumber - startPage;
+ }
+ updateMap(pageNumber, relativePageNumber, 1 << (relativePageNumber % 8), buffer, add);
+ //Write the updated map back to disk
+ getPageChannel().writePage(buffer, getDataPageNumber());
+ }
+ }
+ /**
+ * Usage map whose map is written across one or more entire separate pages
+ * of page type USAGE_MAP. This type of map can contain 32736 pages per
+ * reference page, and a maximum of 16 reference map pages for a total
+ * maximum of 523776 pages (2 GB).
+ * @author Tim McCune
+ */
+ private class ReferenceHandler extends Handler
+ {
+ /** Buffer that contains the current reference map page */
+ private final TempPageHolder _mapPageHolder =
+ TempPageHolder.newHolder(false);
+
+ private ReferenceHandler()
+ throws IOException
+ {
+ setStartOffset(getFormat().OFFSET_USAGE_MAP_PAGE_DATA);
+ // there is no "start page" for a reference usage map, so we get an
+ // extra page reference on top of the number of page references that fit
+ // in the table
+ int numPages = (getFormat().USAGE_MAP_TABLE_BYTE_LENGTH / 4) + 1;
+ for (int i = 0; i < numPages; i++) {
+ int mapPageNum = getDataBuffer().getInt(
+ getRowStart() + getFormat().OFFSET_REFERENCE_MAP_PAGE_NUMBERS +
+ (4 * i));
+ if (mapPageNum > 0) {
+ ByteBuffer mapPageBuffer =
+ _mapPageHolder.setPage(getPageChannel(), mapPageNum);
+ byte pageType = mapPageBuffer.get();
+ if (pageType != PageTypes.USAGE_MAP) {
+ throw new IOException("Looking for usage map at page " +
+ mapPageNum + ", but page type is " +
+ pageType);
+ }
+ mapPageBuffer.position(getFormat().OFFSET_USAGE_MAP_PAGE_DATA);
+ processMap(mapPageBuffer, i, 0);
+ }
+ }
+ }
+
+ @Override
+ public void addOrRemovePageNumber(int pageNumber, boolean add)
+ throws IOException
+ {
+ int pageIndex = (int) Math.floor(pageNumber / getFormat().PAGES_PER_USAGE_MAP_PAGE);
+ int mapPageNum = getDataBuffer().getInt(calculateMapPagePointerOffset(pageIndex));
+ if(mapPageNum <= 0) {
+ //Need to create a new usage map page
+ mapPageNum = createNewUsageMapPage(pageIndex);
+ }
+ ByteBuffer mapPageBuffer = _mapPageHolder.setPage(getPageChannel(),
+ mapPageNum);
+ updateMap(pageNumber, pageNumber - (getFormat().PAGES_PER_USAGE_MAP_PAGE * pageIndex),
+ 1 << ((pageNumber - (getFormat().PAGES_PER_USAGE_MAP_PAGE * pageIndex)) % 8),
+ mapPageBuffer, add);
+ getPageChannel().writePage(mapPageBuffer, mapPageNum);
+ }
+
+ /**
+ * Create a new usage map page and update the map declaration with a
+ * pointer to it.
+ * @param pageIndex Index of the page reference within the map declaration
+ */
+ private int createNewUsageMapPage(int pageIndex) throws IOException {
+ ByteBuffer mapPageBuffer = _mapPageHolder.startNewPage(getPageChannel());
+ mapPageBuffer.put(PageTypes.USAGE_MAP);
+ mapPageBuffer.put((byte) 0x01); //Unknown
+ mapPageBuffer.putShort((short) 0); //Unknown
+ for(int i = 0; i < mapPageBuffer.limit(); ++i) {
+ byte b = mapPageBuffer.get(i);
+ }
+ int mapPageNum = getPageChannel().writeNewPage(mapPageBuffer);
+ _mapPageHolder.finishNewPage(mapPageNum);
+ getDataBuffer().putInt(calculateMapPagePointerOffset(pageIndex),
+ mapPageNum);
+ getPageChannel().writePage(getDataBuffer(), getDataPageNumber());
+ return mapPageNum;
+ }
+
+ private int calculateMapPagePointerOffset(int pageIndex) {
+ return getRowStart() + getFormat().OFFSET_REFERENCE_MAP_PAGE_NUMBERS +
+ (pageIndex * 4);
+ }
+ }
+
+
/**
* Utility class to iterate over the pages in the UsageMap.
*/
_prevSetBit = _nextSetBit;
_nextSetBit = _pageNumbers.nextSetBit(_nextSetBit + 1);
return _prevSetBit + _startPage;
- } else {
- return PageChannel.INVALID_PAGE_NUMBER;
}
+ return PageChannel.INVALID_PAGE_NUMBER;
}
@Override
--_nextSetBit;
}
return _prevSetBit + _startPage;
- } else {
- return PageChannel.INVALID_PAGE_NUMBER;
}
+ return PageChannel.INVALID_PAGE_NUMBER;
}
@Override