Search in sources :

Example 16 with ManagedDocumentLock

use of org.exist.storage.lock.ManagedDocumentLock in project exist by eXist-db.

the class RestoreHandler method restoreResourceEntry.

private DeferredPermission restoreResourceEntry(final Attributes atts) throws SAXException {
    @Nullable final String skip = atts.getValue("skip");
    // Don't process entries which should be skipped
    if (skip != null && !"no".equals(skip)) {
        return new SkippedEntryDeferredPermission();
    }
    @Nullable final String name = atts.getValue("name");
    if (name == null) {
        throw new SAXException("Resource requires a name attribute");
    }
    final boolean xmlType = Optional.ofNullable(atts.getValue("type")).filter(s -> s.equals("XMLResource")).isPresent();
    final String owner = getAttr(atts, "owner", SecurityManager.SYSTEM);
    final String group = getAttr(atts, "group", SecurityManager.DBA_GROUP);
    final String perms = getAttr(atts, "mode", "644");
    final String filename = getAttr(atts, "filename", name);
    @Nullable final String mimeTypeStr = atts.getValue("mimetype");
    @Nullable final String dateCreatedStr = atts.getValue("created");
    @Nullable final String dateModifiedStr = atts.getValue("modified");
    @Nullable final String publicId = atts.getValue("publicid");
    @Nullable final String systemId = atts.getValue("systemid");
    @Nullable final String nameDocType = atts.getValue("namedoctype");
    final XmldbURI docName;
    if (version >= STRICT_URI_VERSION) {
        docName = XmldbURI.create(name);
    } else {
        try {
            docName = URIUtils.encodeXmldbUriFor(name);
        } catch (final URISyntaxException e) {
            final String msg = "Could not parse document name into a URI: " + e.getMessage();
            listener.error(msg);
            LOG.error(msg, e);
            return new SkippedEntryDeferredPermission();
        }
    }
    final EXistInputSource is;
    if (deduplicateBlobs && !xmlType) {
        final String blobId = atts.getValue("blob-id");
        is = descriptor.getBlobInputSource(blobId);
        if (is == null) {
            final String msg = "Failed to restore resource '" + name + "'\nfrom BLOB '" + blobId + "'.\nReason: Unable to obtain its EXistInputSource";
            listener.warn(msg);
            return new SkippedEntryDeferredPermission();
        }
    } else {
        is = descriptor.getInputSource(filename);
        if (is == null) {
            final String msg = "Failed to restore resource '" + name + "'\nfrom file '" + descriptor.getSymbolicPath(name, false) + "'.\nReason: Unable to obtain its EXistInputSource";
            listener.warn(msg);
            return new SkippedEntryDeferredPermission();
        }
    }
    MimeType mimeType = null;
    if (mimeTypeStr != null) {
        mimeType = MimeTable.getInstance().getContentType(mimeTypeStr);
    }
    if (mimeType == null) {
        mimeType = xmlType ? MimeType.XML_TYPE : MimeType.BINARY_TYPE;
    }
    Date dateCreated = null;
    if (dateCreatedStr != null) {
        try {
            dateCreated = new DateTimeValue(dateCreatedStr).getDate();
        } catch (final XPathException xpe) {
            listener.warn("Illegal creation date. Ignoring date...");
        }
    }
    Date dateModified = null;
    if (dateModifiedStr != null) {
        try {
            dateModified = new DateTimeValue(dateModifiedStr).getDate();
        } catch (final XPathException xpe) {
            listener.warn("Illegal modification date. Ignoring date...");
        }
    }
    final DocumentType docType;
    if (publicId != null || systemId != null) {
        docType = new DocumentTypeImpl(nameDocType, publicId, systemId);
    } else {
        docType = null;
    }
    final XmldbURI docUri = currentCollectionUri.append(docName);
    try {
        try (final Txn transaction = beginTransaction()) {
            boolean validated = false;
            try {
                try (final Collection collection = broker.openCollection(currentCollectionUri, Lock.LockMode.WRITE_LOCK);
                    final ManagedDocumentLock docLock = broker.getBrokerPool().getLockManager().acquireDocumentWriteLock(docUri)) {
                    broker.storeDocument(transaction, docName, is, mimeType, dateCreated, dateModified, null, docType, null, collection);
                    validated = true;
                    transaction.commit();
                    // NOTE: early release of Collection lock inline with Asymmetrical Locking scheme
                    collection.close();
                }
            } finally {
                /*
                        This allows us to commit the transaction (so the restore doesn't stop)
                        and still throw an exception to skip over resources that didn't
                        validate. This preserves eXist-db's previous behaviour
                        of "best effort attempt" when restoring a backup,
                        rather than an ACID "all or nothing" approach.
                     */
                if (!validated) {
                    // because `validated == false` we know that there have only been reads on the transaction/sub-transaction!
                    transaction.commit();
                }
            }
        }
        final DeferredPermission deferredPermission;
        if (name.startsWith(XmldbURI.SYSTEM_COLLECTION)) {
            // prevents restore of a backup from changing system collection resource ownership
            deferredPermission = new ResourceDeferredPermission(listener, docUri, SecurityManager.SYSTEM, SecurityManager.DBA_GROUP, Integer.parseInt(perms, 8));
        } else {
            deferredPermission = new ResourceDeferredPermission(listener, docUri, owner, group, Integer.parseInt(perms, 8));
        }
        listener.restoredResource(name);
        return deferredPermission;
    } catch (final Exception e) {
        final String message = String.format("Failed to restore resource '%s'\nfrom file '%s'.\nReason: %s", name, descriptor.getSymbolicPath(name, false), e.getMessage());
        listener.warn(message);
        LOG.error(message, e);
        return new SkippedEntryDeferredPermission();
    } finally {
        is.close();
    }
}
Also used : URIUtils(org.exist.xquery.util.URIUtils) Tuple2(com.evolvedbinary.j8fu.tuple.Tuple2) Txn(org.exist.storage.txn.Txn) java.util(java.util) URISyntaxException(java.net.URISyntaxException) ManagedCollectionLock(org.exist.storage.lock.ManagedCollectionLock) PermissionDeniedException(org.exist.security.PermissionDeniedException) Tuple(com.evolvedbinary.j8fu.tuple.Tuple.Tuple) XMLReader(org.xml.sax.XMLReader) ACLPermission(org.exist.security.ACLPermission) Namespaces(org.exist.Namespaces) RealmImpl(org.exist.security.internal.RealmImpl) Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI) Attributes(org.xml.sax.Attributes) DateTimeValue(org.exist.xquery.value.DateTimeValue) Lock(org.exist.storage.lock.Lock) Permission(org.exist.security.Permission) Nullable(javax.annotation.Nullable) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) RestoreListener(org.exist.backup.restore.listener.RestoreListener) LockedDocument(org.exist.dom.persistent.LockedDocument) UTF_8(java.nio.charset.StandardCharsets.UTF_8) IOException(java.io.IOException) TransactionException(org.exist.storage.txn.TransactionException) DocumentType(org.w3c.dom.DocumentType) DefaultHandler(org.xml.sax.helpers.DefaultHandler) SecurityManager(org.exist.security.SecurityManager) SAXParseException(org.xml.sax.SAXParseException) Logger(org.apache.logging.log4j.Logger) BackupDescriptor(org.exist.backup.BackupDescriptor) DBBroker(org.exist.storage.DBBroker) LockManager(org.exist.storage.lock.LockManager) SAXException(org.xml.sax.SAXException) org.exist.util(org.exist.util) DocumentTypeImpl(org.exist.dom.persistent.DocumentTypeImpl) TriggerException(org.exist.collections.triggers.TriggerException) LogManager(org.apache.logging.log4j.LogManager) BinaryDocument(org.exist.dom.persistent.BinaryDocument) XPathException(org.exist.xquery.XPathException) DateTimeValue(org.exist.xquery.value.DateTimeValue) XPathException(org.exist.xquery.XPathException) DocumentTypeImpl(org.exist.dom.persistent.DocumentTypeImpl) DocumentType(org.w3c.dom.DocumentType) URISyntaxException(java.net.URISyntaxException) Txn(org.exist.storage.txn.Txn) URISyntaxException(java.net.URISyntaxException) PermissionDeniedException(org.exist.security.PermissionDeniedException) IOException(java.io.IOException) TransactionException(org.exist.storage.txn.TransactionException) SAXParseException(org.xml.sax.SAXParseException) SAXException(org.xml.sax.SAXException) TriggerException(org.exist.collections.triggers.TriggerException) XPathException(org.exist.xquery.XPathException) SAXException(org.xml.sax.SAXException) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) Collection(org.exist.collections.Collection) Nullable(javax.annotation.Nullable) XmldbURI(org.exist.xmldb.XmldbURI)

