Search in sources :

Example 1 with BTreeException

use of org.exist.storage.btree.BTreeException in project exist by eXist-db.

the class DOMFile method findValue.

/**
 * Retrieve node at virtual address.
 *
 * @param broker the database broker
 * @param node The virtual address
 * @return The reference of the node
 * @throws IOException if an I/O error occurs
 * @throws BTreeException if an error occurs reading the tree
 */
protected long findValue(final DBBroker broker, final NodeProxy node) throws IOException, BTreeException {
    if (LOG.isDebugEnabled() && !lockManager.isBtreeLocked(getLockName())) {
        LOG.debug("The file doesn't own a lock");
    }
    final DocumentImpl doc = node.getOwnerDocument();
    final NodeRef nodeRef = new NativeBroker.NodeRef(doc.getDocId(), node.getNodeId());
    // first try to find the node in the index
    final long pointer = findValue(nodeRef);
    if (pointer == KEY_NOT_FOUND) {
        // node not found in index: try to find the nearest available
        // ancestor and traverse it
        NodeId nodeID = node.getNodeId();
        long parentPointer = KEY_NOT_FOUND;
        do {
            nodeID = nodeID.getParentId();
            if (nodeID == null) {
                SanityCheck.TRACE("Node " + node.getOwnerDocument().getDocId() + ":<null nodeID> not found.");
                throw new BTreeException("Node not found.");
            }
            if (nodeID == NodeId.DOCUMENT_NODE) {
                SanityCheck.TRACE("Node " + node.getOwnerDocument().getDocId() + ":" + nodeID + " not found.");
                return KEY_NOT_FOUND;
            }
            final NativeBroker.NodeRef parentRef = new NativeBroker.NodeRef(doc.getDocId(), nodeID);
            try {
                parentPointer = findValue(parentRef);
            } catch (final BTreeException bte) {
                LOG.error("report me", bte);
            }
        } while (parentPointer == KEY_NOT_FOUND);
        try {
            final int thisLevel = nodeID.getTreeLevel();
            // lazily initialized below
            Integer childLevel = null;
            final NodeProxy parent = new NodeProxy(doc, nodeID, parentPointer);
            final EmbeddedXMLStreamReader reader = (EmbeddedXMLStreamReader) broker.getXMLStreamReader(parent, true);
            while (reader.hasNext()) {
                final int status = reader.next();
                if (status != XMLStreamReader.END_ELEMENT) {
                    if (childLevel == null) {
                        childLevel = reader.getNode().getNodeType() == Node.ELEMENT_NODE ? thisLevel + 1 : thisLevel;
                    }
                    final NodeId otherId = (NodeId) reader.getProperty(ExtendedXMLStreamReader.PROPERTY_NODE_ID);
                    if (otherId.equals(node.getNodeId())) {
                        return reader.getCurrentPosition();
                    }
                }
                if (status == XMLStreamConstants.END_ELEMENT) {
                    final NodeId otherId = (NodeId) reader.getProperty(ExtendedXMLStreamReader.PROPERTY_NODE_ID);
                    final int otherLevel = otherId.getTreeLevel();
                    if (childLevel != null && childLevel != otherLevel && otherLevel == thisLevel) {
                        // exit-while
                        break;
                    }
                }
            }
            if (LOG.isDebugEnabled()) {
                LOG.debug("Node {} could not be found. Giving up. This is usually not an error.", node.getNodeId());
            }
            return KEY_NOT_FOUND;
        } catch (final XMLStreamException e) {
            SanityCheck.TRACE("Node " + node.getOwnerDocument().getDocId() + ":" + node.getNodeId() + " not found.");
            throw new BTreeException("Node " + node.getNodeId() + " not found.");
        }
    } else {
        return pointer;
    }
}
Also used : NodeRef(org.exist.storage.NativeBroker.NodeRef) BTreeException(org.exist.storage.btree.BTreeException) XMLStreamException(javax.xml.stream.XMLStreamException) NodeId(org.exist.numbering.NodeId) EmbeddedXMLStreamReader(org.exist.stax.EmbeddedXMLStreamReader) NativeBroker(org.exist.storage.NativeBroker) NodeRef(org.exist.storage.NativeBroker.NodeRef) DocumentImpl(org.exist.dom.persistent.DocumentImpl) NodeProxy(org.exist.dom.persistent.NodeProxy)

Example 2 with BTreeException

use of org.exist.storage.btree.BTreeException in project exist by eXist-db.

the class DOMFile method getNodeValue.

