summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2008-04-06 03:45:12 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2008-04-06 03:45:12 +0000
commit095e6cc5493ee363840fd54d20eb0e3977e1ba9d (patch)
tree5b547beaa72c79c8fc691e6b9d4727f377112d2a
parentc262ce564f739d4c9e8179d25663e936728f7c1e (diff)
downloadjackcess-095e6cc5493ee363840fd54d20eb0e3977e1ba9d.tar.gz
jackcess-095e6cc5493ee363840fd54d20eb0e3977e1ba9d.zip
flesh out some of the index page update operations
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@313 f203690c-595d-4dc9-a70b-905162fa7fd2
-rw-r--r--src/java/com/healthmarketscience/jackcess/Index.java2
-rw-r--r--src/java/com/healthmarketscience/jackcess/IndexPageCache.java223
2 files changed, 168 insertions, 57 deletions
diff --git a/src/java/com/healthmarketscience/jackcess/Index.java b/src/java/com/healthmarketscience/jackcess/Index.java
index be86515..7f80d18 100644
--- a/src/java/com/healthmarketscience/jackcess/Index.java
+++ b/src/java/com/healthmarketscience/jackcess/Index.java
@@ -1693,7 +1693,7 @@ public abstract class Index implements Comparable<Index> {
* Returns a copy of this entry as a node Entry with the given
* subPageNumber.
*/
- Entry asNodeEntry(Integer subPageNumber) {
+ protected Entry asNodeEntry(Integer subPageNumber) {
return new NodeEntry(_entryBytes, _rowId, _type, subPageNumber);
}
diff --git a/src/java/com/healthmarketscience/jackcess/IndexPageCache.java b/src/java/com/healthmarketscience/jackcess/IndexPageCache.java
index 8ea0260..62cfe2a 100644
--- a/src/java/com/healthmarketscience/jackcess/IndexPageCache.java
+++ b/src/java/com/healthmarketscience/jackcess/IndexPageCache.java
@@ -75,6 +75,8 @@ public class IndexPageCache
public void setRootPageNumber(int pageNumber) throws IOException {
_rootPage = getDataPage(pageNumber);
+ // root page has no parent
+ _rootPage.setParentPage(INVALID_INDEX_PAGE_NUMBER, false);
}
public void write()
@@ -105,6 +107,19 @@ public class IndexPageCache
DataPageMain main = getDataPage(pageNumber);
return((main != null) ? new CacheDataPage(main) : null);
}
+
+ private DataPageMain getChildDataPage(Integer childPageNumber,
+ DataPageMain parent,
+ boolean isTail)
+ throws IOException
+ {
+ DataPageMain child = getDataPage(childPageNumber);
+ if(child != null) {
+ // set the parent info for this child (if necessary)
+ child.setParentPage(parent._pageNumber, isTail);
+ }
+ return child;
+ }
private DataPageMain getDataPage(Integer pageNumber)
throws IOException
@@ -146,8 +161,8 @@ public class IndexPageCache
return cacheDataPage;
}
- private void removeEntry(CacheDataPage cacheDataPage,
- int entryIdx)
+ private void removeEntry(CacheDataPage cacheDataPage, int entryIdx)
+ throws IOException
{
DataPageMain dpMain = cacheDataPage._main;
DataPageExtra dpExtra = cacheDataPage._extra;
@@ -165,28 +180,10 @@ public class IndexPageCache
if(dpExtra._entries.isEmpty()) {
// this page is dead
- if(dpMain.isRoot()) {
- // clear out this page
- dpMain._firstEntry = null;
- dpMain._lastEntry = null;
- dpExtra._entryPrefix = EMPTY_PREFIX;
- if(dpExtra._totalEntrySize != 0) {
- throw new IllegalStateException("Empty page but size is not 0?");
- }
- } else {
- // FIXME, remove from parent
- Entry oldParentEntry = oldEntry.asNodeEntry(dpMain._pageNumber);
- // FIXME, update next/prev/childTail links
- throw new UnsupportedOperationException();
- }
+ deleteDataPage(cacheDataPage);
} else {
if(updateFirst) {
- dpMain._firstEntry = dpExtra.getFirstEntry();
- Entry oldParentEntry = oldEntry.asNodeEntry(dpMain._pageNumber);
- Entry newParentEntry =
- dpMain._firstEntry.asNodeEntry(dpMain._pageNumber);
- // FIXME, need to update parent
- throw new UnsupportedOperationException();
+ updateFirstEntry(cacheDataPage);
}
if(updateLast) {
dpMain._lastEntry = dpExtra.getLastEntry();
@@ -195,6 +192,120 @@ public class IndexPageCache
}
+ private void deleteDataPage(CacheDataPage cacheDataPage)
+ throws IOException
+ {
+ DataPageMain dpMain = cacheDataPage._main;
+ DataPageExtra dpExtra = cacheDataPage._extra;
+
+ if(dpMain.isRoot()) {
+ // clear out this page (we don't actually delete it)
+ dpMain._firstEntry = null;
+ dpMain._lastEntry = null;
+ dpExtra._entryPrefix = EMPTY_PREFIX;
+ if(dpExtra._totalEntrySize != 0) {
+ throw new IllegalStateException("Empty page but size is not 0? " +
+ cacheDataPage);
+ }
+ return;
+ }
+
+ // remove this page from it's parent page
+ removeFromParent(cacheDataPage);
+
+ // remove this page from any next/prev pages
+ removeFromPeers(cacheDataPage);
+
+ // FIXME, deallocate index page?
+ }
+
+ private void removeFromParent(CacheDataPage childDataPage)
+ throws IOException
+ {
+ DataPageMain childMain = childDataPage._main;
+ DataPageExtra childExtra = childDataPage._extra;
+
+ CacheDataPage parentDataPage =
+ new CacheDataPage(childMain.getParentPage());
+
+ 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);
+ }
+ }
+
+ private void removeFromPeers(CacheDataPage cacheDataPage)
+ throws IOException
+ {
+ DataPageMain dpMain = cacheDataPage._main;
+ DataPageExtra dpExtra = cacheDataPage._extra;
+
+ Integer prevPageNumber = dpMain._prevPageNumber;
+ Integer nextPageNumber = dpMain._nextPageNumber;
+
+ DataPageMain prevMain = dpMain.getPrevPage();
+ if(prevMain != null) {
+ setModified(new CacheDataPage(prevMain));
+ prevMain._nextPageNumber = nextPageNumber;
+ }
+
+ DataPageMain nextMain = dpMain.getNextPage();
+ if(nextMain != null) {
+ setModified(new CacheDataPage(nextMain));
+ nextMain._prevPageNumber = prevPageNumber;
+ }
+ }
+
+ private void updateFirstEntry(CacheDataPage cacheDataPage)
+ throws IOException
+ {
+ DataPageMain dpMain = cacheDataPage._main;
+ DataPageExtra dpExtra = cacheDataPage._extra;
+
+ Entry oldEntry = dpMain._firstEntry;
+ 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);
+ }
+ }
+
+ private void updateParentEntry(CacheDataPage parentDataPage,
+ Entry oldEntry, Entry newEntry)
+ throws IOException
+ {
+ DataPageMain parentMain = parentDataPage._main;
+ DataPageExtra parentExtra = parentDataPage._extra;
+
+ setModified(parentDataPage);
+
+ int idx = parentExtra.findEntry(oldEntry);
+ if(idx < 0) {
+ throw new IllegalStateException(
+ "Could not find child entry in parent; childEntry " + oldEntry +
+ "; parent " + parentDataPage);
+ }
+ replaceEntry(parentDataPage, idx, newEntry);
+ }
+
private void addEntry(CacheDataPage cacheDataPage,
int entryIdx,
Entry newEntry)
@@ -242,17 +353,7 @@ public class IndexPageCache
}
if(updateFirst) {
- Entry oldFirstEntry = dpMain._firstEntry;
- dpMain._firstEntry = newEntry;
- if(!dpMain.isRoot()) {
- // FIXME, handle null oldFirstEntry
- Entry oldParentEntry = oldFirstEntry.asNodeEntry(
- dpMain._pageNumber);
- Entry newParentEntry =
- dpMain._firstEntry.asNodeEntry(dpMain._pageNumber);
- // FIXME, need to update parent
- throw new UnsupportedOperationException();
- }
+ updateFirstEntry(cacheDataPage);
}
if(updateLast) {
dpMain._lastEntry = newEntry;
@@ -281,7 +382,7 @@ public class IndexPageCache
// find first leaf
while(!curPage._leaf) {
- curPage = getDataPage(curPage._firstEntry.getSubPageNumber());
+ curPage = curPage.getChildPage(curPage._firstEntry);
}
return new CacheDataPage(curPage);
@@ -294,7 +395,7 @@ public class IndexPageCache
(childTailPage.compareToPage(e) >= 0)) {
curPage = childTailPage;
} else {
- curPage = getDataPage(curPage._lastEntry.getSubPageNumber());
+ curPage = curPage.getChildPage(curPage._lastEntry);
}
} else {
return new CacheDataPage(curPage);
@@ -322,7 +423,7 @@ public class IndexPageCache
}
Entry nodeEntry = extra._entries.get(idx);
- curPage = getDataPage(nodeEntry.getSubPageNumber());
+ curPage = curPage.getChildPage(nodeEntry);
}
}
@@ -409,40 +510,48 @@ public class IndexPageCache
return(this == _rootPage);
}
- public boolean isTail()
- throws IOException
+ public boolean isTail() throws IOException
{
resolveParent();
return _tail;
}
- public DataPageMain getParentPage()
- throws IOException
+ public DataPageMain getParentPage() throws IOException
{
resolveParent();
return IndexPageCache.this.getDataPage(_parentPageNumber);
}
+
+ public void setParentPage(Integer parentPageNumber, boolean isTail) {
+ if(_parentPageNumber == null) {
+ _parentPageNumber = parentPageNumber;
+ _tail = isTail;
+ }
+ }
- public DataPageMain getPrevPage()
- throws IOException
+ public DataPageMain getPrevPage() throws IOException
{
return IndexPageCache.this.getDataPage(_prevPageNumber);
}
- public DataPageMain getNextPage()
- throws IOException
+ public DataPageMain getNextPage() throws IOException
{
return IndexPageCache.this.getDataPage(_nextPageNumber);
}
- public DataPageMain getChildTailPage()
- throws IOException
+ public DataPageMain getChildPage(Entry e) throws IOException
{
- return IndexPageCache.this.getDataPage(_childTailPageNumber);
+ return IndexPageCache.this.getChildDataPage(
+ e.getSubPageNumber(), this, false);
}
- public DataPageExtra getExtra()
- throws IOException
+ public DataPageMain getChildTailPage() throws IOException
+ {
+ return IndexPageCache.this.getChildDataPage(
+ _childTailPageNumber, this, true);
+ }
+
+ public DataPageExtra getExtra() throws IOException
{
DataPageExtra extra = _extra.get();
if(extra == null) {
@@ -453,8 +562,7 @@ public class IndexPageCache
return extra;
}
- public void setExtra(DataPageExtra extra, boolean isNew)
- throws IOException
+ public void setExtra(DataPageExtra extra, boolean isNew) throws IOException
{
if(isNew) {
@@ -496,11 +604,14 @@ public class IndexPageCache
return _firstEntry.compareTo(other._firstEntry);
}
- private void resolveParent() {
- if((_parentPageNumber == null) && !isRoot()) {
- // FIXME, writeme
- // need to determine _parentPageNumber and _tail
- throw new UnsupportedOperationException();
+ private void resolveParent() throws IOException {
+ if(_parentPageNumber == null) {
+ // the act of searching for the first entry should resolve any parent
+ // pages along the path
+ findCacheDataPage(_firstEntry);
+ if(_parentPageNumber == null) {
+ throw new IllegalStateException("Parent was not resolved");
+ }
}
}