aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2016-04-29 02:45:02 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2016-04-29 02:45:02 +0000
commitb110c2f3ed4abe3d9f29c564407e91b02c27aaa6 (patch)
treeb4fd6576072091df0d10d091380dbc9fe2041177
parentc1c9b4fec21a593e3d9982b5c8be831ac52e9ae7 (diff)
downloadjackcess-b110c2f3ed4abe3d9f29c564407e91b02c27aaa6.tar.gz
jackcess-b110c2f3ed4abe3d9f29c564407e91b02c27aaa6.zip
add usage maps for lval cols
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/mutateops@985 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/LongValueColumnImpl.java13
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java91
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java5
3 files changed, 85 insertions, 24 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/LongValueColumnImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/LongValueColumnImpl.java
index b33c84a..8a137ea 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/LongValueColumnImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/LongValueColumnImpl.java
@@ -71,8 +71,9 @@ class LongValueColumnImpl extends ColumnImpl
_lvalBufferH = new UmapLongValueBufferHolder(ownedPages, freeSpacePages);
}
+ @Override
void collectUsageMapPages(Collection<Integer> pages) {
- // FIXME, writeme
+ _lvalBufferH.collectUsageMapPages(pages);
}
@Override
@@ -446,6 +447,10 @@ class LongValueColumnImpl extends ColumnImpl
getBufferHolder().clear();
}
+ public void collectUsageMapPages(Collection<Integer> pages) {
+ // base does nothing
+ }
+
protected abstract TempPageHolder getBufferHolder();
}
@@ -522,5 +527,11 @@ class LongValueColumnImpl extends ColumnImpl
}
super.clear();
}
+
+ @Override
+ public void collectUsageMapPages(Collection<Integer> pages) {
+ pages.add(_ownedPages.getTablePageNumber());
+ pages.add(_freeSpacePages.getTablePageNumber());
+ }
}
}
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java
index 4d27ed7..a789404 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/TableImpl.java
@@ -29,12 +29,12 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import com.healthmarketscience.jackcess.BatchUpdateException;
import com.healthmarketscience.jackcess.Column;
@@ -1185,6 +1185,12 @@ public class TableImpl implements Table
int umapPos = -1;
if(isLongVal) {
+ // allocate usage maps for the long value col
+ Map.Entry<Integer,Integer> umapInfo = addUsageMaps(2);
+ int umapPageNum = umapInfo.getKey();
+ int umapRow1 = umapInfo.getValue();
+ int umapRow2 = umapRow1 + 1;
+
// skip past index defs
ByteUtil.forward(tableBuffer, (_indexDatas.size() *
(format.SIZE_INDEX_DEFINITION +
@@ -1195,7 +1201,12 @@ public class TableImpl implements Table
ByteUtil.forward(tableBuffer, tableBuffer.getShort());
}
- // FIXME add usage maps...
+ // owned pages umap (both are on same page)
+ tableBuffer.put((byte)umapRow1);
+ ByteUtil.put3ByteInt(tableBuffer, umapPageNum);
+ // free space pages umap
+ tableBuffer.put((byte)umapRow2);
+ ByteUtil.put3ByteInt(tableBuffer, umapPageNum);
}
// sanity check the updates
@@ -1277,28 +1288,61 @@ public class TableImpl implements Table
return tableBuffer;
}
- private Map.Entry<Integer,Integer> addUsageMaps(int numMaps)
+ private Map.Entry<Integer,Integer> addUsageMaps(int numMaps) throws IOException
{
JetFormat format = getFormat();
+ PageChannel pageChannel = getPageChannel();
int umapRowLength = format.OFFSET_USAGE_MAP_START +
format.USAGE_MAP_TABLE_BYTE_LENGTH;
int totalUmapSpaceUsage = getRowSpaceUsage(umapRowLength, format) * numMaps;
int umapPageNumber = PageChannel.INVALID_PAGE_NUMBER;
int firstRowNum = -1;
- ByteBuffer umapBuf = null;
int freeSpace = 0;
- int rowStart = 0;
- int umapRowNum = 0;
// search currently known usage map buffers to find one with enough free
// space (the numMaps should always be small enough to put them all on one
- // page)
- Set<Integer> knownPages = new HashSet<Integer>();
+ // page). pages will free space will probaby be newer pages (higher
+ // numbers), so we sort in reverse order.
+ Set<Integer> knownPages = new TreeSet<Integer>(Collections.reverseOrder());
collectUsageMapPages(knownPages);
- // FIXME
-
-
+ ByteBuffer umapBuf = pageChannel.createPageBuffer();
+ for(Integer pageNum : knownPages) {
+ pageChannel.readPage(umapBuf, pageNum);
+ freeSpace = umapBuf.getShort(format.OFFSET_FREE_SPACE);
+ if(freeSpace >= totalUmapSpaceUsage) {
+ // found a page!
+ umapPageNumber = pageNum;
+ firstRowNum = getRowsOnDataPage(umapBuf, format);
+ break;
+ }
+ }
+
+ if(umapPageNumber == PageChannel.INVALID_PAGE_NUMBER) {
+
+ // didn't find any existing pages, need to create a new one
+ freeSpace = format.DATA_PAGE_INITIAL_FREE_SPACE;
+ firstRowNum = 0;
+ umapBuf = createUsageMapDefPage(pageChannel, freeSpace);
+ }
+
+ // write the actual usage map defs
+ int rowStart = findRowEnd(umapBuf, firstRowNum, format) - umapRowLength;
+ int umapRowNum = firstRowNum;
+ for(int i = 0; i < numMaps; ++i) {
+ umapBuf.putShort(getRowStartOffset(umapRowNum, format), (short)rowStart);
+ umapBuf.put(rowStart, UsageMap.MAP_TYPE_INLINE);
+ rowStart -= umapRowLength;
+ ++umapRowNum;
+ }
+
+ // finish the page
+ freeSpace -= totalUmapSpaceUsage;
+ umapBuf.putShort(format.OFFSET_FREE_SPACE, (short)freeSpace);
+ umapBuf.putShort(format.OFFSET_NUM_ROWS_ON_DATA_PAGE,
+ (short)umapRowNum);
+ pageChannel.writePage(umapBuf, umapPageNumber);
+
return new AbstractMap.SimpleImmutableEntry<Integer,Integer>(
umapPageNumber, firstRowNum);
}
@@ -1310,6 +1354,10 @@ public class TableImpl implements Table
for(IndexData idx : _indexDatas) {
idx.collectUsageMapPages(pages);
}
+
+ for(ColumnImpl col : _columns) {
+ col.collectUsageMapPages(pages);
+ }
}
/**
@@ -1407,13 +1455,7 @@ public class TableImpl implements Table
freeSpace = format.DATA_PAGE_INITIAL_FREE_SPACE;
- umapBuf = pageChannel.createPageBuffer();
- umapBuf.put(PageTypes.DATA);
- umapBuf.put((byte) 0x1); //Unknown
- umapBuf.putShort((short)freeSpace); //Free space in page
- umapBuf.putInt(0); //Table definition
- umapBuf.putInt(0); //Unknown
- umapBuf.putShort((short)0); //Number of records on this page
+ umapBuf = createUsageMapDefPage(pageChannel, freeSpace);
rowStart = findRowEnd(umapBuf, 0, format) - umapRowLength;
umapRowNum = 0;
@@ -1497,6 +1539,19 @@ public class TableImpl implements Table
}
}
+ private static ByteBuffer createUsageMapDefPage(
+ PageChannel pageChannel, int freeSpace)
+ {
+ ByteBuffer umapBuf = pageChannel.createPageBuffer();
+ umapBuf.put(PageTypes.DATA);
+ umapBuf.put((byte) 0x1); //Unknown
+ umapBuf.putShort((short)freeSpace); //Free space in page
+ umapBuf.putInt(0); //Table definition
+ umapBuf.putInt(0); //Unknown
+ umapBuf.putShort((short)0); //Number of records on this page
+ return umapBuf;
+ }
+
/**
* Returns a single ByteBuffer which contains the entire table definition
* (which may span multiple database pages).
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java b/src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java
index fe1500f..2dd2fa5 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/TableMutator.java
@@ -35,7 +35,6 @@ public class TableMutator extends DBMutator
private final TableImpl _table;
private ColumnBuilder _column;
- private ColumnState _columnState;
public TableMutator(TableImpl table) {
super(table.getDatabase());
@@ -55,10 +54,6 @@ public class TableMutator extends DBMutator
// assign column numbers and do some assorted column bookkeeping
short columnNumber = (short)_table.getMaxColumnCount();
_column.setColumnNumber(columnNumber);
- if(_column.getType().isLongValue()) {
- // only lval columns need extra state
- _columnState = new ColumnState();
- }
getPageChannel().startExclusiveWrite();
try {