Back to index

nordugrid-arc-nox  1.1.0~rc6
SRM22Client.cpp
Go to the documentation of this file.
00001 #include <glib.h>
00002 
00003 #include "SRM22Client.h"
00004 
00005 //namespace Arc {
00006   
00007   //Logger SRM22Client::logger(SRMClient::logger, "SRM22Client");
00008 
00009   SRM22Client::SRM22Client(SRMURL url) {
00010     version = "v2.2";
00011     implementation = SRM_IMPLEMENTATION_UNKNOWN;
00012     service_endpoint = url.ContactURL();
00013     csoap = new Arc::HTTPSClientSOAP(service_endpoint.c_str(),
00014                                      &soapobj,
00015                                      url.GSSAPI(),
00016                                      request_timeout,
00017                                      false);
00018     if(!csoap) { csoap=NULL; return; };
00019     if(!*csoap) { delete csoap; csoap=NULL; return; };
00020     soapobj.namespaces=srm2_2_soap_namespaces;
00021   }
00022   
00023   SRM22Client::~SRM22Client(void) {
00024     if(csoap) { csoap->disconnect(); delete csoap; };
00025   }
00026   
00027   
00028   static const char* Supported_Protocols[] = {
00029     "gsiftp","https","httpg","http","ftp","se"
00030   };
00031   
00032   static const int size_of_supported_protocols = 6;
00033   
00034   
00035   SRMReturnCode SRM22Client::ping(std::string& version, bool report_error) {
00036   
00037     SRMReturnCode rc = connect();
00038     if (rc != SRM_OK) return rc;
00039   
00040     SRMv2__srmPingRequest * request = new SRMv2__srmPingRequest;
00041     struct SRMv2__srmPingResponse_ response_struct;
00042     
00043     // do the call
00044     int soap_err = SOAP_OK;
00045     if((soap_err=soap_call_SRMv2__srmPing(&soapobj, csoap->SOAP_URL(), "srmPing", request, response_struct)) != SOAP_OK){
00046       logger.msg(Arc::VERBOSE, "SOAP request failed (%s)", "srmPing");
00047       if(report_error) soap_print_fault(&soapobj, stderr);
00048       csoap->disconnect();
00049       return SRM_ERROR_SOAP;
00050     };
00051   
00052     // get the version info
00053     if (response_struct.srmPingResponse->versionInfo) {
00054       version = response_struct.srmPingResponse->versionInfo;
00055       logger.msg(Arc::VERBOSE, "Server SRM version: %s", version);
00056   
00057       // get the implementation
00058       if (response_struct.srmPingResponse->otherInfo) {
00059         // look through otherInfo for the backend_type
00060         for(int i=0; i<response_struct.srmPingResponse->otherInfo->__sizeextraInfoArray; i++) {
00061           SRMv2__TExtraInfo * extrainfo = response_struct.srmPingResponse->otherInfo->extraInfoArray[i];
00062           if(strcmp((char*)extrainfo->key, "backend_type") != 0) continue;
00063           if(strcmp((char*)extrainfo->value, "dCache") == 0) {
00064             implementation = SRM_IMPLEMENTATION_DCACHE;
00065             logger.msg(Arc::VERBOSE, "Server implementation: %s", "dCache");
00066           }
00067           else if(strcmp((char*)extrainfo->value, "CASTOR") == 0) {
00068             implementation = SRM_IMPLEMENTATION_CASTOR;
00069             logger.msg(Arc::VERBOSE, "Server implementation: %s", "CASTOR");
00070           }
00071           else if(strcmp((char*)extrainfo->value, "DPM") == 0) {
00072             implementation = SRM_IMPLEMENTATION_DPM;
00073             logger.msg(Arc::VERBOSE, "Server implementation: %s", "DPM");
00074           }
00075           else if(strcmp((char*)extrainfo->value, "StoRM") == 0) {
00076             implementation = SRM_IMPLEMENTATION_STORM;
00077             logger.msg(Arc::VERBOSE, "Server implementation: %s", "StoRM");
00078           };
00079         };
00080       };
00081       return SRM_OK;
00082     };
00083     logger.msg(Arc::ERROR, "Could not determine version of server");
00084     return SRM_ERROR_OTHER;
00085   };
00086   
00087   SRMReturnCode SRM22Client::getSpaceTokens(std::list<std::string>& tokens,
00088                                             std::string description) {
00089   
00090     SRMReturnCode rc = connect();
00091     if (rc != SRM_OK) return rc;
00092   
00093     SRMv2__srmGetSpaceTokensRequest * request = new SRMv2__srmGetSpaceTokensRequest;
00094     if(description.compare("") != 0) request->userSpaceTokenDescription = (char*)description.c_str();
00095     struct SRMv2__srmGetSpaceTokensResponse_ response_struct;
00096   
00097     // do the call
00098     int soap_err = SOAP_OK;
00099     if((soap_err=soap_call_SRMv2__srmGetSpaceTokens(&soapobj, csoap->SOAP_URL(), "srmGetSpaceTokens", request, response_struct)) != SOAP_OK){
00100       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmGetSpaceTokens");
00101       soap_print_fault(&soapobj, stderr);
00102       csoap->disconnect();
00103       return SRM_ERROR_SOAP;
00104     };
00105   
00106     SRMv2__srmGetSpaceTokensResponse * response_inst = response_struct.srmGetSpaceTokensResponse;
00107   
00108     if (response_inst->returnStatus->statusCode != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00109       char * msg = response_inst->returnStatus->explanation;
00110       logger.msg(Arc::ERROR, "Error: %s", msg);
00111       return SRM_ERROR_OTHER;
00112     };
00113   
00114     for(int i = 0; i < response_inst->arrayOfSpaceTokens->__sizestringArray; i++) {
00115   
00116       std::string token(response_inst->arrayOfSpaceTokens->stringArray[i]);
00117       logger.msg(Arc::VERBOSE, "Adding space token %s", token);
00118       tokens.push_back(token);
00119     };
00120   
00121     return SRM_OK;
00122   };
00123   
00124   
00125   SRMReturnCode SRM22Client::getRequestTokens(std::list<std::string>& tokens,
00126                                               std::string description) {
00127   
00128     SRMReturnCode rc = connect();
00129     if (rc != SRM_OK) return rc;
00130   
00131     SRMv2__srmGetRequestTokensRequest * request = new SRMv2__srmGetRequestTokensRequest;
00132     if(description.compare("") != 0) request->userRequestDescription = (char*)description.c_str();
00133   
00134     struct SRMv2__srmGetRequestTokensResponse_ response_struct;
00135   
00136     // do the call
00137     int soap_err = SOAP_OK;
00138     if((soap_err=soap_call_SRMv2__srmGetRequestTokens(&soapobj, csoap->SOAP_URL(), "srmGetRequestTokens", request, response_struct)) != SOAP_OK){
00139       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmGetRequestTokens");
00140       soap_print_fault(&soapobj, stderr);
00141       csoap->disconnect();
00142       return SRM_ERROR_SOAP;
00143     };
00144   
00145     SRMv2__srmGetRequestTokensResponse * response_inst = response_struct.srmGetRequestTokensResponse;
00146   
00147     if (response_inst->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCOREINVALID_USCOREREQUEST) {
00148       // no tokens found
00149       logger.msg(Arc::INFO, "No request tokens found");
00150       return SRM_OK;
00151     }
00152     else if (response_inst->returnStatus->statusCode != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00153       char * msg = response_inst->returnStatus->explanation;
00154       logger.msg(Arc::ERROR, "Error: %s", msg);
00155       return SRM_ERROR_OTHER;
00156     };
00157   
00158     for(int i = 0; i < response_inst->arrayOfRequestTokens->__sizetokenArray; i++) {
00159   
00160       std::string token(response_inst->arrayOfRequestTokens->tokenArray[i]->requestToken);
00161       logger.msg(Arc::VERBOSE, "Adding request token %s", token);
00162       tokens.push_back(token);
00163     };
00164   
00165     return SRM_OK;
00166   };
00167   
00168   
00169   SRMReturnCode SRM22Client::getTURLs(SRMClientRequest& req,
00170                                       std::list<std::string>& urls) {
00171     SRMReturnCode rc = connect();
00172     if (rc != SRM_OK) return rc;
00173   
00174     // call get
00175     
00176     // construct get request - only one file requested at a time
00177     SRMv2__TGetFileRequest * req_array = new SRMv2__TGetFileRequest[1];
00178   
00179     SRMv2__TGetFileRequest * r = new SRMv2__TGetFileRequest;
00180     r->sourceSURL=(char*)req.surls().front().c_str();
00181   
00182     req_array[0] = *r;
00183   
00184     SRMv2__ArrayOfTGetFileRequest * file_requests = new SRMv2__ArrayOfTGetFileRequest;
00185     file_requests->__sizerequestArray=1;
00186     file_requests->requestArray=&req_array;
00187   
00188     // transfer parameters with protocols
00189     SRMv2__TTransferParameters * transfer_params = new SRMv2__TTransferParameters;
00190     SRMv2__ArrayOfString * prot_array = new SRMv2__ArrayOfString;
00191     prot_array->__sizestringArray=size_of_supported_protocols;
00192     prot_array->stringArray=(char**)Supported_Protocols;
00193     transfer_params->arrayOfTransferProtocols=prot_array;
00194     
00195     SRMv2__srmPrepareToGetRequest * request = new SRMv2__srmPrepareToGetRequest;
00196     request->transferParameters=transfer_params;
00197     request->arrayOfFileRequests=file_requests;
00198   
00199     struct SRMv2__srmPrepareToGetResponse_ response_struct;
00200   
00201     // do the call
00202     int soap_err = SOAP_OK;
00203     if((soap_err=soap_call_SRMv2__srmPrepareToGet(&soapobj, csoap->SOAP_URL(), "srmPrepareToGet", request, response_struct)) != SOAP_OK){
00204       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmPrepareToGet");
00205       soap_print_fault(&soapobj, stderr);
00206       csoap->disconnect();
00207       return SRM_ERROR_SOAP;
00208     };
00209   
00210     SRMv2__srmPrepareToGetResponse * response_inst = response_struct.srmPrepareToGetResponse;
00211     SRMv2__TStatusCode return_status = response_inst->returnStatus->statusCode;
00212     SRMv2__ArrayOfTGetRequestFileStatus * file_statuses= response_inst->arrayOfFileStatuses;
00213   
00214     // store the request token in the request object
00215     if (response_inst->requestToken) req.request_token(response_inst->requestToken);
00216 
00217     // deal with response code
00218     if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED ||
00219         return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00220       // file is queued - need to wait and query with returned request token
00221       char * request_token = response_inst->requestToken;
00222   
00223       int sleeptime = 1;
00224       if (response_inst->arrayOfFileStatuses->statusArray[0]->estimatedWaitTime)
00225         sleeptime = *(response_inst->arrayOfFileStatuses->statusArray[0]->estimatedWaitTime);
00226       int request_time = 0;
00227   
00228       while (return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00229   
00230         // sleep for recommended time (within limits)
00231         sleeptime = sleeptime<1?1:sleeptime;
00232         sleeptime = sleeptime>request_timeout ? request_timeout-request_time : sleeptime;
00233         logger.msg(Arc::VERBOSE, "%s: File request %s in SRM queue. Sleeping for %i seconds", req.surls().front(), request_token, sleeptime);
00234         sleep(sleeptime);
00235         request_time += sleeptime;
00236   
00237         SRMv2__srmStatusOfGetRequestRequest * sog_request = new SRMv2__srmStatusOfGetRequestRequest;
00238         sog_request->requestToken=request_token;
00239   
00240         struct SRMv2__srmStatusOfGetRequestResponse_ sog_response_struct;
00241   
00242         // call getRequestStatus
00243         if ((soap_err=soap_call_SRMv2__srmStatusOfGetRequest(&soapobj, csoap->SOAP_URL(), "srmStatusOfGetRequest", sog_request, sog_response_struct)) != SOAP_OK) {
00244           logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmStatusOfGetRequest");
00245           soap_print_fault(&soapobj, stderr);
00246           csoap->disconnect();
00247           req.finished_abort();  
00248           return SRM_ERROR_SOAP;
00249         };
00250   
00251         // check return codes - loop will exit on success or return false on error
00252   
00253         return_status = sog_response_struct.srmStatusOfGetRequestResponse->returnStatus->statusCode;
00254         file_statuses = sog_response_struct.srmStatusOfGetRequestResponse->arrayOfFileStatuses;
00255         
00256         if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED ||
00257             return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00258           // still queued - keep waiting
00259           // check for timeout
00260           if (request_time >= request_timeout) {
00261             logger.msg(Arc::ERROR, "Error: PrepareToGet request timed out after %i seconds", request_timeout);
00262             req.finished_abort();
00263             return SRM_ERROR_TEMPORARY;
00264           }
00265           if(file_statuses->statusArray[0]->estimatedWaitTime)
00266             sleeptime = *(file_statuses->statusArray[0]->estimatedWaitTime);
00267         }
00268         else if (return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00269           // error
00270           char * msg = sog_response_struct.srmStatusOfGetRequestResponse->returnStatus->explanation;
00271           logger.msg(Arc::ERROR, "Error: %s", msg);
00272           if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
00273             return SRM_ERROR_TEMPORARY;
00274           return SRM_ERROR_PERMANENT;
00275         };
00276       }; // while
00277   
00278     } // if file queued
00279   
00280     else if (return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00281       // any other return code is a failure
00282       char * msg = response_inst->returnStatus->explanation;
00283       logger.msg(Arc::ERROR, "Error: %s", msg);
00284       if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
00285         return SRM_ERROR_TEMPORARY;
00286       return SRM_ERROR_PERMANENT;
00287     };
00288   
00289     // the file is ready and pinned - we can get the TURL
00290     char * turl = file_statuses->statusArray[0]->transferURL;
00291   
00292     logger.msg(Arc::VERBOSE, "File is ready! TURL is %s", turl);
00293     urls.push_back(std::string(turl));
00294 
00295     req.finished_success();
00296     return SRM_OK;
00297   }
00298   
00299   SRMReturnCode SRM22Client::requestBringOnline(SRMClientRequest& req) {
00300   
00301     SRMReturnCode rc = connect();
00302     if (rc != SRM_OK) return rc;
00303   
00304     // construct bring online request
00305     std::list<std::string> surls = req.surls();
00306     SRMv2__TGetFileRequest ** req_array = new SRMv2__TGetFileRequest*[surls.size()];
00307     
00308     // add each file to the request array
00309     int j = 0;
00310     for (std::list<std::string>::iterator i = surls.begin(); i != surls.end(); ++i) {
00311       SRMv2__TGetFileRequest * r = new SRMv2__TGetFileRequest;
00312       r->sourceSURL=(char*)(*i).c_str();
00313       req_array[j] = r;
00314       j++;
00315     };
00316   
00317     SRMv2__ArrayOfTGetFileRequest * file_requests = new SRMv2__ArrayOfTGetFileRequest;
00318     file_requests->__sizerequestArray=surls.size();
00319     file_requests->requestArray=req_array;
00320   
00321     // transfer parameters with protocols
00322     // should not be needed but dcache returns NullPointerException if
00323     // it is not given
00324     SRMv2__TTransferParameters * transfer_params = new SRMv2__TTransferParameters;
00325     SRMv2__ArrayOfString * prot_array = new SRMv2__ArrayOfString;
00326     prot_array->__sizestringArray=size_of_supported_protocols;
00327     prot_array->stringArray=(char**)Supported_Protocols;
00328     transfer_params->arrayOfTransferProtocols=prot_array;
00329     
00330     SRMv2__srmBringOnlineRequest * request = new SRMv2__srmBringOnlineRequest;
00331     request->arrayOfFileRequests=file_requests;
00332     request->transferParameters=transfer_params;
00333   
00334     // store the user id as part of the request, so they can find it later
00335     char * user = const_cast<char*>(g_get_user_name());
00336     if (user) {
00337       logger.msg(Arc::VERBOSE, "Setting userRequestDescription to %s", user);
00338       request->userRequestDescription = user;
00339     };
00340   
00341     struct SRMv2__srmBringOnlineResponse_ response_struct;
00342     
00343     // do the call
00344     int soap_err = SOAP_OK;
00345     if((soap_err=soap_call_SRMv2__srmBringOnline(&soapobj, csoap->SOAP_URL(), "srmBringOnline", request, response_struct)) != SOAP_OK){
00346       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmBringOnline");
00347       soap_print_fault(&soapobj, stderr);
00348       csoap->disconnect();
00349       return SRM_ERROR_SOAP;
00350     };
00351   
00352     SRMv2__srmBringOnlineResponse * response_inst = response_struct.srmBringOnlineResponse;
00353     SRMv2__TStatusCode return_status = response_inst->returnStatus->statusCode;
00354     SRMv2__ArrayOfTBringOnlineRequestFileStatus * file_statuses= response_inst->arrayOfFileStatuses;
00355   
00356     // store the request token in the request object
00357     if (response_inst->requestToken) req.request_token(response_inst->requestToken);
00358   
00359     // deal with response code - successful ones first
00360     if (return_status == SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00361       // this means files are all already online
00362       for (std::list<std::string>::iterator i = surls.begin();
00363            i != surls.end();
00364            ++i) {
00365         req.surl_statuses(*i, SRM_ONLINE);
00366         req.finished_success();
00367       }
00368       return SRM_OK;
00369     };
00370   
00371     if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED) {
00372       // all files have been queued - leave statuses as unknown
00373       return SRM_OK;
00374     };
00375   
00376     if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00377       // some files have been queued and some are online. check each file
00378       fileStatus(req, file_statuses);
00379       return SRM_OK;
00380     };
00381   
00382     if (return_status == SRMv2__TStatusCode__SRM_USCOREPARTIAL_USCORESUCCESS) {
00383       // some files are already online, some failed. check each file
00384       fileStatus(req, file_statuses);
00385       return SRM_OK;
00386     };
00387   
00388     // here means an error code was returned and all files failed
00389     char * msg = response_inst->returnStatus->explanation;
00390     logger.msg(Arc::ERROR, "Error: %s", msg);
00391     req.finished_error();
00392     if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
00393       return SRM_ERROR_TEMPORARY;
00394     return SRM_ERROR_PERMANENT;  
00395   };
00396   
00397   
00398   SRMReturnCode SRM22Client::requestBringOnlineStatus(SRMClientRequest& req) {
00399   
00400     SRMReturnCode rc = connect();
00401     if (rc != SRM_OK) return rc;
00402   
00403     SRMv2__srmStatusOfBringOnlineRequestRequest * sobo_request = new SRMv2__srmStatusOfBringOnlineRequestRequest;
00404     if(req.request_token().empty()) {
00405       logger.msg(Arc::ERROR, "No request token specified!");
00406       return SRM_ERROR_OTHER;
00407     };
00408     sobo_request->requestToken=(char*)req.request_token().c_str();
00409   
00410     struct SRMv2__srmStatusOfBringOnlineRequestResponse_ sobo_response_struct;
00411   
00412     // do the call
00413     int soap_err = SOAP_OK;
00414     if ((soap_err=soap_call_SRMv2__srmStatusOfBringOnlineRequest(&soapobj, csoap->SOAP_URL(), "srmStatusOfBringOnlineRequest", sobo_request, sobo_response_struct)) != SOAP_OK) {
00415       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmStatusOfBringOnlineRequest");
00416       soap_print_fault(&soapobj, stderr);
00417       csoap->disconnect();
00418       return SRM_ERROR_SOAP;
00419     };
00420   
00421     SRMv2__TStatusCode return_status = sobo_response_struct.srmStatusOfBringOnlineRequestResponse->returnStatus->statusCode;
00422     SRMv2__ArrayOfTBringOnlineRequestFileStatus * file_statuses = sobo_response_struct.srmStatusOfBringOnlineRequestResponse->arrayOfFileStatuses;
00423   
00424     // deal with response code - successful ones first
00425     if (return_status == SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00426       // this means files are all online
00427       fileStatus(req, file_statuses);    
00428       req.finished_success();
00429       return SRM_OK;
00430     };
00431   
00432     if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED) {
00433       // all files are in the queue - leave statuses as they are
00434       return SRM_OK;
00435     };
00436   
00437     if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00438       // some files have been queued and some are online. check each file
00439       fileStatus(req, file_statuses);    
00440       return SRM_OK;
00441     };
00442   
00443     if (return_status == SRMv2__TStatusCode__SRM_USCOREPARTIAL_USCORESUCCESS) {
00444       // some files are online, some failed. check each file
00445       fileStatus(req, file_statuses);
00446       req.finished_partial_success();
00447       return SRM_OK;
00448     };
00449   
00450     if (return_status == SRMv2__TStatusCode__SRM_USCOREABORTED) {
00451       // The request was aborted or finished successfully. dCache reports
00452       // SRM_ABORTED after the first time a successful request is queried
00453       // so we have to look at the explanation string for the real reason.
00454       std::string explanation(sobo_response_struct.srmStatusOfBringOnlineRequestResponse->returnStatus->explanation);
00455       if(explanation.find("All files are done") != std::string::npos) {
00456         logger.msg(Arc::VERBOSE, "Request is reported as ABORTED, but all files are done");
00457         req.finished_success();
00458         return SRM_OK;
00459       }
00460       else if(explanation.find("Canceled") != std::string::npos) {
00461         logger.msg(Arc::VERBOSE, "Request is reported as ABORTED, since it was cancelled");
00462         req.cancelled();
00463         return SRM_OK;
00464       }
00465       else if(explanation.length() != 0){
00466         logger.msg(Arc::VERBOSE, "Request is reported as ABORTED. Reason: %s", explanation);
00467         req.finished_error();
00468         return SRM_ERROR_PERMANENT;
00469       }
00470       else {
00471         logger.msg(Arc::VERBOSE, "Request is reported as ABORTED");
00472         req.finished_error();
00473         return SRM_ERROR_PERMANENT;
00474       }
00475       
00476     };
00477   
00478     // here means an error code was returned and all files failed
00479     // return error, but may be retryable by client
00480     char * msg = sobo_response_struct.srmStatusOfBringOnlineRequestResponse->returnStatus->explanation;
00481     logger.msg(Arc::ERROR, "Error: %s", msg);
00482     if(file_statuses) fileStatus(req, file_statuses);
00483     req.finished_error();
00484     if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
00485       return SRM_ERROR_TEMPORARY;
00486     return SRM_ERROR_PERMANENT;
00487   };
00488   
00489   void SRM22Client::fileStatus(SRMClientRequest& req,
00490                                SRMv2__ArrayOfTBringOnlineRequestFileStatus * file_statuses) {
00491   
00492     int wait_time = 0;
00493   
00494     for (int i=0; i<file_statuses->__sizestatusArray; i++) {
00495         
00496       SRMv2__TReturnStatus * file_status = file_statuses->statusArray[i]->status;
00497       char * surl = file_statuses->statusArray[i]->sourceSURL;
00498       
00499       // store the largest estimated waiting time
00500       if (file_statuses->statusArray[i]->estimatedWaitTime &&
00501           *(file_statuses->statusArray[i]->estimatedWaitTime) > wait_time)
00502         wait_time = *(file_statuses->statusArray[i]->estimatedWaitTime);
00503       
00504       if (file_status->statusCode == SRMv2__TStatusCode__SRM_USCORESUCCESS ||
00505           file_status->statusCode == SRMv2__TStatusCode__SRM_USCOREFILE_USCOREIN_USCORECACHE) {
00506         // file is online
00507         req.surl_statuses(surl, SRM_ONLINE);
00508       }
00509         
00510       else if (file_status->statusCode == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED ||
00511                file_status->statusCode == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00512         // in queue to be staged
00513         req.surl_statuses(surl, SRM_NEARLINE);
00514       }
00515       else {
00516         // error 
00517         req.surl_statuses(surl, SRM_STAGE_ERROR);
00518         if (file_status->explanation) req.surl_failures(surl, file_status->explanation);
00519         else req.surl_failures(surl, "No reason available");
00520       };
00521     };
00522     req.waiting_time(wait_time);
00523   };
00524   
00525   
00526   SRMReturnCode SRM22Client::putTURLs(SRMClientRequest& req,
00527                                       std::list<std::string>& urls,
00528                                       unsigned long long size) {
00529     SRMReturnCode rc = connect();
00530     if (rc != SRM_OK) return rc;
00531   
00532     // call put
00533     
00534     // construct put request - only one file requested at a time
00535     SRMv2__TPutFileRequest * req_array = new SRMv2__TPutFileRequest[1];
00536   
00537     SRMv2__TPutFileRequest * r = new SRMv2__TPutFileRequest;
00538     // need to create new object here or doesn't work
00539     //std::string * surl = new std::string(srm_url.FullURL());
00540     r->targetSURL=(char*)req.surls().front().c_str();
00541     ULONG64 fsize = size;
00542     r->expectedFileSize=&fsize;
00543   
00544     req_array[0] = *r;
00545   
00546     SRMv2__ArrayOfTPutFileRequest * file_requests = new SRMv2__ArrayOfTPutFileRequest;
00547     file_requests->__sizerequestArray=1;
00548     file_requests->requestArray=&req_array;
00549   
00550     // transfer parameters with protocols
00551     SRMv2__TTransferParameters * transfer_params = new SRMv2__TTransferParameters;
00552     SRMv2__ArrayOfString * prot_array = new SRMv2__ArrayOfString;
00553     prot_array->__sizestringArray=size_of_supported_protocols;
00554     prot_array->stringArray=(char**)Supported_Protocols;
00555     transfer_params->arrayOfTransferProtocols=prot_array;
00556     
00557     SRMv2__srmPrepareToPutRequest * request = new SRMv2__srmPrepareToPutRequest;
00558     request->transferParameters=transfer_params;
00559     request->arrayOfFileRequests=file_requests;
00560   
00561     // set space token if supplied
00562     if(req.space_token() != "") request->targetSpaceToken = (char*)req.space_token().c_str();
00563   
00564     // dcache does not handle this correctly yet
00565     //request->desiredTotalRequestTime=(int*)&request_timeout;
00566   
00567     struct SRMv2__srmPrepareToPutResponse_ response_struct;
00568   
00569     // do the call
00570     int soap_err = SOAP_OK;
00571     if((soap_err=soap_call_SRMv2__srmPrepareToPut(&soapobj, csoap->SOAP_URL(), "srmPrepareToPut", request, response_struct)) != SOAP_OK){
00572       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmPrepareToPut");
00573       soap_print_fault(&soapobj, stderr);
00574       csoap->disconnect();
00575       return SRM_ERROR_SOAP;
00576     };
00577   
00578     SRMv2__srmPrepareToPutResponse * response_inst = response_struct.srmPrepareToPutResponse;
00579     SRMv2__TStatusCode return_status = response_inst->returnStatus->statusCode;
00580     SRMv2__ArrayOfTPutRequestFileStatus * file_statuses= response_inst->arrayOfFileStatuses;
00581   
00582     // store the request token in the request object
00583     if (response_inst->requestToken) req.request_token(response_inst->requestToken);
00584   
00585     // deal with response code
00586     if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED ||
00587         return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00588       // file is queued - need to wait and query with returned request token
00589   
00590       char * request_token = response_inst->requestToken;
00591       int sleeptime = 1;
00592       if (response_inst->arrayOfFileStatuses->statusArray[0]->estimatedWaitTime)
00593         sleeptime = *(response_inst->arrayOfFileStatuses->statusArray[0]->estimatedWaitTime);
00594       int request_time = 0;
00595   
00596       while(return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00597   
00598         // sleep for recommended time (within limits)
00599         sleeptime = sleeptime<1?1:sleeptime;
00600         sleeptime = sleeptime>request_timeout ? request_timeout-request_time : sleeptime;
00601         logger.msg(Arc::VERBOSE, "%s: File request %s in SRM queue. Sleeping for %i seconds", req.surls().front(), request_token, sleeptime);
00602         sleep(sleeptime);
00603         request_time += sleeptime;
00604   
00605         SRMv2__srmStatusOfPutRequestRequest * sog_request = new SRMv2__srmStatusOfPutRequestRequest;
00606         sog_request->requestToken=request_token;
00607   
00608         struct SRMv2__srmStatusOfPutRequestResponse_ sog_response_struct;
00609   
00610         // call putRequestStatus
00611         if ((soap_err=soap_call_SRMv2__srmStatusOfPutRequest(&soapobj, csoap->SOAP_URL(), "srmStatusOfPutRequest", sog_request, sog_response_struct)) != SOAP_OK) {
00612           logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmStatusOfPutRequest");
00613           soap_print_fault(&soapobj, stderr);
00614           csoap->disconnect();
00615           req.finished_abort();
00616           return SRM_ERROR_SOAP;
00617         };
00618   
00619         // check return codes - loop will exit on success or return false on error
00620   
00621         return_status = sog_response_struct.srmStatusOfPutRequestResponse->returnStatus->statusCode;
00622         file_statuses = sog_response_struct.srmStatusOfPutRequestResponse->arrayOfFileStatuses;
00623         
00624         if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED ||
00625             return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00626           // still queued - keep waiting
00627           // check for timeout
00628           if (request_time >= request_timeout) {
00629             logger.msg(Arc::ERROR, "Error: PrepareToPut request timed out after %i seconds", request_timeout);
00630             req.finished_abort();
00631             return SRM_ERROR_TEMPORARY;
00632           }
00633           if (file_statuses &&
00634               file_statuses->statusArray &&
00635               file_statuses->statusArray[0] &&
00636               file_statuses->statusArray[0]->estimatedWaitTime) {
00637             sleeptime = *(file_statuses->statusArray[0]->estimatedWaitTime);
00638           }
00639         }
00640         else if (return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00641           // error
00642           // check individual file statuses
00643           if (file_statuses &&
00644               file_statuses->statusArray &&
00645               file_statuses->statusArray[0] &&
00646               file_statuses->statusArray[0]->status) {
00647             if (file_statuses->statusArray[0]->status->statusCode &&
00648                 file_statuses->statusArray[0]->status->statusCode == SRMv2__TStatusCode__SRM_USCOREINVALID_USCOREPATH) {
00649               // make directories
00650               logger.msg(Arc::VERBOSE, "Path %s is invalid, creating required directories", req.surls().front());
00651               SRMReturnCode mkdirres = mkDir(req);
00652               if (mkdirres == SRM_OK)
00653                 return putTURLs(req, urls, size);
00654               logger.msg(Arc::ERROR, "Error creating required directories for %s", req.surls().front());
00655               return mkdirres;
00656             }
00657             // log file-level error message
00658             if (file_statuses->statusArray[0]->status->explanation)
00659               logger.msg(Arc::ERROR, "Error: %s", file_statuses->statusArray[0]->status->explanation);
00660           }
00661           char * msg = sog_response_struct.srmStatusOfPutRequestResponse->returnStatus->explanation;
00662           logger.msg(Arc::ERROR, "Error: %s", msg);
00663           if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
00664             return SRM_ERROR_TEMPORARY;
00665           return SRM_ERROR_PERMANENT;
00666         };
00667       }; // while
00668   
00669     } // if file queued
00670   
00671     else if (return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00672       // any other return code is a failure
00673       // check individual file statuses
00674       if (file_statuses &&
00675           file_statuses->statusArray &&
00676           file_statuses->statusArray[0] &&
00677           file_statuses->statusArray[0]->status) {
00678         if (file_statuses->statusArray[0]->status->statusCode &&
00679             file_statuses->statusArray[0]->status->statusCode == SRMv2__TStatusCode__SRM_USCOREINVALID_USCOREPATH) {
00680           // make directories
00681           logger.msg(Arc::VERBOSE, "Path %s is invalid, creating required directories", req.surls().front());
00682           SRMReturnCode mkdirres = mkDir(req);
00683           if (mkdirres == SRM_OK)
00684             return putTURLs(req, urls, size);
00685           logger.msg(Arc::ERROR, "Error creating required directories for %s", req.surls().front());
00686           return mkdirres;
00687         }
00688         // log file-level error message
00689         if (file_statuses->statusArray[0]->status->explanation)
00690           logger.msg(Arc::ERROR, "Error: %s", file_statuses->statusArray[0]->status->explanation);
00691       }  
00692       char * msg = response_inst->returnStatus->explanation;
00693       logger.msg(Arc::ERROR, "Error: %s", msg);
00694       if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
00695         return SRM_ERROR_TEMPORARY;
00696       return SRM_ERROR_PERMANENT;
00697     };
00698   
00699     // the file is ready and pinned - we can get the TURL
00700     char * turl = file_statuses->statusArray[0]->transferURL;
00701   
00702     logger.msg(Arc::VERBOSE, "File is ready! TURL is %s", turl);
00703     urls.push_back(std::string(turl));
00704 
00705     req.finished_success();
00706     return SRM_OK;
00707   }
00708   
00709   SRMReturnCode SRM22Client::info(SRMClientRequest& req,
00710                                   std::list<struct SRMFileMetaData>& metadata,
00711                                   const int recursive,
00712                                   bool report_error) {
00713     return info(req, metadata, recursive, report_error, 0, 0);
00714   }
00715   
00716   SRMReturnCode SRM22Client::info(SRMClientRequest& req,
00717                                   std::list<struct SRMFileMetaData>& metadata,
00718                                   const int recursive,
00719                                   bool report_error,
00720                                   const int offset,
00721                                   const int count) {
00722   
00723     SRMReturnCode rc = connect();
00724     if (rc != SRM_OK) return rc;
00725   
00726     // call ls
00727   
00728     // construct ls request - only one SURL requested at a time
00729     xsd__anyURI * req_array = new xsd__anyURI[1];
00730     req_array[0] = (char*)req.surls().front().c_str();
00731   
00732     SRMv2__ArrayOfAnyURI * surls_array = new SRMv2__ArrayOfAnyURI;
00733     surls_array->__sizeurlArray=1;
00734     surls_array->urlArray=req_array;
00735   
00736     SRMv2__srmLsRequest * request = new SRMv2__srmLsRequest;
00737     request->arrayOfSURLs=surls_array;
00738     // 0 corresponds to list the directory entry not the files in it
00739     // 1 corresponds to list the files in a directory - this is the desired
00740     // behaviour of ngls with no recursion, so we add 1 to the -r value
00741     request->numOfLevels=new int(recursive+1);
00742     
00743     // add count and offset options, if set
00744     if (offset != 0) request->offset = new int(offset);
00745     if (count != 0) request->count = new int(count);
00746     
00747     if (req.long_list()) request->fullDetailedList = new bool(true);
00748   
00749     struct SRMv2__srmLsResponse_ response_struct;
00750     
00751     int soap_err = SOAP_OK;
00752    
00753     // do the srmLs call
00754     if((soap_err=soap_call_SRMv2__srmLs(&soapobj, csoap->SOAP_URL(), "srmLs", request, response_struct)) != SOAP_OK){
00755       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmLs");
00756       soap_print_fault(&soapobj, stderr);
00757       csoap->disconnect();
00758       return SRM_ERROR_SOAP;
00759     };
00760   
00761     SRMv2__srmLsResponse * response_inst = response_struct.srmLsResponse;
00762     SRMv2__TStatusCode return_status = response_inst->returnStatus->statusCode;
00763     SRMv2__ArrayOfTMetaDataPathDetail * file_details= response_inst->details;
00764   
00765     if (response_inst->requestToken) req.request_token(response_inst->requestToken);
00766   
00767     // deal with response code - successful ones first
00768     if (return_status == SRMv2__TStatusCode__SRM_USCORESUCCESS) {
00769       // request is finished - we can get all the details
00770     }
00771     else if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED ||
00772         return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00773       // file is queued - need to wait and query with returned request token
00774   
00775       char * request_token = response_inst->requestToken;
00776       int sleeptime = 1;
00777       int request_time = 0;
00778   
00779       while(return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS &&
00780             request_time < request_timeout) {
00781   
00782         // sleep for some time (no estimated time is given by the server)
00783         logger.msg(Arc::VERBOSE, "%s: File request %s in SRM queue. Sleeping for %i seconds", req.surls().front(), request_token, sleeptime);
00784         sleep(sleeptime);
00785         request_time += sleeptime;
00786   
00787         SRMv2__srmStatusOfLsRequestRequest * sols_request = new SRMv2__srmStatusOfLsRequestRequest;
00788         sols_request->requestToken=request_token;
00789   
00790         struct SRMv2__srmStatusOfLsRequestResponse_ sols_response_struct;
00791   
00792         // call statusOfLsResponse
00793         if ((soap_err=soap_call_SRMv2__srmStatusOfLsRequest(&soapobj, csoap->SOAP_URL(), "srmStatusOfLsRequest", sols_request, sols_response_struct)) != SOAP_OK) {
00794           logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmStatusOfLsRequest");
00795           soap_print_fault(&soapobj, stderr);
00796           csoap->disconnect();
00797           return SRM_ERROR_SOAP;
00798         };
00799   
00800         // check return codes - loop will exit on success or return false on error
00801   
00802         return_status = sols_response_struct.srmStatusOfLsRequestResponse->returnStatus->statusCode;
00803         file_details = sols_response_struct.srmStatusOfLsRequestResponse->details;
00804         
00805         if (return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS &&
00806             return_status != SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED &&
00807             return_status != SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
00808           // error
00809           const char * msg = "Error in srmLs";
00810           if (sols_response_struct.srmStatusOfLsRequestResponse->returnStatus->explanation)
00811             msg = sols_response_struct.srmStatusOfLsRequestResponse->returnStatus->explanation;
00812           if (report_error) {
00813             logger.msg(Arc::ERROR, "Error: %s", msg);
00814           } else {
00815             logger.msg(Arc::VERBOSE, "Error: %s", msg);
00816           }
00817           // check if individual file status gives more info
00818           if (sols_response_struct.srmStatusOfLsRequestResponse->details &&
00819               sols_response_struct.srmStatusOfLsRequestResponse->details->pathDetailArray &&
00820               sols_response_struct.srmStatusOfLsRequestResponse->details->__sizepathDetailArray > 0 &&
00821               sols_response_struct.srmStatusOfLsRequestResponse->details->pathDetailArray[0]->status &&
00822               sols_response_struct.srmStatusOfLsRequestResponse->details->pathDetailArray[0]->status->explanation) {
00823             if (report_error) {
00824               logger.msg(Arc::ERROR, "Error: %s", sols_response_struct.srmStatusOfLsRequestResponse->details->pathDetailArray[0]->status->explanation);
00825             } else {
00826               logger.msg(Arc::VERBOSE, "Error: %s", sols_response_struct.srmStatusOfLsRequestResponse->details->pathDetailArray[0]->status->explanation);
00827             }
00828           }
00829           if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
00830             return SRM_ERROR_TEMPORARY;
00831           return SRM_ERROR_PERMANENT;
00832         };
00833       }; // while
00834   
00835       // check for timeout
00836       if (request_time >= request_timeout) {
00837         logger.msg(Arc::ERROR, "Error: Ls request timed out after %i seconds", request_timeout);
00838         abort(req);
00839         return SRM_ERROR_TEMPORARY;
00840       }
00841   
00842     } // else if request queued
00843   
00844     else {
00845       // any other return code is a failure
00846       const char * msg = "Error in srmLs";
00847       if (response_inst->returnStatus->explanation)
00848         msg = response_inst->returnStatus->explanation;
00849       if (report_error) {
00850         logger.msg(Arc::ERROR, "Error: %s", msg);
00851       } else {
00852         logger.msg(Arc::VERBOSE, "Error: %s", msg);
00853       }
00854       // check if individual file status gives more info
00855       if (response_inst->details &&
00856           response_inst->details->pathDetailArray &&
00857           response_inst->details->__sizepathDetailArray > 0 &&
00858           response_inst->details->pathDetailArray[0]->status &&
00859           response_inst->details->pathDetailArray[0]->status->explanation) {
00860         if (report_error) {
00861           logger.msg(Arc::ERROR, "Error: %s", response_inst->details->pathDetailArray[0]->status->explanation);
00862         } else {
00863           logger.msg(Arc::VERBOSE, "Error: %s", response_inst->details->pathDetailArray[0]->status->explanation);
00864         }
00865       }
00866       if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
00867         return SRM_ERROR_TEMPORARY;
00868       return SRM_ERROR_PERMANENT;
00869     }
00870   
00871     // the request is ready - collect the details
00872     if (!file_details || !file_details->pathDetailArray || file_details->__sizepathDetailArray == 0 || !file_details->pathDetailArray[0]) return SRM_OK; // see bug 1364
00873     // first the file or directory corresponding to the surl
00874     SRMv2__TMetaDataPathDetail * details = file_details->pathDetailArray[0];
00875     if (!details->type || *(details->type) != SRMv2__TFileType__DIRECTORY || recursive < 0) {
00876       // it can happen that with multiple calls to info() for large dirs the last
00877       // call returns one directory. In this case we want to list it without the
00878       // directory structure.
00879       if (count == 0) metadata.push_back(fillDetails(details, false));
00880       else metadata.push_back(fillDetails(details, true));
00881     };
00882   
00883     // look for sub paths (files in a directory)
00884     SRMv2__ArrayOfTMetaDataPathDetail * subpaths;
00885     
00886     // schema differs by implementation...
00887     // dcache and dpm
00888     if (details->arrayOfSubPaths) subpaths = details->arrayOfSubPaths;
00889     // castor
00890     else if (file_details->__sizepathDetailArray > 1) subpaths = file_details;
00891     // no subpaths
00892     else return SRM_OK;
00893  
00894     // sometimes we don't know if we have a file or dir so take out the
00895     // entry added above if there are subpaths and offset is 0
00896     if (offset == 0 && subpaths->__sizepathDetailArray > 0)
00897       metadata.clear();
00898   
00899     // if there are more entries than max_files_list, we have to call info()
00900     // multiple times, setting offset and count
00901     for (int i = 0; i<subpaths->__sizepathDetailArray; i++) {
00902       if (i == max_files_list) {
00903         // call multiple times
00904         logger.msg(Arc::INFO, "Directory size is larger than %i files, will have to call multiple times", max_files_list);
00905         std::list<SRMFileMetaData> list_metadata;
00906         int list_no = 1;
00907         int list_offset = 0;
00908         int list_count = 0;
00909         do {
00910           list_metadata.clear();
00911           SRMClientRequest list_req(req.surls().front());
00912           list_offset = max_files_list * list_no;
00913           list_count = max_files_list;
00914           SRMReturnCode res = info(list_req, list_metadata, 0, true, list_offset, list_count);
00915           if (res != SRM_OK) return res;
00916           list_no++;
00917           // append to metadata
00918           for (std::list<SRMFileMetaData>::iterator it = list_metadata.begin();
00919                it != list_metadata.end();
00920                ++it) {
00921             metadata.push_back(*it);
00922           }
00923         } while (list_metadata.size() == max_files_list);
00924         break;
00925       }
00926       SRMv2__TMetaDataPathDetail * sub_details = subpaths->pathDetailArray[i];
00927       if (sub_details) metadata.push_back(fillDetails(sub_details, true));
00928   
00929     };
00930   
00931     // if castor take out the first two entries which are the directory
00932     if (file_details->__sizepathDetailArray > 1) {
00933       metadata.pop_front();
00934       // only take off the second one if no offset
00935       if (offset == 0) metadata.pop_front();
00936     };
00937   
00938     // sort list by filename
00939     //metadata.sort(compare_srm_file_meta_data);
00940   
00941     return SRM_OK;
00942   }
00943   
00944   SRMFileMetaData SRM22Client::fillDetails(SRMv2__TMetaDataPathDetail * details,
00945                                            bool directory) {
00946   
00947     SRMFileMetaData metadata;
00948   
00949     if(details->path){
00950       char * path = details->path;
00951       metadata.path = path;
00952       std::string::size_type i = metadata.path.find("//", 0);
00953       while (i != std::string::npos) {
00954         metadata.path.erase(i, 1);
00955         i = metadata.path.find("//", 0);
00956       };
00957       if (metadata.path.find("/") != 0) metadata.path = "/" + metadata.path;
00958       if (directory) {
00959        // only use the basename of the path
00960        metadata.path = metadata.path.substr(metadata.path.rfind("/", metadata.path.length())+1);
00961       };
00962     };
00963   
00964     if(details->size){
00965       ULONG64 * fsize = details->size;
00966       metadata.size = *fsize;
00967     }
00968     else {metadata.size = -1;};
00969   
00970     if(details->checkSumType){
00971       char * checksum_type = details->checkSumType;
00972       metadata.checkSumType = checksum_type;
00973     }
00974     else {metadata.checkSumType = "";};
00975   
00976     if(details->checkSumValue){
00977       char * checksum_value = details->checkSumValue;
00978       metadata.checkSumValue = checksum_value;
00979     }
00980     else {metadata.checkSumValue = "";};
00981   
00982     if(details->createdAtTime){
00983       time_t * creation_time = details->createdAtTime;
00984       metadata.createdAtTime = *creation_time;
00985     } 
00986     else {metadata.createdAtTime = 0;};
00987   
00988     if(details->type){
00989       SRMv2__TFileType * file_type = details->type;
00990       if (*file_type == SRMv2__TFileType__FILE_) metadata.fileType = SRM_FILE;
00991       else if (*file_type == SRMv2__TFileType__DIRECTORY) metadata.fileType = SRM_DIRECTORY;
00992       else if (*file_type == SRMv2__TFileType__LINK) metadata.fileType = SRM_LINK;
00993     }
00994     else {metadata.fileType = SRM_FILE_TYPE_UNKNOWN;};
00995   
00996     if(details->fileLocality){
00997       SRMv2__TFileLocality * file_locality = details->fileLocality;
00998       if (*file_locality == SRMv2__TFileLocality__ONLINE ||
00999           *file_locality == SRMv2__TFileLocality__ONLINE_USCOREAND_USCORENEARLINE) {
01000         metadata.fileLocality = SRM_ONLINE;
01001       }
01002       else if (*file_locality == SRMv2__TFileLocality__NEARLINE) {
01003         metadata.fileLocality = SRM_NEARLINE;
01004       };
01005     }
01006     else { metadata.fileLocality = SRM_UNKNOWN; };
01007 
01008     if(details->arrayOfSpaceTokens && details->arrayOfSpaceTokens->__sizestringArray > 0) {
01009       std::string tokens;
01010       for(int i = 0; i < details->arrayOfSpaceTokens->__sizestringArray; i++) {
01011         if (i == details->arrayOfSpaceTokens->__sizestringArray - 1) tokens += details->arrayOfSpaceTokens->stringArray[i];
01012         else tokens += std::string(details->arrayOfSpaceTokens->stringArray[i]) + ",";
01013       }
01014       metadata.arrayOfSpaceTokens = tokens;
01015     }
01016     
01017     if(details->ownerPermission && details->groupPermission && details->otherPermission) {
01018       std::string perm;
01019       if(details->ownerPermission->userID) metadata.owner = details->ownerPermission->userID;
01020       if(details->groupPermission->groupID) metadata.group = details->groupPermission->groupID;
01021       if(details->ownerPermission->mode &&
01022          details->groupPermission->mode &&
01023          details->otherPermission) {
01024         std::string perms;
01025         if (details->ownerPermission->mode & 4) perms += 'r'; else perms += '-';
01026         if (details->ownerPermission->mode & 2) perms += 'w'; else perms += '-';
01027         if (details->ownerPermission->mode & 1) perms += 'x'; else perms += '-';
01028         if (details->groupPermission->mode & 4) perms += 'r'; else perms += '-';
01029         if (details->groupPermission->mode & 2) perms += 'w'; else perms += '-';
01030         if (details->groupPermission->mode & 1) perms += 'x'; else perms += '-';
01031         if (*(details->otherPermission) & 4) perms += 'r'; else perms += '-';
01032         if (*(details->otherPermission) & 2) perms += 'w'; else perms += '-';
01033         if (*(details->otherPermission) & 1) perms += 'x'; else perms += '-';
01034         metadata.permission = perms;
01035        }
01036     }
01037     
01038     if(details->lastModificationTime) {
01039       time_t * mod_time = details->lastModificationTime;
01040       metadata.lastModificationTime = *mod_time;
01041     }
01042     else {metadata.lastModificationTime = 0;}
01043     
01044     if(details->lifetimeAssigned) metadata.lifetimeAssigned = *(details->lifetimeAssigned);
01045     else metadata.lifetimeAssigned = 0;
01046     if(details->lifetimeLeft) metadata.lifetimeLeft = *(details->lifetimeLeft);  
01047     else metadata.lifetimeLeft = 0;
01048     
01049     if(details->retentionPolicyInfo) {
01050       if (details->retentionPolicyInfo->retentionPolicy == SRMv2__TRetentionPolicy__REPLICA) metadata.retentionPolicy = SRM_REPLICA;
01051       else if (details->retentionPolicyInfo->retentionPolicy == SRMv2__TRetentionPolicy__OUTPUT) metadata.retentionPolicy = SRM_OUTPUT;
01052       else if (details->retentionPolicyInfo->retentionPolicy == SRMv2__TRetentionPolicy__CUSTODIAL) metadata.retentionPolicy = SRM_CUSTODIAL;
01053       else metadata.retentionPolicy = SRM_RETENTION_UNKNOWN;
01054     }
01055     else {metadata.retentionPolicy = SRM_RETENTION_UNKNOWN;}
01056     
01057     if(details->fileStorageType) {
01058       SRMv2__TFileStorageType * file_storage_type = details->fileStorageType;
01059       if (*file_storage_type == SRMv2__TFileStorageType__VOLATILE) metadata.fileStorageType = SRM_VOLATILE;
01060       else if (*file_storage_type == SRMv2__TFileStorageType__DURABLE) metadata.fileStorageType = SRM_DURABLE;
01061       else if (*file_storage_type == SRMv2__TFileStorageType__PERMANENT) metadata.fileStorageType = SRM_PERMANENT;
01062       else metadata.fileStorageType = SRM_FILE_STORAGE_UNKNOWN;
01063     }
01064     else {metadata.fileStorageType = SRM_FILE_STORAGE_UNKNOWN;}
01065     
01066     // if any other value, leave undefined
01067   
01068     return metadata;
01069   
01070   }
01071   
01072   SRMReturnCode SRM22Client::releaseGet(SRMClientRequest& req) {
01073   
01074     // Release all the pins referred to by the request token in the request object
01075     SRMv2__srmReleaseFilesRequest * request = new SRMv2__srmReleaseFilesRequest;
01076     if(req.request_token().empty()) {
01077       logger.msg(Arc::ERROR, "No request token specified!");
01078       return SRM_ERROR_OTHER;
01079     };
01080     request->requestToken=(char*)req.request_token().c_str();
01081   
01082     struct SRMv2__srmReleaseFilesResponse_ response_struct;
01083   
01084     int soap_err = SOAP_OK;
01085    
01086     // do the srmReleaseFiles call
01087     if((soap_err=soap_call_SRMv2__srmReleaseFiles(&soapobj, csoap->SOAP_URL(), "srmReleaseFiles", request, response_struct)) != SOAP_OK){
01088       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmReleaseFiles");
01089       soap_print_fault(&soapobj, stderr);
01090       csoap->disconnect();
01091       return SRM_ERROR_SOAP;
01092     };
01093   
01094     if (response_struct.srmReleaseFilesResponse->returnStatus->statusCode != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
01095       char * msg = response_struct.srmReleaseFilesResponse->returnStatus->explanation;
01096       logger.msg(Arc::ERROR, "Error: %s", msg);
01097       csoap->disconnect();
01098       if (response_struct.srmReleaseFilesResponse->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
01099         return SRM_ERROR_TEMPORARY;
01100       return SRM_ERROR_PERMANENT;
01101     };
01102   
01103     // release went ok
01104     logger.msg(Arc::VERBOSE, "Files associated with request token %s released successfully", req.request_token());
01105     return SRM_OK;
01106   
01107   };
01108   
01109   
01110   SRMReturnCode SRM22Client::releasePut(SRMClientRequest& req) {
01111   
01112     // Set the files referred to by the request token in the request object
01113     // which were prepared to put to done
01114     SRMv2__srmPutDoneRequest * request = new SRMv2__srmPutDoneRequest;
01115     if(req.request_token().empty()) {
01116       logger.msg(Arc::ERROR, "No request token specified!");
01117       return SRM_ERROR_OTHER;
01118     };
01119     request->requestToken=(char*)req.request_token().c_str();
01120 
01121     // add the SURLs to the request
01122     xsd__anyURI * req_array = new xsd__anyURI[1];
01123     req_array[0] = (char*)req.surls().front().c_str();
01124   
01125     SRMv2__ArrayOfAnyURI * surls_array = new SRMv2__ArrayOfAnyURI;
01126     surls_array->__sizeurlArray=1;
01127     surls_array->urlArray=req_array;
01128   
01129     request->arrayOfSURLs=surls_array;
01130     
01131     struct SRMv2__srmPutDoneResponse_ response_struct;
01132   
01133     int soap_err = SOAP_OK;
01134    
01135     // do the srmPutDone call
01136     if((soap_err=soap_call_SRMv2__srmPutDone(&soapobj, csoap->SOAP_URL(), "srmPutDone", request, response_struct)) != SOAP_OK){
01137       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmPutDone");
01138       soap_print_fault(&soapobj, stderr);
01139       csoap->disconnect();
01140       return SRM_ERROR_SOAP;
01141     };
01142   
01143     if (response_struct.srmPutDoneResponse->returnStatus->statusCode != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
01144       char * msg = response_struct.srmPutDoneResponse->returnStatus->explanation;
01145       logger.msg(Arc::ERROR, "Error: %s", msg);
01146       csoap->disconnect();
01147       if (response_struct.srmPutDoneResponse->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
01148         return SRM_ERROR_TEMPORARY;
01149       return SRM_ERROR_PERMANENT;
01150     };
01151   
01152     // release went ok
01153     logger.msg(Arc::VERBOSE, "Files associated with request token %s put done successfully", req.request_token());
01154     return SRM_OK;
01155   
01156   };
01157   
01158   SRMReturnCode SRM22Client::abort(SRMClientRequest& req) {
01159   
01160     // Call srmAbortRequest on the files in the request token
01161     SRMv2__srmAbortRequestRequest * request = new SRMv2__srmAbortRequestRequest;
01162     if(req.request_token().empty()) {
01163       logger.msg(Arc::ERROR, "No request token specified!");
01164       return SRM_ERROR_OTHER;
01165     };
01166     request->requestToken=(char*)req.request_token().c_str();
01167   
01168     struct SRMv2__srmAbortRequestResponse_ response_struct;
01169   
01170     int soap_err = SOAP_OK;
01171    
01172     // do the srmAbortRequest call
01173     if((soap_err=soap_call_SRMv2__srmAbortRequest(&soapobj, csoap->SOAP_URL(), "srmAbortRequest", request, response_struct)) != SOAP_OK){
01174       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmAbortRequest");
01175       soap_print_fault(&soapobj, stderr);
01176       csoap->disconnect();
01177       return SRM_ERROR_SOAP;
01178     };
01179   
01180     if (response_struct.srmAbortRequestResponse->returnStatus->statusCode != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
01181       char * msg = response_struct.srmAbortRequestResponse->returnStatus->explanation;
01182       logger.msg(Arc::ERROR, "Error: %s", msg);
01183       csoap->disconnect();
01184       if (response_struct.srmAbortRequestResponse->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
01185         return SRM_ERROR_TEMPORARY;
01186       return SRM_ERROR_PERMANENT;
01187     };
01188   
01189     // release went ok
01190     logger.msg(Arc::VERBOSE, "Files associated with request token %s aborted successfully", req.request_token());
01191     return SRM_OK;
01192   
01193   };
01194   
01195   SRMReturnCode SRM22Client::remove(SRMClientRequest& req) {
01196   
01197     // TODO: bulk remove
01198   
01199     // call info() to find out if we are dealing with a file or directory
01200     SRMClientRequest inforeq(req.surls());
01201     std::list<struct SRMFileMetaData> metadata;
01202   
01203     // set recursion to -1, meaning don't list entries in a dir
01204     SRMReturnCode res = info(inforeq, metadata, -1);
01205     if(res != SRM_OK) {
01206       logger.msg(Arc::ERROR, "Failed to find metadata info on file %s", inforeq.surls().front());
01207       return res;
01208     };
01209   
01210     if(metadata.front().fileType == SRM_FILE) {
01211       logger.msg(Arc::VERBOSE, "Type is file, calling srmRm");
01212       return removeFile(req);
01213     };
01214     if(metadata.front().fileType == SRM_DIRECTORY) {
01215       logger.msg(Arc::VERBOSE, "Type is dir, calling srmRmDir");
01216       return removeDir(req);
01217     };
01218   
01219     logger.msg(Arc::WARNING, "File type is not available, attempting file delete");
01220     if (removeFile(req) == SRM_OK)
01221       return SRM_OK;
01222     logger.msg(Arc::WARNING, "File delete failed, attempting directory delete");
01223     return removeDir(req);
01224   };
01225   
01226   SRMReturnCode SRM22Client::removeFile(SRMClientRequest& req) {
01227   
01228     SRMReturnCode rc = connect();
01229     if (rc != SRM_OK) return rc;
01230 
01231     // construct rm request - only one file requested at a time
01232     xsd__anyURI * req_array = new xsd__anyURI[1];
01233     req_array[0] = (char*)req.surls().front().c_str();
01234   
01235     SRMv2__ArrayOfAnyURI * surls_array = new SRMv2__ArrayOfAnyURI;
01236     surls_array->__sizeurlArray=1;
01237     surls_array->urlArray=req_array;
01238   
01239     // Call srmRm on the files in the request token
01240     SRMv2__srmRmRequest * request = new SRMv2__srmRmRequest;
01241     request->arrayOfSURLs=surls_array;
01242   
01243     struct SRMv2__srmRmResponse_ response_struct;
01244   
01245     int soap_err = SOAP_OK;
01246    
01247     // do the srmRm call
01248     if((soap_err=soap_call_SRMv2__srmRm(&soapobj, csoap->SOAP_URL(), "srmRm", request, response_struct)) != SOAP_OK){
01249       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmRm");
01250       soap_print_fault(&soapobj, stderr);
01251       csoap->disconnect();
01252       return SRM_ERROR_SOAP;
01253     };
01254   
01255     if (response_struct.srmRmResponse->returnStatus->statusCode != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
01256       char * msg = response_struct.srmRmResponse->returnStatus->explanation;
01257       logger.msg(Arc::ERROR, "Error: %s", msg);
01258       csoap->disconnect();
01259       if (response_struct.srmRmResponse->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
01260         return SRM_ERROR_TEMPORARY;
01261       return SRM_ERROR_PERMANENT;
01262     };
01263   
01264     // remove went ok
01265     logger.msg(Arc::VERBOSE, "File %s removed successfully", req.surls().front());
01266     return SRM_OK;
01267   
01268   };
01269   
01270   
01271   SRMReturnCode SRM22Client::removeDir(SRMClientRequest& req) {
01272   
01273     SRMReturnCode rc = connect();
01274     if (rc != SRM_OK) return rc;
01275 
01276     // construct rmdir request - only one file requested at a time
01277     xsd__anyURI surl = (char*)req.surls().front().c_str();
01278   
01279     // Call srmRmdir on the files in the request token
01280     SRMv2__srmRmdirRequest * request = new SRMv2__srmRmdirRequest;
01281     request->SURL = surl;
01282   
01283     struct SRMv2__srmRmdirResponse_ response_struct;
01284   
01285     int soap_err = SOAP_OK;
01286    
01287     // do the srmRm call
01288     if((soap_err=soap_call_SRMv2__srmRmdir(&soapobj, csoap->SOAP_URL(), "srmRmdir", request, response_struct)) != SOAP_OK){
01289       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmRmdir");
01290       soap_print_fault(&soapobj, stderr);
01291       csoap->disconnect();
01292       return SRM_ERROR_SOAP;
01293     };
01294   
01295     if (response_struct.srmRmdirResponse->returnStatus->statusCode != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
01296       char * msg = response_struct.srmRmdirResponse->returnStatus->explanation;
01297       logger.msg(Arc::ERROR, "Error: %s", msg);
01298       csoap->disconnect();
01299       if (response_struct.srmRmdirResponse->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
01300         return SRM_ERROR_TEMPORARY;
01301       return SRM_ERROR_PERMANENT;
01302     };
01303   
01304     // remove went ok
01305     logger.msg(Arc::VERBOSE, "Directory %s removed successfully", req.surls().front());
01306     return SRM_OK;
01307   
01308   };
01309   
01310   SRMReturnCode SRM22Client::copy(SRMClientRequest& req, const std::string& source) {
01311     
01312     // construct copy request
01313     SRMv2__TCopyFileRequest * copyrequest = new SRMv2__TCopyFileRequest;
01314     copyrequest->sourceSURL = (char*)source.c_str();
01315     copyrequest->targetSURL = (char*)req.surls().front().c_str();
01316     
01317     SRMv2__TCopyFileRequest ** req_array = new SRMv2__TCopyFileRequest*[1];
01318     req_array[0] = copyrequest;
01319   
01320     SRMv2__ArrayOfTCopyFileRequest * file_requests = new SRMv2__ArrayOfTCopyFileRequest;
01321     file_requests->__sizerequestArray=1;
01322     file_requests->requestArray=req_array;
01323   
01324     SRMv2__srmCopyRequest * request = new SRMv2__srmCopyRequest;
01325     request->arrayOfFileRequests=file_requests;
01326   
01327     // set space token if supplied
01328     if(req.space_token() != "") request->targetSpaceToken = (char*)req.space_token().c_str();
01329   
01330     struct SRMv2__srmCopyResponse_ response_struct;
01331   
01332     // do the call
01333     int soap_err = SOAP_OK;
01334     if((soap_err=soap_call_SRMv2__srmCopy(&soapobj, csoap->SOAP_URL(), "srmCopy", request, response_struct)) != SOAP_OK){
01335       logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmCopy");
01336       soap_print_fault(&soapobj, stderr);
01337       csoap->disconnect();
01338       return SRM_ERROR_SOAP;
01339     };
01340   
01341     SRMv2__srmCopyResponse * response_inst = response_struct.srmCopyResponse;
01342     SRMv2__TStatusCode return_status = response_inst->returnStatus->statusCode;
01343     SRMv2__ArrayOfTCopyRequestFileStatus * file_statuses= response_inst->arrayOfFileStatuses;
01344   
01345     // store the request token in the request object
01346     if (response_inst->requestToken) req.request_token(response_inst->requestToken);
01347   
01348     // set timeout for copying. Since we don't know the progress of the 
01349     // transfer we hard code a value 10 x the request timeout
01350     time_t copy_timeout = request_timeout * 10;
01351     
01352     // deal with response code
01353     if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED ||
01354         return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
01355       // request is queued - need to wait and query with returned request token
01356       char * request_token = response_inst->requestToken;
01357   
01358       int sleeptime = 1;
01359       if (response_inst->arrayOfFileStatuses->statusArray[0]->estimatedWaitTime)
01360         sleeptime = *(response_inst->arrayOfFileStatuses->statusArray[0]->estimatedWaitTime);
01361       int request_time = 0;
01362   
01363       while(return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS &&
01364             request_time < copy_timeout) {
01365   
01366         // sleep for recommended time (within limits)
01367         sleeptime = sleeptime<1?1:sleeptime;
01368         sleeptime = sleeptime>10?10:sleeptime;
01369         logger.msg(Arc::VERBOSE, "%s: File request %s in SRM queue. Sleeping for %i seconds", req.surls().front(), request_token, sleeptime);
01370         sleep(sleeptime);
01371         request_time += sleeptime;
01372   
01373         SRMv2__srmStatusOfCopyRequestRequest * soc_request = new SRMv2__srmStatusOfCopyRequestRequest;
01374         soc_request->requestToken=request_token;
01375   
01376         struct SRMv2__srmStatusOfCopyRequestResponse_ soc_response_struct;
01377   
01378         // call statusOfCopyRequest
01379         if ((soap_err=soap_call_SRMv2__srmStatusOfCopyRequest(&soapobj, csoap->SOAP_URL(), "srmStatusOfCopyRequest", soc_request, soc_response_struct)) != SOAP_OK) {
01380           logger.msg(Arc::INFO, "SOAP request failed (%s)", "srmStatusOfCopyRequest");
01381           soap_print_fault(&soapobj, stderr);
01382           csoap->disconnect();
01383           req.finished_abort();
01384           return SRM_ERROR_SOAP;
01385         };
01386   
01387         // check return codes - loop will exit on success or return false on error
01388   
01389         return_status = soc_response_struct.srmStatusOfCopyRequestResponse->returnStatus->statusCode;
01390         file_statuses = soc_response_struct.srmStatusOfCopyRequestResponse->arrayOfFileStatuses;
01391         
01392         if (return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREQUEUED ||
01393             return_status == SRMv2__TStatusCode__SRM_USCOREREQUEST_USCOREINPROGRESS) {
01394           // still queued - keep waiting
01395           if(file_statuses->statusArray[0]->estimatedWaitTime)
01396             sleeptime = *(file_statuses->statusArray[0]->estimatedWaitTime);
01397         }
01398         else if (return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
01399           // error
01400           char * msg = soc_response_struct.srmStatusOfCopyRequestResponse->returnStatus->explanation;
01401           logger.msg(Arc::ERROR, "Error: %s", msg);
01402           if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
01403             return SRM_ERROR_TEMPORARY;
01404           return SRM_ERROR_PERMANENT;
01405         };
01406       }; // while
01407   
01408       // check for timeout
01409       if (request_time >= copy_timeout) {
01410         logger.msg(Arc::ERROR, "Error: copy request timed out after %i seconds", copy_timeout);
01411         req.finished_abort();
01412         return SRM_ERROR_TEMPORARY;
01413       }
01414   
01415     } // if file queued
01416   
01417     else if (return_status != SRMv2__TStatusCode__SRM_USCORESUCCESS) {
01418       // any other return code is a failure
01419       char * msg = response_inst->returnStatus->explanation;
01420       logger.msg(Arc::ERROR, "Error: %s", msg);
01421       if (return_status == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
01422         return SRM_ERROR_TEMPORARY;
01423       return SRM_ERROR_PERMANENT;
01424     };
01425     req.finished_success();
01426     return SRM_OK;
01427   };
01428   
01429   SRMReturnCode SRM22Client::mkDir(SRMClientRequest& req) {
01430     
01431     std::string surl = req.surls().front();
01432     std::string::size_type slashpos = surl.find('/', 6);
01433     slashpos = surl.find('/', slashpos+1); // don't create root dir
01434     bool keeplisting = true; // whether to keep checking dir exists
01435     while (slashpos != std::string::npos) {
01436       std::string dirname = surl.substr(0, slashpos);
01437       // list dir to see if it exists
01438       SRMClientRequest listreq(dirname);
01439       std::list<struct SRMFileMetaData> metadata;
01440       if (keeplisting) {
01441         logger.msg(Arc::VERBOSE, "Checking for existence of %s", dirname);
01442         if (info(listreq, metadata, -1, false) == SRM_OK) {
01443           if (metadata.front().fileType == SRM_FILE) {
01444             logger.msg(Arc::ERROR, "File already exists: %s", dirname);
01445             return SRM_ERROR_PERMANENT;
01446           }
01447           slashpos = surl.find("/", slashpos+1);
01448           continue;
01449         }; 
01450       };
01451       
01452       logger.msg(Arc::VERBOSE, "Creating directory %s", dirname);
01453       // construct mkdir request
01454       xsd__anyURI dir = (char*)dirname.c_str();
01455       SRMv2__srmMkdirRequest * request = new SRMv2__srmMkdirRequest;
01456       request->SURL = dir;
01457   
01458       struct SRMv2__srmMkdirResponse_ response_struct;
01459   
01460       int soap_err = SOAP_OK;
01461    
01462       // do the srmMkdir call
01463       if((soap_err=soap_call_SRMv2__srmMkdir(&soapobj, csoap->SOAP_URL(), "srmMkdir", request, response_struct)) != SOAP_OK){
01464         logger.msg(Arc::INFO, "SOAP request failed (srmMkdir)");
01465         soap_print_fault(&soapobj, stderr);
01466         csoap->disconnect();
01467         return SRM_ERROR_SOAP;
01468       };
01469   
01470       slashpos = surl.find("/", slashpos+1);
01471       
01472       // there can be undetectable errors in creating dirs that already exist
01473       // so only report error on creating the final dir
01474       if (response_struct.srmMkdirResponse->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCORESUCCESS ||
01475           response_struct.srmMkdirResponse->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCOREDUPLICATION_USCOREERROR) 
01476         keeplisting = false;
01477       else if (slashpos == std::string::npos) {
01478         char * msg = response_struct.srmMkdirResponse->returnStatus->explanation;
01479         logger.msg(Arc::ERROR, "Error creating directory %s: %s", dir, msg);
01480         csoap->disconnect();
01481         if (response_struct.srmMkdirResponse->returnStatus->statusCode == SRMv2__TStatusCode__SRM_USCOREINTERNAL_USCOREERROR)
01482           return SRM_ERROR_TEMPORARY;
01483         return SRM_ERROR_PERMANENT;
01484       };
01485     };
01486     return SRM_OK;
01487   };
01488 
01489 //} // namespace Arc