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();
}
}
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;
}
}
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;
}
}
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;
}
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);
}
}
Aggregations