]> source.dussan.org Git - jackcess.git/commitdiff
flesh out some of the index page update operations
authorJames Ahlborn <jtahlborn@yahoo.com>
Sun, 6 Apr 2008 03:45:12 +0000 (03:45 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Sun, 6 Apr 2008 03:45:12 +0000 (03:45 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@313 f203690c-595d-4dc9-a70b-905162fa7fd2

src/java/com/healthmarketscience/jackcess/Index.java
src/java/com/healthmarketscience/jackcess/IndexPageCache.java

index be86515f152b1891a0ee9cd02d09006a404823e7..7f80d182108d217d16e7e77634189f0f66b6a1ba 100644 (file)
@@ -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);
     }
     
index 8ea02609f7575b3ec2eb92307570d3a0ef789ec1..62cfe2a150aa7874686587f096701d09a11cf968 100644 (file)
@@ -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");
+        }
       }
     }