Example 17 with ManagedDocumentLock

use of org.exist.storage.lock.ManagedDocumentLock in project exist by eXist-db.

the class STXTemplatesCache method getOrUpdateTemplate.

/**
 * Will get the compiled stylesheet from the cache.
 *
 * If the stylesheet is not present in the cache it will be compiled and added to the cache.
 * If the stylesheet is in the cache, but older than the current stylesheet it will be re-compiled and cached.
 *
 * @param broker Database broker for accessing the serializer pool
 * @param stylesheet The stylesheet document
 * @throws TransformerConfigurationException if there is an error in the transformations
 * @throws SAXException if a SAX error comes up
 * @throws LockException if dbbroker is locked
 *
 * @return The compiled stylesheet
 */
public Templates getOrUpdateTemplate(final DBBroker broker, final DocumentImpl stylesheet) throws TransformerConfigurationException, SAXException, LockException {
    try (final ManagedDocumentLock documentLock = broker.getBrokerPool().getLockManager().acquireDocumentReadLock(stylesheet.getURI())) {
        final XmldbURI stylesheetUri = stylesheet.getURI();
        final long lastModified = stylesheet.getLastModified();
        CachedTemplate cachedTemplate = cache.getIfPresent(stylesheetUri);
        if (cachedTemplate != null && lastModified > cachedTemplate.getLastUpdated()) {
            // template has been modified since the version in the cache
            // invalidate the cached template
            cachedTemplate = null;
            LOG.trace("Invalidating cached STX Template '{}' as it is outdated.", stylesheetUri.toString());
        } else {
            LOG.trace("Retrieved STX Template '{}' from cache.", stylesheetUri.toString());
        }
        if (cachedTemplate == null) {
            // compile and cache the template
            final Templates compiled = compileTemplate(broker, stylesheet);
            cachedTemplate = new CachedTemplate(compiled, lastModified);
            cache.put(stylesheetUri, cachedTemplate);
            LOG.trace("Compiled and cached STX Template '{}'.", stylesheetUri.toString());
        }
        return cachedTemplate.templates;
    }
}
Also used : ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) Templates(javax.xml.transform.Templates) XmldbURI(org.exist.xmldb.XmldbURI)

