Skip to content
Snippets Groups Projects
Commit 9153377b authored by Steven Murray's avatar Steven Murray
Browse files

Replaced pipe code of cta command-line with XrdCl::File Open, Read and Close

This commit works towards fixing the following issue:

https://gitlab.cern.ch/cta/CTA/issues/46
issues when creating 100+1000 files on eos-cta via Kubernetes setup
parent a5ab3f90
No related branches found
No related tags found
No related merge requests found
......@@ -35,6 +35,7 @@
#include <string.h>
#include <unistd.h>
#include <stdexcept>
#include <xrootd/XrdCl/XrdClFile.hh>
/**
* Returns true if --stderr is on the command-line.
......@@ -119,64 +120,70 @@ std::string formatCommandPath(const int argc, const char **argv) {
* @return the return code
*/
int sendCommand(const int argc, const char **argv) {
int rc = 0;
const bool writeToStderr = stderrIsOnTheCmdLine(argc, 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 write side of the pipe (replaced by std::out)
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
XrdCl::PropertyList results;
XrdCl::CopyProcess copyProcess;
//ConnectionWindow timeout
XrdCl::Env *env = XrdCl::DefaultEnv::GetEnv();
env->PutInt("ConnectionWindow", 3); //timeout in 3 secs if frontend server does not respond
XrdCl::XRootDStatus status = copyProcess.AddJob(properties, &results);
if(!status.IsOK())
const std::string cmdPath = formatCommandPath(argc, argv);
XrdCl::File xrootFile;
// Open the xroot file reprsenting the execution of the command
{
throw std::runtime_error(status.ToStr());
const XrdCl::XRootDStatus openStatus = xrootFile.Open(cmdPath, XrdCl::OpenFlags::Read);
if(!openStatus.IsOK()) {
throw std::runtime_error(std::string("Failed to open ") + cmdPath + ": " + openStatus.GetErrorMessage());
}
}
status = copyProcess.Prepare();
if(!status.IsOK())
// The cta frontend return code is the first char of the answer
{
throw std::runtime_error(status.ToStr());
uint64_t readOffset = 0;
uint32_t bytesRead = 0;
char rc_char = '0';
const XrdCl::XRootDStatus readStatus = xrootFile.Read(readOffset, 1, &rc_char, bytesRead);
if(!readStatus.IsOK()) {
throw std::runtime_error(std::string("Failed to read first byte from ") + cmdPath + ": " +
readStatus.GetErrorMessage());
}
if(bytesRead != 1) {
throw std::runtime_error(std::string("Failed to read first byte from ") + cmdPath +
": Expected to read exactly 1 byte, actually read " + std::to_string(bytesRead) + " bytes");
}
rc = rc_char - '0';
}
XrdCl::CopyProgressHandler copyProgressHandler;
status = copyProcess.Run(&copyProgressHandler);
if(!status.IsOK())
// Read and print the command result
{
throw std::runtime_error(status.ToStr());
uint64_t readOffset = 1; // The first character at offset 0 has already been read
uint32_t bytesRead = 0;
do {
bytesRead = 0;
char buf[1024];
memset(buf, 0, sizeof(buf));
const XrdCl::XRootDStatus readStatus = xrootFile.Read(readOffset, sizeof(buf - 1), buf, bytesRead);
if(!readStatus.IsOK()) {
//throw std::runtime_error(std::string("Failed to read ") + cmdPath + ": " + readStatus.GetErrorMessage());
throw std::runtime_error(std::string("Failed to read ") + cmdPath + ": " + readStatus.ToString());
}
if(bytesRead > 0) {
std::cout << buf;
if(writeToStderr) {
std::cerr<<buf;
}
}
readOffset += bytesRead;
} while(bytesRead > 0);
}
dup2(saved_stdout, STDOUT_FILENO); //re-redirecting std::out to the original (everything we want is in the pipe by now)
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::cout<<buf;
if(writeToStderr) {
std::cerr<<buf;
// Close the xroot file reprsenting the execution of the command
{
const XrdCl::XRootDStatus closeStatus = xrootFile.Close();
if(!closeStatus.IsOK()) {
throw std::runtime_error(std::string("Failed to close ") + cmdPath + ": " + closeStatus.GetErrorMessage());
}
bzero(buf, sizeof(buf));
}
close(p[0]);
return rc;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment