Search in sources :

Example 1 with Lock

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

the class LocalCollectionManagementService method moveResource.

@Override
public void moveResource(final XmldbURI src, final XmldbURI dest, final XmldbURI name) throws XMLDBException {
    final XmldbURI srcPath = resolve(src);
    final XmldbURI destPath = dest == null ? srcPath.removeLastSegment() : resolve(dest);
    final XmldbURI newName;
    if (name == null) {
        newName = srcPath.lastSegment();
    } else {
        newName = name;
    }
    withDb((broker, transaction) -> modify(broker, transaction, srcPath.removeLastSegment()).apply((sourceCol, b1, t1) -> {
        try (final LockedDocument lockedSource = sourceCol.getDocumentWithLock(b1, srcPath.lastSegment(), Lock.LockMode.WRITE_LOCK)) {
            final DocumentImpl source = lockedSource == null ? null : lockedSource.getDocument();
            if (source == null) {
                // NOTE: early release of Collection lock inline with Asymmetrical Locking scheme
                sourceCol.close();
                throw new XMLDBException(ErrorCodes.NO_SUCH_RESOURCE, "Resource " + srcPath + " not found");
            }
            return modify(b1, t1, destPath).apply((destinationCol, b2, t2) -> {
                try (final ManagedDocumentLock lockedDestination = b2.getBrokerPool().getLockManager().acquireDocumentWriteLock(destinationCol.getURI().append(newName))) {
                    b2.moveResource(t2, source, destinationCol, newName);
                    // NOTE: early release of Collection locks inline with Asymmetrical Locking scheme
                    destinationCol.close();
                    sourceCol.close();
                }
                return null;
            });
        }
    }));
}
Also used : XMLDBException(org.xmldb.api.base.XMLDBException) Tuple2(com.evolvedbinary.j8fu.tuple.Tuple2) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) LockedDocument(org.exist.dom.persistent.LockedDocument) BrokerPool(org.exist.storage.BrokerPool) Date(java.util.Date) URISyntaxException(java.net.URISyntaxException) ManagedCollectionLock(org.exist.storage.lock.ManagedCollectionLock) PreserveType(org.exist.storage.DBBroker.PreserveType) LockException(org.exist.util.LockException) Subject(org.exist.security.Subject) Optional(java.util.Optional) DocumentImpl(org.exist.dom.persistent.DocumentImpl) EXistException(org.exist.EXistException) TriggerException(org.exist.collections.triggers.TriggerException) ErrorCodes(org.xmldb.api.base.ErrorCodes) Lock(org.exist.storage.lock.Lock) Nullable(javax.annotation.Nullable) Collection(org.xmldb.api.base.Collection) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) LockedDocument(org.exist.dom.persistent.LockedDocument) XMLDBException(org.xmldb.api.base.XMLDBException) DocumentImpl(org.exist.dom.persistent.DocumentImpl)

Example 2 with Lock

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

the class FluentBrokerAPITest method collectionThenCollectionAndDoc.

@Test
public void collectionThenCollectionAndDoc() throws PermissionDeniedException, EXistException, LockException {
    final XmldbURI docUri = uri("all-test.xml");
    final long collectionCreated = 1234;
    final IMocksControl ctrl = createStrictControl();
    ctrl.checkOrder(true);
    final BrokerPool mockBrokerPool = ctrl.createMock(BrokerPool.class);
    final DBBroker mockBroker = ctrl.createMock(DBBroker.class);
    final Collection mockCollection = ctrl.createMock(Collection.class);
    final LockedDocument mockLockedDocument = ctrl.createMock(LockedDocument.class);
    final DocumentImpl mockDocument = ctrl.createMock(DocumentImpl.class);
    expect(mockBrokerPool.getBroker()).andReturn(mockBroker);
    expect(mockBroker.openCollection(TEST_COLLECTION_URI, READ_LOCK)).andReturn(mockCollection);
    expect(mockCollection.getCreated()).andReturn(collectionCreated);
    expect(mockCollection.getDocumentWithLock(mockBroker, docUri, READ_LOCK)).andReturn(mockLockedDocument);
    expect(mockLockedDocument.getDocument()).andReturn(mockDocument);
    expect(mockCollection.getURI()).andReturn(TEST_COLLECTION_URI);
    expect(mockDocument.getFileURI()).andReturn(docUri);
    // NOTE: checks that Collection lock is release before Document lock
    mockCollection.close();
    mockLockedDocument.close();
    mockBroker.close();
    ctrl.replay();
    final Function<Collection, Long> collectionOp = collection -> collection.getCreated();
    final BiFunction<Collection, DocumentImpl, String> collectionDocOp = (collection, doc) -> collection.getURI().append(doc.getFileURI()).toString();
    final Tuple2<Long, String> result = FluentBrokerAPI.builder(mockBrokerPool).withCollection(TEST_COLLECTION_URI, READ_LOCK).execute(collectionOp).withDocument(collection -> new Tuple2<>(docUri, READ_LOCK)).execute(collectionDocOp).doAll();
    assertEquals(collectionCreated, result._1.longValue());
    assertEquals(TEST_COLLECTION_URI.append(docUri), result._2);
    ctrl.verify();
}
Also used : Tuple3(com.evolvedbinary.j8fu.tuple.Tuple3) Tuple2(com.evolvedbinary.j8fu.tuple.Tuple2) IMocksControl(org.easymock.IMocksControl) LockMode(org.exist.storage.lock.Lock.LockMode) LockedDocument(org.exist.dom.persistent.LockedDocument) EasyMock.createStrictControl(org.easymock.EasyMock.createStrictControl) BiFunction(java.util.function.BiFunction) Test(org.junit.Test) PermissionDeniedException(org.exist.security.PermissionDeniedException) EasyMock.expect(org.easymock.EasyMock.expect) Function(java.util.function.Function) FluentBrokerAPI.uri(org.exist.storage.FluentBrokerAPI.uri) LockException(org.exist.util.LockException) Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI) DocumentImpl(org.exist.dom.persistent.DocumentImpl) EXistException(org.exist.EXistException) Lock(org.exist.storage.lock.Lock) Assert.assertEquals(org.junit.Assert.assertEquals) DocumentImpl(org.exist.dom.persistent.DocumentImpl) IMocksControl(org.easymock.IMocksControl) LockedDocument(org.exist.dom.persistent.LockedDocument) Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI) Test(org.junit.Test)