Example 18 with ManagedDocumentLock

use of org.exist.storage.lock.ManagedDocumentLock in project exist by eXist-db.

the class DefaultDocumentSet method lock.

@Override
public ManagedLocks<ManagedDocumentLock> lock(final DBBroker broker, final boolean exclusive) throws LockException {
    final LockManager lockManager = broker.getBrokerPool().getLockManager();
    final List<ManagedDocumentLock> managedDocumentLocks = new ArrayList<>();
    final Iterator<DocumentImpl> documentIterator = getDocumentIterator();
    try {
        while (documentIterator.hasNext()) {
            final DocumentImpl document = documentIterator.next();
            final ManagedDocumentLock managedDocumentLock;
            if (exclusive) {
                managedDocumentLock = lockManager.acquireDocumentWriteLock(document.getURI());
            } else {
                managedDocumentLock = lockManager.acquireDocumentReadLock(document.getURI());
            }
            managedDocumentLocks.add(managedDocumentLock);
        }
        return new ManagedLocks<>(managedDocumentLocks);
    } catch (final LockException e) {
        // unlock any previously locked documents
        if (!managedDocumentLocks.isEmpty()) {
            new ManagedLocks<>(managedDocumentLocks).close();
        }
        throw e;
    }
}
Also used : ManagedLocks(org.exist.collections.ManagedLocks) LockManager(org.exist.storage.lock.LockManager) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) LockException(org.exist.util.LockException)

Example 19 with ManagedDocumentLock

use of org.exist.storage.lock.ManagedDocumentLock in project exist by eXist-db.

the class ExtCollection method toSequence.

private Sequence toSequence(final DocumentSet docs) throws XPathException {
    final Sequence result = new ValueSequence();
    final LockManager lockManager = context.getBroker().getBrokerPool().getLockManager();
    for (final Iterator<DocumentImpl> i = docs.getDocumentIterator(); i.hasNext(); ) {
        final DocumentImpl doc = i.next();
        // filter out binary documents, fn:collection should only return XML documents
        if (doc.getResourceType() == DocumentImpl.XML_FILE) {
            ManagedDocumentLock dlock = null;
            try {
                if (!context.inProtectedMode()) {
                    dlock = lockManager.acquireDocumentReadLock(doc.getURI());
                }
                result.add(new NodeProxy(doc));
            } catch (final LockException e) {
                throw new XPathException(this, ErrorCodes.FODC0002, e);
            } finally {
                if (dlock != null) {
                    dlock.close();
                }
            }
        }
    }
    return result;
}
Also used : LockManager(org.exist.storage.lock.LockManager) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) LockException(org.exist.util.LockException)

