From: Wolfgang M. M. <wol...@us...> - 2004-04-14 12:18:03
|
Update of /cvsroot/exist/eXist-1.0/src/org/exist/storage/store In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20167/src/org/exist/storage/store Modified Files: DOMFileIterator.java BFile.java NodeIterator.java DOMFile.java StorageAddress.java Added Files: ItemId.java Log Message: Improved page organization in dom.dbx to fix known XUpdate issues. Index: DOMFile.java =================================================================== RCS file: /cvsroot/exist/eXist-1.0/src/org/exist/storage/store/DOMFile.java,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** DOMFile.java 29 Mar 2004 14:15:12 -0000 1.20 --- DOMFile.java 14 Apr 2004 12:17:22 -0000 1.21 *************** *** 2,25 **** /* ! * eXist Open Source Native XML Database ! * Copyright (C) 2001, Wolfgang M. Meier (wol...@ex...) ! * ! * This library is free software; you can redistribute it and/or ! * modify it under the terms of the GNU Library General Public License ! * as published by the Free Software Foundation; either version 2 ! * of the License, or (at your option) any later version. ! * [...3302 lines suppressed...] ! return true; ! } ! } ! ! protected final static class RecordPos { ! ! int offset = -1; ! ! DOMPage page = null; ! ! short tid = 0; ! ! public RecordPos(int offset, DOMPage page, short tid) { ! this.offset = offset; ! this.page = page; ! this.tid = tid; ! } ! } ! } \ No newline at end of file Index: BFile.java =================================================================== RCS file: /cvsroot/exist/eXist-1.0/src/org/exist/storage/store/BFile.java,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** BFile.java 29 Mar 2004 14:15:12 -0000 1.16 --- BFile.java 14 Apr 2004 12:17:22 -0000 1.17 *************** *** 70,74 **** public class BFile extends BTree { ! public final static short FILE_FORMAT_VERSION_ID = 2; // minimum free space a page should have to be --- 70,74 ---- public class BFile extends BTree { ! public final static short FILE_FORMAT_VERSION_ID = 3; // minimum free space a page should have to be *************** *** 88,93 **** public int fixedKeyLen = -1; - private int overflow = 0; - public BFile() { super(); --- 88,91 ---- *************** *** 466,474 **** if (wp == null) { final Page page = getPage(pos); - final byte[] data = page.read(); if (page == null) { LOG.debug("page " + pos + " not found!"); return null; } if (page.getPageHeader().getStatus() == MULTI_PAGE) return new OverflowPage(page, data); --- 464,472 ---- if (wp == null) { final Page page = getPage(pos); if (page == null) { LOG.debug("page " + pos + " not found!"); return null; } + final byte[] data = page.read(); if (page.getPageHeader().getStatus() == MULTI_PAGE) return new OverflowPage(page, data); *************** *** 848,852 **** private OrderedLinkedList freeList = new OrderedLinkedList(); ! private long freeSpacePage = -1; private long lastDataPage = -1; --- 846,850 ---- private OrderedLinkedList freeList = new OrderedLinkedList(); ! private long lastDataPage = -1; *************** *** 1498,1502 **** } ! private final class SimplePageInputStream extends ByteArrayInputStream implements PageInputStream { --- 1496,1500 ---- } ! private final static class SimplePageInputStream extends ByteArrayInputStream implements PageInputStream { *************** *** 1519,1526 **** * @author wolf */ ! private class MultiPageInputStream extends InputStream implements PageInputStream { private SinglePage nextPage_; - private int len_ = -1; private int pageLen_; private int offset_ = 0; --- 1517,1523 ---- * @author wolf */ ! private final class MultiPageInputStream extends InputStream implements PageInputStream { private SinglePage nextPage_; private int pageLen_; private int offset_ = 0; *************** *** 1529,1533 **** public MultiPageInputStream(SinglePage first, long address) { nextPage_ = first; - len_ = first.ph.getDataLength() - 6; offset_ = 6; pageLen_ = fileHeader.getWorkSize(); --- 1526,1529 ---- *************** *** 1607,1611 **** public void close() throws IOException { nextPage_ = null; - len_ = -1; } --- 1603,1606 ---- Index: NodeIterator.java =================================================================== RCS file: /cvsroot/exist/eXist-1.0/src/org/exist/storage/store/NodeIterator.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** NodeIterator.java 25 Feb 2004 15:31:57 -0000 1.4 --- NodeIterator.java 14 Apr 2004 12:17:22 -0000 1.5 *************** *** 26,38 **** private final static Logger LOG = Logger.getLogger(NodeIterator.class); ! DOMFile db = null; ! NodeProxy node = null; ! DocumentImpl doc = null; ! int offset; ! short lastTID = -1; ! DOMFile.DOMPage p = null; ! long page; ! long startAddress = -1; ! Object lockKey; public NodeIterator(Object lock, DOMFile db, NodeProxy node) --- 26,38 ---- private final static Logger LOG = Logger.getLogger(NodeIterator.class); ! private DOMFile db = null; ! private NodeProxy node = null; ! private DocumentImpl doc = null; ! private int offset; ! private short lastTID = -1; ! private DOMFile.DOMPage p = null; ! private long page; ! private long startAddress = -1; ! private Object lockKey; public NodeIterator(Object lock, DOMFile db, NodeProxy node) *************** *** 61,65 **** */ public long currentAddress() { ! return StorageAddress.createPointer((int) page, lastTID); } --- 61,65 ---- */ public long currentAddress() { ! return StorageAddress.createPointer((int) page, ItemId.getId(lastTID)); } *************** *** 98,104 **** /** ! * Returns the raw data of the next node in the sequence. ! * ! *@return Description of the Return Value */ public Object next() { --- 98,102 ---- /** ! * Returns the next node in document order. */ public Object next() { *************** *** 112,151 **** } if(gotoNextPosition()) { ! final DOMFile.DOMFilePageHeader ph = p.getPageHeader(); ! // next value larger than length of the current page? ! if (offset >= ph.getDataLength()) { ! // load next page in chain ! final long nextPage = ph.getNextDataPage(); ! if (nextPage < 0) { ! LOG.debug("bad link to next " + p.page.getPageInfo()); ! return null; } ! page = nextPage; ! p = db.getCurrentPage(nextPage); ! db.addToBuffer(p); ! offset = 0; ! } ! // extract the value ! lastTID = ByteConversion.byteToShort(p.data, offset); ! short l = ByteConversion.byteToShort(p.data, offset + 2); ! if(l == DOMFile.OVERFLOW) { ! // overflow page: load the overflow value ! l = 8; ! final long overflow = ByteConversion.byteToLong(p.data, offset + 4); ! final byte[] odata = db.getOverflowValue(overflow); ! nextNode = NodeImpl.deserialize(odata, 0, odata.length, doc); ! } else { ! nextNode = NodeImpl.deserialize(p.data, offset + 4, l, doc); ! } ! nextNode.setInternalAddress(StorageAddress.createPointer((int) page, lastTID)); ! nextNode.setOwnerDocument(doc); ! offset = offset + 4 + l; } return nextNode; } catch (BTreeException e) { ! Thread.dumpStack(); ! LOG.warn(e); } catch (IOException e) { ! LOG.warn(e); } finally { lock.release(); --- 110,169 ---- } if(gotoNextPosition()) { ! do { ! DOMFile.DOMFilePageHeader ph = p.getPageHeader(); ! // next value larger than length of the current page? ! if (offset >= ph.getDataLength()) { ! // load next page in chain ! long nextPage = ph.getNextDataPage(); ! if (nextPage < 0) { ! LOG.debug("bad link to next " + p.page.getPageInfo()); ! return null; ! } ! page = nextPage; ! p = db.getCurrentPage(nextPage); ! db.addToBuffer(p); ! offset = 0; } ! // extract the tid ! lastTID = ByteConversion.byteToShort(p.data, offset); ! if(ItemId.getId(lastTID) < 0) ! LOG.debug("tid < 0: " + lastTID + " at "+ p.page.getPageInfo()); ! offset += 2; ! // check if this is just a link to a relocated node ! if(ItemId.isLink(lastTID)) { ! // skip this ! offset += 8; ! continue; ! } ! // read data length ! short l = ByteConversion.byteToShort(p.data, offset); ! offset += 2; ! if(ItemId.isRelocated(lastTID)) { ! // found a relocated node. Skip the next 8 bytes ! offset += 8; ! } ! // overflow page? load the overflow value ! if(l == DOMFile.OVERFLOW) { ! l = 8; ! final long overflow = ByteConversion.byteToLong(p.data, offset); ! offset += 8; ! final byte[] odata = db.getOverflowValue(overflow); ! nextNode = NodeImpl.deserialize(odata, 0, odata.length, doc); ! // normal node ! } else { ! nextNode = NodeImpl.deserialize(p.data, offset, l, doc); ! offset += l; ! } ! nextNode.setInternalAddress( ! StorageAddress.createPointer((int) page, ItemId.getId(lastTID)) ! ); ! nextNode.setOwnerDocument(doc); ! } while(nextNode == null); } return nextNode; } catch (BTreeException e) { ! LOG.warn(e.getMessage(), e); } catch (IOException e) { ! LOG.warn(e.getMessage(), e); } finally { lock.release(); *************** *** 161,165 **** if (addr == BTree.KEY_NOT_FOUND) return false; ! DOMFile.RecordPos rec = db.findValuePosition(addr); page = rec.page.getPageNum(); p = rec.page; --- 179,183 ---- if (addr == BTree.KEY_NOT_FOUND) return false; ! DOMFile.RecordPos rec = db.findRecord(addr); page = rec.page.getPageNum(); p = rec.page; *************** *** 167,171 **** node = null; } else if (-1 < startAddress) { ! final DOMFile.RecordPos rec = db.findValuePosition(startAddress); page = rec.page.getPageNum(); offset = rec.offset - 2; --- 185,189 ---- node = null; } else if (-1 < startAddress) { ! final DOMFile.RecordPos rec = db.findRecord(startAddress); page = rec.page.getPageNum(); offset = rec.offset - 2; Index: StorageAddress.java =================================================================== RCS file: /cvsroot/exist/eXist-1.0/src/org/exist/storage/store/StorageAddress.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** StorageAddress.java 29 Jan 2004 15:06:46 -0000 1.2 --- StorageAddress.java 14 Apr 2004 12:17:22 -0000 1.3 *************** *** 1,7 **** - /* - * StorageAddress.java - May 25, 2003 - * - * @author wolf - */ package org.exist.storage.store; --- 1,2 ---- Index: DOMFileIterator.java =================================================================== RCS file: /cvsroot/exist/eXist-1.0/src/org/exist/storage/store/DOMFileIterator.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** DOMFileIterator.java 25 Nov 2003 12:54:15 -0000 1.3 --- DOMFileIterator.java 14 Apr 2004 12:17:21 -0000 1.4 *************** *** 16,22 **** /** ! * Class DOMFileIterator is used to iterate over nodes in the DOM storage. ! * This implementation returns the raw value of the node. You have to call ! * Node.deserialize() to read the node from the value data. * * The DOM file is locked to locate the data and released afterwards. Before --- 16,23 ---- /** ! * Iterate through all nodes of a document in the DOM storage. Returns the ! * raw data of the node in a {@link org.dbxml.core.data.Value}. Use class ! * {@link org.exist.storage.store.NodeIterator} to get node objects instead of ! * raw data. * * The DOM file is locked to locate the data and released afterwards. Before *************** *** 38,50 **** Object lockKey; - /** - * Constructor for the DOMFileIterator object - * - *@param doc Description of the Parameter - *@param db Description of the Parameter - *@param node Description of the Parameter - *@exception BTreeException Description of the Exception - *@exception IOException Description of the Exception - */ public DOMFileIterator(Object lock, DOMFile db, NodeProxy node) throws BTreeException, IOException { --- 39,42 ---- *************** *** 57,69 **** } - /** - * Constructor for the DOMFileIterator object - * - *@param doc Description of the Parameter - *@param db Description of the Parameter - *@param address Description of the Parameter - *@exception BTreeException Description of the Exception - *@exception IOException Description of the Exception - */ public DOMFileIterator(Object lock, DOMFile db, long address) throws BTreeException, IOException { --- 49,52 ---- *************** *** 96,135 **** return false; } ! if (node != null) { ! db.setOwnerObject(lockKey); ! long addr = db.findValue(lockKey, node); ! if (addr == BTree.KEY_NOT_FOUND) ! return false; ! final DOMFile.RecordPos rec = db.findValuePosition(addr); ! page = rec.page.getPageNum(); ! p = rec.page; ! offset = rec.offset - 2; ! node = null; ! } else if (-1 < startAddress) { ! final DOMFile.RecordPos rec = db.findValuePosition(startAddress); ! page = rec.page.getPageNum(); ! offset = rec.offset - 2; ! p = rec.page; ! } else if (page > -1) ! p = db.getCurrentPage(page); ! else { lock.release(); ! return false; ! } ! db.getPageBuffer().add(p); ! final DOMFilePageHeader ph = p.getPageHeader(); ! lock.release(); ! if (offset < ph.getDataLength()) ! return true; ! else if (ph.getNextDataPage() < 0) ! return false; ! else ! return true; } catch (BTreeException e) { LOG.warn(e); } catch (IOException e) { LOG.warn(e); } - lock.release(); return false; } --- 79,101 ---- return false; } ! if(gotoNextPosition()) { ! db.getPageBuffer().add(p); ! final DOMFilePageHeader ph = p.getPageHeader(); lock.release(); ! if (offset < ph.getDataLength()) ! return true; ! else if (ph.getNextDataPage() < 0) ! return false; ! else ! return true; ! } else ! return false; } catch (BTreeException e) { LOG.warn(e); } catch (IOException e) { LOG.warn(e); + } finally { + lock.release(); } return false; } *************** *** 148,203 **** return null; } ! // position the iterator at the start of the first value ! if (node != null) { ! db.setOwnerObject(lockKey); ! final long addr = db.findValue(lockKey, node); ! if (addr == BTree.KEY_NOT_FOUND) ! return null; ! DOMFile.RecordPos rec = db.findValuePosition(addr); ! page = rec.page.getPageNum(); ! p = rec.page; ! offset = rec.offset - 2; ! node = null; ! } else if (-1 < startAddress) { ! final DOMFile.RecordPos rec = db.findValuePosition(startAddress); ! page = rec.page.getPageNum(); ! offset = rec.offset - 2; ! p = rec.page; ! startAddress = -1; ! } else if (page > -1) ! p = db.getCurrentPage(page); ! else { ! lock.release(); ! return null; ! } ! final DOMFilePageHeader ph = p.getPageHeader(); ! // next value larger than length of the current page? ! if (offset >= ph.getDataLength()) { ! // load next page in chain ! final long nextPage = ph.getNextDataPage(); ! if (nextPage < 0) { ! LOG.debug("bad link to next " + p.page.getPageInfo()); ! lock.release(); ! return null; ! } ! page = nextPage; ! p = db.getCurrentPage(nextPage); ! offset = 0; } - // extract the value - lastTID = ByteConversion.byteToShort(p.data, offset); - short l = ByteConversion.byteToShort(p.data, offset + 2); - Value nextVal; - if(l == DOMFile.OVERFLOW) { - final long op = ByteConversion.byteToLong(p.data, offset + 4); - final byte[] data = db.getOverflowValue(op); - nextVal = new Value(data); - l = 8; - } else - nextVal = new Value(p.data, offset + 4, l); - nextVal.setAddress(StorageAddress.createPointer((int) page, lastTID)); - lastOffset = offset; - offset = offset + 4 + l; - lock.release(); return nextVal; } catch (BTreeException e) { --- 114,165 ---- return null; } ! Value nextVal = null; ! if(gotoNextPosition()) { ! do { ! DOMFilePageHeader ph = p.getPageHeader(); ! // next value larger than length of the current page? ! if (offset >= ph.getDataLength()) { ! // load next page in chain ! final long nextPage = ph.getNextDataPage(); ! if (nextPage < 0) { ! LOG.debug("bad link to next " + p.page.getPageInfo()); ! return null; ! } ! page = nextPage; ! p = db.getCurrentPage(nextPage); ! offset = 0; ! } ! lastOffset = offset; ! ! // extract tid ! lastTID = ByteConversion.byteToShort(p.data, offset); ! offset += 2; ! // check if this is just a link to a relocated node ! if(ItemId.isLink(lastTID)) { ! // skip this ! offset += 8; ! continue; ! } ! // read data length ! short l = ByteConversion.byteToShort(p.data, offset); ! offset += 2; ! if(ItemId.isRelocated(lastTID)) { ! // found a relocated node. Skip the next 8 bytes ! offset += 8; ! } ! if(l == DOMFile.OVERFLOW) { ! final long op = ByteConversion.byteToLong(p.data, offset); ! offset += 8; ! final byte[] data = db.getOverflowValue(op); ! nextVal = new Value(data); ! } else { ! nextVal = new Value(p.data, offset, l); ! offset += l; ! } ! nextVal.setAddress( ! StorageAddress.createPointer((int) page, ItemId.getId(lastTID)) ! ); ! } while(nextVal == null); } return nextVal; } catch (BTreeException e) { *************** *** 205,210 **** } catch (IOException e) { LOG.warn(e); } - lock.release(); return null; } --- 167,173 ---- } catch (IOException e) { LOG.warn(e); + } finally { + lock.release(); } return null; } *************** *** 222,229 **** lock.acquire(Lock.WRITE_LOCK); DOMPage p = db.getCurrentPage(page); ! short l = ByteConversion.byteToShort(p.data, lastOffset + 2); // if this is an overflow value, remove it if(l == DOMFile.OVERFLOW) { ! final long op = ByteConversion.byteToLong(p.data, lastOffset + 4); db.removeOverflowValue(op); } --- 185,209 ---- lock.acquire(Lock.WRITE_LOCK); DOMPage p = db.getCurrentPage(page); ! short itemId = ByteConversion.byteToShort(p.data, lastOffset); ! lastOffset += 2; ! short l = ByteConversion.byteToShort(p.data, lastOffset); ! lastOffset += 2; ! if(ItemId.isRelocated(itemId)) { ! long backLink = ByteConversion.byteToLong(p.data, lastOffset); ! lastOffset += 8; ! DOMFile.RecordPos origRec = db.findRecord(backLink, false); ! DOMFilePageHeader ph = origRec.page.getPageHeader(); ! ph.decRecordCount(); ! //LOG.debug("Removing link from " + StorageAddress.pageFromPointer(backLink) + "; count=" + ph.getRecordCount()); ! origRec.page.setDirty(true); ! if(ph.getRecordCount() == 0) { ! //LOG.debug("Removing linked page: " + origRec.page.getPageNum()); ! db.removePage(origRec.page); ! } ! } // if this is an overflow value, remove it if(l == DOMFile.OVERFLOW) { ! final long op = ByteConversion.byteToLong(p.data, lastOffset); ! lastOffset += 8; db.removeOverflowValue(op); } *************** *** 232,259 **** DOMFilePageHeader ph = p.getPageHeader(); ph.decRecordCount(); p.setDirty(true); // if record count == 0, remove the page if (ph.getRecordCount() == 0) { long np = ph.getNextDataPage(); ! try { ! if (np > -1) { ! DOMPage next = db.getCurrentPage(np); ! next.getPageHeader().prevDataPage = -1; ! db.getPageBuffer().add(next); ! } ! ph.setNextDataPage(-1); ! ph.setPrevDataPage(-1); ! ph.setDataLength(0); ! //ph.setNextTID((short)0); ! ph.setRecordCount((short) 0); ! p.setDirty(true); ! db.getPageBuffer().remove(p); ! db.unlinkPages(p.page); ! } catch (IOException ioe) { ! LOG.warn(ioe); ! } page = np; offset = 0; ! } } catch (LockException e) { LOG.warn(e); --- 212,225 ---- DOMFilePageHeader ph = p.getPageHeader(); ph.decRecordCount(); + //LOG.debug("removed value from " + p.getPageNum() + "; size=" + ph.getRecordCount()); p.setDirty(true); // if record count == 0, remove the page if (ph.getRecordCount() == 0) { long np = ph.getNextDataPage(); ! db.removePage(p); page = np; offset = 0; ! } else ! db.getPageBuffer().add(p); } catch (LockException e) { LOG.warn(e); *************** *** 263,266 **** --- 229,261 ---- } + private boolean gotoNextPosition() throws BTreeException, IOException { + if (node != null) { + db.setOwnerObject(lockKey); + long addr = db.findValue(lockKey, node); + if (addr == BTree.KEY_NOT_FOUND) + return false; + DOMFile.RecordPos rec = db.findRecord(addr); + if(rec != null) { + page = rec.page.getPageNum(); + p = rec.page; + offset = rec.offset - 2; + node = null; + } else + return false; + } else if (-1 < startAddress) { + DOMFile.RecordPos rec = db.findRecord(startAddress); + if(rec != null) { + page = rec.page.getPageNum(); + offset = rec.offset - 2; + p = rec.page; + startAddress = -1; + return true; + } else + return false; + } else if (page > -1) + p = db.getCurrentPage(page); + return true; + } + /** * Reposition the iterator at the address of the proxy node. --- NEW FILE: ItemId.java --- /* * eXist Open Source Native XML Database * Copyright (C) 2001-03 Wolfgang M. Meier * wol...@ex... * http://exist.sourceforge.net * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: ItemId.java,v 1.1 2004/04/14 12:17:22 wolfgang_m Exp $ */ package org.exist.storage.store; class ItemId { public static final short RELOCATED_MASK = (short) 0x8000; public static final short LINK_MASK = (short) 0x4000; public static final short ID_MASK = (short) 0x3FFF; public final static short getId(short id) { return (short) (id & ID_MASK); } public final static short setIsRelocated(short id) { return (short)(id | RELOCATED_MASK); } public final static boolean isLink(short id) { return (id & LINK_MASK) != 0; } public final static short setIsLink(short id) { return (short) (id | LINK_MASK); } public final static boolean isRelocated(short id) { return (id & RELOCATED_MASK) != 0; } } |