diff options
author | James Ahlborn <jtahlborn@yahoo.com> | 2008-04-06 03:45:12 +0000 |
---|---|---|
committer | James Ahlborn <jtahlborn@yahoo.com> | 2008-04-06 03:45:12 +0000 |
commit | 095e6cc5493ee363840fd54d20eb0e3977e1ba9d (patch) | |
tree | 5b547beaa72c79c8fc691e6b9d4727f377112d2a | |
parent | c262ce564f739d4c9e8179d25663e936728f7c1e (diff) | |
download | jackcess-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.java | 2 | ||||
-rw-r--r-- | src/java/com/healthmarketscience/jackcess/IndexPageCache.java | 223 |
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"); + } } } |