package org.dcache.srm.handler;
import com.google.common.base.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.util.Arrays;
import org.dcache.srm.AbstractStorageElement;
import org.dcache.srm.SRM;
import org.dcache.srm.SRMInternalErrorException;
import org.dcache.srm.SRMInvalidRequestException;
import org.dcache.srm.SRMNotSupportedException;
import org.dcache.srm.SRMUser;
import org.dcache.srm.request.GetRequest;
import org.dcache.srm.scheduler.IllegalStateTransition;
import org.dcache.srm.util.Configuration;
import org.dcache.srm.util.JDC;
import org.dcache.srm.util.Lifetimes;
import org.dcache.srm.util.Tools;
import org.dcache.srm.v2_2.ArrayOfTExtraInfo;
import org.dcache.srm.v2_2.SrmPrepareToGetRequest;
import org.dcache.srm.v2_2.SrmPrepareToGetResponse;
import org.dcache.srm.v2_2.TExtraInfo;
import org.dcache.srm.v2_2.TGetFileRequest;
import org.dcache.srm.v2_2.TReturnStatus;
import org.dcache.srm.v2_2.TStatusCode;
import org.dcache.srm.v2_2.TTransferParameters;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.in;
import static com.google.common.collect.Iterables.any;
import static java.util.Arrays.asList;
public class SrmPrepareToGet
{
private static final Logger LOGGER =
LoggerFactory.getLogger(SrmPrepareToGet.class);
private final AbstractStorageElement storage;
private final SrmPrepareToGetRequest request;
private final SRMUser user;
private final SRM srm;
private final Configuration configuration;
private final String clientHost;
private SrmPrepareToGetResponse response;
public SrmPrepareToGet(SRMUser user,
SrmPrepareToGetRequest request,
AbstractStorageElement storage,
SRM srm,
String clientHost)
{
this.request = checkNotNull(request);
this.user = checkNotNull(user);
this.clientHost = clientHost;
this.storage = checkNotNull(storage);
this.configuration = checkNotNull(srm.getConfiguration());
this.srm = checkNotNull(srm);
}
public SrmPrepareToGetResponse getResponse()
{
if (response == null) {
try {
response = srmPrepareToGet();
} catch (SRMNotSupportedException e) {
response = getFailedResponse(e.getMessage(), TStatusCode.SRM_NOT_SUPPORTED);
} catch (SRMInvalidRequestException e) {
response = getFailedResponse(e.getMessage(), TStatusCode.SRM_INVALID_REQUEST);
} catch (SRMInternalErrorException e) {
LOGGER.error(e.getMessage());
response = getFailedResponse(e.getMessage(), TStatusCode.SRM_INTERNAL_ERROR);
} catch (InterruptedException e) {
LOGGER.error(e.toString());
response = getFailedResponse("Operation interrupted", TStatusCode.SRM_INTERNAL_ERROR);
} catch (IllegalStateTransition e) {
LOGGER.error(e.toString());
response = getFailedResponse("Scheduling failed", TStatusCode.SRM_INTERNAL_ERROR);
}
}
return response;
}
private SrmPrepareToGetResponse srmPrepareToGet()
throws IllegalStateTransition, InterruptedException, SRMInvalidRequestException, SRMNotSupportedException,
SRMInternalErrorException
{
String[] protocols = getTransferProtocols(request);
String clientHost = getClientHost(request).or(this.clientHost);
long lifetime = Lifetimes.calculateLifetime(request.getDesiredTotalRequestTime(), configuration.getGetLifetime());
String[] supportedProtocols = storage.supportedGetProtocols();
URI[] surls = getSurls(request);
if (protocols != null && protocols.length > 0) {
boolean isAnyProtocolSupported = any(asList(protocols), in(asList(supportedProtocols)));
if (!isAnyProtocolSupported) {
throw new SRMNotSupportedException("Protocol(s) not supported: " + Arrays.toString(protocols));
}
}
GetRequest r =
new GetRequest(
user,
surls,
protocols,
lifetime,
configuration.getGetMaxPollPeriod(),
request.getUserRequestDescription(),
clientHost);
try (JDC ignored = r.applyJdc()) {
srm.schedule(r);
return r.getSrmPrepareToGetResponse(configuration.getGetSwitchToAsynchronousModeDelay());
}
}
private static URI[] getSurls(SrmPrepareToGetRequest request)
throws SRMInvalidRequestException
{
TGetFileRequest[] fileRequests = getFileRequests(request);
URI[] surls = new URI[fileRequests.length];
for (int i = 0; i < fileRequests.length; ++i) {
TGetFileRequest nextRequest = fileRequests[i];
if (nextRequest == null) {
throw new SRMInvalidRequestException("file request #" + (i + 1) + " is null");
}
if (nextRequest.getSourceSURL() == null) {
throw new SRMInvalidRequestException("can't get surl of file request #" + (i + 1) + " null");
}
surls[i] = URI.create(nextRequest.getSourceSURL().toString());
}
return surls;
}
private static TGetFileRequest[] getFileRequests(SrmPrepareToGetRequest request)
throws SRMInvalidRequestException
{
TGetFileRequest[] fileRequests = request.getArrayOfFileRequests().getRequestArray();
if (fileRequests == null || fileRequests.length <= 0) {
throw new SRMInvalidRequestException("arrayOfFileRequest is empty");
}
return fileRequests;
}
private static Optional<String> getClientHost(SrmPrepareToGetRequest request)
{
TTransferParameters transferParameters = request.getTransferParameters();
if (transferParameters != null && transferParameters.getArrayOfClientNetworks() != null) {
String[] clientNetworks = transferParameters.getArrayOfClientNetworks().getStringArray();
if (clientNetworks != null && clientNetworks.length > 0 && clientNetworks[0] != null) {
return Optional.of(clientNetworks[0]);
}
}
return Optional.absent();
}
private static String[] getTransferProtocols(SrmPrepareToGetRequest request)
throws SRMInvalidRequestException
{
TTransferParameters transferParameters = request.getTransferParameters();
if (transferParameters != null && transferParameters.getArrayOfTransferProtocols() != null) {
String[] protocols = transferParameters.getArrayOfTransferProtocols().getStringArray();
protocols = Tools.trimStringArray(protocols);
if (protocols != null && protocols.length > 0) {
return protocols;
}
}
throw new SRMInvalidRequestException("request contains no transfer protocols");
}
public static final SrmPrepareToGetResponse getFailedResponse(String error)
{
return getFailedResponse(error, TStatusCode.SRM_FAILURE);
}
public static final SrmPrepareToGetResponse getFailedResponse(String error, TStatusCode statusCode)
{
SrmPrepareToGetResponse srmPrepareToGetResponse = new SrmPrepareToGetResponse();
srmPrepareToGetResponse.setReturnStatus(new TReturnStatus(statusCode, error));
return srmPrepareToGetResponse;
}
}