Example 3 with Lock

use of org.exist.storage.lock.Lock 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 4 with Lock

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

the class LocalCollectionManagementService method copyResource.

private void copyResource(final XmldbURI src, final XmldbURI dest, final XmldbURI name, final PreserveType preserve) throws XMLDBException {
    final XmldbURI srcPath = resolve(src);
    final XmldbURI destPath = dest == null ? srcPath.removeLastSegment() : resolve(dest);
    final XmldbURI newName;
    if (name == null) {
        newName = srcPath.lastSegment();
    } else {
        newName = name;
    }
    withDb((broker, transaction) -> read(broker, transaction, srcPath.removeLastSegment()).apply((sourceCol, b1, t1) -> {
        try (final LockedDocument lockedSource = sourceCol.getDocumentWithLock(b1, srcPath.lastSegment(), Lock.LockMode.READ_LOCK)) {
            final DocumentImpl source = lockedSource == null ? null : lockedSource.getDocument();
            if (source == null) {
                // NOTE: early release of Collection lock inline with Asymmetrical Locking scheme
                sourceCol.close();
                throw new XMLDBException(ErrorCodes.NO_SUCH_RESOURCE, "Resource " + srcPath + " not found");
            }
            return modify(b1, t1, destPath).apply((destinationCol, b2, t2) -> {
                try (final ManagedDocumentLock lockedDestination = b2.getBrokerPool().getLockManager().acquireDocumentWriteLock(destinationCol.getURI().append(newName))) {
                    try {
                        b2.copyResource(t2, source, destinationCol, newName, preserve);
                        // NOTE: early release of Collection locks inline with Asymmetrical Locking scheme
                        destinationCol.close();
                        sourceCol.close();
                        return null;
                    } catch (final EXistException e) {
                        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "failed to copy resource " + srcPath, e);
                    }
                }
            });
        }
    }));
}
Also used : XMLDBException(org.xmldb.api.base.XMLDBException) Tuple2(com.evolvedbinary.j8fu.tuple.Tuple2) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) LockedDocument(org.exist.dom.persistent.LockedDocument) BrokerPool(org.exist.storage.BrokerPool) Date(java.util.Date) URISyntaxException(java.net.URISyntaxException) ManagedCollectionLock(org.exist.storage.lock.ManagedCollectionLock) PreserveType(org.exist.storage.DBBroker.PreserveType) LockException(org.exist.util.LockException) Subject(org.exist.security.Subject) Optional(java.util.Optional) DocumentImpl(org.exist.dom.persistent.DocumentImpl) EXistException(org.exist.EXistException) TriggerException(org.exist.collections.triggers.TriggerException) ErrorCodes(org.xmldb.api.base.ErrorCodes) Lock(org.exist.storage.lock.Lock) Nullable(javax.annotation.Nullable) Collection(org.xmldb.api.base.Collection) ManagedDocumentLock(org.exist.storage.lock.ManagedDocumentLock) LockedDocument(org.exist.dom.persistent.LockedDocument) XMLDBException(org.xmldb.api.base.XMLDBException) EXistException(org.exist.EXistException) DocumentImpl(org.exist.dom.persistent.DocumentImpl)

Example 5 with Lock

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

the class FluentBrokerAPITest method all.

