package org.dcache.srm.handler;
import org.apache.axis.types.UnsignedLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.dcache.srm.AbstractStorageElement;
import org.dcache.srm.SRM;
import org.dcache.srm.SRMException;
import org.dcache.srm.SRMInternalErrorException;
import org.dcache.srm.SRMInvalidRequestException;
import org.dcache.srm.SRMUser;
import org.dcache.srm.request.ReserveSpaceRequest;
import org.dcache.srm.scheduler.IllegalStateTransition;
import org.dcache.srm.util.Configuration;
import org.dcache.srm.v2_2.SrmReserveSpaceRequest;
import org.dcache.srm.v2_2.SrmReserveSpaceResponse;
import org.dcache.srm.v2_2.TAccessLatency;
import org.dcache.srm.v2_2.TRetentionPolicy;
import org.dcache.srm.v2_2.TRetentionPolicyInfo;
import org.dcache.srm.v2_2.TReturnStatus;
import org.dcache.srm.v2_2.TStatusCode;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.SECONDS;
public class SrmReserveSpace
{
private static final Logger LOGGER =
LoggerFactory.getLogger(SrmReserveSpace.class);
private final SrmReserveSpaceRequest request;
private final SRMUser user;
private final Configuration configuration;
private final String client_host;
private SrmReserveSpaceResponse response;
private final SRM srm;
public SrmReserveSpace(SRMUser user,
SrmReserveSpaceRequest request,
AbstractStorageElement storage,
SRM srm,
String clientHost)
{
this.request = checkNotNull(request);
this.user = checkNotNull(user);
this.configuration = checkNotNull(srm.getConfiguration());
this.client_host = checkNotNull(clientHost);
this.srm = checkNotNull(srm);
}
public SrmReserveSpaceResponse getResponse()
{
if (response == null) {
try {
response = reserveSpace();
} catch (SRMInternalErrorException e) {
LOGGER.error(e.toString());
response = getFailedResponse(e.getMessage(), TStatusCode.SRM_INTERNAL_ERROR);
} catch (SRMInvalidRequestException e) {
response = getFailedResponse(e.getMessage(), TStatusCode.SRM_INVALID_REQUEST);
} catch (SRMException e) {
response = getFailedResponse(e.getMessage(), TStatusCode.SRM_FAILURE);
}
}
return response;
}
private SrmReserveSpaceResponse reserveSpace()
throws SRMException
{
TRetentionPolicyInfo retentionPolicyInfo = request.getRetentionPolicyInfo();
if (retentionPolicyInfo == null) {
throw new SRMInvalidRequestException("retentionPolicyInfo is missing");
}
TRetentionPolicy retentionPolicy = retentionPolicyInfo.getRetentionPolicy();
if (retentionPolicy == null) {
throw new SRMInvalidRequestException("retentionPolicy is missing");
}
TAccessLatency accessLatency = retentionPolicyInfo.getAccessLatency();
UnsignedLong size = request.getDesiredSizeOfGuaranteedSpace();
String userSpaceTokenDescription = request.getUserSpaceTokenDescription();
long lifetime = getDesiredLifetimeOfReservedSpace(request, configuration.getDefaultSpaceLifetime());
long requestLifetime = getRequestLifetime(lifetime);
try {
ReserveSpaceRequest reserveRequest =
new ReserveSpaceRequest(
user,
requestLifetime,
configuration.getReserveSpaceMaxPollPeriod(),
size.longValue(),
lifetime,
retentionPolicy,
accessLatency,
userSpaceTokenDescription,
client_host);
reserveRequest.applyJdc();
srm.schedule(reserveRequest);
return reserveRequest.getSrmReserveSpaceResponse();
} catch (InterruptedException e) {
throw new SRMInternalErrorException("Operation interrupted");
} catch (IllegalStateTransition e) {
LOGGER.error("Failed to schedule srmReserveSpace: {}", e);
throw new SRMException("Failed to schedule operation");
}
}
private static long getRequestLifetime(long lifetime)
{
//make reserve request lifetime no longer than 24 hours
//request lifetime is different from space reservation lifetime
if (lifetime == -1 || lifetime > DAYS.toMillis(1)) {
return DAYS.toMillis(1);
} else {
return lifetime;
}
}
private static long getDesiredLifetimeOfReservedSpace(SrmReserveSpaceRequest request, long defaultLifetime)
throws SRMInvalidRequestException
{
Integer desiredLifetimeOfReservedSpace = request.getDesiredLifetimeOfReservedSpace();
long lifetime;
if (desiredLifetimeOfReservedSpace == null) {
lifetime = SECONDS.toMillis(defaultLifetime);
} else if (desiredLifetimeOfReservedSpace == -1) {
lifetime = -1;
} else if (desiredLifetimeOfReservedSpace > 0) {
lifetime = SECONDS.toMillis(desiredLifetimeOfReservedSpace);
} else {
throw new SRMInvalidRequestException("Invalid lifetime: " + desiredLifetimeOfReservedSpace);
}
return lifetime;
}
public static final SrmReserveSpaceResponse getFailedResponse(String text)
{
return getFailedResponse(text, TStatusCode.SRM_FAILURE);
}
public static final SrmReserveSpaceResponse getFailedResponse(String text, TStatusCode statusCode)
{
SrmReserveSpaceResponse response = new SrmReserveSpaceResponse();
response.setReturnStatus(new TReturnStatus(statusCode, text));
return response;
}
}