Example 20 with ManagedDocumentLock

use of org.exist.storage.lock.ManagedDocumentLock in project exist by eXist-db.

the class InMemoryOutputStream method stream.

public void stream(final XmldbURL xmldbURL, final InputStream is, @Deprecated final int length) throws IOException {
    BrokerPool db;
    try {
        db = BrokerPool.getInstance();
    } catch (EXistException e) {
        throw new IOException(e);
    }
    try (final DBBroker broker = db.getBroker()) {
        final XmldbURI collectionUri = XmldbURI.create(xmldbURL.getCollection());
        final XmldbURI documentUri = XmldbURI.create(xmldbURL.getDocumentName());
        final TransactionManager transact = db.getTransactionManager();
        try (final Txn txn = transact.beginTransaction();
            final Collection collection = broker.getOrCreateCollection(txn, collectionUri)) {
            if (collection == null) {
                throw new IOException("Resource " + collectionUri.toString() + " is not a collection.");
            }
            final LockManager lockManager = db.getLockManager();
            txn.acquireCollectionLock(() -> lockManager.acquireCollectionWriteLock(collectionUri));
            if (collection.hasChildCollection(broker, documentUri)) {
                throw new IOException("Resource " + documentUri.toString() + " is a collection.");
            }
            try (final FilterInputStreamCache cache = FilterInputStreamCacheFactory.getCacheInstance(() -> (String) broker.getConfiguration().getProperty(Configuration.BINARY_CACHE_CLASS_PROPERTY), is);
                final CachingFilterInputStream cfis = new CachingFilterInputStream(cache)) {
                final MimeType mime = MimeTable.getInstance().getContentTypeFor(documentUri);
                try (final ManagedDocumentLock lock = lockManager.acquireDocumentWriteLock(documentUri)) {
                    broker.storeDocument(txn, documentUri, new CachingFilterInputStreamInputSource(cfis), mime, collection);
                }
            }
            txn.commit();
        }
    } catch (final IOException ex) {
        LOG.debug(ex);
        throw ex;
    } catch (final Exception ex) {
        LOG.debug(ex);
        throw new IOException(ex.getMessage(), ex);
    }
}
Also used : EXistException(org.exist.EXistException) IOException(java.io.IOException) Txn(org.exist.storage.txn.Txn) FilterInputStreamCache(org.exist.util.io.FilterInputStreamCache) CachingFilterInputStreamInputSource(org.exist.util.CachingFilterInputStreamInputSource) MimeType(org.exist.util.MimeType) IOException(java.io.IOException) EXistException(org.exist.EXistException) LockManager(org.exist.storage.lock.LockManager) DBBroker(org.exist.storage.DBBroker) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) TransactionManager(org.exist.storage.txn.TransactionManager) Collection(org.exist.collections.Collection) CachingFilterInputStream(org.exist.util.io.CachingFilterInputStream) BrokerPool(org.exist.storage.BrokerPool) XmldbURI(org.exist.xmldb.XmldbURI)

Aggregations

ManagedDocumentLock (org.exist.storage.lock.ManagedDocumentLock)23 LockManager (org.exist.storage.lock.LockManager)10 LockException (org.exist.util.LockException)7 EXistException (org.exist.EXistException)6 URISyntaxException (java.net.URISyntaxException)5 DocumentImpl (org.exist.dom.persistent.DocumentImpl)5 XmldbURI (org.exist.xmldb.XmldbURI)5 ManagedLocks (org.exist.collections.ManagedLocks)4 PermissionDeniedException (org.exist.security.PermissionDeniedException)4 DBBroker (org.exist.storage.DBBroker)4 Tuple2 (com.evolvedbinary.j8fu.tuple.Tuple2)3 Nullable (javax.annotation.Nullable)3 Collection (org.exist.collections.Collection)3 TriggerException (org.exist.collections.triggers.TriggerException)3 LockedDocument (org.exist.dom.persistent.LockedDocument)3 ACLPermission (org.exist.security.ACLPermission)3 Permission (org.exist.security.Permission)3 BrokerPool (org.exist.storage.BrokerPool)3 Lock (org.exist.storage.lock.Lock)3 ManagedCollectionLock (org.exist.storage.lock.ManagedCollectionLock)3