diff --git a/cmdline/CTACmdMain.cpp b/cmdline/CTACmdMain.cpp index f86a043cfc8e7195bd6f4d5a8ff2b4232b6b946c..574056d2eca4c9b0e3bf003152411998a046bd07 100644 --- a/cmdline/CTACmdMain.cpp +++ b/cmdline/CTACmdMain.cpp @@ -18,6 +18,7 @@ #include "common/Configuration.hpp" #include "common/exception/Exception.hpp" +#include "common/dataStructures/FrontendReturnCode.hpp" #include "XrdCl/XrdClCopyProcess.hh" @@ -27,6 +28,12 @@ #include <iostream> #include <future> #include <chrono> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> /** * Replaces all occurrences in a string "str" of a substring "from" with the string "to" @@ -98,6 +105,17 @@ std::string formatCommandPath(const int argc, const char **argv) { * @return the return code */ int sendCommand(const int argc, const char **argv) { + + int p[2]; + pipe(p); //Pipe to redirect std::out + int saved_stdout = dup(STDOUT_FILENO); //Saving std::out for later usage (re-redirection) + dup2(p[1], STDOUT_FILENO); //Do the actual redirection + close(p[1]); //Closing the read side of the pipe (not used in our case) + long flags = fcntl(p[0], F_GETFL); + flags |= O_NONBLOCK; //Setting fd as a NONBLOCKING one so that read returns zero when data is finished + fcntl(p[0], F_SETFL, flags); + //std::out is now redirected to p[0] + XrdCl::PropertyList properties; properties.Set("source", formatCommandPath(argc, argv)); properties.Set("target", "-"); //destination is stdout @@ -122,7 +140,21 @@ int sendCommand(const int argc, const char **argv) { { throw cta::exception::Exception(status.ToStr()); } - return 0; + + char rc_char = '0'; + read(p[0], &rc_char, 1); //The cta frontend return code is the first char of the answer + int rc = rc_char - '0'; + char buf[1024]; + bzero(buf, sizeof(buf)); + while(read(p[0], buf, sizeof(buf)-1)>0) { //read the rest of the answer and pipe it to std::err + buf[sizeof(buf)-1]=0; + std::cerr<<buf; + bzero(buf, sizeof(buf)); + } + close(p[0]); + + dup2(saved_stdout, STDOUT_FILENO); + return rc; } /** @@ -132,25 +164,24 @@ int sendCommand(const int argc, const char **argv) { * @param argv The command-line arguments. */ int main(const int argc, const char **argv) { - try { + try { std::chrono::system_clock::time_point five_secs_passed = std::chrono::system_clock::now() + std::chrono::seconds(5); - // call function asynchronously: + // call function asynchronously so we can timeout if server is unreachable: std::future<int> fut = std::async(std::launch::async, sendCommand, argc, argv); if(std::future_status::ready == fut.wait_until(five_secs_passed)) { return fut.get(); } - else { - std::cout<<"Timeout!\n"; - exit(1); + else {//timeout + exit(cta::common::dataStructures::FrontendReturnCode::ctaFrontendTimeout); } } catch(cta::exception::Exception &ex) { std::cerr << "Failed to execute the command. Reason: " << ex.getMessageValue() << std::endl; - return 1; + return cta::common::dataStructures::FrontendReturnCode::ctaErrorNoRetry; } catch (std::exception &ex) { std::cerr << "Failed to execute the command. Reason: " << ex.what() << std::endl; - return 1; + return cta::common::dataStructures::FrontendReturnCode::ctaErrorNoRetry; } catch (...) { std::cerr << "Failed to execute the command for an unknown reason" << std::endl; - return 1; + return cta::common::dataStructures::FrontendReturnCode::ctaErrorNoRetry; } } diff --git a/xroot_plugins/XrdCtaFile.cpp b/xroot_plugins/XrdCtaFile.cpp index 1e0cf962aa6314f938c450d0f7762d3af9026341..2cbb9587eac5787fa6399cfee210ec0b3d3c9bea 100644 --- a/xroot_plugins/XrdCtaFile.cpp +++ b/xroot_plugins/XrdCtaFile.cpp @@ -216,6 +216,7 @@ const char* XrdCtaFile::FName() { // getMmap //------------------------------------------------------------------------------ int XrdCtaFile::getMmap(void **Addr, off_t &Size) { + m_data = std::to_string(m_rc) + m_data; *Addr = const_cast<char *>(m_data.c_str()); Size = m_data.length(); return SFS_OK; //change to "return SFS_ERROR;" in case the read function below is wanted, in that case uncomment the lines in that function. @@ -2013,7 +2014,6 @@ int XrdCtaFile::xCom_archive(const std::vector<std::string> &tokens, const cta:: if(encoded_s!="true" && encoded_s!="false") { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } bool encoded = encoded_s=="true"?true:false; @@ -2036,7 +2036,6 @@ int XrdCtaFile::xCom_archive(const std::vector<std::string> &tokens, const cta:: || storageclass.empty() || instance.empty() || diskfilepath.empty() || diskfileowner.empty() || diskfilegroup.empty() || recoveryblob.empty() || diskpool.empty() || throughput_s.empty()) { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } uint64_t size = stringParameterToUint64("--size", size_s); @@ -2065,7 +2064,6 @@ int XrdCtaFile::xCom_archive(const std::vector<std::string> &tokens, const cta:: std::stringstream res_ss; res_ss << archiveFileId << std::endl; m_data = res_ss.str(); - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } @@ -2080,7 +2078,6 @@ int XrdCtaFile::xCom_retrieve(const std::vector<std::string> &tokens, const cta: if(encoded_s!="true" && encoded_s!="false") { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } bool encoded = encoded_s=="true"?true:false; @@ -2097,7 +2094,6 @@ int XrdCtaFile::xCom_retrieve(const std::vector<std::string> &tokens, const cta: if(user.empty() || group.empty() || id_s.empty() || dsturl.empty() || diskfilepath.empty() || diskfileowner.empty() || diskfilegroup.empty() || recoveryblob.empty() || diskpool.empty() || throughput_s.empty()) { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } uint64_t id = stringParameterToUint64("--id", id_s); @@ -2118,7 +2114,6 @@ int XrdCtaFile::xCom_retrieve(const std::vector<std::string> &tokens, const cta: request.requester=originator; request.dstURL=dsturl; m_scheduler->queueRetrieve(cliIdentity, request); - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } @@ -2132,7 +2127,6 @@ int XrdCtaFile::xCom_deletearchive(const std::vector<std::string> &tokens, const if(encoded_s!="true" && encoded_s!="false") { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } bool encoded = encoded_s=="true"?true:false; @@ -2142,7 +2136,6 @@ int XrdCtaFile::xCom_deletearchive(const std::vector<std::string> &tokens, const if(user.empty() || group.empty() || id_s.empty()) { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } uint64_t id = stringParameterToUint64("--id", id_s); @@ -2153,7 +2146,6 @@ int XrdCtaFile::xCom_deletearchive(const std::vector<std::string> &tokens, const request.archiveFileID=id; request.requester=originator; m_scheduler->deleteArchive(cliIdentity, request); - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } @@ -2168,7 +2160,6 @@ int XrdCtaFile::xCom_cancelretrieve(const std::vector<std::string> &tokens, cons if(encoded_s!="true" && encoded_s!="false") { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } bool encoded = encoded_s=="true"?true:false; @@ -2183,7 +2174,6 @@ int XrdCtaFile::xCom_cancelretrieve(const std::vector<std::string> &tokens, cons if(user.empty() || group.empty() || id_s.empty() || dsturl.empty() || diskfilepath.empty() || diskfileowner.empty() || diskfilegroup.empty() || recoveryblob.empty()) { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } uint64_t id = stringParameterToUint64("--id", id_s); @@ -2201,7 +2191,6 @@ int XrdCtaFile::xCom_cancelretrieve(const std::vector<std::string> &tokens, cons request.requester=originator; request.dstURL=dsturl; m_scheduler->cancelRetrieve(cliIdentity, request); - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } @@ -2216,7 +2205,6 @@ int XrdCtaFile::xCom_updatefilestorageclass(const std::vector<std::string> &toke if(encoded_s!="true" && encoded_s!="false") { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } bool encoded = encoded_s=="true"?true:false; @@ -2231,7 +2219,6 @@ int XrdCtaFile::xCom_updatefilestorageclass(const std::vector<std::string> &toke if(user.empty() || group.empty() || id_s.empty() || storageclass.empty() || diskfilepath.empty() || diskfileowner.empty() || diskfilegroup.empty() || recoveryblob.empty()) { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } uint64_t id = stringParameterToUint64("--id", id_s); @@ -2249,7 +2236,6 @@ int XrdCtaFile::xCom_updatefilestorageclass(const std::vector<std::string> &toke request.requester=originator; request.storageClass=storageclass; m_scheduler->updateFileStorageClass(cliIdentity, request); - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } @@ -2264,7 +2250,6 @@ int XrdCtaFile::xCom_updatefileinfo(const std::vector<std::string> &tokens, cons if(encoded_s!="true" && encoded_s!="false") { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } bool encoded = encoded_s=="true"?true:false; @@ -2275,8 +2260,7 @@ int XrdCtaFile::xCom_updatefileinfo(const std::vector<std::string> &tokens, cons std::string recoveryblob = getOptionValue(tokens, "", "--recoveryblob", encoded); if(id_s.empty() || diskfilepath.empty() || diskfileowner.empty() || diskfilegroup.empty() || recoveryblob.empty()) { m_data = help.str(); - m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; + m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; return SFS_OK; } uint64_t id = stringParameterToUint64("--id", id_s); @@ -2289,7 +2273,6 @@ int XrdCtaFile::xCom_updatefileinfo(const std::vector<std::string> &tokens, cons request.drData=drData; request.archiveFileID=id; m_scheduler->updateFileInfo(cliIdentity, request); - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } @@ -2303,7 +2286,6 @@ int XrdCtaFile::xCom_liststorageclass(const std::vector<std::string> &tokens, co if(encoded_s!="true" && encoded_s!="false") { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } bool encoded = encoded_s=="true"?true:false; @@ -2312,7 +2294,6 @@ int XrdCtaFile::xCom_liststorageclass(const std::vector<std::string> &tokens, co if(user.empty() || group.empty()) { m_data = help.str(); m_rc = cta::common::dataStructures::FrontendReturnCode::userErrorNoRetry; - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; } cta::common::dataStructures::UserIdentity originator; @@ -2321,7 +2302,6 @@ int XrdCtaFile::xCom_liststorageclass(const std::vector<std::string> &tokens, co cta::common::dataStructures::ListStorageClassRequest request; request.requester=originator; m_scheduler->listStorageClass(cliIdentity, request); - m_data = std::string("[") + cta::common::dataStructures::toString(m_rc) + "]\n" + m_data; return SFS_OK; }