/**
 * Retrieve the string value of the specified node. This is an optimized low-level method
 * which will directly traverse the stored DOM nodes and collect the string values of
 * the specified root node and all its descendants. By directly scanning the stored
 * node data, we do not need to create a potentially large amount of node objects
 * and thus save memory and time for garbage collection.
 *
 * @param broker the database broker
 * @param node the node
 * @param addWhitespace true if whitespace should be added to the node value
 * @return string value of the specified node
 */
public String getNodeValue(final DBBroker broker, final IStoredNode node, final boolean addWhitespace) {
    if (LOG.isDebugEnabled() && !lockManager.isBtreeLocked(getLockName())) {
        LOG.debug("The file doesn't own a lock");
    }
    try {
        long address = node.getInternalAddress();
        RecordPos recordPos = null;
        // try to directly locate the root node through its storage address
        if (StorageAddress.hasAddress(address)) {
            recordPos = findRecord(address);
        }
        if (recordPos == null) {
            // fallback to a BTree lookup if the node could not be found
            // by its storage address
            address = findValue(broker, new NodeProxy(node));
            if (address == BTree.KEY_NOT_FOUND) {
                LOG.error("Node value not found: {}", node);
                // TODO : throw exception ? -pb
                return null;
            }
            recordPos = findRecord(address);
            SanityCheck.THROW_ASSERT(recordPos != null, "Node data could not be found!");
        // TODO : throw exception ? -pb
        }
        // we collect the string values in binary format and append them to a ByteArrayOutputStream
        try (final UnsynchronizedByteArrayOutputStream os = new UnsynchronizedByteArrayOutputStream(32)) {
            // now traverse the tree
            getNodeValue(broker.getBrokerPool(), os, recordPos, true, addWhitespace);
            final byte[] data = os.toByteArray();
            final XMLString str = UTF8.decode(data);
            if (str != null) {
                return str.toString();
            } else {
                return "";
            }
        }
    } catch (final BTreeException e) {
        LOG.error("BTree error while reading node value", e);
    // TODO : rethrow exception ? -pb
    } catch (final Exception e) {
        LOG.error("IO error while reading node value", e);
    // TODO : rethrow exception ? -pb
    }
    // TODO : remove if exceptions thrown...
    return null;
}
Also used : BTreeException(org.exist.storage.btree.BTreeException) UnsynchronizedByteArrayOutputStream(org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream) NodeProxy(org.exist.dom.persistent.NodeProxy) JournalException(org.exist.storage.journal.JournalException) TerminatedException(org.exist.xquery.TerminatedException) XMLStreamException(javax.xml.stream.XMLStreamException) DBException(org.exist.storage.btree.DBException) BTreeException(org.exist.storage.btree.BTreeException) IOException(java.io.IOException)

Example 3 with BTreeException

use of org.exist.storage.btree.BTreeException in project exist by eXist-db.

the class NodeIterator method next.

/**
 *  Returns the next node in document order.
 */
