Skip to content

Commit

Permalink
Implements isOpen() / close() methods on RemoteCollection
Browse files Browse the repository at this point in the history
  • Loading branch information
reinhapa committed Dec 6, 2019
1 parent d63f2c8 commit 0fa83f3
Show file tree
Hide file tree
Showing 17 changed files with 690 additions and 927 deletions.
54 changes: 37 additions & 17 deletions exist-core/src/main/java/org/exist/util/Leasable.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import net.jcip.annotations.ThreadSafe;

import javax.annotation.Nullable;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;

Expand Down Expand Up @@ -135,17 +136,30 @@ public boolean isLeased() {
}
}

public boolean isClosed() {
lock.readLock().lock();
try {
return Leasable.this.closed;
} finally {
lock.readLock().unlock();
}
}

/**
* Represents a lease of the leasable object.
*/
public class Lease implements AutoCloseable {
private final AtomicBoolean leaseClosed = new AtomicBoolean();

/**
* Access to the leased object.
*
* @return the leased object.
*/
public T get() {
if (leaseClosed.get()) {
throw new IllegalLeasableState("Lease is closed");
}
lock.readLock().lock();
try {
if (closed) {
Expand All @@ -167,26 +181,32 @@ public T get() {
*/
@Override
public void close() {
lock.writeLock().lock();
try {
if (closed) {
throw new IllegalLeasableState("Object is closed");
}

if(leases == 0) {
throw new IllegalLeasableState("Lease was already returned");
}

leases--;

if (leases == 0 && closer != null) {
closer.accept(object);
closed = true;
if (leaseClosed.compareAndSet(false, true)) {
lock.writeLock().lock();
try {
if (Leasable.this.closed) {
throw new IllegalLeasableState("Object is closed");
}

if(leases == 0) {
throw new IllegalLeasableState("Lease was already returned");
}

leases--;

if (leases == 0 && closer != null) {
closer.accept(object);
Leasable.this.closed = true;
}
} finally {
lock.writeLock().unlock();
}
} finally {
lock.writeLock().unlock();
}
}

public boolean isClosed() {
return leaseClosed.get();
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import java.util.zip.Inflater;

import com.evolvedbinary.j8fu.lazy.LazyVal;
import org.apache.xmlrpc.XmlRpcException;

import org.apache.xmlrpc.client.XmlRpcClient;
import org.exist.security.Permission;
Expand All @@ -52,7 +51,6 @@

public abstract class AbstractRemoteResource extends AbstractRemote
implements EXistResource, ExtendedResource, Resource {
protected final Leasable<XmlRpcClient>.Lease xmlRpcClientLease;
protected final XmldbURI path;
private String mimeType;

Expand All @@ -67,9 +65,8 @@ public abstract class AbstractRemoteResource extends AbstractRemote
Date dateCreated = null;
Date dateModified = null;

protected AbstractRemoteResource(final Leasable<XmlRpcClient>.Lease xmlRpcClientLease, final RemoteCollection parent, final XmldbURI documentName, final String mimeType) {
protected AbstractRemoteResource(final RemoteCollection parent, final XmldbURI documentName, final String mimeType) {
super(parent);
this.xmlRpcClientLease = xmlRpcClientLease;
if (documentName.numSegments() > 1) {
this.path = documentName;
} else {
Expand Down Expand Up @@ -162,11 +159,7 @@ public void setLastModificationTime(final Date dateModified) throws XMLDBExcepti
params.add(path.toString());
params.add(dateModified.getTime());

try {
xmlRpcClientLease.get().execute("setLastModified", params);
} catch (final XmlRpcException e) {
throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, e.getMessage(), e);
}
collection.execute("setLastModified", params);

this.dateModified = dateModified;
}
Expand Down Expand Up @@ -282,7 +275,7 @@ protected void getRemoteContentIntoLocalFile(final OutputStream os, final boolea
final TemporaryFileManager tempFileManager = TemporaryFileManager.getInstance();
final VirtualTempPath tempFile = new VirtualTempPath(getInMemorySize(properties), tempFileManager);

Map<?, ?> table = (Map<?, ?>) xmlRpcClientLease.get().execute(command, params);
Map<?, ?> table = (Map<?, ?>) collection.execute(command, params);

final String method;
final boolean useLongOffset;
Expand Down Expand Up @@ -329,7 +322,7 @@ protected void getRemoteContentIntoLocalFile(final OutputStream os, final boolea
params.clear();
params.add(table.get("handle"));
params.add(useLongOffset ? Long.toString(offset) : Integer.valueOf((int) offset));
table = (Map<?, ?>) xmlRpcClientLease.get().execute(method, params);
table = (Map<?, ?>) collection.execute(method, params);
offset = useLongOffset ? Long.parseLong((String) table.get("offset")) : ((Integer) table.get("offset"));
data = (byte[]) table.get("data");

Expand Down Expand Up @@ -359,8 +352,6 @@ protected void getRemoteContentIntoLocalFile(final OutputStream os, final boolea
}

contentFile = tempFile;
} catch (final XmlRpcException xre) {
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, xre.getMessage(), xre);
} catch (final IOException | DataFormatException e) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
}
Expand Down Expand Up @@ -493,20 +484,16 @@ protected long getStreamLengthInternal(final Object obj)
final List<Object> params = new ArrayList<>();
params.add(path.toString());
params.add(getProperties());
try {
final Map<?, ?> table = (Map<?, ?>) xmlRpcClientLease.get().execute("describeResource", params);
if (table.containsKey("content-length-64bit")) {
final Object o = table.get("content-length-64bit");
if (o instanceof Long) {
retval = ((Long) o);
} else {
retval = Long.parseLong((String) o);
}
final Map<?, ?> table = (Map<?, ?>) collection.execute("describeResource", params);
if (table.containsKey("content-length-64bit")) {
final Object o = table.get("content-length-64bit");
if (o instanceof Long) {
retval = ((Long) o);
} else {
retval = ((Integer) table.get("content-length"));
retval = Long.parseLong((String) o);
}
} catch (final XmlRpcException xre) {
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, xre.getMessage(), xre);
} else {
retval = ((Integer) table.get("content-length"));
}
}

Expand Down Expand Up @@ -567,7 +554,6 @@ public final void close() {
contentFile.close();
contentFile = null;
}
xmlRpcClientLease.close();
} finally {
closed = true;
}
Expand Down
28 changes: 12 additions & 16 deletions exist-core/src/main/java/org/exist/xmldb/RemoteBinaryResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ public class RemoteBinaryResource
private BlobId blobId = null;
private MessageDigest contentDigest = null;

public RemoteBinaryResource(final Leasable<XmlRpcClient>.Lease xmlRpcClientLease, final RemoteCollection parent, final XmldbURI documentName) throws XMLDBException {
super(xmlRpcClientLease, parent, documentName, MimeType.BINARY_TYPE.getName());
public RemoteBinaryResource(final RemoteCollection parent, final XmldbURI documentName) throws XMLDBException {
super(parent, documentName, MimeType.BINARY_TYPE.getName());
}

public RemoteBinaryResource(final Leasable<XmlRpcClient>.Lease xmlRpcClientLease, final RemoteCollection parent, final XmldbURI documentName, final String type, final byte[] content) throws XMLDBException {
super(xmlRpcClientLease, parent, documentName, MimeType.BINARY_TYPE.getName());
public RemoteBinaryResource(final RemoteCollection parent, final XmldbURI documentName, final String type, final byte[] content) throws XMLDBException {
super(parent, documentName, MimeType.BINARY_TYPE.getName());
this.type = type;
this.content = content;
}
Expand Down Expand Up @@ -149,20 +149,16 @@ public MessageDigest getContentDigest(final DigestType digestType) throws XMLDBE
params.add(path.toString());
params.add(digestType.getCommonNames()[0]);

try {
final Map result = (Map) xmlRpcClientLease.get().execute("getContentDigest", params);
final String digestAlgorithm = (String)result.get("digest-algorithm");
final byte[] digest = (byte[])result.get("digest");
final Map result = (Map) collection.execute("getContentDigest", params);
final String digestAlgorithm = (String)result.get("digest-algorithm");
final byte[] digest = (byte[])result.get("digest");

final MessageDigest messageDigest = new MessageDigest(DigestType.forCommonName(digestAlgorithm), digest);
if (this.contentDigest == null) {
this.contentDigest = messageDigest;
}
return messageDigest;

} catch (final XmlRpcException xre) {
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, xre.getMessage(), xre);
final MessageDigest messageDigest = new MessageDigest(DigestType.forCommonName(digestAlgorithm), digest);
if (this.contentDigest == null) {
this.contentDigest = messageDigest;
}
return messageDigest;

}

public void setContentDigest(final MessageDigest contentDigest) {
Expand Down
41 changes: 41 additions & 0 deletions exist-core/src/main/java/org/exist/xmldb/RemoteCallSite.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* eXist Open Source Native XML Database
* Copyright (C) 2019 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.exist.xmldb;

import org.xmldb.api.base.XMLDBException;

import java.util.List;

/**
* Represents a remote method call site.
*/
@FunctionalInterface
public interface RemoteCallSite {
/**
* Executes the given {@code methodName} with the given {@code parameters} and returns the result. In case of
* an error a {@link XMLDBException} will be thrown.
*
* @param methodName the method name to be invoked
* @param parameters the list of method arguments
* @return the result of the method
* @throws XMLDBException in case of the invocation fails
*/
Object execute(String methodName, List<Object> parameters) throws XMLDBException;
}
Loading

0 comments on commit 0fa83f3

Please sign in to comment.