Search in sources :

Example 1 with VariableByteArrayInput

use of org.exist.storage.io.VariableByteArrayInput in project exist by eXist-db.

the class NativeValueIndex method remove.

private <T> void remove(final PendingChanges<T> pending, final FunctionE<T, Value, EXistException> dbKeyFn) {
    final VariableByteOutputStream nodeIdOs = new VariableByteOutputStream();
    for (final Map.Entry<T, List<NodeId>> entry : pending.changes.entrySet()) {
        final T key = entry.getKey();
        final List<NodeId> storedGIDList = entry.getValue();
        final List<NodeId> newGIDList = new ArrayList<>();
        os.clear();
        try (final ManagedLock<ReentrantLock> bfileLock = lockManager.acquireBtreeWriteLock(dbValues.getLockName())) {
            // Compute a key for the value
            final Value searchKey = dbKeyFn.apply(key);
            final Value value = dbValues.get(searchKey);
            // Does the value already has data in the index ?
            if (value != null) {
                // Add its data to the new list
                final VariableByteArrayInput is = new VariableByteArrayInput(value.getData());
                while (is.available() > 0) {
                    final int storedDocId = is.readInt();
                    final int gidsCount = is.readInt();
                    final int size = is.readFixedInt();
                    if (storedDocId != this.doc.getDocId()) {
                        // data are related to another document:
                        // append them to any existing data
                        os.writeInt(storedDocId);
                        os.writeInt(gidsCount);
                        os.writeFixedInt(size);
                        is.copyRaw(os, size);
                    } else {
                        // data are related to our document:
                        // feed the new list with the GIDs
                        NodeId previous = null;
                        for (int j = 0; j < gidsCount; j++) {
                            final NodeId nodeId = broker.getBrokerPool().getNodeFactory().createFromStream(previous, is);
                            previous = nodeId;
                            // in the list of removed nodes
                            if (!containsNode(storedGIDList, nodeId)) {
                                newGIDList.add(nodeId);
                            }
                        }
                    }
                }
                // append the data from the new list
                if (newGIDList.size() > 0) {
                    final int gidsCount = newGIDList.size();
                    // Don't forget this one
                    FastQSort.sort(newGIDList, 0, gidsCount - 1);
                    os.writeInt(this.doc.getDocId());
                    os.writeInt(gidsCount);
                    // Compute the new GID list
                    try {
                        NodeId previous = null;
                        for (final NodeId nodeId : newGIDList) {
                            previous = nodeId.write(previous, nodeIdOs);
                        }
                        final byte[] nodeIdsData = nodeIdOs.toByteArray();
                        // clear the buf for the next iteration
                        nodeIdOs.clear();
                        // Write length of node IDs (bytes)
                        os.writeFixedInt(nodeIdsData.length);
                        // write the node IDs
                        os.write(nodeIdsData);
                    } catch (final IOException e) {
                        LOG.warn("IO error while writing range index: {}", e.getMessage(), e);
                    // TODO : throw exception?
                    }
                }
                // dbValues.remove(value);
                if (dbValues.update(value.getAddress(), searchKey, os.data()) == BFile.UNKNOWN_ADDRESS) {
                    LOG.error("Could not update index data for value '{}'", searchKey);
                // TODO: throw exception ?
                }
            } else {
                if (dbValues.put(searchKey, os.data()) == BFile.UNKNOWN_ADDRESS) {
                    LOG.error("Could not put index data for value '{}'", searchKey);
                // TODO : throw exception ?
                }
            }
        } catch (final EXistException | IOException e) {
            LOG.error(e.getMessage(), e);
        } catch (final LockException e) {
            LOG.warn("Failed to acquire lock for '{}'", FileUtils.fileName(dbValues.getFile()), e);
        // TODO : return ?
        } finally {
            os.clear();
        }
    }
    pending.changes.clear();
}
Also used : ReentrantLock(java.util.concurrent.locks.ReentrantLock) IOException(java.io.IOException) EXistException(org.exist.EXistException) VariableByteArrayInput(org.exist.storage.io.VariableByteArrayInput) VariableByteOutputStream(org.exist.storage.io.VariableByteOutputStream) NodeId(org.exist.numbering.NodeId) AtomicValue(org.exist.xquery.value.AtomicValue) StringValue(org.exist.xquery.value.StringValue) Value(org.exist.storage.btree.Value)

Example 2 with VariableByteArrayInput

use of org.exist.storage.io.VariableByteArrayInput in project exist by eXist-db.

the class NativeValueIndex method dropIndex.

private <T> void dropIndex(final int docId, final PendingChanges<T> pending, final FunctionE<T, Value, EXistException> dbKeyFn) throws EXistException, IOException {
    for (final Map.Entry<T, List<NodeId>> entry : pending.changes.entrySet()) {
        final T key = entry.getKey();
        // Compute a key for the indexed value in the collection
        final Value v = dbKeyFn.apply(key);
        final Value value = dbValues.get(v);
        if (value == null) {
            continue;
        }
        final VariableByteArrayInput is = new VariableByteArrayInput(value.getData());
        boolean changed = false;
        os.clear();
        while (is.available() > 0) {
            final int storedDocId = is.readInt();
            final int gidsCount = is.readInt();
            final int size = is.readFixedInt();
            if (storedDocId != docId) {
                // data are related to another document:
                // copy them (keep them)
                os.writeInt(storedDocId);
                os.writeInt(gidsCount);
                os.writeFixedInt(size);
                is.copyRaw(os, size);
            } else {
                // data are related to our document:
                // skip them (remove them)
                is.skipBytes(size);
                changed = true;
            }
        }
        // Store new data, if relevant
        if (changed) {
            if (os.data().size() == 0) {
                // nothing to store:
                // remove the existing key/value pair
                dbValues.remove(v);
            } else {
                // modify the existing value for the key
                if (dbValues.put(v, os.data()) == BFile.UNKNOWN_ADDRESS) {
                    LOG.error("Could not put index data for key '{}'", v);
                // TODO : throw exception ?
                }
            }
        }
    }
    pending.changes.clear();
}
Also used : VariableByteArrayInput(org.exist.storage.io.VariableByteArrayInput) AtomicValue(org.exist.xquery.value.AtomicValue) StringValue(org.exist.xquery.value.StringValue) Value(org.exist.storage.btree.Value)

Aggregations

Value (org.exist.storage.btree.Value)2 VariableByteArrayInput (org.exist.storage.io.VariableByteArrayInput)2 AtomicValue (org.exist.xquery.value.AtomicValue)2 StringValue (org.exist.xquery.value.StringValue)2 IOException (java.io.IOException)1 ReentrantLock (java.util.concurrent.locks.ReentrantLock)1 EXistException (org.exist.EXistException)1 NodeId (org.exist.numbering.NodeId)1 VariableByteOutputStream (org.exist.storage.io.VariableByteOutputStream)1