@Test
public void all() throws PermissionDeniedException, EXistException, LockException {
    final XmldbURI docUri = uri("all-test.xml");
    final long collectionCreated = 1234;
    final long docLastModified = 5678;
    final IMocksControl ctrl = createStrictControl();
    ctrl.checkOrder(true);
    final BrokerPool mockBrokerPool = ctrl.createMock(BrokerPool.class);
    final DBBroker mockBroker = ctrl.createMock(DBBroker.class);
    final Collection mockCollection = ctrl.createMock(Collection.class);
    final LockedDocument mockLockedDocument = ctrl.createMock(LockedDocument.class);
    final DocumentImpl mockDocument = ctrl.createMock(DocumentImpl.class);
    expect(mockBrokerPool.getBroker()).andReturn(mockBroker);
    expect(mockBroker.openCollection(TEST_COLLECTION_URI, READ_LOCK)).andReturn(mockCollection);
    expect(mockCollection.getCreated()).andReturn(collectionCreated);
    expect(mockCollection.getDocumentWithLock(mockBroker, docUri, READ_LOCK)).andReturn(mockLockedDocument);
    expect(mockLockedDocument.getDocument()).andReturn(mockDocument);
    expect(mockCollection.getURI()).andReturn(TEST_COLLECTION_URI);
    expect(mockDocument.getFileURI()).andReturn(docUri);
    // NOTE: checks that Collection lock is release before Document lock
    mockCollection.close();
    expect(mockDocument.getLastModified()).andReturn(docLastModified);
    mockLockedDocument.close();
    mockBroker.close();
    ctrl.replay();
    final Function<Collection, Long> collectionOp = collection -> collection.getCreated();
    final BiFunction<Collection, DocumentImpl, String> collectionDocOp = (collection, doc) -> collection.getURI().append(doc.getFileURI()).toString();
    final Function<DocumentImpl, Long> documentOp = document -> document.getLastModified();
    final Tuple3<Long, String, Long> result = FluentBrokerAPI.builder(mockBrokerPool).withCollection(TEST_COLLECTION_URI, READ_LOCK).execute(collectionOp).withDocument(collection -> new Tuple2<>(docUri, READ_LOCK)).execute(collectionDocOp).withoutCollection().execute(documentOp).doAll();
    assertEquals(collectionCreated, result._1.longValue());
    assertEquals(TEST_COLLECTION_URI.append(docUri), result._2);
    assertEquals(docLastModified, result._3.longValue());
    ctrl.verify();
}
Also used : Tuple3(com.evolvedbinary.j8fu.tuple.Tuple3) Tuple2(com.evolvedbinary.j8fu.tuple.Tuple2) IMocksControl(org.easymock.IMocksControl) LockMode(org.exist.storage.lock.Lock.LockMode) LockedDocument(org.exist.dom.persistent.LockedDocument) EasyMock.createStrictControl(org.easymock.EasyMock.createStrictControl) BiFunction(java.util.function.BiFunction) Test(org.junit.Test) PermissionDeniedException(org.exist.security.PermissionDeniedException) EasyMock.expect(org.easymock.EasyMock.expect) Function(java.util.function.Function) FluentBrokerAPI.uri(org.exist.storage.FluentBrokerAPI.uri) LockException(org.exist.util.LockException) Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI) DocumentImpl(org.exist.dom.persistent.DocumentImpl) EXistException(org.exist.EXistException) Lock(org.exist.storage.lock.Lock) Assert.assertEquals(org.junit.Assert.assertEquals) DocumentImpl(org.exist.dom.persistent.DocumentImpl) IMocksControl(org.easymock.IMocksControl) LockedDocument(org.exist.dom.persistent.LockedDocument) Collection(org.exist.collections.Collection) XmldbURI(org.exist.xmldb.XmldbURI) Test(org.junit.Test)

Aggregations

Tuple2 (com.evolvedbinary.j8fu.tuple.Tuple2)9 LockedDocument (org.exist.dom.persistent.LockedDocument)9 Lock (org.exist.storage.lock.Lock)9 EXistException (org.exist.EXistException)8 DocumentImpl (org.exist.dom.persistent.DocumentImpl)8 LockException (org.exist.util.LockException)8 Collection (org.exist.collections.Collection)7 PermissionDeniedException (org.exist.security.PermissionDeniedException)7 XmldbURI (org.exist.xmldb.XmldbURI)7 Tuple3 (com.evolvedbinary.j8fu.tuple.Tuple3)6 BiFunction (java.util.function.BiFunction)6 Function (java.util.function.Function)6 EasyMock.createStrictControl (org.easymock.EasyMock.createStrictControl)6 EasyMock.expect (org.easymock.EasyMock.expect)6 IMocksControl (org.easymock.IMocksControl)6 FluentBrokerAPI.uri (org.exist.storage.FluentBrokerAPI.uri)6 LockMode (org.exist.storage.lock.Lock.LockMode)6 Assert.assertEquals (org.junit.Assert.assertEquals)6 Test (org.junit.Test)6 URISyntaxException (java.net.URISyntaxException)3