package org.dcache.srm.handler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.DataAccessException; import java.net.URI; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.dcache.srm.AbstractStorageElement; import org.dcache.srm.SRM; import org.dcache.srm.SRMInternalErrorException; import org.dcache.srm.SRMInvalidRequestException; import org.dcache.srm.SRMUser; import org.dcache.srm.request.BringOnlineFileRequest; import org.dcache.srm.request.BringOnlineRequest; import org.dcache.srm.request.ContainerRequest; import org.dcache.srm.request.GetFileRequest; import org.dcache.srm.request.GetRequest; import org.dcache.srm.request.Request; import org.dcache.srm.util.JDC; import org.dcache.srm.v2_2.ArrayOfAnyURI; import org.dcache.srm.v2_2.ArrayOfTSURLReturnStatus; import org.dcache.srm.v2_2.SrmReleaseFilesRequest; import org.dcache.srm.v2_2.SrmReleaseFilesResponse; import org.dcache.srm.v2_2.TReturnStatus; import org.dcache.srm.v2_2.TSURLReturnStatus; import org.dcache.srm.v2_2.TStatusCode; import static java.util.Arrays.asList; import static org.dcache.srm.handler.ReturnStatuses.getSummaryReturnStatus; public class SrmReleaseFiles { private static final Logger LOGGER = LoggerFactory.getLogger(SrmReleaseFiles.class); private final AbstractStorageElement storage; private final SrmReleaseFilesRequest srmReleaseFilesRequest; private final SRMUser user; private SrmReleaseFilesResponse response; public SrmReleaseFiles(SRMUser user, SrmReleaseFilesRequest srmReleaseFilesRequest, AbstractStorageElement storage, SRM srm, String clientHost) { this.srmReleaseFilesRequest = srmReleaseFilesRequest; this.user = user; this.storage = storage; } public SrmReleaseFilesResponse getResponse() { if (response == null) { try { response = srmReleaseFiles(); } catch (DataAccessException e) { LOGGER.error(e.toString()); response = getFailedResponse("Internal database error, please try again.", TStatusCode.SRM_INTERNAL_ERROR); } catch (SRMInvalidRequestException e) { response = getFailedResponse(e.getMessage(), TStatusCode.SRM_INVALID_REQUEST); } catch (SRMInternalErrorException e) { LOGGER.error(e.toString()); response = getFailedResponse(e.getMessage(), TStatusCode.SRM_INTERNAL_ERROR); } } return response; } private SrmReleaseFilesResponse srmReleaseFiles() throws DataAccessException, SRMInvalidRequestException, SRMInternalErrorException { ArrayOfAnyURI arrayOfSURLs = srmReleaseFilesRequest.getArrayOfSURLs(); org.apache.axis.types.URI[] surls; if (arrayOfSURLs != null) { surls = arrayOfSURLs.getUrlArray(); } else { surls = null; } if (surls != null && surls.length == 0) { throw new SRMInvalidRequestException("Request contains no SURL"); } String requestToken = srmReleaseFilesRequest.getRequestToken(); if (requestToken == null) { if (surls == null) { throw new SRMInvalidRequestException("Request contains no SURL"); } return releaseBySURLs(surls); } ContainerRequest<?> requestToRelease; try { requestToRelease = Request.getRequest(requestToken, ContainerRequest.class); } catch (SRMInvalidRequestException e) { return unpinBySURLAndRequestToken(requestToken, surls); } try (JDC ignored = requestToRelease.applyJdc()) { TSURLReturnStatus[] surlReturnStatuses; if (requestToRelease instanceof GetRequest) { GetRequest getRequest = (GetRequest) requestToRelease; if (surls == null) { surlReturnStatuses = getRequest.release(); } else { surlReturnStatuses = getRequest.releaseFiles(surls); } getRequest.updateStatus(); } else if (requestToRelease instanceof BringOnlineRequest) { BringOnlineRequest bringOnlineRequest = (BringOnlineRequest) requestToRelease; if (surls == null) { surlReturnStatuses = bringOnlineRequest.release(); } else { surlReturnStatuses = bringOnlineRequest.releaseFiles(surls); } bringOnlineRequest.updateStatus(); } else { throw new SRMInvalidRequestException("No such get or bring online request: " + requestToken); } return new SrmReleaseFilesResponse( getSummaryReturnStatus(surlReturnStatuses), new ArrayOfTSURLReturnStatus(surlReturnStatuses)); } } private SrmReleaseFilesResponse unpinBySURLAndRequestToken(String requestToken, org.apache.axis.types.URI[] surls) throws SRMInternalErrorException { TSURLReturnStatus[] surlReturnStatusArray = new TSURLReturnStatus[surls.length]; for (int i = 0; i < surls.length; ++i) { org.apache.axis.types.URI surl = surls[i]; TReturnStatus returnStatus = BringOnlineFileRequest.unpinBySURLandRequestToken( storage, user, requestToken, URI.create(surl.toString())); surlReturnStatusArray[i] = new TSURLReturnStatus(surl, returnStatus); } return new SrmReleaseFilesResponse( getSummaryReturnStatus(surlReturnStatusArray), new ArrayOfTSURLReturnStatus(surlReturnStatusArray)); } private SrmReleaseFilesResponse releaseBySURLs(org.apache.axis.types.URI[] surls) throws DataAccessException, SRMInternalErrorException, SRMInvalidRequestException { URI[] uris = toUris(surls); Map<URI, TReturnStatus> returnStatuses = new HashMap<>(); releaseFileRequestsBySURLs(uris, returnStatuses); unpinBySURLs(uris, returnStatuses); TSURLReturnStatus[] surlReturnStatusArray = toTSURLReturnStatus(surls, returnStatuses); return new SrmReleaseFilesResponse( getSummaryReturnStatus(surlReturnStatusArray), new ArrayOfTSURLReturnStatus(surlReturnStatusArray)); } private void unpinBySURLs(URI[] surls, Map<URI, TReturnStatus> surlsMap) { for (URI surl : surls) { try { BringOnlineFileRequest.unpinBySURL(storage, user, surl); surlsMap.put(surl, new TReturnStatus(TStatusCode.SRM_SUCCESS, "released")); } catch (Exception e) { LOGGER.warn(e.toString()); TReturnStatus existingStatus = surlsMap.get(surl); if (existingStatus == null || existingStatus.getStatusCode().equals(TStatusCode.SRM_SUCCESS)) { surlsMap.put(surl, new TReturnStatus(TStatusCode.SRM_FAILURE, "release failed: " + e)); } } } } private static void releaseFileRequestsBySURLs(URI[] surls, Map<URI, TReturnStatus> returnStatuses) throws DataAccessException, SRMInvalidRequestException, SRMInternalErrorException { for (BringOnlineFileRequest fileRequest : findBringOnlineFileRequestBySURLs(surls)) { TReturnStatus returnStatus = fileRequest.release(fileRequest.getContainerRequest().getUser()); URI surl = fileRequest.getSurl(); TReturnStatus existingStatus = returnStatuses.get(surl); if (existingStatus == null || existingStatus.getStatusCode().equals(TStatusCode.SRM_SUCCESS)) { returnStatuses.put(surl, returnStatus); } } for (GetFileRequest fileRequest : findGetFileRequestBySURLs(surls)) { TReturnStatus returnStatus = fileRequest.release(); URI surl = fileRequest.getSurl(); TReturnStatus existingStatus = returnStatuses.get(surl); if (existingStatus == null || existingStatus.getStatusCode().equals(TStatusCode.SRM_SUCCESS)) { returnStatuses.put(surl, returnStatus); } } } private static Set<BringOnlineFileRequest> findBringOnlineFileRequestBySURLs(URI[] surls) throws DataAccessException { Collection<URI> surlList = (surls.length > 2) ? new HashSet<>(asList(surls)) : asList(surls); Set<BringOnlineFileRequest> requests = new HashSet<>(); for (BringOnlineFileRequest request : SRM.getSRM().getActiveJobs(BringOnlineFileRequest.class)) { if (surlList.contains(request.getSurl())) { requests.add(request); } } return requests; } private static Set<GetFileRequest> findGetFileRequestBySURLs(URI[] surls) throws DataAccessException { Collection<URI> surlList = (surls.length > 2) ? new HashSet<>(asList(surls)) : asList(surls); Set<GetFileRequest> requests = new HashSet<>(); for (GetFileRequest request : SRM.getSRM().getActiveJobs(GetFileRequest.class)) { if (surlList.contains(request.getSurl())) { requests.add(request); } } return requests; } private static URI[] toUris(org.apache.axis.types.URI[] uris) { URI[] result = new URI[uris.length]; for (int i = 0; i < uris.length; i++) { result[i] = URI.create(uris[i].toString()); } return result; } private static TSURLReturnStatus[] toTSURLReturnStatus(org.apache.axis.types.URI[] surls, Map<URI, TReturnStatus> returnStatuses) { TSURLReturnStatus[] surlReturnStatusArray = new TSURLReturnStatus[surls.length]; for (int i = 0; i < surls.length; i++) { TReturnStatus status = returnStatuses.get(URI.create(surls[i].toString())); if (status == null) { status = new TReturnStatus(TStatusCode.SRM_INVALID_PATH, "No pin found"); } surlReturnStatusArray[i] = new TSURLReturnStatus(surls[i], status); } return surlReturnStatusArray; } public static final SrmReleaseFilesResponse getFailedResponse(String error) { return getFailedResponse(error, TStatusCode.SRM_FAILURE); } public static final SrmReleaseFilesResponse getFailedResponse(String error, TStatusCode statusCode) { SrmReleaseFilesResponse srmReleaseFilesResponse = new SrmReleaseFilesResponse(); srmReleaseFilesResponse.setReturnStatus(new TReturnStatus(statusCode, error)); return srmReleaseFilesResponse; } }