summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2008-04-08 01:05:15 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2008-04-08 01:05:15 +0000
commit4bf77267a5871e0da49c07e7e750e9207a9daddd (patch)
tree88e4509037f5c2ac258a1f6e952d731a5cb62734
parent7bc622cabb0840a223011f4d6cd1f7e60e099015 (diff)
downloadjackcess-4bf77267a5871e0da49c07e7e750e9207a9daddd.tar.gz
jackcess-4bf77267a5871e0da49c07e7e750e9207a9daddd.zip
more minor refactoring
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@317 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/java/com/healthmarketscience/jackcess/Index.java8
-rw-r--r--src/java/com/healthmarketscience/jackcess/IndexPageCache.java141
2 files changed, 108 insertions, 41 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/Index.java b/src/java/com/healthmarketscience/jackcess/Index.java
index 4dc822f..cb8867f 100644
--- a/src/java/com/healthmarketscience/jackcess/Index.java
+++ b/src/java/com/healthmarketscience/jackcess/Index.java
@@ -586,7 +586,7 @@ public abstract class Index implements Comparable<Index> {
DataPage nextDataPage = null;
while(nextPageNumber != INVALID_INDEX_PAGE_NUMBER) {
DataPage dp = getDataPage(nextPageNumber);
- if(!dp.getEntries().isEmpty()) {
+ if(!dp.isEmpty()) {
nextDataPage = dp;
break;
}
@@ -615,7 +615,7 @@ public abstract class Index implements Comparable<Index> {
DataPage prevDataPage = null;
while(prevPageNumber != INVALID_INDEX_PAGE_NUMBER) {
DataPage dp = getDataPage(prevPageNumber);
- if(!dp.getEntries().isEmpty()) {
+ if(!dp.isEmpty()) {
prevDataPage = dp;
break;
}
@@ -2199,6 +2199,10 @@ public abstract class Index implements Comparable<Index> {
throws IOException;
public abstract void removeEntry(int idx)
throws IOException;
+
+ public final boolean isEmpty() {
+ return getEntries().isEmpty();
+ }
public final int getCompressedEntrySize() {
// when written to the index page, the entryPrefix bytes will only be
diff --git a/src/java/com/healthmarketscience/jackcess/IndexPageCache.java b/src/java/com/healthmarketscience/jackcess/IndexPageCache.java
index da4acb7..1e94f86 100644
--- a/src/java/com/healthmarketscience/jackcess/IndexPageCache.java
+++ b/src/java/com/healthmarketscience/jackcess/IndexPageCache.java
@@ -34,8 +34,10 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+
import org.apache.commons.lang.ObjectUtils;
import static com.healthmarketscience.jackcess.Index.*;
@@ -86,26 +88,56 @@ public class IndexPageCache
public void write()
throws IOException
{
+ // first discard any empty pages
+ handleEmptyPages();
+ // next, handle any necessary page splitting
preparePagesForWriting();
+ // finally, write all the modified pages (which are not being deleted)
writeDataPages();
}
- private void preparePagesForWriting()
- throws IOException
+ private void handleEmptyPages() throws IOException
{
- // FIXME, writeme
+ for(Iterator<CacheDataPage> iter = _modifiedPages.iterator();
+ iter.hasNext(); ) {
+ CacheDataPage cacheDataPage = iter.next();
+ if(cacheDataPage.isEmpty()) {
+ if(!cacheDataPage._main.isRoot()) {
+ deleteDataPage(cacheDataPage);
+ } else {
+ writeDataPage(cacheDataPage);
+ }
+ iter.remove();
+ }
+ }
+ }
+
+ private void preparePagesForWriting() throws IOException
+ {
+ boolean splitPages = false;
+ int maxPageEntrySize = getIndex().getMaxPageEntrySize();
+ do {
+ splitPages = false;
+
+ for(CacheDataPage cacheDataPage : _modifiedPages) {
+ if(cacheDataPage.getCompressedEntrySize() > maxPageEntrySize) {
+ // need to split this page
+ splitPages = true;
+ splitDataPage(cacheDataPage);
+ }
+ }
+
+ } while(splitPages);
}
- private void writeDataPages()
- throws IOException
+ private void writeDataPages() throws IOException
{
for(CacheDataPage cacheDataPage : _modifiedPages) {
- if(!cacheDataPage.getEntries().isEmpty() ||
- cacheDataPage._main.isRoot()) {
- writeDataPage(cacheDataPage);
- } else {
- deleteDataPage(cacheDataPage);
+ if(cacheDataPage.isEmpty()) {
+ throw new IllegalStateException("Unexpected empty page " +
+ cacheDataPage);
}
+ writeDataPage(cacheDataPage);
}
_modifiedPages.clear();
}
@@ -219,12 +251,12 @@ public class IndexPageCache
setModified(cacheDataPage);
- boolean updateFirst = false;
+ boolean updateFirst = (entryIdx == 0);
boolean updateLast = false;
+ boolean mayUpdatePrefix = true;
switch(upType) {
case ADD: {
- updateFirst = (entryIdx == 0);
updateLast = (entryIdx == dpExtra._entries.size());
dpExtra._entries.add(entryIdx, newEntry);
@@ -232,7 +264,6 @@ public class IndexPageCache
break;
}
case REPLACE: {
- updateFirst = (entryIdx == 0);
updateLast = (entryIdx == (dpExtra._entries.size() - 1));
Entry oldEntry = dpExtra._entries.set(entryIdx, newEntry);
@@ -240,18 +271,20 @@ public class IndexPageCache
break;
}
case REMOVE: {
- updateFirst = (entryIdx == 0);
updateLast = (entryIdx == (dpExtra._entries.size() - 1));
Entry oldEntry = dpExtra._entries.remove(entryIdx);
dpExtra._totalEntrySize -= oldEntry.size();
+ // note, we don't need to futz with the _entryPrefix on removal because
+ // the prefix is always still valid after removal
+ mayUpdatePrefix = false;
break;
}
default:
throw new RuntimeException("unknown update type " + upType);
}
- if(dpExtra._entries.isEmpty()) {
+ if(cacheDataPage.isEmpty()) {
// this page is dead
removeDataPage(cacheDataPage);
} else {
@@ -261,9 +294,7 @@ public class IndexPageCache
if(updateLast) {
dpMain._lastEntry = dpExtra.getLastEntry();
}
- // note, we don't need to futz with the _entryPrefix on removal because
- // the prefix is always still valid after removal
- if((upType != UpdateType.REMOVE) && (updateFirst || updateLast)) {
+ if(mayUpdatePrefix && (updateFirst || updateLast)) {
// update the prefix
dpExtra._entryPrefix = findNewPrefix(dpExtra._entryPrefix, newEntry);
}
@@ -306,20 +337,12 @@ public class IndexPageCache
setModified(parentDataPage);
DataPageMain parentMain = parentDataPage._main;
- DataPageExtra parentExtra = parentDataPage._extra;
if(childMain.isTail()) {
parentMain._childTailPageNumber = INVALID_INDEX_PAGE_NUMBER;
} else {
- Entry oldParentEntry = childMain._firstEntry.asNodeEntry(
- childMain._pageNumber);
- int idx = parentExtra.findEntry(oldParentEntry);
- if(idx < 0) {
- throw new IllegalStateException(
- "Could not find child entry in parent; child " + childDataPage +
- "; parent " + parentDataPage);
- }
- removeEntry(parentDataPage, idx);
+ updateParentEntry(parentDataPage, childDataPage,
+ childMain._firstEntry, null, UpdateType.REMOVE);
}
}
@@ -354,31 +377,65 @@ public class IndexPageCache
dpMain._firstEntry = dpExtra.getFirstEntry();
DataPageMain parentMain = dpMain.getParentPage();
if(parentMain != null) {
- Entry oldParentEntry = oldEntry.asNodeEntry(dpMain._pageNumber);
- Entry newParentEntry =
- dpMain._firstEntry.asNodeEntry(dpMain._pageNumber);
updateParentEntry(new CacheDataPage(parentMain),
- oldParentEntry, newParentEntry);
+ cacheDataPage,
+ oldEntry, dpMain._firstEntry,
+ UpdateType.REPLACE);
}
}
private void updateParentEntry(CacheDataPage parentDataPage,
- Entry oldEntry, Entry newEntry)
+ CacheDataPage childDataPage,
+ Entry oldEntry, Entry newEntry,
+ UpdateType upType)
throws IOException
{
+ DataPageMain childMain = childDataPage._main;
DataPageExtra parentExtra = parentDataPage._extra;
- setModified(parentDataPage);
+ if(oldEntry != null) {
+ oldEntry = oldEntry.asNodeEntry(childMain._pageNumber);
+ }
+ if(newEntry != null) {
+ newEntry = newEntry.asNodeEntry(childMain._pageNumber);
+ }
+
+ boolean expectFound = true;
+ int idx = 0;
+
+ switch(upType) {
+ case ADD:
+ expectFound = false;
+ idx = parentExtra.findEntry(newEntry);
+ break;
- int idx = parentExtra.findEntry(oldEntry);
+ case REPLACE:
+ case REMOVE:
+ idx = parentExtra.findEntry(oldEntry);
+ break;
+
+ default:
+ throw new RuntimeException("unknown update type " + upType);
+ }
+
if(idx < 0) {
- throw new IllegalStateException(
- "Could not find child entry in parent; childEntry " + oldEntry +
- "; parent " + parentDataPage);
+ if(expectFound) {
+ throw new IllegalStateException(
+ "Could not find child entry in parent; childEntry " + oldEntry +
+ "; parent " + parentDataPage);
+ }
+ idx = missingIndexToInsertionPoint(idx);
+ } else {
+ if(!expectFound) {
+ throw new IllegalStateException(
+ "Unexpectedly found child entry in parent; childEntry " +
+ newEntry + "; parent " + parentDataPage);
+ }
}
- replaceEntry(parentDataPage, idx, newEntry);
+ updateEntry(parentDataPage, idx, newEntry, upType);
}
+
private void validateEntryForPage(DataPageMain dataPage, Entry entry) {
if(dataPage._leaf != entry.isLeafEntry()) {
throw new IllegalStateException(
@@ -386,6 +443,12 @@ public class IndexPageCache
dataPage._leaf + ", entryLeaf " + entry.isLeafEntry());
}
}
+
+ private void splitDataPage(CacheDataPage cacheDataPage)
+ throws IOException
+ {
+ // FIXME, writeme
+ }
public CacheDataPage findCacheDataPage(Entry e)
throws IOException