Commit 92440616 authored by Maiken's avatar Maiken

Merge branch 'bug_3777' into 'master'

Redirect logging messages from external gridftp process into logger

See merge request nordugrid/arc!531
parents 55585f2f e329943e
......@@ -42,23 +42,15 @@ namespace ArcDMCGridFTP {
argv.push_front("-s");
argv.push_front(Arc::level_to_string(logger.getThreshold()));
argv.push_front("-V");
LogFormat format = LogDestination::getDefaultFormat();
std::list<LogDestination*> destinations = logger.getDestinations();
if(!destinations.empty()) {
if(destinations.front()) format = destinations.front()->getFormat();
} else {
std::list<LogDestination*> destinations = Logger::getRootLogger().getDestinations();
if(!destinations.empty()) {
if(destinations.front()) format = destinations.front()->getFormat();
}
}
LogFormat format = ShortFormat; // Header is then added while redirecting stderr
argv.push_front(Arc::tostring(format));
argv.push_front("-F");
argv.push_front(Arc::ArcLocation::Get()+G_DIR_SEPARATOR_S+PKGLIBSUBDIR+G_DIR_SEPARATOR_S+"arc-dmcgridftp");
run = new Run(argv);
run->KeepStdin(false);
run->KeepStdout(false);
run->KeepStderr(true);
run->KeepStderr(false);
run->AssignStderr(log_redirect);
if(!run->Start()) {
return DataStatus(errCode, "Failed to start helper process for "+url.plainstr());
}
......@@ -530,6 +522,37 @@ namespace ArcDMCGridFTP {
return true;
}
std::string::size_type const DataPointGridFTPDelegate::LogRedirect::level_size_max_ = 32;
std::string::size_type const DataPointGridFTPDelegate::LogRedirect::buffer_size_max_ = 4096;
void DataPointGridFTPDelegate::LogRedirect::Append(char const* data, unsigned int size) {
while(size >= 0) {
char const* sep = (char const*)memchr(data, '\n', size);
if (sep == NULL) break;
if(buffer_.length() < buffer_size_max_) buffer_.append(data,sep-data);
Flush();
size -= sep-data+1;
data = sep+1;
}
if (size > 0) buffer_.append(data,size);
}
void DataPointGridFTPDelegate::LogRedirect::Flush() {
if(!buffer_.empty()) {
// I could not find any better method for recovering message level
std::string::size_type dsep = buffer_.find(':');
if((dsep != std::string::npos) &&
(dsep < level_size_max_) &&
(string_to_level(buffer_.substr(0,dsep),level_))) {
dsep += 1;
} else {
dsep = 0;
}
logger.msg(level_, "%s", buffer_.c_str()+dsep);
buffer_.clear();
}
}
} // namespace ArcDMCGridFTP
extern Arc::PluginDescriptor const ARC_PLUGINS_TABLE_NAME[] = {
......
......@@ -30,7 +30,22 @@ namespace ArcDMCGridFTP {
class DataPointGridFTPDelegate
: public DataPointDirect {
private:
class LogRedirect: public Run::Data {
public:
LogRedirect(): level_(FATAL) { };
virtual ~LogRedirect() { Flush(); };
virtual void Append(char const* data, unsigned int size);
void Flush();
private:
// for sanity checks
static std::string::size_type const level_size_max_;
static std::string::size_type const buffer_size_max_;
LogLevel level_;
std::string buffer_;
};
static Logger logger;
LogRedirect log_redirect;
int ftp_threads;
bool autodir;
......
......@@ -19,10 +19,33 @@ namespace Arc {
* \headerfile Run.h arc/Run.h */
class Run {
friend class RunPump;
public:
class Data {
public:
virtual ~Data() {};
virtual void Append(char const* data, unsigned int size) {};
virtual void Remove(unsigned int size) {};
virtual char const* Get() const { return NULL; };
virtual unsigned int Size() const { return 0; };
};
private:
Run(const Run&);
Run& operator=(Run&);
protected:
class StringData: public Data {
public:
StringData();
virtual ~StringData();
void Assign(std::string& str);
virtual void Append(char const* data, unsigned int size);
virtual void Remove(unsigned int size);
virtual char const* Get() const;
virtual unsigned int Size() const;
private:
std::string* content_;
};
// working directory
std::string working_directory;
// Handles
......@@ -30,9 +53,12 @@ namespace Arc {
int stderr_;
int stdin_;
// Associated string containers
std::string *stdout_str_;
std::string *stderr_str_;
std::string *stdin_str_;
Data *stdout_str_;
Data *stderr_str_;
Data *stdin_str_;
StringData stdout_str_wrap_;
StringData stderr_str_wrap_;
StringData stdin_str_wrap_;
//
bool stdout_keep_;
bool stderr_keep_;
......@@ -141,14 +167,17 @@ namespace Arc {
/** This method must be called before Start(). str object
must be valid as long as this object exists. */
void AssignStdout(std::string& str);
void AssignStdout(Data& str);
/// Associate stderr handle of executable with string.
/** This method must be called before Start(). str object
must be valid as long as this object exists. */
void AssignStderr(std::string& str);
void AssignStderr(Data& str);
/// Associate stdin handle of executable with string.
/** This method must be called before Start(). str object
must be valid as long as this object exists. */
void AssignStdin(std::string& str);
void AssignStdin(Data& str);
/// Keep stdout same as parent's if keep = true.
void KeepStdout(bool keep = true);
/// Keep stderr same as parent's if keep = true.
......
......@@ -602,7 +602,7 @@ namespace Arc {
CloseStdout();
return false;
} else {
stdout_str_->append(buf, l);
stdout_str_->Append(buf, l);
}
} else {
// Event shouldn't happen if not expected
......@@ -619,7 +619,7 @@ namespace Arc {
CloseStderr();
return false;
} else {
stderr_str_->append(buf, l);
stderr_str_->Append(buf, l);
}
} else {
// Event shouldn't happen if not expected
......@@ -630,17 +630,16 @@ namespace Arc {
bool Run::stdin_handler(Glib::IOCondition) {
if (stdin_str_) {
if (stdin_str_->length() == 0) {
if (stdin_str_->Size() == 0) {
CloseStdin();
stdin_str_ = NULL;
} else {
int l = WriteStdin(0, stdin_str_->c_str(), stdin_str_->length());
int l = WriteStdin(0, stdin_str_->Get(), stdin_str_->Size());
if (l == -1) {
CloseStdin();
return false;
} else {
// Not very effective
*stdin_str_ = stdin_str_->substr(l);
stdin_str_->Remove(l);
}
}
} else {
......@@ -849,15 +848,42 @@ namespace Arc {
}
void Run::AssignStdout(std::string& str) {
if (!running_) stdout_str_ = &str;
if (!running_) {
stdout_str_wrap_.Assign(str);
stdout_str_ = &stdout_str_wrap_;
}
}
void Run::AssignStdout(Data& str) {
if (!running_) {
stdout_str_ = &str;
}
}
void Run::AssignStderr(std::string& str) {
if (!running_) stderr_str_ = &str;
if (!running_) {
stderr_str_wrap_.Assign(str);
stderr_str_ = &stderr_str_wrap_;
}
}
void Run::AssignStderr(Data& str) {
if (!running_) {
stderr_str_ = &str;
}
}
void Run::AssignStdin(std::string& str) {
if (!running_) stdin_str_ = &str;
if (!running_) {
stdin_str_wrap_.Assign(str);
stdin_str_ = &stdin_str_wrap_;
}
}
void Run::AssignStdin(Data& str) {
if (!running_) {
stdin_str_ = &str;
}
}
void Run::KeepStdout(bool keep) {
......@@ -1071,5 +1097,35 @@ namespace Arc {
return Listen(-1,error);
}
Run::StringData::StringData(): content_(NULL) {
}
Run::StringData::~StringData() {
}
void Run::StringData::Assign(std::string& str) {
content_ = &str;
}
void Run::StringData::Append(char const* data, unsigned int size) {
if(content_) content_->append(data, size);
}
void Run::StringData::Remove(unsigned int size) {
if(content_) content_->erase(0, size);
}
char const* Run::StringData::Get() const {
if(!content_) return NULL;
return content_->c_str();
}
unsigned int Run::StringData::Size() const {
if(!content_) return 0;
return content_->length();
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment