mirror of
https://github.com/ashaduri/gsmartcontrol.git
synced 2026-09-27 06:15:45 +00:00
Refactored command executors (better naming, documentation).
This commit is contained in:
+3
-2
@@ -20,8 +20,9 @@ src/gsc_preferences_window.cpp
|
||||
src/gsc_text_window.h
|
||||
|
||||
src/applib/app_builder_widget.h
|
||||
src/applib/cli_executors.h
|
||||
src/applib/cmdex_sync_gui.cpp
|
||||
src/applib/cli_executor_3ware.h
|
||||
src/applib/cli_executor_areca.h
|
||||
src/applib/command_executor_gui.cpp
|
||||
src/applib/selftest.cpp
|
||||
src/applib/smartctl_executor.cpp
|
||||
src/applib/smartctl_executor.h
|
||||
|
||||
@@ -7,20 +7,21 @@
|
||||
add_library(applib STATIC)
|
||||
|
||||
target_sources(applib PRIVATE
|
||||
async_command_executor.cpp
|
||||
async_command_executor.h
|
||||
app_builder_widget.h
|
||||
app_gtkmm_features.h
|
||||
app_gtkmm_utils.cpp
|
||||
app_gtkmm_utils.h
|
||||
app_pcrecpp.h
|
||||
cli_executors.h
|
||||
cmdex.cpp
|
||||
cmdex.h
|
||||
cmdex_sync.cpp
|
||||
cmdex_sync_gui.cpp
|
||||
cmdex_sync_gui.h
|
||||
cmdex_sync.h
|
||||
executor_factory.cpp
|
||||
executor_factory.h
|
||||
command_executor.h
|
||||
command_executor.cpp
|
||||
command_executor_3ware.h
|
||||
command_executor_areca.h
|
||||
command_executor_gui.cpp
|
||||
command_executor_gui.h
|
||||
command_executor_factory.cpp
|
||||
command_executor_factory.h
|
||||
gui_utils.cpp
|
||||
gui_utils.h
|
||||
selftest.cpp
|
||||
|
||||
@@ -9,7 +9,6 @@ Copyright:
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
// TODO Remove this in gtkmm4.
|
||||
#include "local_glibmm.h"
|
||||
|
||||
#include <string>
|
||||
@@ -28,7 +27,7 @@ Copyright:
|
||||
#include "hz/debug.h"
|
||||
#include "hz/env_tools.h" // hz::ScopedEnv
|
||||
|
||||
#include "cmdex.h"
|
||||
#include "async_command_executor.h"
|
||||
|
||||
|
||||
using hz::Error;
|
||||
@@ -46,21 +45,21 @@ extern "C" {
|
||||
/// Child process watcher callback
|
||||
inline void cmdex_child_watch_handler(GPid arg_pid, int waitpid_status, gpointer data)
|
||||
{
|
||||
Cmdex::on_child_watch_handler(arg_pid, waitpid_status, data);
|
||||
AsyncCommandExecutor::on_child_watch_handler(arg_pid, waitpid_status, data);
|
||||
}
|
||||
|
||||
|
||||
/// Child process stdout handler callback
|
||||
inline gboolean cmdex_on_channel_io_stdout(GIOChannel* source, GIOCondition cond, gpointer data)
|
||||
{
|
||||
return Cmdex::on_channel_io(source, cond, static_cast<Cmdex*>(data), Cmdex::Channel::standard_output);
|
||||
return AsyncCommandExecutor::on_channel_io(source, cond, static_cast<AsyncCommandExecutor*>(data), AsyncCommandExecutor::Channel::standard_output);
|
||||
}
|
||||
|
||||
|
||||
/// Child process stderr handler callback
|
||||
inline gboolean cmdex_on_channel_io_stderr(GIOChannel* source, GIOCondition cond, gpointer data)
|
||||
{
|
||||
return Cmdex::on_channel_io(source, cond, static_cast<Cmdex*>(data), Cmdex::Channel::standard_error);
|
||||
return AsyncCommandExecutor::on_channel_io(source, cond, static_cast<AsyncCommandExecutor*>(data), AsyncCommandExecutor::Channel::standard_error);
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +67,7 @@ extern "C" {
|
||||
inline gboolean cmdex_on_term_timeout(gpointer data)
|
||||
{
|
||||
DBG_FUNCTION_ENTER_MSG;
|
||||
auto* self = static_cast<Cmdex*>(data);
|
||||
auto* self = static_cast<AsyncCommandExecutor*>(data);
|
||||
self->try_stop(hz::Signal::Terminate);
|
||||
return FALSE; // one-time call
|
||||
}
|
||||
@@ -78,7 +77,7 @@ extern "C" {
|
||||
inline gboolean cmdex_on_kill_timeout(gpointer data)
|
||||
{
|
||||
DBG_FUNCTION_ENTER_MSG;
|
||||
auto* self = static_cast<Cmdex*>(data);
|
||||
auto* self = static_cast<AsyncCommandExecutor*>(data);
|
||||
self->try_stop(hz::Signal::Kill);
|
||||
return FALSE; // one-time call
|
||||
}
|
||||
@@ -90,8 +89,36 @@ extern "C" {
|
||||
|
||||
|
||||
|
||||
AsyncCommandExecutor::AsyncCommandExecutor(AsyncCommandExecutor::exited_callback_func_t exited_cb)
|
||||
: timer_(g_timer_new()),
|
||||
exited_callback_(std::move(exited_cb))
|
||||
{ }
|
||||
|
||||
bool Cmdex::execute()
|
||||
|
||||
|
||||
AsyncCommandExecutor::~AsyncCommandExecutor()
|
||||
{
|
||||
// This will help if object is destroyed after the command has exited, but before
|
||||
// stopped_cleanup() has been called.
|
||||
stopped_cleanup();
|
||||
|
||||
g_timer_destroy(timer_);
|
||||
|
||||
// no need to destroy the channels - stopped_cleanup() calls
|
||||
// cleanup_members(), which deletes them.
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AsyncCommandExecutor::set_command(const std::string& command_exec, const std::string& command_args)
|
||||
{
|
||||
command_exec_ = command_exec;
|
||||
command_args_ = command_args;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool AsyncCommandExecutor::execute()
|
||||
{
|
||||
DBG_FUNCTION_ENTER_MSG;
|
||||
if (this->running_ || this->stopped_cleanup_needed()) {
|
||||
@@ -213,9 +240,7 @@ bool Cmdex::execute()
|
||||
|
||||
|
||||
|
||||
|
||||
// send SIGTERM(15) (terminate)
|
||||
bool Cmdex::try_stop(hz::Signal sig)
|
||||
bool AsyncCommandExecutor::try_stop(hz::Signal sig)
|
||||
{
|
||||
DBG_FUNCTION_ENTER_MSG;
|
||||
if (!this->running_ || this->pid_ == 0)
|
||||
@@ -239,7 +264,7 @@ bool Cmdex::try_stop(hz::Signal sig)
|
||||
|
||||
|
||||
|
||||
bool Cmdex::try_kill()
|
||||
bool AsyncCommandExecutor::try_kill()
|
||||
{
|
||||
DBG_TRACE_POINT_AUTO;
|
||||
return try_stop(hz::Signal::Kill);
|
||||
@@ -247,7 +272,7 @@ bool Cmdex::try_kill()
|
||||
|
||||
|
||||
|
||||
void Cmdex::set_stop_timeouts(std::chrono::milliseconds term_timeout_msec, std::chrono::milliseconds kill_timeout_msec)
|
||||
void AsyncCommandExecutor::set_stop_timeouts(std::chrono::milliseconds term_timeout_msec, std::chrono::milliseconds kill_timeout_msec)
|
||||
{
|
||||
DBG_FUNCTION_ENTER_MSG;
|
||||
DBG_ASSERT(term_timeout_msec.count() == 0 || kill_timeout_msec.count() == 0 || kill_timeout_msec > term_timeout_msec);
|
||||
@@ -268,8 +293,7 @@ void Cmdex::set_stop_timeouts(std::chrono::milliseconds term_timeout_msec, std::
|
||||
|
||||
|
||||
|
||||
|
||||
void Cmdex::unset_stop_timeouts()
|
||||
void AsyncCommandExecutor::unset_stop_timeouts()
|
||||
{
|
||||
DBG_FUNCTION_ENTER_MSG;
|
||||
if (event_source_id_term != 0) {
|
||||
@@ -290,8 +314,7 @@ void Cmdex::unset_stop_timeouts()
|
||||
|
||||
|
||||
|
||||
// Executed manually by the caller.
|
||||
void Cmdex::stopped_cleanup()
|
||||
void AsyncCommandExecutor::stopped_cleanup()
|
||||
{
|
||||
DBG_FUNCTION_ENTER_MSG;
|
||||
if (this->running_ || !this->stopped_cleanup_needed()) // huh?
|
||||
@@ -335,13 +358,10 @@ void Cmdex::stopped_cleanup()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Called when child exits
|
||||
void Cmdex::on_child_watch_handler([[maybe_unused]] GPid arg_pid, int waitpid_status, gpointer data)
|
||||
void AsyncCommandExecutor::on_child_watch_handler([[maybe_unused]] GPid arg_pid, int waitpid_status, gpointer data)
|
||||
{
|
||||
// DBG_FUNCTION_ENTER_MSG;
|
||||
auto* self = static_cast<Cmdex*>(data);
|
||||
auto* self = static_cast<AsyncCommandExecutor*>(data);
|
||||
|
||||
g_timer_stop(self->timer_); // stop the timer
|
||||
|
||||
@@ -396,13 +416,11 @@ void Cmdex::on_child_watch_handler([[maybe_unused]] GPid arg_pid, int waitpid_st
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
gboolean Cmdex::on_channel_io(GIOChannel* channel,
|
||||
GIOCondition cond, Cmdex* self, Channel channel_type)
|
||||
gboolean AsyncCommandExecutor::on_channel_io(GIOChannel* channel,
|
||||
GIOCondition cond, AsyncCommandExecutor* self, Channel channel_type)
|
||||
{
|
||||
// DBG_FUNCTION_ENTER_MSG;
|
||||
// debug_out_dump("app", "Cmdex::on_channel_io("
|
||||
// debug_out_dump("app", "AsyncCommandExecutor::on_channel_io("
|
||||
// << (type == Channel::standard_output ? "STDOUT" : "STDERR") << ") " << int(cond) << "\n");
|
||||
|
||||
bool continue_events = true;
|
||||
@@ -456,7 +474,80 @@ gboolean Cmdex::on_channel_io(GIOChannel* channel,
|
||||
|
||||
|
||||
|
||||
void Cmdex::cleanup_members()
|
||||
bool AsyncCommandExecutor::stopped_cleanup_needed()
|
||||
{
|
||||
return (child_watch_handler_called_);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool AsyncCommandExecutor::is_running() const
|
||||
{
|
||||
return running_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AsyncCommandExecutor::set_buffer_sizes(gsize stdout_buffer_size, gsize stderr_buffer_size)
|
||||
{
|
||||
if (stdout_buffer_size > 0) {
|
||||
channel_stdout_buffer_size_ = stdout_buffer_size; // 100K by default
|
||||
}
|
||||
if (stderr_buffer_size > 0) {
|
||||
channel_stderr_buffer_size_ = stderr_buffer_size; // 10K by default
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string AsyncCommandExecutor::get_stdout_str(bool clear_existing)
|
||||
{
|
||||
// debug_out_dump("app", str_stdout_);
|
||||
if (clear_existing) {
|
||||
std::string ret = str_stdout_;
|
||||
str_stdout_.clear();
|
||||
return ret;
|
||||
}
|
||||
return str_stdout_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string AsyncCommandExecutor::get_stderr_str(bool clear_existing)
|
||||
{
|
||||
if (clear_existing) {
|
||||
std::string ret = str_stderr_;
|
||||
str_stderr_.clear();
|
||||
return ret;
|
||||
}
|
||||
return str_stderr_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double AsyncCommandExecutor::get_execution_time_sec()
|
||||
{
|
||||
gulong microsec = 0;
|
||||
return g_timer_elapsed(timer_, µsec);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AsyncCommandExecutor::set_exit_status_translator(AsyncCommandExecutor::exit_status_translator_func_t func)
|
||||
{
|
||||
translator_func_ = std::move(func);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AsyncCommandExecutor::set_exited_callback(AsyncCommandExecutor::exited_callback_func_t func)
|
||||
{
|
||||
exited_callback_ = std::move(func);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AsyncCommandExecutor::cleanup_members()
|
||||
{
|
||||
kill_signal_sent_ = 0;
|
||||
child_watch_handler_called_ = false;
|
||||
@@ -4,8 +4,8 @@ Copyright:
|
||||
(C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef APP_CMDEX_H
|
||||
#define APP_CMDEX_H
|
||||
#ifndef ASYNC_COMMAND_EXECUTOR_H
|
||||
#define ASYNC_COMMAND_EXECUTOR_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <string>
|
||||
@@ -22,7 +22,7 @@ Copyright:
|
||||
/// 1. Add a callback to signal_exited.
|
||||
/// 2. Manually poll stopped_cleanup_needed().
|
||||
/// In both cases, stopped_cleanup() must be called afterwards.
|
||||
class Cmdex : public hz::ErrorHolder {
|
||||
class AsyncCommandExecutor : public hz::ErrorHolder {
|
||||
public:
|
||||
|
||||
/// A function that translates the exit error code into a readable string
|
||||
@@ -33,37 +33,31 @@ class Cmdex : public hz::ErrorHolder {
|
||||
|
||||
|
||||
/// Constructor
|
||||
explicit Cmdex(exited_callback_func_t exited_cb = nullptr)
|
||||
: timer_(g_timer_new()),
|
||||
exited_callback_(std::move(exited_cb))
|
||||
{ }
|
||||
explicit AsyncCommandExecutor(exited_callback_func_t exited_cb = nullptr);
|
||||
|
||||
/// Deleted
|
||||
AsyncCommandExecutor(const AsyncCommandExecutor& other) = delete;
|
||||
|
||||
/// Deleted
|
||||
AsyncCommandExecutor(const AsyncCommandExecutor&& other) = delete;
|
||||
|
||||
/// Deleted
|
||||
AsyncCommandExecutor& operator=(const AsyncCommandExecutor& other) = delete;
|
||||
|
||||
/// Deleted
|
||||
AsyncCommandExecutor& operator=(const AsyncCommandExecutor&& other) = delete;
|
||||
|
||||
|
||||
/// Destructor. Don't destroy this object unless the child has exited. It will leak stuff
|
||||
/// and possibly crash, etc... .
|
||||
~Cmdex() override
|
||||
{
|
||||
// This will help if object is destroyed after the command has exited, but before
|
||||
// stopped_cleanup() has been called.
|
||||
stopped_cleanup();
|
||||
|
||||
g_timer_destroy(timer_);
|
||||
|
||||
// no need to destroy the channels - stopped_cleanup() calls
|
||||
// cleanup_members(), which deletes them.
|
||||
}
|
||||
~AsyncCommandExecutor() override;
|
||||
|
||||
|
||||
/// Set the command to execute. Call before execute().
|
||||
/// Note: The command and the arguments _must_ be shell-escaped.
|
||||
/// Use g_shell_quote() or Glib::shell_quote(). Note that each argument
|
||||
/// must be escaped separately.
|
||||
void set_command(const std::string& command_exec, const std::string& command_args)
|
||||
{
|
||||
command_exec_ = command_exec;
|
||||
command_args_ = command_args;
|
||||
}
|
||||
void set_command(const std::string& command_exec, const std::string& command_args);
|
||||
|
||||
|
||||
/// Launch the command.
|
||||
@@ -92,7 +86,6 @@ class Cmdex : public hz::ErrorHolder {
|
||||
/// This has an effect only if the command is running (after execute()).
|
||||
void unset_stop_timeouts();
|
||||
|
||||
|
||||
/// If stopped_cleanup_needed() returned true, call this. The command
|
||||
/// should be exited by this time. Must be called before the next execute().
|
||||
void stopped_cleanup();
|
||||
@@ -101,19 +94,13 @@ class Cmdex : public hz::ErrorHolder {
|
||||
/// Returns true if command has stopped.
|
||||
/// Call repeatedly in a waiting function, after execute().
|
||||
/// When it returns true, call stopped_cleanup().
|
||||
bool stopped_cleanup_needed()
|
||||
{
|
||||
return (child_watch_handler_called_);
|
||||
}
|
||||
bool stopped_cleanup_needed();
|
||||
|
||||
|
||||
/// Check if the process is running. Note that if this returns false, it doesn't mean that
|
||||
/// the io channels have been closed or that the data may be read safely. Poll
|
||||
/// stopped_cleanup_needed() instead.
|
||||
[[nodiscard]] bool is_running() const
|
||||
{
|
||||
return running_;
|
||||
}
|
||||
[[nodiscard]] bool is_running() const;
|
||||
|
||||
|
||||
|
||||
@@ -129,69 +116,36 @@ class Cmdex : public hz::ErrorHolder {
|
||||
/// Another way is to delay the command exit so that the event source callback
|
||||
/// catches on and reads the buffer.
|
||||
// Use 0 to ignore the parameter. Call this before execute().
|
||||
void set_buffer_sizes(gsize stdout_buffer_size = 0, gsize stderr_buffer_size = 0)
|
||||
{
|
||||
if (stdout_buffer_size)
|
||||
channel_stdout_buffer_size_ = stdout_buffer_size; // 100K by default
|
||||
if (stderr_buffer_size)
|
||||
channel_stderr_buffer_size_ = stderr_buffer_size; // 10K by default
|
||||
}
|
||||
void set_buffer_sizes(gsize stdout_buffer_size = 0, gsize stderr_buffer_size = 0);
|
||||
|
||||
|
||||
|
||||
/// If stdout_make_str_as_available_ is false, call this after stopped_cleanup(),
|
||||
/// before next execute(). If it's true, you may call this before the command has
|
||||
/// stopped, but it will decrease performance significantly.
|
||||
std::string get_stdout_str(bool clear_existing = false)
|
||||
{
|
||||
// debug_out_dump("app", str_stdout_);
|
||||
if (clear_existing) {
|
||||
std::string ret = str_stdout_;
|
||||
str_stdout_.clear();
|
||||
return ret;
|
||||
}
|
||||
return str_stdout_;
|
||||
}
|
||||
std::string get_stdout_str(bool clear_existing = false);
|
||||
|
||||
|
||||
/// See notes on get_stdout_str().
|
||||
std::string get_stderr_str(bool clear_existing = false)
|
||||
{
|
||||
if (clear_existing) {
|
||||
std::string ret = str_stderr_;
|
||||
str_stderr_.clear();
|
||||
return ret;
|
||||
}
|
||||
return str_stderr_;
|
||||
}
|
||||
/// See notes for \ref get_stdout_str().
|
||||
std::string get_stderr_str(bool clear_existing = false);
|
||||
|
||||
|
||||
/// Return execution time, in seconds. Call this after execute().
|
||||
double get_execution_time()
|
||||
{
|
||||
gulong microsec = 0;
|
||||
return g_timer_elapsed(timer_, µsec);
|
||||
}
|
||||
[[maybe_unused]] double get_execution_time_sec();
|
||||
|
||||
|
||||
/// Set exit status translator callback, disconnecting the old one.
|
||||
/// Call only before execute().
|
||||
void set_exit_status_translator(exit_status_translator_func_t func)
|
||||
{
|
||||
translator_func_ = std::move(func);
|
||||
}
|
||||
void set_exit_status_translator(exit_status_translator_func_t func);
|
||||
|
||||
|
||||
/// Set exit notifier callback, disconnecting the old one.
|
||||
/// You can poll stopped_cleanup_needed() instead of using this function.
|
||||
void set_exited_callback(exited_callback_func_t func)
|
||||
{
|
||||
exited_callback_ = std::move(func);
|
||||
}
|
||||
void set_exited_callback(exited_callback_func_t func);
|
||||
|
||||
|
||||
|
||||
// these are sorta-private
|
||||
// these are sort of private
|
||||
|
||||
/// Channel type, for passing to callbacks
|
||||
enum class Channel {
|
||||
@@ -206,7 +160,7 @@ class Cmdex : public hz::ErrorHolder {
|
||||
static void on_child_watch_handler(GPid arg_pid, int waitpid_status, gpointer data);
|
||||
|
||||
/// Channel I/O handler
|
||||
static gboolean on_channel_io(GIOChannel* channel, GIOCondition cond, Cmdex* self, Channel channel_type);
|
||||
static gboolean on_channel_io(GIOChannel* channel, GIOCondition cond, AsyncCommandExecutor* self, Channel channel_type);
|
||||
|
||||
|
||||
private:
|
||||
@@ -218,8 +172,8 @@ class Cmdex : public hz::ErrorHolder {
|
||||
|
||||
|
||||
// default command and its args. std::strings, not ustrings.
|
||||
std::string command_exec_{ }; /// Binary name to execute. NOT affected by cleanup_members().
|
||||
std::string command_args_{ }; /// Arguments that always go with the binary. NOT affected by cleanup_members().
|
||||
std::string command_exec_; /// Binary name to execute. NOT affected by cleanup_members().
|
||||
std::string command_args_; /// Arguments that always go with the binary. NOT affected by cleanup_members().
|
||||
|
||||
|
||||
bool running_ = false; ///< If true, the child process is running now. NOT affected by cleanup_members().
|
||||
@@ -248,8 +202,8 @@ class Cmdex : public hz::ErrorHolder {
|
||||
guint event_source_id_stdout_ = 0; ///< IO watcher event source ID for stdout
|
||||
guint event_source_id_stderr_ = 0; ///< IO watcher event source ID for stderr
|
||||
|
||||
std::string str_stdout_{ }; ///< stdout data read during execution. NOT affected by cleanup_members().
|
||||
std::string str_stderr_{ }; ///< stderr data read during execution. NOT affected by cleanup_members().
|
||||
std::string str_stdout_; ///< stdout data read during execution. NOT affected by cleanup_members().
|
||||
std::string str_stderr_; ///< stderr data read during execution. NOT affected by cleanup_members().
|
||||
|
||||
|
||||
// signals
|
||||
@@ -1,223 +0,0 @@
|
||||
/******************************************************************************
|
||||
License: GNU General Public License v3.0 only
|
||||
Copyright:
|
||||
(C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
******************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup applib
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#ifndef CLI_EXECUTORS_H
|
||||
#define CLI_EXECUTORS_H
|
||||
|
||||
#include "local_glibmm.h"
|
||||
|
||||
#include "cmdex.h"
|
||||
#include "cmdex_sync.h"
|
||||
|
||||
|
||||
|
||||
/// Executor for tw_cli (3ware utility)
|
||||
template<class ExecutorSync>
|
||||
class TwCliExecutorGeneric : public ExecutorSync {
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
TwCliExecutorGeneric(const std::string& cmd, const std::string& cmdargs)
|
||||
: ExecutorSync(cmd, cmdargs)
|
||||
{
|
||||
this->construct();
|
||||
}
|
||||
|
||||
|
||||
/// Constructor
|
||||
TwCliExecutorGeneric()
|
||||
{
|
||||
this->construct();
|
||||
}
|
||||
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~TwCliExecutorGeneric() = default;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/// Called from constructors
|
||||
void construct()
|
||||
{
|
||||
ExecutorSync::get_command_executor().set_exit_status_translator(&TwCliExecutorGeneric::translate_exit_status);
|
||||
this->set_error_header(std::string(_("An error occurred while executing tw_cli:")) + "\n\n");
|
||||
}
|
||||
|
||||
|
||||
/// Exit status translate handler
|
||||
static std::string translate_exit_status([[maybe_unused]] int status)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
/// Import the last error from command executor and clear all errors there
|
||||
void import_error() override
|
||||
{
|
||||
Cmdex& cmdex = this->get_command_executor();
|
||||
Cmdex::error_list_t errors = cmdex.get_errors(); // these are not clones
|
||||
|
||||
hz::ErrorBase* e = nullptr;
|
||||
// find the last relevant error.
|
||||
for (auto iter = errors.crbegin(); iter != errors.crend(); ++iter) {
|
||||
// ignore iochannel errors, they may mask the real errors
|
||||
if ((*iter)->get_type() != "giochannel" && (*iter)->get_type() != "custom") {
|
||||
e = (*iter)->clone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cmdex.clear_errors(); // and clear them
|
||||
|
||||
if (e) { // if error is present, alert the user
|
||||
on_error_warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// This is called when an error occurs in command executor.
|
||||
/// Note: The warnings are already printed via debug_* in cmdex.
|
||||
void on_error_warn(hz::ErrorBase* e) override
|
||||
{
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
// import the error only if it's relevant.
|
||||
std::string error_type = e->get_type();
|
||||
|
||||
// ignore giochannel errors - higher level errors will be triggered, and they more user-friendly.
|
||||
if (error_type == "giochannel" || error_type == "custom") {
|
||||
return;
|
||||
}
|
||||
|
||||
this->set_error_msg(e->get_message());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// tw_cli executor without GUI support
|
||||
using TwCliExecutor = TwCliExecutorGeneric<CmdexSync>;
|
||||
|
||||
|
||||
/// tw_cli executor with GUI support
|
||||
using TwCliExecutorGui = TwCliExecutorGeneric<CmdexSyncGui>;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Executor for cli (Areca utility)
|
||||
template<class ExecutorSync>
|
||||
class ArecaCliExecutorGeneric : public ExecutorSync {
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
ArecaCliExecutorGeneric(const std::string& cmd, const std::string& cmdargs)
|
||||
: ExecutorSync(cmd, cmdargs)
|
||||
{
|
||||
this->construct();
|
||||
}
|
||||
|
||||
|
||||
/// Constructor
|
||||
ArecaCliExecutorGeneric()
|
||||
{
|
||||
this->construct();
|
||||
}
|
||||
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~ArecaCliExecutorGeneric() = default;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/// Called from constructors
|
||||
void construct()
|
||||
{
|
||||
ExecutorSync::get_command_executor().set_exit_status_translator(&ArecaCliExecutorGeneric::translate_exit_status);
|
||||
this->set_error_header(std::string(_("An error occurred while executing Areca cli:")) + "\n\n");
|
||||
}
|
||||
|
||||
|
||||
/// Exit status translate handler
|
||||
static std::string translate_exit_status([[maybe_unused]] int status)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
/// Import the last error from command executor and clear all errors there
|
||||
void import_error() override
|
||||
{
|
||||
Cmdex& cmdex = this->get_command_executor();
|
||||
Cmdex::error_list_t errors = cmdex.get_errors(); // these are not clones
|
||||
|
||||
hz::ErrorBase* e = nullptr;
|
||||
// find the last relevant error.
|
||||
for (auto iter = errors.crbegin(); iter != errors.crend(); ++iter) {
|
||||
// ignore iochannel errors, they may mask the real errors
|
||||
if ((*iter)->get_type() != "giochannel" && (*iter)->get_type() != "custom") {
|
||||
e = (*iter)->clone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cmdex.clear_errors(); // and clear them
|
||||
|
||||
if (e) { // if error is present, alert the user
|
||||
on_error_warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// This is called when an error occurs in command executor.
|
||||
/// Note: The warnings are already printed via debug_* in cmdex.
|
||||
void on_error_warn(hz::ErrorBase* e) override
|
||||
{
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
// import the error only if it's relevant.
|
||||
std::string error_type = e->get_type();
|
||||
|
||||
// ignore giochannel errors - higher level errors will be triggered, and they more user-friendly.
|
||||
if (error_type == "giochannel" || error_type == "custom") {
|
||||
return;
|
||||
}
|
||||
|
||||
this->set_error_msg(e->get_message());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// tw_cli executor without GUI support
|
||||
using ArecaCliExecutor = ArecaCliExecutorGeneric<CmdexSync>;
|
||||
|
||||
|
||||
/// tw_cli executor with GUI support
|
||||
using ArecaCliExecutorGui = ArecaCliExecutorGeneric<CmdexSyncGui>;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -12,28 +12,28 @@ Copyright:
|
||||
#include "local_glibmm.h"
|
||||
#include <glib.h> // g_usleep()
|
||||
|
||||
#include "cmdex_sync.h"
|
||||
#include "command_executor.h"
|
||||
|
||||
|
||||
|
||||
cmdex_signal_execute_finish_type& cmdex_sync_signal_execute_finish()
|
||||
cmdex_signal_execute_finish_t& cmdex_sync_signal_execute_finish()
|
||||
{
|
||||
/// "Execution finished" signal
|
||||
static sigc::signal<void, const CmdexSyncCommandInfo&> s_cmdex_sync_signal_execute_finish;
|
||||
static sigc::signal<void, const CommandExecutorResult&> s_cmdex_sync_signal_execute_finish;
|
||||
return s_cmdex_sync_signal_execute_finish;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CmdexSync::CmdexSync(std::string command_name, std::string command_args)
|
||||
: CmdexSync()
|
||||
CommandExecutor::CommandExecutor(std::string command_name, std::string command_args)
|
||||
: CommandExecutor()
|
||||
{
|
||||
this->set_command(std::move(command_name), std::move(command_args));
|
||||
}
|
||||
|
||||
|
||||
|
||||
CmdexSync::CmdexSync()
|
||||
CommandExecutor::CommandExecutor()
|
||||
{
|
||||
/// Translators: {command} will be replaced by command name.
|
||||
running_msg_ = _("Running {command}...");
|
||||
@@ -42,7 +42,7 @@ CmdexSync::CmdexSync()
|
||||
|
||||
|
||||
|
||||
void CmdexSync::set_command(std::string command_name, std::string command_args)
|
||||
void CommandExecutor::set_command(std::string command_name, std::string command_args)
|
||||
{
|
||||
cmdex_.set_command(command_name, command_args);
|
||||
// keep a copy locally to avoid locking on get() every time
|
||||
@@ -52,27 +52,27 @@ void CmdexSync::set_command(std::string command_name, std::string command_args)
|
||||
|
||||
|
||||
|
||||
std::string CmdexSync::get_command_name() const
|
||||
std::string CommandExecutor::get_command_name() const
|
||||
{
|
||||
return command_name_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string CmdexSync::get_command_args() const
|
||||
std::string CommandExecutor::get_command_args() const
|
||||
{
|
||||
return command_args_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CmdexSync::execute()
|
||||
bool CommandExecutor::execute()
|
||||
{
|
||||
set_error_msg(""); // clear old error if present
|
||||
|
||||
bool slot_connected = !(signal_execute_tick.slots().begin() == signal_execute_tick.slots().end());
|
||||
bool slot_connected = !(signal_execute_tick().slots().begin() == signal_execute_tick().slots().end());
|
||||
|
||||
if (slot_connected && !signal_execute_tick.emit(TickStatus::starting))
|
||||
if (slot_connected && !signal_execute_tick().emit(TickStatus::starting))
|
||||
return false;
|
||||
|
||||
if (!cmdex_.execute()) { // try to execute
|
||||
@@ -80,11 +80,11 @@ bool CmdexSync::execute()
|
||||
import_error(); // get error from cmdex and display warnings if needed
|
||||
|
||||
// emit this for execution loggers
|
||||
cmdex_sync_signal_execute_finish().emit(CmdexSyncCommandInfo(get_command_name(),
|
||||
cmdex_sync_signal_execute_finish().emit(CommandExecutorResult(get_command_name(),
|
||||
get_command_args(), get_stdout_str(), get_stderr_str(), get_error_msg()));
|
||||
|
||||
if (slot_connected)
|
||||
signal_execute_tick.emit(TickStatus::failed);
|
||||
signal_execute_tick().emit(TickStatus::failed);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ bool CmdexSync::execute()
|
||||
if (!stop_requested) { // running and no stop requested yet
|
||||
// call the tick function with "running" periodically.
|
||||
// if it returns false, try to stop.
|
||||
if (slot_connected && !signal_execute_tick.emit(TickStatus::running)) {
|
||||
if (slot_connected && !signal_execute_tick().emit(TickStatus::running)) {
|
||||
debug_out_info("app", DBG_FUNC_MSG << "execute_tick slot returned false, trying to stop the program.\n");
|
||||
stop_requested = true;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ bool CmdexSync::execute()
|
||||
|
||||
// alert the tick function
|
||||
if (stop_requested && slot_connected) {
|
||||
signal_execute_tick.emit(TickStatus::stopping); // ignore returned value here
|
||||
signal_execute_tick().emit(TickStatus::stopping); // ignore returned value here
|
||||
}
|
||||
|
||||
|
||||
@@ -140,25 +140,88 @@ bool CmdexSync::execute()
|
||||
import_error(); // get error from cmdex and display warnings if needed
|
||||
|
||||
// emit this for execution loggers
|
||||
cmdex_sync_signal_execute_finish().emit(CmdexSyncCommandInfo(get_command_name(),
|
||||
cmdex_sync_signal_execute_finish().emit(CommandExecutorResult(get_command_name(),
|
||||
get_command_args(), get_stdout_str(), get_stderr_str(), get_error_msg()));
|
||||
|
||||
if (slot_connected)
|
||||
signal_execute_tick.emit(TickStatus::stopped); // last call
|
||||
signal_execute_tick().emit(TickStatus::stopped); // last call
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CmdexSync::set_forced_kill_timeout(std::chrono::milliseconds timeout_msec)
|
||||
void CommandExecutor::set_forced_kill_timeout(std::chrono::milliseconds timeout_msec)
|
||||
{
|
||||
forced_kill_timeout_msec_ = timeout_msec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string CmdexSync::get_error_msg(bool with_header) const
|
||||
bool CommandExecutor::try_stop(hz::Signal sig)
|
||||
{
|
||||
return cmdex_.try_stop(sig);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CommandExecutor::try_kill()
|
||||
{
|
||||
return cmdex_.try_kill();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CommandExecutor::set_stop_timeouts(std::chrono::milliseconds term_timeout_msec, std::chrono::milliseconds kill_timeout_msec)
|
||||
{
|
||||
cmdex_.set_stop_timeouts(term_timeout_msec, kill_timeout_msec);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CommandExecutor::unset_stop_timeouts()
|
||||
{
|
||||
cmdex_.unset_stop_timeouts();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CommandExecutor::is_running() const
|
||||
{
|
||||
return cmdex_.is_running();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CommandExecutor::set_buffer_sizes(gsize stdout_buffer_size, gsize stderr_buffer_size)
|
||||
{
|
||||
cmdex_.set_buffer_sizes(stdout_buffer_size, stderr_buffer_size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string CommandExecutor::get_stdout_str(bool clear_existing)
|
||||
{
|
||||
return cmdex_.get_stdout_str(clear_existing);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string CommandExecutor::get_stderr_str(bool clear_existing)
|
||||
{
|
||||
return cmdex_.get_stderr_str(clear_existing);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CommandExecutor::set_exit_status_translator(AsyncCommandExecutor::exit_status_translator_func_t func)
|
||||
{
|
||||
cmdex_.set_exit_status_translator(std::move(func));
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string CommandExecutor::get_error_msg(bool with_header) const
|
||||
{
|
||||
if (with_header)
|
||||
return error_header_ + error_msg_;
|
||||
@@ -167,30 +230,37 @@ std::string CmdexSync::get_error_msg(bool with_header) const
|
||||
|
||||
|
||||
|
||||
void CmdexSync::set_running_msg(const std::string& msg)
|
||||
void CommandExecutor::set_running_msg(const std::string& msg)
|
||||
{
|
||||
running_msg_ = msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CmdexSync::set_error_header(const std::string& msg)
|
||||
void CommandExecutor::set_error_header(const std::string& msg)
|
||||
{
|
||||
error_header_ = msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string CmdexSync::get_error_header()
|
||||
std::string CommandExecutor::get_error_header()
|
||||
{
|
||||
return error_header_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CmdexSync::import_error()
|
||||
sigc::signal<bool, CommandExecutor::TickStatus>& CommandExecutor::signal_execute_tick()
|
||||
{
|
||||
Cmdex::error_list_t errors = cmdex_.get_errors(); // these are not clones
|
||||
return signal_execute_tick_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CommandExecutor::import_error()
|
||||
{
|
||||
AsyncCommandExecutor::error_list_t errors = cmdex_.get_errors(); // these are not clones
|
||||
hz::ErrorBase* e = nullptr;
|
||||
if (!errors.empty())
|
||||
e = errors.back()->clone();
|
||||
@@ -203,7 +273,7 @@ void CmdexSync::import_error()
|
||||
|
||||
|
||||
|
||||
void CmdexSync::on_error_warn(hz::ErrorBase* e)
|
||||
void CommandExecutor::on_error_warn(hz::ErrorBase* e)
|
||||
{
|
||||
if (e) {
|
||||
set_error_msg(e->get_message()); // this message will be displayed
|
||||
@@ -212,21 +282,21 @@ void CmdexSync::on_error_warn(hz::ErrorBase* e)
|
||||
|
||||
|
||||
|
||||
void CmdexSync::set_error_msg(const std::string& error_msg)
|
||||
void CommandExecutor::set_error_msg(const std::string& error_msg)
|
||||
{
|
||||
error_msg_ = error_msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::string CmdexSync::get_running_msg() const
|
||||
std::string CommandExecutor::get_running_msg() const
|
||||
{
|
||||
return running_msg_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Cmdex& CmdexSync::get_command_executor()
|
||||
AsyncCommandExecutor& CommandExecutor::get_async_executor()
|
||||
{
|
||||
return cmdex_;
|
||||
}
|
||||
@@ -9,8 +9,8 @@ Copyright:
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#ifndef APP_CMDEX_SYNC_H
|
||||
#define APP_CMDEX_SYNC_H
|
||||
#ifndef COMMAND_EXECUTOR_H
|
||||
#define COMMAND_EXECUTOR_H
|
||||
|
||||
#include <sigc++/sigc++.h>
|
||||
#include <string>
|
||||
@@ -20,50 +20,67 @@ Copyright:
|
||||
#include "hz/error.h"
|
||||
#include "hz/process_signal.h" // hz::SIGNAL_*
|
||||
|
||||
#include "cmdex.h"
|
||||
#include "async_command_executor.h"
|
||||
|
||||
|
||||
|
||||
/// Information about a finished command.
|
||||
struct CmdexSyncCommandInfo {
|
||||
CmdexSyncCommandInfo(std::string c, std::string p,
|
||||
std::string so, std::string se, std::string em)
|
||||
: command(std::move(c)), parameters(std::move(p)), std_output(std::move(so)),
|
||||
std_error(std::move(se)), error_msg(std::move(em))
|
||||
struct CommandExecutorResult {
|
||||
CommandExecutorResult(std::string arg_command, std::string arg_parameters,
|
||||
std::string arg_std_output, std::string arg_std_error, std::string arg_error_message)
|
||||
: command(std::move(arg_command)),
|
||||
parameters(std::move(arg_parameters)),
|
||||
std_output(std::move(arg_std_output)),
|
||||
std_error(std::move(arg_std_error)),
|
||||
error_message(std::move(arg_error_message))
|
||||
{ }
|
||||
|
||||
const std::string command; ///< Executed command
|
||||
const std::string parameters; ///< Command parameters
|
||||
const std::string std_output; ///< Stdout data
|
||||
const std::string std_error; ///< Stderr data
|
||||
const std::string error_msg; ///< Execution error message
|
||||
const std::string error_message; ///< Execution error message
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// cmdex_sync_signal_execute_finish() return signal.
|
||||
using cmdex_signal_execute_finish_type = sigc::signal<void, const CmdexSyncCommandInfo&>;
|
||||
using cmdex_signal_execute_finish_t = sigc::signal<void, const CommandExecutorResult&>;
|
||||
|
||||
|
||||
/// This signal is emitted every time execute() finishes.
|
||||
cmdex_signal_execute_finish_type& cmdex_sync_signal_execute_finish();
|
||||
cmdex_signal_execute_finish_t& cmdex_sync_signal_execute_finish();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Synchronous Cmdex (command executor) with ticking support.
|
||||
class CmdexSync : public sigc::trackable {
|
||||
/// Synchronous AsyncCommandExecutor (command executor) with ticking support.
|
||||
class CommandExecutor : public sigc::trackable {
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
CmdexSync();
|
||||
CommandExecutor();
|
||||
|
||||
/// Constructor
|
||||
CmdexSync(std::string command_name, std::string command_args);
|
||||
CommandExecutor(std::string command_name, std::string command_args);
|
||||
|
||||
|
||||
/// Deleted
|
||||
CommandExecutor(const CommandExecutor& other) = delete;
|
||||
|
||||
/// Deleted
|
||||
CommandExecutor(const CommandExecutor&& other) = delete;
|
||||
|
||||
/// Deleted
|
||||
CommandExecutor& operator=(CommandExecutor& other) = delete;
|
||||
|
||||
/// Deleted
|
||||
CommandExecutor& operator=(const CommandExecutor&& other) = delete;
|
||||
|
||||
|
||||
/// Virtual destructor
|
||||
virtual ~CmdexSync() = default;
|
||||
virtual ~CommandExecutor() = default;
|
||||
|
||||
|
||||
/// Set command to execute and its parameters
|
||||
@@ -92,67 +109,40 @@ class CmdexSync : public sigc::trackable {
|
||||
|
||||
|
||||
/// Try to stop the process. Call this from ticker slot while executing.
|
||||
bool try_stop(hz::Signal sig = hz::Signal::Terminate)
|
||||
{
|
||||
return cmdex_.try_stop(sig);
|
||||
}
|
||||
bool try_stop(hz::Signal sig = hz::Signal::Terminate);
|
||||
|
||||
|
||||
/// Same as try_stop(hz::SIGNAL_SIGKILL).
|
||||
bool try_kill()
|
||||
{
|
||||
return cmdex_.try_kill();
|
||||
}
|
||||
bool try_kill();
|
||||
|
||||
|
||||
/// Set a timeout (since call to this function) to terminate, kill or both (use 0 to ignore the parameter).
|
||||
/// the timeouts will be unset automatically when the command exits.
|
||||
/// Call from ticker slot while executing.
|
||||
void set_stop_timeouts(std::chrono::milliseconds term_timeout_msec, std::chrono::milliseconds kill_timeout_msec)
|
||||
{
|
||||
cmdex_.set_stop_timeouts(term_timeout_msec, kill_timeout_msec);
|
||||
}
|
||||
void set_stop_timeouts(std::chrono::milliseconds term_timeout_msec, std::chrono::milliseconds kill_timeout_msec);
|
||||
|
||||
|
||||
/// Unset terminate / kill timeouts. This will stop the timeout counters.
|
||||
/// Call from ticker slot while executing.
|
||||
void unset_stop_timeouts()
|
||||
{
|
||||
cmdex_.unset_stop_timeouts();
|
||||
}
|
||||
void unset_stop_timeouts();
|
||||
|
||||
|
||||
/// Check if the child process is running. See Cmdex::is_running().
|
||||
/// Check if the child process is running. See AsyncCommandExecutor::is_running().
|
||||
/// Call from ticker slot while executing.
|
||||
bool is_running() const
|
||||
{
|
||||
return cmdex_.is_running();
|
||||
}
|
||||
bool is_running() const;
|
||||
|
||||
|
||||
/// See Cmdex::set_buffer_sizes() for details. Call this before execute().
|
||||
void set_buffer_sizes(gsize stdout_buffer_size = 0, gsize stderr_buffer_size = 0)
|
||||
{
|
||||
cmdex_.set_buffer_sizes(stdout_buffer_size, stderr_buffer_size);
|
||||
}
|
||||
/// See AsyncCommandExecutor::set_buffer_sizes() for details. Call this before execute().
|
||||
void set_buffer_sizes(gsize stdout_buffer_size = 0, gsize stderr_buffer_size = 0);
|
||||
|
||||
/// See Cmdex::get_stdout_str() for details.
|
||||
std::string get_stdout_str(bool clear_existing = false)
|
||||
{
|
||||
return cmdex_.get_stdout_str(clear_existing);
|
||||
}
|
||||
/// See AsyncCommandExecutor::get_stdout_str() for details.
|
||||
std::string get_stdout_str(bool clear_existing = false);
|
||||
|
||||
/// See Cmdex::get_stderr_str() for details.
|
||||
std::string get_stderr_str(bool clear_existing = false)
|
||||
{
|
||||
return cmdex_.get_stderr_str(clear_existing);
|
||||
}
|
||||
/// See AsyncCommandExecutor::get_stderr_str() for details.
|
||||
std::string get_stderr_str(bool clear_existing = false);
|
||||
|
||||
/// See Cmdex::set_exit_status_translator() for details.
|
||||
void set_exit_status_translator(Cmdex::exit_status_translator_func_t func)
|
||||
{
|
||||
cmdex_.set_exit_status_translator(std::move(func));
|
||||
}
|
||||
/// See AsyncCommandExecutor::set_exit_status_translator() for details.
|
||||
void set_exit_status_translator(AsyncCommandExecutor::exit_status_translator_func_t func);
|
||||
|
||||
|
||||
/// Get command execution error message. If \c with_header
|
||||
@@ -185,9 +175,7 @@ class CmdexSync : public sigc::trackable {
|
||||
};
|
||||
|
||||
|
||||
/// This signal is emitted whenever something happens with the execution
|
||||
/// (the status is changed), and periodically while the process is running.
|
||||
sigc::signal<bool, TickStatus> signal_execute_tick;
|
||||
sigc::signal<bool, TickStatus>& signal_execute_tick();
|
||||
|
||||
|
||||
|
||||
@@ -211,12 +199,12 @@ class CmdexSync : public sigc::trackable {
|
||||
|
||||
|
||||
/// Get command executor object
|
||||
Cmdex& get_command_executor();
|
||||
AsyncCommandExecutor& get_async_executor();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Cmdex cmdex_; ///< Command executor
|
||||
AsyncCommandExecutor cmdex_; ///< Command executor
|
||||
|
||||
std::string command_name_; ///< Command name
|
||||
std::string command_args_; ///< Command arguments
|
||||
@@ -228,6 +216,12 @@ class CmdexSync : public sigc::trackable {
|
||||
std::string error_msg_; ///< Execution error message
|
||||
std::string error_header_; ///< The error message may have this prepended to it.
|
||||
|
||||
|
||||
/// This signal is emitted whenever something happens with the execution
|
||||
/// (the status is changed), and periodically while the process is running.
|
||||
sigc::signal<bool, TickStatus> signal_execute_tick_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/******************************************************************************
|
||||
License: GNU General Public License v3.0 only
|
||||
Copyright:
|
||||
(C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
******************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup applib
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#ifndef COMMAND_EXECUTOR_3WARE_H
|
||||
#define COMMAND_EXECUTOR_3WARE_H
|
||||
|
||||
#include "local_glibmm.h"
|
||||
|
||||
#include "async_command_executor.h"
|
||||
#include "command_executor.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/// Executor for tw_cli (3ware utility)
|
||||
template<class ExecutorPolicy>
|
||||
class TwCliExecutorGeneric : public ExecutorPolicy {
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
TwCliExecutorGeneric();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
/// Exit status translate handler
|
||||
static std::string translate_exit_status(int status);
|
||||
|
||||
|
||||
/// Import the last error from command executor and clear all errors there
|
||||
void import_error() override;
|
||||
|
||||
|
||||
/// This is called when an error occurs in command executor.
|
||||
/// Note: The warnings are already printed via debug_* in cmdex.
|
||||
void on_error_warn(hz::ErrorBase* e) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// tw_cli executor without GUI support
|
||||
using TwCliExecutor = TwCliExecutorGeneric<CommandExecutor>;
|
||||
|
||||
|
||||
/// tw_cli executor with GUI support
|
||||
using TwCliExecutorGui = TwCliExecutorGeneric<CommandExecutorGui>;
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------- Implementation
|
||||
|
||||
|
||||
|
||||
template<class ExecutorPolicy>
|
||||
TwCliExecutorGeneric<ExecutorPolicy>::TwCliExecutorGeneric()
|
||||
{
|
||||
ExecutorPolicy::get_async_executor().set_exit_status_translator(&TwCliExecutorGeneric::translate_exit_status);
|
||||
this->set_error_header(std::string(_("An error occurred while executing tw_cli:")) + "\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class ExecutorPolicy>
|
||||
std::string TwCliExecutorGeneric<ExecutorPolicy>::translate_exit_status([[maybe_unused]] int status)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class ExecutorPolicy>
|
||||
void TwCliExecutorGeneric<ExecutorPolicy>::import_error()
|
||||
{
|
||||
AsyncCommandExecutor& cmdex = this->get_async_executor();
|
||||
AsyncCommandExecutor::error_list_t errors = cmdex.get_errors(); // these are not clones
|
||||
|
||||
hz::ErrorBase* e = nullptr;
|
||||
// find the last relevant error.
|
||||
for (auto iter = errors.crbegin(); iter != errors.crend(); ++iter) {
|
||||
// ignore iochannel errors, they may mask the real errors
|
||||
if ((*iter)->get_type() != "giochannel" && (*iter)->get_type() != "custom") {
|
||||
e = (*iter)->clone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cmdex.clear_errors(); // and clear them
|
||||
|
||||
if (e) { // if error is present, alert the user
|
||||
on_error_warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class ExecutorPolicy>
|
||||
void TwCliExecutorGeneric<ExecutorPolicy>::on_error_warn(hz::ErrorBase* e)
|
||||
{
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
// import the error only if it's relevant.
|
||||
std::string error_type = e->get_type();
|
||||
|
||||
// ignore giochannel errors - higher level errors will be triggered, and they more user-friendly.
|
||||
if (error_type == "giochannel" || error_type == "custom") {
|
||||
return;
|
||||
}
|
||||
|
||||
this->set_error_msg(e->get_message());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -0,0 +1,131 @@
|
||||
/******************************************************************************
|
||||
License: GNU General Public License v3.0 only
|
||||
Copyright:
|
||||
(C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
|
||||
******************************************************************************/
|
||||
/// \file
|
||||
/// \author Alexander Shaduri
|
||||
/// \ingroup applib
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#ifndef COMMAND_EXECUTOR_ARECA_H
|
||||
#define COMMAND_EXECUTOR_ARECA_H
|
||||
|
||||
#include "local_glibmm.h"
|
||||
|
||||
#include "async_command_executor.h"
|
||||
#include "command_executor.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/// Executor for cli (Areca utility)
|
||||
template<class ExecutorPolicy>
|
||||
class ArecaCliExecutorGeneric : public ExecutorPolicy {
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
ArecaCliExecutorGeneric();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
/// Exit status translate handler
|
||||
static std::string translate_exit_status([[maybe_unused]] [[maybe_unused]] int status);
|
||||
|
||||
|
||||
/// Import the last error from command executor and clear all errors there
|
||||
void import_error() override;
|
||||
|
||||
|
||||
/// This is called when an error occurs in command executor.
|
||||
/// Note: The warnings are already printed via debug_* in cmdex.
|
||||
void on_error_warn(hz::ErrorBase* e) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// tw_cli executor without GUI support
|
||||
using ArecaCliExecutor = ArecaCliExecutorGeneric<CommandExecutor>;
|
||||
|
||||
|
||||
/// tw_cli executor with GUI support
|
||||
using ArecaCliExecutorGui = ArecaCliExecutorGeneric<CommandExecutorGui>;
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------- Implementation
|
||||
|
||||
|
||||
|
||||
template<class ExecutorPolicy>
|
||||
ArecaCliExecutorGeneric<ExecutorPolicy>::ArecaCliExecutorGeneric()
|
||||
{
|
||||
ExecutorPolicy::get_async_executor().set_exit_status_translator(&ArecaCliExecutorGeneric::translate_exit_status);
|
||||
this->set_error_header(std::string(_("An error occurred while executing Areca cli:")) + "\n\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class ExecutorPolicy>
|
||||
std::string ArecaCliExecutorGeneric<ExecutorPolicy>::translate_exit_status([[maybe_unused]] int status)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class ExecutorPolicy>
|
||||
void ArecaCliExecutorGeneric<ExecutorPolicy>::import_error()
|
||||
{
|
||||
AsyncCommandExecutor& cmdex = this->get_async_executor();
|
||||
AsyncCommandExecutor::error_list_t errors = cmdex.get_errors(); // these are not clones
|
||||
|
||||
hz::ErrorBase* e = nullptr;
|
||||
// find the last relevant error.
|
||||
for (auto iter = errors.crbegin(); iter != errors.crend(); ++iter) {
|
||||
// ignore iochannel errors, they may mask the real errors
|
||||
if ((*iter)->get_type() != "giochannel" && (*iter)->get_type() != "custom") {
|
||||
e = (*iter)->clone();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cmdex.clear_errors(); // and clear them
|
||||
|
||||
if (e) { // if error is present, alert the user
|
||||
on_error_warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<class ExecutorPolicy>
|
||||
void ArecaCliExecutorGeneric<ExecutorPolicy>::on_error_warn(hz::ErrorBase* e)
|
||||
{
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
// import the error only if it's relevant.
|
||||
std::string error_type = e->get_type();
|
||||
|
||||
// ignore giochannel errors - higher level errors will be triggered, and they more user-friendly.
|
||||
if (error_type == "giochannel" || error_type == "custom") {
|
||||
return;
|
||||
}
|
||||
|
||||
this->set_error_msg(e->get_message());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/// @}
|
||||
@@ -10,20 +10,20 @@ Copyright:
|
||||
/// @{
|
||||
|
||||
#include "hz/debug.h"
|
||||
#include "executor_factory.h"
|
||||
#include "command_executor_factory.h"
|
||||
#include "smartctl_executor_gui.h"
|
||||
#include "cli_executors.h"
|
||||
#include "command_executor_areca.h"
|
||||
#include "command_executor_3ware.h"
|
||||
|
||||
|
||||
|
||||
|
||||
ExecutorFactory::ExecutorFactory(bool use_gui, Gtk::Window* parent)
|
||||
CommandExecutorFactory::CommandExecutorFactory(bool use_gui, Gtk::Window* parent)
|
||||
: use_gui_(use_gui), parent_(parent)
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
std::shared_ptr<CmdexSync> ExecutorFactory::create_executor(ExecutorFactory::ExecutorType type)
|
||||
std::shared_ptr<CommandExecutor> CommandExecutorFactory::create_executor(CommandExecutorFactory::ExecutorType type)
|
||||
{
|
||||
switch (type) {
|
||||
case ExecutorType::Smartctl:
|
||||
@@ -56,7 +56,7 @@ std::shared_ptr<CmdexSync> ExecutorFactory::create_executor(ExecutorFactory::Exe
|
||||
}
|
||||
|
||||
DBG_ASSERT(0);
|
||||
return std::make_shared<CmdexSync>();
|
||||
return std::make_shared<CommandExecutor>();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ Copyright:
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#ifndef EXECUTOR_FACTORY_H
|
||||
#define EXECUTOR_FACTORY_H
|
||||
#ifndef COMMAND_EXECUTOR_FACTORY_H
|
||||
#define COMMAND_EXECUTOR_FACTORY_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "cmdex_sync.h"
|
||||
#include "command_executor.h"
|
||||
|
||||
|
||||
// Forward declaration
|
||||
@@ -26,7 +26,7 @@ namespace Gtk {
|
||||
|
||||
/// This class allows you to create new executors for different commands,
|
||||
/// without carrying the GUI/CLI stuff manually.
|
||||
class ExecutorFactory {
|
||||
class CommandExecutorFactory {
|
||||
public:
|
||||
|
||||
/// Executor type for create_executor()
|
||||
@@ -38,11 +38,11 @@ class ExecutorFactory {
|
||||
|
||||
|
||||
/// Constructor. If \c use_gui is true, specify \c parent for the GUI dialogs.
|
||||
explicit ExecutorFactory(bool use_gui, Gtk::Window* parent = nullptr);
|
||||
explicit CommandExecutorFactory(bool use_gui, Gtk::Window* parent = nullptr);
|
||||
|
||||
|
||||
/// Create a new executor instance according to \c type and the constructor parameters.
|
||||
std::shared_ptr<CmdexSync> create_executor(ExecutorType type);
|
||||
std::shared_ptr<CommandExecutor> create_executor(ExecutorType type);
|
||||
|
||||
|
||||
private:
|
||||
@@ -54,8 +54,8 @@ class ExecutorFactory {
|
||||
|
||||
|
||||
|
||||
/// A reference-counting pointer to ExecutorFactory
|
||||
using ExecutorFactoryPtr = std::shared_ptr<ExecutorFactory>;
|
||||
/// A reference-counting pointer to CommandExecutorFactory
|
||||
using ExecutorFactoryPtr = std::shared_ptr<CommandExecutorFactory>;
|
||||
|
||||
|
||||
|
||||
@@ -17,16 +17,16 @@ Copyright:
|
||||
|
||||
#include "hz/string_algo.h"
|
||||
#include "hz/fs_ns.h"
|
||||
#include "cmdex_sync_gui.h"
|
||||
#include "command_executor_gui.h"
|
||||
|
||||
|
||||
|
||||
|
||||
bool CmdexSyncGui::execute()
|
||||
bool CommandExecutorGui::execute()
|
||||
{
|
||||
this->create_running_dialog(); // create, but don't show.
|
||||
this->set_running_dialog_abort_mode(false); // reset and set the message
|
||||
return CmdexSync::execute();
|
||||
return CommandExecutor::execute();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ bool CmdexSyncGui::execute()
|
||||
|
||||
|
||||
|
||||
Gtk::MessageDialog* CmdexSyncGui::create_running_dialog(Gtk::Window* parent, const Glib::ustring& msg)
|
||||
Gtk::MessageDialog* CommandExecutorGui::create_running_dialog(Gtk::Window* parent, const Glib::ustring& msg)
|
||||
{
|
||||
if (running_dialog_)
|
||||
return running_dialog_.get();
|
||||
@@ -53,7 +53,7 @@ Gtk::MessageDialog* CmdexSyncGui::create_running_dialog(Gtk::Window* parent, con
|
||||
}
|
||||
|
||||
running_dialog_->signal_response().connect(sigc::mem_fun(*this,
|
||||
&CmdexSyncGui::on_running_dialog_response));
|
||||
&CommandExecutorGui::on_running_dialog_response));
|
||||
|
||||
running_dialog_->set_decorated(false);
|
||||
running_dialog_->set_deletable(false);
|
||||
@@ -70,7 +70,7 @@ Gtk::MessageDialog* CmdexSyncGui::create_running_dialog(Gtk::Window* parent, con
|
||||
|
||||
|
||||
|
||||
void CmdexSyncGui::show_hide_dialog(bool show)
|
||||
void CommandExecutorGui::show_hide_dialog(bool show)
|
||||
{
|
||||
if (running_dialog_) {
|
||||
if (show) {
|
||||
@@ -88,7 +88,7 @@ void CmdexSyncGui::show_hide_dialog(bool show)
|
||||
|
||||
|
||||
|
||||
void CmdexSyncGui::update_dialog_show_timer()
|
||||
void CommandExecutorGui::update_dialog_show_timer()
|
||||
{
|
||||
double timeout = 2.; // 2 sec for normal dialogs
|
||||
if (running_dialog_abort_mode_)
|
||||
@@ -110,7 +110,7 @@ void CmdexSyncGui::update_dialog_show_timer()
|
||||
|
||||
|
||||
|
||||
void CmdexSyncGui::set_running_dialog_abort_mode(bool aborting)
|
||||
void CommandExecutorGui::set_running_dialog_abort_mode(bool aborting)
|
||||
{
|
||||
if (!running_dialog_)
|
||||
return;
|
||||
@@ -144,7 +144,7 @@ void CmdexSyncGui::set_running_dialog_abort_mode(bool aborting)
|
||||
|
||||
|
||||
|
||||
bool CmdexSyncGui::execute_tick_func(TickStatus status)
|
||||
bool CommandExecutorGui::execute_tick_func(TickStatus status)
|
||||
{
|
||||
if (status == TickStatus::starting) {
|
||||
if (execution_running_)
|
||||
@@ -9,39 +9,39 @@ Copyright:
|
||||
/// \weakgroup applib
|
||||
/// @{
|
||||
|
||||
#ifndef APP_CMDEX_SYNC_GUI_H
|
||||
#define APP_CMDEX_SYNC_GUI_H
|
||||
#ifndef COMMAND_EXECUTOR_GUI_H
|
||||
#define COMMAND_EXECUTOR_GUI_H
|
||||
|
||||
#include "local_glibmm.h"
|
||||
#include <gtkmm.h>
|
||||
#include <memory>
|
||||
|
||||
#include "cmdex_sync.h"
|
||||
#include "command_executor.h"
|
||||
|
||||
|
||||
|
||||
/// Same as CmdexSync, but with GTK UI support.
|
||||
/// Same as CommandExecutor, but with GTK UI support.
|
||||
/// This one is noncopyable, because we can't copy the dialogs, etc...
|
||||
class CmdexSyncGui : public CmdexSync {
|
||||
class CommandExecutorGui : public CommandExecutor {
|
||||
public:
|
||||
|
||||
/// Constructor
|
||||
CmdexSyncGui(const std::string& cmd, const std::string& cmdargs)
|
||||
: CmdexSync(cmd, cmdargs)
|
||||
CommandExecutorGui(const std::string& cmd, const std::string& cmdargs)
|
||||
: CommandExecutor(cmd, cmdargs)
|
||||
{
|
||||
signal_execute_tick.connect(sigc::mem_fun(*this, &CmdexSyncGui::execute_tick_func));
|
||||
signal_execute_tick().connect(sigc::mem_fun(*this, &CommandExecutorGui::execute_tick_func));
|
||||
}
|
||||
|
||||
|
||||
/// Constructor
|
||||
CmdexSyncGui()
|
||||
CommandExecutorGui()
|
||||
{
|
||||
signal_execute_tick.connect(sigc::mem_fun(*this, &CmdexSyncGui::execute_tick_func));
|
||||
signal_execute_tick().connect(sigc::mem_fun(*this, &CommandExecutorGui::execute_tick_func));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Reimplemented from CmdexSync
|
||||
// Reimplemented from CommandExecutor
|
||||
bool execute() override;
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ class CmdexSyncGui : public CmdexSync {
|
||||
}
|
||||
|
||||
|
||||
/// This function is attached to CmdexSync::signal_execute_tick.
|
||||
/// This function is attached to CommandExecutor::signal_execute_tick().
|
||||
bool execute_tick_func(TickStatus status);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ int main()
|
||||
// sd.add_match_patterns(match_patterns);
|
||||
sd.add_blacklist_patterns(blacklist_patterns);
|
||||
|
||||
auto ex_factory = std::make_shared<ExecutorFactory>(false);
|
||||
auto ex_factory = std::make_shared<CommandExecutorFactory>(false);
|
||||
std::string error_msg = sd.detect_and_fetch_basic_data(drives, ex_factory);
|
||||
if (!error_msg.empty()) {
|
||||
std::cerr << error_msg << "\n";
|
||||
|
||||
@@ -112,7 +112,7 @@ bool SelfTest::is_supported() const
|
||||
|
||||
|
||||
// start the test
|
||||
std::string SelfTest::start(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
std::string SelfTest::start(const std::shared_ptr<CommandExecutor>& smartctl_ex)
|
||||
{
|
||||
if (!drive_)
|
||||
return "[internal error: drive must not be NULL]";
|
||||
@@ -146,9 +146,9 @@ std::string SelfTest::start(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
|
||||
|
||||
// update our members
|
||||
// error_msg = this->update(smartctl_ex);
|
||||
// if (!error_msg.empty()) // update can error out too.
|
||||
// return error_msg;
|
||||
// error_message = this->update(smartctl_ex);
|
||||
// if (!error_message.empty()) // update can error out too.
|
||||
// return error_message;
|
||||
|
||||
// Don't update here - the logs may not be updated this fast.
|
||||
// Better to wait several seconds and then call it manually.
|
||||
@@ -174,7 +174,7 @@ std::string SelfTest::start(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
|
||||
|
||||
// abort test.
|
||||
std::string SelfTest::force_stop(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
std::string SelfTest::force_stop(const std::shared_ptr<CommandExecutor>& smartctl_ex)
|
||||
{
|
||||
if (!drive_)
|
||||
return "[internal error: drive must not be NULL]";
|
||||
@@ -228,7 +228,7 @@ std::string SelfTest::force_stop(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
|
||||
// update status variables. note: the returned error is an error in logic,
|
||||
// not an hw defect error.
|
||||
std::string SelfTest::update(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
std::string SelfTest::update(const std::shared_ptr<CommandExecutor>& smartctl_ex)
|
||||
{
|
||||
using namespace std::literals;
|
||||
|
||||
@@ -236,7 +236,7 @@ std::string SelfTest::update(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
return "[internal error: drive must not be NULL]";
|
||||
|
||||
std::string output;
|
||||
// std::string error_msg = drive_->execute_device_smartctl("--log=selftest", smartctl_ex, output);
|
||||
// std::string error_message = drive_->execute_device_smartctl("--log=selftest", smartctl_ex, output);
|
||||
std::string error_msg = drive_->execute_device_smartctl("--capabilities", smartctl_ex, output);
|
||||
|
||||
if (!error_msg.empty()) // checks for empty output too
|
||||
|
||||
@@ -19,7 +19,7 @@ Copyright:
|
||||
#include <unordered_map>
|
||||
|
||||
#include "storage_device.h"
|
||||
#include "cmdex_sync.h"
|
||||
#include "command_executor.h"
|
||||
|
||||
|
||||
|
||||
@@ -98,17 +98,17 @@ class SelfTest {
|
||||
/// Start the test. Note that this object is not reusable, start() must be called
|
||||
/// only on newly constructed objects.
|
||||
/// \return error message on error, empty string on success.
|
||||
std::string start(const std::shared_ptr<CmdexSync>& smartctl_ex = nullptr);
|
||||
std::string start(const std::shared_ptr<CommandExecutor>& smartctl_ex = nullptr);
|
||||
|
||||
|
||||
/// Abort the running test.
|
||||
/// \return error message on error, empty string on success.
|
||||
std::string force_stop(const std::shared_ptr<CmdexSync>& smartctl_ex = nullptr);
|
||||
std::string force_stop(const std::shared_ptr<CommandExecutor>& smartctl_ex = nullptr);
|
||||
|
||||
|
||||
/// Update status variables. The user should call this every get_poll_in_seconds() seconds.
|
||||
/// \return error message on error, empty string on success.
|
||||
std::string update(const std::shared_ptr<CmdexSync>& smartctl_ex = nullptr);
|
||||
std::string update(const std::shared_ptr<CommandExecutor>& smartctl_ex = nullptr);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -70,7 +70,7 @@ hz::fs::path get_smartctl_binary()
|
||||
|
||||
std::string execute_smartctl(const std::string& device, const std::string& device_opts,
|
||||
const std::string& command_options,
|
||||
std::shared_ptr<CmdexSync> smartctl_ex, std::string& smartctl_output)
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex, std::string& smartctl_output)
|
||||
{
|
||||
#ifndef _WIN32 // win32 doesn't have slashes in devices names
|
||||
{
|
||||
|
||||
@@ -15,8 +15,8 @@ Copyright:
|
||||
#include "local_glibmm.h"
|
||||
#include <vector>
|
||||
|
||||
#include "cmdex.h"
|
||||
#include "cmdex_sync.h"
|
||||
#include "async_command_executor.h"
|
||||
#include "command_executor.h"
|
||||
#include "hz/fs_ns.h"
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ class SmartctlExecutorGeneric : public ExecutorSync {
|
||||
/// Called by constructors
|
||||
void construct()
|
||||
{
|
||||
ExecutorSync::get_command_executor().set_exit_status_translator(&SmartctlExecutorGeneric::translate_exit_status);
|
||||
ExecutorSync::get_async_executor().set_exit_status_translator(&SmartctlExecutorGeneric::translate_exit_status);
|
||||
this->set_error_header(std::string(_("An error occurred while executing smartctl:")) + "\n\n");
|
||||
}
|
||||
|
||||
@@ -96,9 +96,9 @@ class SmartctlExecutorGeneric : public ExecutorSync {
|
||||
/// Import the last error from command executor and clear all errors there
|
||||
void import_error() override
|
||||
{
|
||||
Cmdex& cmdex = this->get_command_executor();
|
||||
AsyncCommandExecutor& cmdex = this->get_async_executor();
|
||||
|
||||
Cmdex::error_list_t errors = cmdex.get_errors(); // these are not clones
|
||||
AsyncCommandExecutor::error_list_t errors = cmdex.get_errors(); // these are not clones
|
||||
|
||||
hz::ErrorBase* e = nullptr;
|
||||
// find the last relevant error.
|
||||
@@ -156,7 +156,7 @@ class SmartctlExecutorGeneric : public ExecutorSync {
|
||||
|
||||
|
||||
/// Smartctl executor without GUI support
|
||||
using SmartctlExecutor = SmartctlExecutorGeneric<CmdexSync>;
|
||||
using SmartctlExecutor = SmartctlExecutorGeneric<CommandExecutor>;
|
||||
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@ hz::fs::path get_smartctl_binary();
|
||||
/// \return error message on error, empty string on success.
|
||||
std::string execute_smartctl(const std::string& device, const std::string& device_opts,
|
||||
const std::string& command_options,
|
||||
std::shared_ptr<CmdexSync> smartctl_ex, std::string& smartctl_output);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex, std::string& smartctl_output);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,12 +13,12 @@ Copyright:
|
||||
#define SMARTCTL_EXECUTOR_GUI_H
|
||||
|
||||
#include "smartctl_executor.h"
|
||||
#include "cmdex_sync_gui.h"
|
||||
#include "command_executor_gui.h"
|
||||
|
||||
|
||||
|
||||
/// Smartctl executor with GUI support
|
||||
using SmartctlExecutorGui = SmartctlExecutorGeneric<CmdexSyncGui>;
|
||||
using SmartctlExecutorGui = SmartctlExecutorGeneric<CommandExecutorGui>;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -43,11 +43,11 @@ std::string StorageDetector::detect(std::vector<StorageDevicePtr>& drives, const
|
||||
|
||||
#elif defined CONFIG_KERNEL_FAMILY_WINDOWS
|
||||
|
||||
error_msg = detect_drives_win32(all_detected, ex_factory); // win32
|
||||
error_message = detect_drives_win32(all_detected, ex_factory); // win32
|
||||
|
||||
#else // freebsd, etc...
|
||||
|
||||
error_msg = detect_drives_other(all_detected, ex_factory); // bsd, etc... . scans /dev.
|
||||
error_message = detect_drives_other(all_detected, ex_factory); // bsd, etc... . scans /dev.
|
||||
|
||||
#endif
|
||||
|
||||
@@ -101,7 +101,7 @@ std::string StorageDetector::fetch_basic_data(std::vector<StorageDevicePtr>& dri
|
||||
fetch_data_errors_.clear();
|
||||
fetch_data_error_outputs_.clear();
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
for (auto& drive : drives) {
|
||||
debug_out_info("app", "Retrieving basic information about the device...\n");
|
||||
@@ -123,7 +123,7 @@ std::string StorageDetector::fetch_basic_data(std::vector<StorageDevicePtr>& dri
|
||||
if (!error_msg.empty()) {
|
||||
// use original executor error if present (permits matches by our users).
|
||||
// if (!smartctl_ex->get_error_msg().empty())
|
||||
// error_msg = smartctl_ex->get_error_msg();
|
||||
// error_message = smartctl_ex->get_error_msg();
|
||||
|
||||
fetch_data_errors_.push_back(error_msg);
|
||||
fetch_data_error_outputs_.push_back(smartctl_ex->get_stdout_str());
|
||||
|
||||
@@ -16,8 +16,8 @@ Copyright:
|
||||
#include <string>
|
||||
|
||||
#include "storage_device.h"
|
||||
#include "cmdex_sync.h"
|
||||
#include "executor_factory.h"
|
||||
#include "command_executor.h"
|
||||
#include "command_executor_factory.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Copyright:
|
||||
#include "local_glibmm.h" // Glib::shell_quote(), compose
|
||||
|
||||
#include "build_config.h"
|
||||
#include "executor_factory.h"
|
||||
#include "command_executor_factory.h"
|
||||
#include "storage_device.h"
|
||||
#include "rconfig/rconfig.h"
|
||||
#include "app_pcrecpp.h"
|
||||
@@ -30,7 +30,7 @@ Copyright:
|
||||
/// \return error message
|
||||
inline std::string execute_tw_cli(const ExecutorFactoryPtr& ex_factory, const std::string& command_options, std::string& output)
|
||||
{
|
||||
std::shared_ptr<CmdexSync> executor = ex_factory->create_executor(ExecutorFactory::ExecutorType::TwCli);
|
||||
std::shared_ptr<CommandExecutor> executor = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::TwCli);
|
||||
|
||||
auto binary = rconfig::get_data<std::string>("system/tw_cli_binary");
|
||||
|
||||
@@ -155,7 +155,7 @@ inline std::string tw_cli_get_controllers(const ExecutorFactoryPtr& ex_factory,
|
||||
inline std::string smartctl_scan_drives_sequentially(const std::string& dev, const std::string& type,
|
||||
int from, int to, std::vector<StorageDevicePtr>& drives, const ExecutorFactoryPtr& ex_factory, std::string& last_output)
|
||||
{
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
for (int i = from; i <= to; ++i) {
|
||||
std::string type_arg = hz::string_sprintf(type.c_str(), i);
|
||||
|
||||
@@ -417,7 +417,7 @@ inline std::string detect_drives_linux_proc_partitions(std::vector<StorageDevice
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
for (const auto& device : devices) {
|
||||
auto drive = std::make_shared<StorageDevice>(device);
|
||||
@@ -639,7 +639,7 @@ inline std::string detect_drives_linux_adaptec(std::vector<StorageDevicePtr>& dr
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
std::set<int> controller_hosts;
|
||||
|
||||
@@ -776,7 +776,7 @@ inline std::string detect_drives_linux_areca(std::vector<StorageDevicePtr>& driv
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
for (auto& iter : controller_hosts) {
|
||||
const int host_num = iter.first;
|
||||
@@ -906,7 +906,7 @@ inline std::string detect_drives_linux_cciss(std::vector<StorageDevicePtr>& driv
|
||||
return std::string(); // no controllers
|
||||
}
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
for (int controller_no : controllers) {
|
||||
std::string dev = std::string("/dev/cciss/c") + hz::number_to_string_nolocale(controller_no) + "d0";
|
||||
@@ -985,7 +985,7 @@ inline std::string detect_drives_linux_hpsa(std::vector<StorageDevicePtr>& drive
|
||||
return error_msg;
|
||||
}
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
std::set<int> controller_hosts;
|
||||
|
||||
@@ -1069,7 +1069,7 @@ std::string detect_drives_linux(std::vector<StorageDevicePtr>& drives, const Exe
|
||||
// For example, on Ubuntu 8.04, /dev/disk/by-id contains two device
|
||||
// links for two drives, but both point to the same sdb (instead of
|
||||
// sda and sdb). Plus, there are no "*-partN" files (not that we need them).
|
||||
// error_msg = detect_drives_linux_udev_byid(devices); // linux udev
|
||||
// error_message = detect_drives_linux_udev_byid(devices); // linux udev
|
||||
|
||||
error_msg = detect_drives_linux_proc_partitions(drives, ex_factory);
|
||||
if (!error_msg.empty()) {
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright:
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "executor_factory.h"
|
||||
#include "command_executor_factory.h"
|
||||
#include "storage_device.h"
|
||||
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ std::string get_scan_open_multiport_devices(std::vector<StorageDevicePtr>& drive
|
||||
{
|
||||
debug_out_info("app", "Getting multi-port devices through smartctl --scan-open...\n");
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
auto smartctl_binary = get_smartctl_binary();
|
||||
|
||||
@@ -261,7 +261,7 @@ std::string get_scan_open_multiport_devices(std::vector<StorageDevicePtr>& drive
|
||||
inline std::string execute_areca_cli(const ExecutorFactoryPtr& ex_factory, const std::string& cli_binary,
|
||||
const std::string& command_options, std::string& output)
|
||||
{
|
||||
std::shared_ptr<CmdexSync> executor = ex_factory->create_executor(ExecutorFactory::ExecutorType::ArecaCli);
|
||||
std::shared_ptr<CommandExecutor> executor = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::ArecaCli);
|
||||
|
||||
executor->set_command(Glib::shell_quote(cli_binary), command_options);
|
||||
|
||||
@@ -550,7 +550,7 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
// --- CLI mode
|
||||
|
||||
@@ -561,7 +561,7 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
debug_out_dump("app", "Testing Areca controller presence using smartctl...\n");
|
||||
|
||||
auto drive = std::make_shared<StorageDevice>("/dev/arcmsr0", "areca,1");
|
||||
std::string error_msg = drive->fetch_basic_data_and_parse(smartctl_ex);
|
||||
std::string error_message = drive->fetch_basic_data_and_parse(smartctl_ex);
|
||||
std::string output = drive->get_info_output();
|
||||
if (app_pcre_match("/No Areca controller found/mi", output)
|
||||
|| app_pcre_match("/Smartctl open device: .* failed: No such device/mi", output) ) {
|
||||
@@ -575,10 +575,10 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
debug_out_info("app", "Scanning Areca drives using CLI...\n");
|
||||
int cli_max_controllers = 1; // TODO controller # with CLI.
|
||||
for (int controller_no = 0; controller_no < cli_max_controllers; ++controller_no) {
|
||||
std::string error_msg = areca_cli_get_drives(cli_binary.string(),
|
||||
std::string error_message = areca_cli_get_drives(cli_binary.string(),
|
||||
"/dev/arcmsr" + hz::number_to_string_nolocale(controller_no), controller_no, drives, ex_factory);
|
||||
// If we get an error on controller 0, fall back to no-cli detection.
|
||||
if (!error_msg.empty() && controller_no == 0) {
|
||||
if (!error_message.empty() && controller_no == 0) {
|
||||
use_cli = 0;
|
||||
debug_out_warn("app", "Areca scan using CLI failed.\n");
|
||||
if (scan_detect) {
|
||||
@@ -609,9 +609,9 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
|
||||
std::size_t old_drive_count = drives.size();
|
||||
std::string last_output;
|
||||
std::string error_msg = smartctl_scan_drives_sequentially(dev, "areca,%d", 1, max_noenc_ports, drives, ex_factory, last_output);
|
||||
std::string error_message = smartctl_scan_drives_sequentially(dev, "areca,%d", 1, max_noenc_ports, drives, ex_factory, last_output);
|
||||
// If the scan stopped because of no controller, stop it all.
|
||||
if (!error_msg.empty() && (app_pcre_match("/No Areca controller found/mi", last_output)
|
||||
if (!error_message.empty() && (app_pcre_match("/No Areca controller found/mi", last_output)
|
||||
|| app_pcre_match("/Smartctl open device: .* failed: No such device/mi", last_output)) ) {
|
||||
debug_out_dump("app", "Areca controller " << controller_no << " not present, stopping sequential scan.\n");
|
||||
break;
|
||||
@@ -623,7 +623,7 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
for (int enclosure_no = 1; enclosure_no < max_enclosures; ++enclosure_no) {
|
||||
debug_out_dump("app", "Starting brute-force port scan (enclosure #" << enclosure_no << ") on 1-" << max_enc_ports << " ports, device \"" << dev
|
||||
<< "\". Change the maximums by setting \"system/win32_areca_onc_max_scan_port\" and \"system/win32_areca_enc_max_enclosure\" config keys.\n");
|
||||
error_msg = smartctl_scan_drives_sequentially(dev, "areca,%d/" + hz::number_to_string_nolocale(enclosure_no), 1, max_enc_ports, drives, ex_factory, last_output);
|
||||
error_message = smartctl_scan_drives_sequentially(dev, "areca,%d/" + hz::number_to_string_nolocale(enclosure_no), 1, max_enc_ports, drives, ex_factory, last_output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,22 +650,22 @@ inline std::string detect_drives_win32_areca(std::vector<StorageDevicePtr>& driv
|
||||
std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const ExecutorFactoryPtr& ex_factory)
|
||||
{
|
||||
std::vector<std::string> error_msgs;
|
||||
std::string error_msg;
|
||||
std::string error_message;
|
||||
|
||||
// Construct drive letter map
|
||||
debug_out_info("app", "Checking which drive corresponds to which \\\\.\\PhysicalDriveN device...\n");
|
||||
std::map<char, DriveLetterInfo> drive_letter_map = win32_get_drive_letter_map();
|
||||
|
||||
|
||||
std::shared_ptr<CmdexSync> smartctl_ex = ex_factory->create_executor(ExecutorFactory::ExecutorType::Smartctl);
|
||||
std::shared_ptr<CommandExecutor> smartctl_ex = ex_factory->create_executor(CommandExecutorFactory::ExecutorType::Smartctl);
|
||||
|
||||
// Fetch multiport devices using --scan-open.
|
||||
// Note that this may return duplicates (e.g. /dev/sda and /dev/csmi0,0)
|
||||
|
||||
std::set<int> used_pds;
|
||||
error_msg = get_scan_open_multiport_devices(drives, ex_factory, drive_letter_map, used_pds);
|
||||
if (!error_msg.empty()) {
|
||||
error_msgs.push_back(error_msg);
|
||||
error_message = get_scan_open_multiport_devices(drives, ex_factory, drive_letter_map, used_pds);
|
||||
if (!error_message.empty()) {
|
||||
error_msgs.push_back(error_message);
|
||||
}
|
||||
|
||||
bool multiport_found = !drives.empty();
|
||||
@@ -782,7 +782,7 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Exe
|
||||
if (!inst_path.empty()) {
|
||||
debug_out_dump("app", "3ware 3DM2 found at\"" << inst_path << "\".\n");
|
||||
std::vector<int> controllers;
|
||||
error_msg = tw_cli_get_controllers(ex_factory, controllers);
|
||||
error_message = tw_cli_get_controllers(ex_factory, controllers);
|
||||
// ignore the error message above, it's of no use.
|
||||
for (std::size_t i = 0; i < controllers.size(); ++i) {
|
||||
// don't specify device, it's ignored in tw_cli mode
|
||||
@@ -796,8 +796,8 @@ std::string detect_drives_win32(std::vector<StorageDevicePtr>& drives, const Exe
|
||||
|
||||
if (!areca_open_found) {
|
||||
detect_drives_win32_areca(drives, ex_factory);
|
||||
if (!error_msg.empty()) {
|
||||
error_msgs.push_back(error_msg);
|
||||
if (!error_message.empty()) {
|
||||
error_msgs.push_back(error_message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ void StorageDevice::clear_fetched(bool including_outputs) {
|
||||
|
||||
|
||||
|
||||
std::string StorageDevice::fetch_basic_data_and_parse(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
std::string StorageDevice::fetch_basic_data_and_parse(const std::shared_ptr<CommandExecutor>& smartctl_ex)
|
||||
{
|
||||
if (this->test_is_active_)
|
||||
return _("A test is currently being performed on this drive.");
|
||||
@@ -254,7 +254,7 @@ std::string StorageDevice::parse_basic_data(bool do_set_properties, bool emit_si
|
||||
|
||||
|
||||
|
||||
std::string StorageDevice::fetch_data_and_parse(const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
std::string StorageDevice::fetch_data_and_parse(const std::shared_ptr<CommandExecutor>& smartctl_ex)
|
||||
{
|
||||
if (this->test_is_active_)
|
||||
return _("A test is currently being performed on this drive.");
|
||||
@@ -346,7 +346,7 @@ StorageDevice::ParseStatus StorageDevice::get_parse_status() const
|
||||
|
||||
|
||||
|
||||
std::string StorageDevice::set_smart_enabled(bool b, const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
std::string StorageDevice::set_smart_enabled(bool b, const std::shared_ptr<CommandExecutor>& smartctl_ex)
|
||||
{
|
||||
if (this->test_is_active_)
|
||||
return _("A test is currently being performed on this drive.");
|
||||
@@ -386,7 +386,7 @@ A mandatory SMART command failed: exiting. To continue, add one or more '-T perm
|
||||
|
||||
|
||||
|
||||
std::string StorageDevice::set_aodc_enabled(bool b, const std::shared_ptr<CmdexSync>& smartctl_ex)
|
||||
std::string StorageDevice::set_aodc_enabled(bool b, const std::shared_ptr<CommandExecutor>& smartctl_ex)
|
||||
{
|
||||
if (this->test_is_active_) {
|
||||
return _("A test is currently being performed on this drive.");
|
||||
@@ -809,7 +809,7 @@ std::string StorageDevice::get_device_options() const
|
||||
|
||||
|
||||
std::string StorageDevice::execute_device_smartctl(const std::string& command_options,
|
||||
const std::shared_ptr<CmdexSync>& smartctl_ex, std::string& smartctl_output, bool check_type)
|
||||
const std::shared_ptr<CommandExecutor>& smartctl_ex, std::string& smartctl_output, bool check_type)
|
||||
{
|
||||
// don't forbid running on currently tested drive - we need to call this from the test code.
|
||||
|
||||
|
||||
@@ -84,14 +84,14 @@ class StorageDevice {
|
||||
/// Calls "smartctl -i -H -c" (info section, health, capabilities), then parse_basic_data().
|
||||
/// Called during drive detection.
|
||||
/// Note: this will clear the non-basic properties!
|
||||
std::string fetch_basic_data_and_parse(const std::shared_ptr<CmdexSync>& smartctl_ex = nullptr);
|
||||
std::string fetch_basic_data_and_parse(const std::shared_ptr<CommandExecutor>& smartctl_ex = nullptr);
|
||||
|
||||
/// Detects type, smart support, smart status (on / off).
|
||||
/// Note: this will clear the non-basic properties!
|
||||
std::string parse_basic_data(bool do_set_properties = true, bool emit_signal = true);
|
||||
|
||||
/// Execute smartctl --all (all sections), get output, parse it (basic data too), fill properties.
|
||||
std::string fetch_data_and_parse(const std::shared_ptr<CmdexSync>& smartctl_ex); // returns error message on error.
|
||||
std::string fetch_data_and_parse(const std::shared_ptr<CommandExecutor>& smartctl_ex); // returns error message on error.
|
||||
|
||||
// Parses full info. If failed, try to parse it as basic info.
|
||||
/// \return error message on error.
|
||||
@@ -103,11 +103,11 @@ class StorageDevice {
|
||||
|
||||
/// Try to enable SMART.
|
||||
/// \return error message on error, empty string on success
|
||||
std::string set_smart_enabled(bool b, const std::shared_ptr<CmdexSync>&);
|
||||
std::string set_smart_enabled(bool b, const std::shared_ptr<CommandExecutor>&);
|
||||
|
||||
/// Try to enable Automatic Offline Data Collection.
|
||||
/// \return error message on error, empty string on success
|
||||
std::string set_aodc_enabled(bool b, const std::shared_ptr<CmdexSync>&);
|
||||
std::string set_aodc_enabled(bool b, const std::shared_ptr<CommandExecutor>&);
|
||||
|
||||
|
||||
/// Get SMART status
|
||||
@@ -240,7 +240,7 @@ class StorageDevice {
|
||||
/// Execute smartctl on this device. Nothing is modified in this class.
|
||||
/// \return error message on error, empty string on success
|
||||
std::string execute_device_smartctl(const std::string& command_options,
|
||||
const std::shared_ptr<CmdexSync>& smartctl_ex, std::string& output, bool check_type = false);
|
||||
const std::shared_ptr<CommandExecutor>& smartctl_ex, std::string& output, bool check_type = false);
|
||||
|
||||
|
||||
/// Emitted whenever new information is available
|
||||
|
||||
@@ -103,7 +103,7 @@ GscExecutorLogWindow::GscExecutorLogWindow(BaseObjectType* gtkcobj, Glib::RefPtr
|
||||
|
||||
// ---------------
|
||||
|
||||
// Connect to CmdexSync signal
|
||||
// Connect to CommandExecutor signal
|
||||
cmdex_sync_signal_execute_finish().connect(sigc::mem_fun(*this,
|
||||
&GscExecutorLogWindow::on_command_output_received));
|
||||
|
||||
@@ -148,9 +148,9 @@ void GscExecutorLogWindow::clear_view_widgets()
|
||||
|
||||
|
||||
|
||||
void GscExecutorLogWindow::on_command_output_received(const CmdexSyncCommandInfo& info)
|
||||
void GscExecutorLogWindow::on_command_output_received(const CommandExecutorResult& info)
|
||||
{
|
||||
auto entry = std::make_shared<CmdexSyncCommandInfo>(info);
|
||||
auto entry = std::make_shared<CommandExecutorResult>(info);
|
||||
entries.push_back(entry);
|
||||
|
||||
// update tree model
|
||||
@@ -189,7 +189,7 @@ void GscExecutorLogWindow::on_window_save_current_button_clicked()
|
||||
return;
|
||||
|
||||
Gtk::TreeIter iter = selection->get_selected();
|
||||
std::shared_ptr<CmdexSyncCommandInfo> entry = (*iter)[col_entry];
|
||||
std::shared_ptr<CommandExecutorResult> entry = (*iter)[col_entry];
|
||||
|
||||
static std::string last_dir;
|
||||
if (last_dir.empty()) {
|
||||
@@ -305,7 +305,7 @@ void GscExecutorLogWindow::on_window_save_all_button_clicked()
|
||||
exss << "\n---------------" << "STDERR" << "---------------\n";
|
||||
exss << entries[i]->std_error << "\n\n";
|
||||
exss << "\n---------------" << "Error Message" << "---------------\n";
|
||||
exss << entries[i]->error_msg << "\n\n";
|
||||
exss << entries[i]->error_message << "\n\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +416,7 @@ void GscExecutorLogWindow::on_tree_selection_changed()
|
||||
Gtk::TreeIter iter = selection->get_selected();
|
||||
Gtk::TreeRow row = *iter;
|
||||
|
||||
std::shared_ptr<CmdexSyncCommandInfo> entry = row[col_entry];
|
||||
std::shared_ptr<CommandExecutorResult> entry = row[col_entry];
|
||||
|
||||
if (auto* output_textview = this->lookup_widget<Gtk::TextView*>("output_textview")) {
|
||||
Glib::RefPtr<Gtk::TextBuffer> buffer = output_textview->get_buffer();
|
||||
|
||||
@@ -18,7 +18,7 @@ Copyright:
|
||||
#include <memory>
|
||||
|
||||
#include "applib/app_builder_widget.h"
|
||||
#include "applib/cmdex_sync.h"
|
||||
#include "applib/command_executor.h"
|
||||
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class GscExecutorLogWindow : public AppBuilderWidget<GscExecutorLogWindow, false
|
||||
// -------------------- callbacks
|
||||
|
||||
/// Callback attached to external source, adds entries in real time.
|
||||
void on_command_output_received(const CmdexSyncCommandInfo& info);
|
||||
void on_command_output_received(const CommandExecutorResult& info);
|
||||
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class GscExecutorLogWindow : public AppBuilderWidget<GscExecutorLogWindow, false
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::shared_ptr<CmdexSyncCommandInfo>> entries; ///< Command information entries
|
||||
std::vector<std::shared_ptr<CommandExecutorResult>> entries; ///< Command information entries
|
||||
|
||||
|
||||
Glib::RefPtr<Gtk::ListStore> list_store; ///< List store
|
||||
@@ -90,7 +90,7 @@ class GscExecutorLogWindow : public AppBuilderWidget<GscExecutorLogWindow, false
|
||||
|
||||
Gtk::TreeModelColumn<std::size_t> col_num; ///< Tree column
|
||||
Gtk::TreeModelColumn<std::string> col_command; ///< Tree column
|
||||
Gtk::TreeModelColumn<std::shared_ptr<CmdexSyncCommandInfo>> col_entry; ///< Tree column
|
||||
Gtk::TreeModelColumn<std::shared_ptr<CommandExecutorResult>> col_entry; ///< Tree column
|
||||
|
||||
|
||||
};
|
||||
|
||||
@@ -2021,7 +2021,7 @@ void GscInfoWindow::on_test_execute_button_clicked()
|
||||
|
||||
|
||||
// We don't use idle function here, because it has the following problem:
|
||||
// CmdexSync::execute() (which is called on force_stop()) calls g_main_context_pending(),
|
||||
// CommandExecutor::execute() (which is called on force_stop()) calls g_main_context_pending(),
|
||||
// which returns true EVERY time, until the idle callback returns false.
|
||||
// So, force_stop() exits its "execute abort" command only when the
|
||||
// idle callback polls the drive on the next timeout and sees that the test
|
||||
|
||||
@@ -39,7 +39,7 @@ Copyright:
|
||||
#include "gsc_main_window_iconview.h"
|
||||
#include "gsc_main_window.h"
|
||||
#include "gsc_add_device_window.h"
|
||||
#include "applib/executor_factory.h"
|
||||
#include "applib/command_executor_factory.h"
|
||||
#include "gsc_startup_settings.h"
|
||||
|
||||
|
||||
@@ -1026,14 +1026,14 @@ void GscMainWindow::rescan_devices()
|
||||
sd.add_blacklist_patterns(blacklist_patterns);
|
||||
|
||||
|
||||
auto ex_factory = std::make_shared<ExecutorFactory>(true, this); // run it with GUI support
|
||||
auto ex_factory = std::make_shared<CommandExecutorFactory>(true, this); // run it with GUI support
|
||||
|
||||
std::string error_msg = sd.detect_and_fetch_basic_data(drives_, ex_factory);
|
||||
|
||||
bool error = false;
|
||||
|
||||
// Catch permission errors.
|
||||
// executor errors and outputs, not reported through error_msg.
|
||||
// executor errors and outputs, not reported through error_message.
|
||||
std::vector<std::string> fetch_outputs = sd.get_fetch_data_error_outputs();
|
||||
for (const auto& fetch_output : fetch_outputs) {
|
||||
// debug_out_error("app", DBG_FUNC_MSG << fetch_outputs[i] << "\n");
|
||||
@@ -1119,7 +1119,7 @@ bool GscMainWindow::add_device(const std::string& file, const std::string& type_
|
||||
drive->set_extra_arguments(extra_args);
|
||||
drive->set_is_manually_added(true);
|
||||
|
||||
auto ex_factory = std::make_shared<ExecutorFactory>(true, this); // pass this as dialog parent
|
||||
auto ex_factory = std::make_shared<CommandExecutorFactory>(true, this); // pass this as dialog parent
|
||||
|
||||
std::vector<StorageDevicePtr> tmp_drives;
|
||||
tmp_drives.push_back(drive);
|
||||
|
||||
Reference in New Issue
Block a user