package org.dcache.srm.handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import org.dcache.srm.AbstractStorageElement;
import org.dcache.srm.SRM;
import org.dcache.srm.SRMAuthorizationException;
import org.dcache.srm.SRMDuplicationException;
import org.dcache.srm.SRMException;
import org.dcache.srm.SRMInternalErrorException;
import org.dcache.srm.SRMInvalidPathException;
import org.dcache.srm.SRMUser;
import org.dcache.srm.v2_2.SrmMvRequest;
import org.dcache.srm.v2_2.SrmMvResponse;
import org.dcache.srm.v2_2.TReturnStatus;
import org.dcache.srm.v2_2.TStatusCode;
import static com.google.common.base.Preconditions.checkNotNull;
public class SrmMv
{
private static final Logger LOGGER =
LoggerFactory.getLogger(SrmMv.class);
private final AbstractStorageElement storage;
private final SrmMvRequest request;
private final SRMUser user;
private final SRM srm;
private SrmMvResponse response;
public SrmMv(SRMUser user,
SrmMvRequest request,
AbstractStorageElement storage,
SRM srm,
String clientHost)
{
this.request = checkNotNull(request);
this.user = checkNotNull(user);
this.storage = checkNotNull(storage);
this.srm = checkNotNull(srm);
}
public SrmMvResponse getResponse()
{
if (response == null) {
response = srmMv();
}
return response;
}
private SrmMvResponse srmMv()
{
TReturnStatus returnStatus;
try {
URI to_surl = URI.create(request.getToSURL().toString());
URI from_surl = URI.create(request.getFromSURL().toString());
// [SRM 2.2, 4.6.3] SRM_INVALID_PATH: status of fromSURL is SRM_FILE_BUSY.
// [SRM 2.2, 4.6.2, c)] srmMv must fail on SURL that its status is SRM_FILE_BUSY,
// and SRM_FILE_BUSY must be returned.
// [SRM 2.2, 4.6.2, e)] When moving an SURL to already existing SURL,
// SRM_DUPLICATION_ERROR must be returned.
//
// The SRM spec is somewhat inconsistent on what the correct return code should be.
// Instead we use SRM_DUPLICATION_ERROR if the target SURL is busy (consistent with
// how this situation is handled in srmPrepareToPut) and SRM_FILE_BUSY if the source
// SURL is busy.
if (srm.isFileBusy(from_surl)) {
returnStatus = new TReturnStatus(TStatusCode.SRM_FILE_BUSY,
"The source SURL is being used by another client.");
} else if (srm.isFileBusy(to_surl)) {
returnStatus = new TReturnStatus(TStatusCode.SRM_DUPLICATION_ERROR,
"The target SURL is being used by another client.");
} else {
storage.moveEntry(user, from_surl, to_surl);
returnStatus = new TReturnStatus(TStatusCode.SRM_SUCCESS, null);
}
} catch (SRMDuplicationException e) {
returnStatus = new TReturnStatus(TStatusCode.SRM_DUPLICATION_ERROR, e.getMessage());
} catch (SRMInternalErrorException e) {
LOGGER.error(e.toString());
returnStatus = new TReturnStatus(TStatusCode.SRM_INTERNAL_ERROR, e.getMessage());
} catch (SRMInvalidPathException e) {
returnStatus = new TReturnStatus(TStatusCode.SRM_INVALID_PATH, e.getMessage());
} catch (SRMAuthorizationException e) {
LOGGER.warn(e.toString());
returnStatus = new TReturnStatus(TStatusCode.SRM_AUTHORIZATION_FAILURE, e.getMessage());
} catch (SRMException e) {
LOGGER.error(e.toString());
returnStatus = new TReturnStatus(TStatusCode.SRM_FAILURE, e.getMessage());
}
return new SrmMvResponse(returnStatus);
}
public static final SrmMvResponse getFailedResponse(String error)
{
return getFailedResponse(error, TStatusCode.SRM_FAILURE);
}
public static final SrmMvResponse getFailedResponse(String error, TStatusCode statusCode)
{
SrmMvResponse response = new SrmMvResponse();
response.setReturnStatus(new TReturnStatus(statusCode, error));
return response;
}
}