diff options
Diffstat (limited to 'src/core/function/gpg/GpgCommandExecutor.cpp')
-rw-r--r-- | src/core/function/gpg/GpgCommandExecutor.cpp | 246 |
1 files changed, 124 insertions, 122 deletions
diff --git a/src/core/function/gpg/GpgCommandExecutor.cpp b/src/core/function/gpg/GpgCommandExecutor.cpp index fb1d647d..5cf57b27 100644 --- a/src/core/function/gpg/GpgCommandExecutor.cpp +++ b/src/core/function/gpg/GpgCommandExecutor.cpp @@ -28,112 +28,22 @@ #include "GpgCommandExecutor.h" #include <boost/format.hpp> -#include <string> +#include <utility> #include "GpgFunctionObject.h" -#include "core/thread/DataObject.h" +#include "core/model/DataObject.h" +#include "core/module/Module.h" +#include "core/thread/Task.h" #include "core/thread/TaskRunnerGetter.h" -#include "module/Module.h" -#include "spdlog/spdlog.h" -#include "thread/Task.h" namespace GpgFrontend { -GpgCommandExecutor::ExecuteContext::ExecuteContext( - std::string cmd, std::vector<std::string> arguments, - GpgCommandExecutorCallback callback, Module::TaskRunnerPtr task_runner, - GpgCommandExecutorInteractor int_func) - : cmd(cmd), - arguments(arguments), - cb_func(callback), - int_func(int_func), - task_runner(task_runner) {} - -GpgCommandExecutor::GpgCommandExecutor(int channel) - : SingletonFunctionObject<GpgCommandExecutor>(channel) {} - -void GpgCommandExecutor::ExecuteSync(ExecuteContext context) { - Thread::Task *task = build_task_from_exec_ctx(context); - - QEventLoop looper; - QObject::connect(task, &Thread::Task::SignalTaskEnd, &looper, - &QEventLoop::quit); - - Thread::TaskRunnerPtr target_task_runner = nullptr; - - if (context.task_runner != nullptr) { - target_task_runner = context.task_runner; - } else { - target_task_runner = - GpgFrontend::Thread::TaskRunnerGetter::GetInstance().GetTaskRunner( - Thread::TaskRunnerGetter::kTaskRunnerType_External_Process); - } - - target_task_runner->PostTask(task); - - // to arvoid dead lock issue we need to check if current thread is the same as - // target thread. if it is, we can't call exec() because it will block the - // current thread. - if (QThread::currentThread() != target_task_runner->GetThread()) { - // block until task finished - // this is to keep reference vaild until task finished - looper.exec(); - } -} - -void GpgCommandExecutor::ExecuteConcurrentlyAsync(ExecuteContexts contexts) { - for (auto &context : contexts) { - auto &cmd = context.cmd; - SPDLOG_INFO("gpg concurrently called cmd {}", cmd); - - Thread::Task *task = build_task_from_exec_ctx(context); - - if (context.task_runner != nullptr) - context.task_runner->PostTask(task); - else - GpgFrontend::Thread::TaskRunnerGetter::GetInstance() - .GetTaskRunner( - Thread::TaskRunnerGetter::kTaskRunnerType_External_Process) - ->PostTask(task); - } -} - -void GpgCommandExecutor::ExecuteConcurrentlySync( - const ExecuteContexts contexts) { - QEventLoop looper; - int remainingTasks = contexts.size(); - - for (auto &context : contexts) { - auto &cmd = context.cmd; - SPDLOG_INFO("gpg concurrently called cmd {}", cmd); - - Thread::Task *task = build_task_from_exec_ctx(context); - - QObject::connect(task, &Thread::Task::SignalTaskEnd, [&]() { - --remainingTasks; - if (remainingTasks <= 0) { - looper.quit(); - } - }); - - if (context.task_runner != nullptr) - context.task_runner->PostTask(task); - else - GpgFrontend::Thread::TaskRunnerGetter::GetInstance() - .GetTaskRunner( - Thread::TaskRunnerGetter::kTaskRunnerType_External_Process) - ->PostTask(task); - } - - looper.exec(); -} - -Thread::Task *GpgCommandExecutor::build_task_from_exec_ctx( - const ExecuteContext &context) { - auto &cmd = context.cmd; - auto &arguments = context.arguments; - auto &interact_function = context.int_func; - auto &cmd_executor_callback = context.cb_func; +auto BuildTaskFromExecCtx(const GpgCommandExecutor::ExecuteContext &context) + -> Thread::Task * { + const auto &cmd = context.cmd; + const auto &arguments = context.arguments; + const auto &interact_function = context.int_func; + const auto &cmd_executor_callback = context.cb_func; const std::string joined_argument = std::accumulate( std::begin(arguments), std::end(arguments), std::string(), @@ -145,21 +55,20 @@ Thread::Task *GpgCommandExecutor::build_task_from_exec_ctx( arguments.size()); Thread::Task::TaskCallback result_callback = - [cmd, joined_argument](int rtn, Thread::DataObjectPtr data_object) { + [cmd, joined_argument](int /*rtn*/, const DataObjectPtr &data_object) { SPDLOG_DEBUG( "data object args count of cmd executor result callback: {}", data_object->GetObjectSize()); if (!data_object->Check<int, std::string, std::string, - GpgCommandExecutorCallback>()) + GpgCommandExecutorCallback>()) { throw std::runtime_error("invalid data object size"); + } - auto exit_code = Thread::ExtractParams<int>(data_object, 0); - auto process_stdout = - Thread::ExtractParams<std::string>(data_object, 1); - auto process_stderr = - Thread::ExtractParams<std::string>(data_object, 2); + auto exit_code = ExtractParams<int>(data_object, 0); + auto process_stdout = ExtractParams<std::string>(data_object, 1); + auto process_stderr = ExtractParams<std::string>(data_object, 2); auto callback = - Thread::ExtractParams<GpgCommandExecutorCallback>(data_object, 3); + ExtractParams<GpgCommandExecutorCallback>(data_object, 3); // call callback SPDLOG_DEBUG( @@ -170,31 +79,38 @@ Thread::Task *GpgCommandExecutor::build_task_from_exec_ctx( }; Thread::Task::TaskRunnable runner = - [joined_argument](Thread::DataObjectPtr data_object) -> int { + [joined_argument](const DataObjectPtr &data_object) -> int { SPDLOG_DEBUG("process runner called, data object size: {}", data_object->GetObjectSize()); if (!data_object->Check<std::string, std::vector<std::string>, GpgCommandExecutorInteractor, - GpgCommandExecutorCallback>()) + GpgCommandExecutorCallback>()) { throw std::runtime_error("invalid data object size"); + } // get arguments - auto cmd = Thread::ExtractParams<std::string>(data_object, 0); - auto arguments = - Thread::ExtractParams<std::vector<std::string>>(data_object, 1); + auto cmd = ExtractParams<std::string>(data_object, 0); + auto arguments = ExtractParams<std::vector<std::string>>(data_object, 1); auto interact_func = - Thread::ExtractParams<GpgCommandExecutorInteractor>(data_object, 2); - auto callback = - Thread::ExtractParams<GpgCommandExecutorCallback>(data_object, 3); + ExtractParams<GpgCommandExecutorInteractor>(data_object, 2); + auto callback = ExtractParams<GpgCommandExecutorCallback>(data_object, 3); + // create process auto *cmd_process = new QProcess(); + // move to current thread + // cmd_process->moveToThread(QThread::currentThread()); + // set process channel mode + // this is to make sure we can get all output from stdout and stderr cmd_process->setProcessChannelMode(QProcess::MergedChannels); cmd_process->setProgram(QString::fromStdString(cmd)); + + // set arguments QStringList q_arguments; - for (const auto &argument : arguments) + for (const auto &argument : arguments) { q_arguments.append(QString::fromStdString(argument)); + } cmd_process->setArguments(q_arguments); QObject::connect( @@ -223,9 +139,9 @@ Thread::Task *GpgCommandExecutor::build_task_from_exec_ctx( cmd_process->waitForFinished(); std::string process_stdout = - cmd_process->readAllStandardOutput().toStdString(), - process_stderr = - cmd_process->readAllStandardError().toStdString(); + cmd_process->readAllStandardOutput().toStdString(); + std::string process_stderr = + cmd_process->readAllStandardError().toStdString(); int exit_code = cmd_process->exitCode(); SPDLOG_DEBUG( @@ -251,9 +167,95 @@ Thread::Task *GpgCommandExecutor::build_task_from_exec_ctx( std::move(runner), (boost::format("GpgCommamdExecutor(%1%){%2%}") % cmd % joined_argument) .str(), - Thread::TransferParams(cmd, arguments, interact_function, - cmd_executor_callback), + TransferParams(cmd, arguments, interact_function, cmd_executor_callback), std::move(result_callback)); } +GpgCommandExecutor::ExecuteContext::ExecuteContext( + std::string cmd, std::vector<std::string> arguments, + GpgCommandExecutorCallback callback, Module::TaskRunnerPtr task_runner, + GpgCommandExecutorInteractor int_func) + : cmd(std::move(cmd)), + arguments(std::move(arguments)), + cb_func(std::move(callback)), + int_func(std::move(int_func)), + task_runner(std::move(task_runner)) {} + +void GpgCommandExecutor::ExecuteSync(ExecuteContext context) { + Thread::Task *task = BuildTaskFromExecCtx(context); + + QEventLoop looper; + QObject::connect(task, &Thread::Task::SignalTaskEnd, &looper, + &QEventLoop::quit); + + Thread::TaskRunnerPtr target_task_runner = nullptr; + + if (context.task_runner != nullptr) { + target_task_runner = context.task_runner; + } else { + target_task_runner = + GpgFrontend::Thread::TaskRunnerGetter::GetInstance().GetTaskRunner( + Thread::TaskRunnerGetter::kTaskRunnerType_External_Process); + } + + target_task_runner->PostTask(task); + + // to arvoid dead lock issue we need to check if current thread is the same as + // target thread. if it is, we can't call exec() because it will block the + // current thread. + if (QThread::currentThread() != target_task_runner->GetThread()) { + // block until task finished + // this is to keep reference vaild until task finished + looper.exec(); + } +} + +void GpgCommandExecutor::ExecuteConcurrentlyAsync(ExecuteContexts contexts) { + for (auto &context : contexts) { + const auto &cmd = context.cmd; + SPDLOG_INFO("gpg concurrently called cmd {}", cmd); + + Thread::Task *task = BuildTaskFromExecCtx(context); + + if (context.task_runner != nullptr) { + context.task_runner->PostTask(task); + } else { + GpgFrontend::Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner( + Thread::TaskRunnerGetter::kTaskRunnerType_External_Process) + ->PostTask(task); + } + } +} + +void GpgCommandExecutor::ExecuteConcurrentlySync(ExecuteContexts contexts) { + QEventLoop looper; + auto remaining_tasks = contexts.size(); + + for (auto &context : contexts) { + const auto &cmd = context.cmd; + SPDLOG_INFO("gpg concurrently called cmd {}", cmd); + + Thread::Task *task = BuildTaskFromExecCtx(context); + + QObject::connect(task, &Thread::Task::SignalTaskEnd, [&]() { + --remaining_tasks; + if (remaining_tasks <= 0) { + looper.quit(); + } + }); + + if (context.task_runner != nullptr) { + context.task_runner->PostTask(task); + } else { + GpgFrontend::Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner( + Thread::TaskRunnerGetter::kTaskRunnerType_External_Process) + ->PostTask(task); + } + } + + looper.exec(); +} + } // namespace GpgFrontend
\ No newline at end of file |