@Override
public IStoredNode next() {
    try (final ManagedLock<ReentrantLock> domFileLock = lockManager.acquireBtreeReadLock(db.getLockName())) {
        db.setOwnerObject(broker);
        IStoredNode nextNode = null;
        if (gotoNextPosition()) {
            long backLink = 0;
            do {
                final DOMFile.DOMFilePageHeader pageHeader = page.getPageHeader();
                // Next value larger than length of the current page?
                if (offset >= pageHeader.getDataLength()) {
                    // Load next page in chain
                    long nextPageNum = pageHeader.getNextDataPage();
                    if (nextPageNum == Page.NO_PAGE) {
                        SanityCheck.TRACE("bad link to next " + page.page.getPageInfo() + "; previous: " + pageHeader.getPreviousDataPage() + "; offset = " + offset + "; lastTupleID = " + lastTupleID);
                        if (LOG.isDebugEnabled()) {
                            LOG.debug(db.debugPageContents(page));
                        }
                        // TODO : throw exception here ? -pb
                        return null;
                    }
                    pageNum = nextPageNum;
                    page = db.getDOMPage(nextPageNum);
                    db.addToBuffer(page);
                    offset = 0;
                }
                // Extract the tuple ID
                lastTupleID = ByteConversion.byteToShort(page.data, offset);
                offset += DOMFile.LENGTH_TID;
                // Check if this is just a link to a relocated node
                if (ItemId.isLink(lastTupleID)) {
                    // Skip this
                    offset += DOMFile.LENGTH_FORWARD_LOCATION;
                    // Continue the iteration
                    continue;
                }
                // Read data length
                short vlen = ByteConversion.byteToShort(page.data, offset);
                offset += DOMFile.LENGTH_DATA_LENGTH;
                if (vlen < 0) {
                    LOG.error("Got negative length{} at offset {}!!!", vlen, offset);
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(db.debugPageContents(page));
                    }
                // TODO : throw an exception right now ?
                }
                if (ItemId.isRelocated(lastTupleID)) {
                    // Found a relocated node. Read the original address
                    backLink = ByteConversion.byteToLong(page.data, offset);
                    offset += DOMFile.LENGTH_ORIGINAL_LOCATION;
                }
                // Overflow page? Load the overflow value
                if (vlen == DOMFile.OVERFLOW) {
                    vlen = DOMFile.LENGTH_OVERFLOW_LOCATION;
                    final long overflow = ByteConversion.byteToLong(page.data, offset);
                    offset += DOMFile.LENGTH_OVERFLOW_LOCATION;
                    try {
                        final byte[] overflowValue = db.getOverflowValue(overflow);
                        nextNode = StoredNode.deserialize(overflowValue, 0, overflowValue.length, doc, useNodePool);
                    } catch (final Exception e) {
                        LOG.warn("Exception while loading overflow value: {}; originating page: {}", e.getMessage(), page.page.getPageInfo());
                    // TODO : rethrow exception ? -pb
                    }
                // Normal node
                } else {
                    try {
                        nextNode = StoredNode.deserialize(page.data, offset, vlen, doc, useNodePool);
                        offset += vlen;
                    } catch (final Exception e) {
                        LOG.error("Error while deserializing node: {}", e.getMessage(), e);
                        LOG.error("Reading from offset: {}; len = {}", offset, vlen);
                        if (LOG.isDebugEnabled()) {
                            LOG.debug(db.debugPageContents(page));
                        }
                        throw new RuntimeException(e);
                    }
                }
                if (nextNode == null) {
                    LOG.error("illegal node on page {}; tid = {}; next = {}; prev = {}; offset = {}; len = {}", page.getPageNum(), ItemId.getId(lastTupleID), page.getPageHeader().getNextDataPage(), page.getPageHeader().getPreviousDataPage(), offset - vlen, page.getPageHeader().getDataLength());
                    if (LOG.isDebugEnabled()) {
                        LOG.debug(db.debugPageContents(page));
                    }
                    // TODO : throw an exception here ? -pb
                    return null;
                }
                if (ItemId.isRelocated(lastTupleID)) {
                    nextNode.setInternalAddress(backLink);
                } else {
                    nextNode.setInternalAddress(StorageAddress.createPointer((int) pageNum, ItemId.getId(lastTupleID)));
                }
                nextNode.setOwnerDocument(doc);
            } while (nextNode == null);
        }
        return nextNode;
    } catch (final LockException e) {
        LOG.warn("Failed to acquire read lock on {}", FileUtils.fileName(db.getFile()));
        // TODO : throw exception here ? -pb
        return null;
    } catch (final BTreeException | IOException e) {
        LOG.error(e.getMessage(), e);
    // TODO : re-throw exception ? -pb
    }
    return null;
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) IOException(java.io.IOException) BTreeException(org.exist.storage.btree.BTreeException) IOException(java.io.IOException) LockException(org.exist.util.LockException) BTreeException(org.exist.storage.btree.BTreeException) LockException(org.exist.util.LockException) IStoredNode(org.exist.dom.persistent.IStoredNode)

Example 4 with BTreeException

use of org.exist.storage.btree.BTreeException in project exist by eXist-db.

the class NativeValueIndex method dropIndex.

@Override
public void dropIndex(final Collection collection) {
    try (final ManagedLock<ReentrantLock> bfileLock = lockManager.acquireBtreeWriteLock(dbValues.getLockName())) {
        flush();
        // remove generic index
        Value ref = new SimpleValue(collection.getId());
        dbValues.removeAll(null, new IndexQuery(IndexQuery.TRUNC_RIGHT, ref));
        // remove QName index
        ref = new QNameValue(collection.getId());
        dbValues.removeAll(null, new IndexQuery(IndexQuery.TRUNC_RIGHT, ref));
    } catch (final LockException e) {
        LOG.warn("Failed to acquire lock for '{}'", FileUtils.fileName(dbValues.getFile()), e);
    } catch (final BTreeException | IOException e) {
        LOG.error(e.getMessage(), e);
    }
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) BTreeException(org.exist.storage.btree.BTreeException) IndexQuery(org.exist.storage.btree.IndexQuery) AtomicValue(org.exist.xquery.value.AtomicValue) StringValue(org.exist.xquery.value.StringValue) Value(org.exist.storage.btree.Value) IOException(java.io.IOException)

Example 5 with BTreeException

