Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
srm: Fix srmAbortFiles and srmAbortRequest implementations
srmAbortFiles and srmAbortRequest are not at all compliant with the SRM 2.2 spec. One symptom is that one may get failurs like 23 Sep 2013 23:06:57 (SRM-dcache-vm) [127.0.0.1:39844 t+Q:1:srm2:abortFiles:-2147482647] Illegal State Transition : Illegal state transition from Done to Canceled when aborting requests that have already completed. Another big fault is that the SURL return status used is that of the file request, whereas the spec defines it to be the return status of the abort operation, with only three legal return values. Finally, the return status of the entire request doesn't reflect the return status of the individual SURLs. These problems are addresses by this patch. A utility method for computing a summary return status for the request has been added and a number of otherwise unrelated classes are modified to make use of the utility method. Target: trunk Require-book: no Require-notes: yes Acked-by: Paul Millar <paul.millar@desy.de> Acked-by: Dmitry Litvintsev <litvinse@fnal.gov> Patch: http://rb.dcache.org/r/6040/
- Loading branch information
Showing
15 changed files
with
414 additions
and
350 deletions.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
modules/srm-server/src/main/java/org/dcache/srm/handler/ReturnStatuses.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package org.dcache.srm.handler; | ||
|
||
import org.dcache.srm.v2_2.TReturnStatus; | ||
import org.dcache.srm.v2_2.TSURLReturnStatus; | ||
import org.dcache.srm.v2_2.TStatusCode; | ||
|
||
public class ReturnStatuses | ||
{ | ||
private ReturnStatuses() | ||
{ | ||
} | ||
|
||
public static TReturnStatus getSummaryReturnStatus(TSURLReturnStatus[] returnStatuses) | ||
{ | ||
boolean hasFailure = false; | ||
boolean hasSuccess = false; | ||
for (TSURLReturnStatus returnStatus : returnStatuses) { | ||
if (returnStatus.getStatus().getStatusCode() == TStatusCode.SRM_SUCCESS) { | ||
hasSuccess = true; | ||
} else { | ||
hasFailure = true; | ||
} | ||
} | ||
return getSummaryReturnStatus(hasFailure, hasSuccess); | ||
} | ||
|
||
public static TReturnStatus getSummaryReturnStatus(boolean hasFailure, boolean hasSuccess) | ||
{ | ||
if (!hasFailure) { | ||
return new TReturnStatus(TStatusCode.SRM_SUCCESS, null); | ||
} else if (!hasSuccess) { | ||
return new TReturnStatus(TStatusCode.SRM_FAILURE, "The operation failed for all SURLs"); | ||
} else { | ||
return new TReturnStatus(TStatusCode.SRM_PARTIAL_SUCCESS, "The operation failed for some SURLs"); | ||
} | ||
} | ||
} |
199 changes: 64 additions & 135 deletions
199
modules/srm-server/src/main/java/org/dcache/srm/handler/SrmAbortFiles.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,183 +1,112 @@ | ||
/* | ||
* SrmLs.java | ||
* | ||
* Created on October 4, 2005, 3:40 PM | ||
*/ | ||
|
||
package org.dcache.srm.handler; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
|
||
import org.dcache.srm.AbstractStorageElement; | ||
import org.dcache.srm.SRM; | ||
import org.dcache.srm.SRMException; | ||
import org.dcache.srm.SRMFileRequestNotFoundException; | ||
import org.dcache.srm.SRMInvalidRequestException; | ||
import org.dcache.srm.SRMUser; | ||
import org.dcache.srm.request.ContainerRequest; | ||
import org.dcache.srm.request.FileRequest; | ||
import org.dcache.srm.request.Job; | ||
import org.dcache.srm.request.Request; | ||
import org.dcache.srm.request.RequestCredential; | ||
import org.dcache.srm.scheduler.IllegalStateTransition; | ||
import org.dcache.srm.scheduler.Scheduler; | ||
import org.dcache.srm.scheduler.State; | ||
import org.dcache.srm.util.Configuration; | ||
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.SrmAbortFilesRequest; | ||
import org.dcache.srm.v2_2.SrmAbortFilesResponse; | ||
import org.dcache.srm.v2_2.TReturnStatus; | ||
import org.dcache.srm.v2_2.TSURLReturnStatus; | ||
import org.dcache.srm.v2_2.TStatusCode; | ||
|
||
import static org.dcache.srm.handler.ReturnStatuses.getSummaryReturnStatus; | ||
|
||
/** | ||
* | ||
* @author timur | ||
*/ | ||
public class SrmAbortFiles { | ||
|
||
private static Logger logger = | ||
LoggerFactory.getLogger(SrmAbortFiles.class); | ||
public class SrmAbortFiles | ||
{ | ||
private final SrmAbortFilesRequest request; | ||
private SrmAbortFilesResponse response; | ||
|
||
private final static String SFN_STRING="?SFN="; | ||
AbstractStorageElement storage; | ||
SrmAbortFilesRequest srmAbortFilesRequest; | ||
SrmAbortFilesResponse response; | ||
Scheduler getScheduler; | ||
SRMUser user; | ||
RequestCredential credential; | ||
Configuration configuration; | ||
private int results_num; | ||
private int max_results_num; | ||
int numOfLevels; | ||
/** Creates a new instance of SrmLs */ | ||
public SrmAbortFiles( | ||
SRMUser user, | ||
RequestCredential credential, | ||
SrmAbortFilesRequest srmAbortFilesRequest, | ||
SrmAbortFilesRequest request, | ||
AbstractStorageElement storage, | ||
SRM srm, | ||
String client_host) { | ||
this.srmAbortFilesRequest = srmAbortFilesRequest; | ||
this.user = user; | ||
this.credential = credential; | ||
this.storage = storage; | ||
this.getScheduler = srm.getGetRequestScheduler(); | ||
this.configuration = srm.getConfiguration(); | ||
} | ||
|
||
boolean longFormat; | ||
String servicePathAndSFNPart = ""; | ||
int port; | ||
String host; | ||
public SrmAbortFilesResponse getResponse() { | ||
if(response != null ) { | ||
return response; | ||
} | ||
try { | ||
response = srmAbortFiles(); | ||
} catch(URISyntaxException mue) { | ||
logger.debug(" malformed uri : "+mue.getMessage()); | ||
response = getFailedResponse(" malformed uri : "+mue.getMessage(), | ||
TStatusCode.SRM_INVALID_REQUEST); | ||
} catch(SRMInvalidRequestException ire) { | ||
logger.debug(" invalid request : "+ire.getMessage()); | ||
response = getFailedResponse(" invalid request : "+ire.getMessage(), | ||
TStatusCode.SRM_INVALID_REQUEST); | ||
} catch(SRMException srme) { | ||
logger.error(srme.toString()); | ||
response = getFailedResponse(srme.toString()); | ||
} catch(IllegalStateTransition ist) { | ||
logger.error("Illegal State Transition : " +ist.getMessage()); | ||
response = getFailedResponse("Illegal State Transition : " +ist.getMessage()); | ||
} | ||
return response; | ||
} | ||
|
||
public static final SrmAbortFilesResponse getFailedResponse(String error) { | ||
return getFailedResponse(error,null); | ||
String clientHost) | ||
{ | ||
this.request = request; | ||
} | ||
|
||
public static final SrmAbortFilesResponse getFailedResponse(String error,TStatusCode statusCode) { | ||
if(statusCode == null) { | ||
statusCode =TStatusCode.SRM_FAILURE; | ||
} | ||
TReturnStatus status = new TReturnStatus(statusCode, error); | ||
public static SrmAbortFilesResponse getFailedResponse(String error, | ||
TStatusCode statusCode) | ||
{ | ||
SrmAbortFilesResponse srmAbortFilesResponse = new SrmAbortFilesResponse(); | ||
srmAbortFilesResponse.setReturnStatus(status); | ||
srmAbortFilesResponse.setReturnStatus(new TReturnStatus(statusCode, error)); | ||
return srmAbortFilesResponse; | ||
} | ||
|
||
private static URI[] toUris(org.apache.axis.types.URI[] uris) | ||
throws URISyntaxException | ||
private SrmAbortFilesResponse abortFiles() | ||
throws SRMInvalidRequestException | ||
{ | ||
URI[] result = new URI[uris.length]; | ||
for (int i = 0; i < uris.length; i++) { | ||
result[i] = new URI(uris[i].toString()); | ||
ContainerRequest<?> requestToAbort = | ||
Request.getRequest(this.request.getRequestToken(), ContainerRequest.class); | ||
try (JDC ignored = requestToAbort.applyJdc()) { | ||
org.apache.axis.types.URI[] surls = getSurls(); | ||
|
||
TSURLReturnStatus[] surlReturnStatusArray = new TSURLReturnStatus[surls.length]; | ||
for (int i = 0; i < surls.length; i++) { | ||
TReturnStatus returnStatus = abortSurl(requestToAbort, surls[i]); | ||
surlReturnStatusArray[i] = new TSURLReturnStatus(surls[i], returnStatus); | ||
} | ||
|
||
// we do this to make the srm update the status of the request if it changed | ||
requestToAbort.getTReturnStatus(); | ||
|
||
return new SrmAbortFilesResponse( | ||
getSummaryReturnStatus(surlReturnStatusArray), | ||
new ArrayOfTSURLReturnStatus(surlReturnStatusArray)); | ||
} | ||
return result; | ||
} | ||
|
||
/** | ||
* implementation of srm ls | ||
*/ | ||
public SrmAbortFilesResponse srmAbortFiles() | ||
throws SRMException,URISyntaxException, | ||
IllegalStateTransition | ||
private TReturnStatus abortSurl(ContainerRequest<?> request, org.apache.axis.types.URI surl) | ||
{ | ||
String requestToken = srmAbortFilesRequest.getRequestToken(); | ||
if( requestToken == null ) { | ||
return getFailedResponse("request contains no request token"); | ||
} | ||
long requestId; | ||
try { | ||
requestId = Long.parseLong(requestToken); | ||
} catch (NumberFormatException nfe){ | ||
return getFailedResponse(" requestToken \""+ | ||
requestToken+"\"is not valid", | ||
TStatusCode.SRM_INVALID_REQUEST); | ||
request.getFileRequestBySurl(new URI(surl.toString())).abort(); | ||
return new TReturnStatus(TStatusCode.SRM_SUCCESS, null); | ||
} catch (SRMFileRequestNotFoundException | URISyntaxException e) { | ||
return new TReturnStatus(TStatusCode.SRM_INVALID_PATH, | ||
"SURL does match any existing file request associated with the request token"); | ||
} catch (IllegalStateTransition e) { | ||
return new TReturnStatus(TStatusCode.SRM_FAILURE, e.getMessage()); | ||
} | ||
} | ||
|
||
ContainerRequest<?> request = Job.getJob(requestId, ContainerRequest.class); | ||
request.applyJdc(); | ||
|
||
URI[] surls; | ||
if( srmAbortFilesRequest.getArrayOfSURLs() == null ){ | ||
return getFailedResponse("request does not contain any SURLs", | ||
TStatusCode.SRM_INVALID_REQUEST); | ||
|
||
} else { | ||
surls = toUris(srmAbortFilesRequest.getArrayOfSURLs().getUrlArray()); | ||
} | ||
if(surls.length == 0) { | ||
return getFailedResponse("0 length SiteURLs array", | ||
TStatusCode.SRM_INVALID_REQUEST); | ||
} | ||
for (URI surl: surls) { | ||
FileRequest<?> fileRequest = request.getFileRequestBySurl(surl); | ||
fileRequest.setState(State.CANCELED,"SrmAbortFiles called"); | ||
private org.apache.axis.types.URI[] getSurls() throws SRMInvalidRequestException | ||
{ | ||
ArrayOfAnyURI arrayOfSURLs = request.getArrayOfSURLs(); | ||
if (arrayOfSURLs == null || arrayOfSURLs.getUrlArray().length == 0) { | ||
throw new SRMInvalidRequestException("Request contains no SURL"); | ||
} | ||
return arrayOfSURLs.getUrlArray(); | ||
} | ||
|
||
SrmAbortFilesResponse srmAbortFilesResponse = new SrmAbortFilesResponse(); | ||
srmAbortFilesResponse.setReturnStatus(new TReturnStatus(TStatusCode.SRM_SUCCESS, null)); | ||
TSURLReturnStatus[] surlReturnStatusArray = request.getArrayOfTSURLReturnStatus(surls); | ||
for (TSURLReturnStatus surlReturnStatus:surlReturnStatusArray) { | ||
if(surlReturnStatus.getStatus().getStatusCode() == TStatusCode.SRM_ABORTED) { | ||
surlReturnStatus.getStatus().setStatusCode(TStatusCode.SRM_SUCCESS); | ||
public SrmAbortFilesResponse getResponse() | ||
{ | ||
if (response == null) { | ||
try { | ||
response = abortFiles(); | ||
} catch (SRMInvalidRequestException e) { | ||
response = getFailedResponse(e.getMessage(), TStatusCode.SRM_INVALID_REQUEST); | ||
} | ||
} | ||
|
||
srmAbortFilesResponse.setArrayOfFileStatuses( | ||
new ArrayOfTSURLReturnStatus(surlReturnStatusArray)); | ||
// we do this to make the srm update the status of the request if it changed | ||
request.getTReturnStatus(); | ||
|
||
return srmAbortFilesResponse; | ||
|
||
return response; | ||
} | ||
|
||
|
||
public static SrmAbortFilesResponse getFailedResponse(String error) | ||
{ | ||
return getFailedResponse(error, TStatusCode.SRM_FAILURE); | ||
} | ||
} |
Oops, something went wrong.