use of org.exist.storage.btree.BTreeException in project exist by eXist-db.

the class NativeValueIndex method findAll.

/**
 * find.
 *
 * @param comparison The type of comparison the search is performing
 * @param docs       The documents to search for matches within
 * @param contextSet DOCUMENT ME!
 * @param axis       DOCUMENT ME!
 * @param qnames     DOCUMENT ME!
 * @param value      right hand comparison value
 * @param result     DOCUMENT ME!
 * @return DOCUMENT ME!
 * @throws TerminatedException DOCUMENT ME!
 */
private NodeSet findAll(final XQueryWatchDog watchDog, final Comparison comparison, final DocumentSet docs, final NodeSet contextSet, final int axis, final List<QName> qnames, final Indexable value, final NodeSet result) throws TerminatedException {
    final SearchCallback cb = new SearchCallback(docs, contextSet, result, axis == NodeSet.ANCESTOR);
    final int idxOp = toIndexQueryOp(comparison);
    for (final Iterator<Collection> iter = docs.getCollectionIterator(); iter.hasNext(); ) {
        final int collectionId = iter.next().getId();
        watchDog.proceed(null);
        if (qnames == null) {
            try (final ManagedLock<ReentrantLock> bfileLock = lockManager.acquireBtreeReadLock(dbValues.getLockName())) {
                final Value searchKey = new SimpleValue(collectionId, value);
                final IndexQuery query = new IndexQuery(idxOp, searchKey);
                if (idxOp == IndexQuery.EQ) {
                    dbValues.query(query, cb);
                } else {
                    final Value prefixKey = new SimplePrefixValue(collectionId, value.getType());
                    dbValues.query(query, prefixKey, cb);
                }
            } catch (final EXistException | BTreeException | IOException e) {
                LOG.error(e.getMessage(), e);
            } catch (final LockException e) {
                LOG.warn("Failed to acquire lock for '{}'", FileUtils.fileName(dbValues.getFile()), e);
            }
        } else {
            for (final QName qname : qnames) {
                try (final ManagedLock<ReentrantLock> bfileLock = lockManager.acquireBtreeReadLock(dbValues.getLockName())) {
                    // Compute a key for the value in the collection
                    final Value searchKey = new QNameValue(collectionId, qname, value, broker.getBrokerPool().getSymbols());
                    final IndexQuery query = new IndexQuery(idxOp, searchKey);
                    if (idxOp == IndexQuery.EQ) {
                        dbValues.query(query, cb);
                    } else {
                        final Value prefixKey = new QNamePrefixValue(collectionId, qname, value.getType(), broker.getBrokerPool().getSymbols());
                        dbValues.query(query, prefixKey, cb);
                    }
                } catch (final EXistException | BTreeException | IOException e) {
                    LOG.error(e.getMessage(), e);
                } catch (final LockException e) {
                    LOG.warn("Failed to acquire lock for '{}'", FileUtils.fileName(dbValues.getFile()), e);
                }
            }
        }
    }
    return result;
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) IndexQuery(org.exist.storage.btree.IndexQuery) QName(org.exist.dom.QName) EXistException(org.exist.EXistException) IOException(java.io.IOException) BTreeException(org.exist.storage.btree.BTreeException) AtomicValue(org.exist.xquery.value.AtomicValue) StringValue(org.exist.xquery.value.StringValue) Value(org.exist.storage.btree.Value) Collection(org.exist.collections.Collection)

Aggregations

BTreeException (org.exist.storage.btree.BTreeException)20 IOException (java.io.IOException)19 ReentrantLock (java.util.concurrent.locks.ReentrantLock)18 Value (org.exist.storage.btree.Value)15 IndexQuery (org.exist.storage.btree.IndexQuery)12 EXistException (org.exist.EXistException)11 TerminatedException (org.exist.xquery.TerminatedException)7 Collection (org.exist.collections.Collection)6 QName (org.exist.dom.QName)5 AtomicValue (org.exist.xquery.value.AtomicValue)5 StringValue (org.exist.xquery.value.StringValue)5 NodeProxy (org.exist.dom.persistent.NodeProxy)3 XMLStreamException (javax.xml.stream.XMLStreamException)2 ElementValue (org.exist.storage.ElementValue)2 LockException (org.exist.util.LockException)2 UnsynchronizedByteArrayOutputStream (org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream)1 DocumentImpl (org.exist.dom.persistent.DocumentImpl)1 ExtArrayNodeSet (org.exist.dom.persistent.ExtArrayNodeSet)1 IStoredNode (org.exist.dom.persistent.IStoredNode)1 NodeSet (org.exist.dom.persistent.NodeSet)1