Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

daemon: D-Bus API to cancel current transaction #1665

Merged
merged 2 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions dnf5/download_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ int DownloadCallbacks::progress(void * user_cb_data, double total_to_download, d
if (is_time_to_print()) {
print();
}
return 0;
return ReturnCode::OK;
}

int DownloadCallbacks::end(void * user_cb_data, TransferStatus status, const char * msg) {
Expand All @@ -87,7 +87,7 @@ int DownloadCallbacks::end(void * user_cb_data, TransferStatus status, const cha
break;
}
print();
return 0;
return ReturnCode::OK;
}

int DownloadCallbacks::mirror_failure(void * user_cb_data, const char * msg, const char * url, const char * metadata) {
Expand All @@ -98,7 +98,7 @@ int DownloadCallbacks::mirror_failure(void * user_cb_data, const char * msg, con
}
progress_bar->add_message(libdnf5::cli::progressbar::MessageType::ERROR, message);
print();
return 0;
return ReturnCode::OK;
}

void DownloadCallbacks::reset_progress_bar() {
Expand Down
9 changes: 6 additions & 3 deletions dnf5daemon-server/callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ void * DownloadCB::add_new_download(void * user_data, const char * description,
}

int DownloadCB::progress(void * user_cb_data, double total_to_download, double downloaded) {
if (session.get_cancel_download() == Session::CancelDownload::REQUESTED) {
return ReturnCode::ERROR;
}
try {
if (is_time_to_print()) {
auto signal = create_signal_download(dnfdaemon::SIGNAL_DOWNLOAD_PROGRESS, user_cb_data);
Expand All @@ -75,7 +78,7 @@ int DownloadCB::progress(void * user_cb_data, double total_to_download, double d
}
} catch (...) {
}
return 0;
return ReturnCode::OK;
}

int DownloadCB::end(void * user_cb_data, TransferStatus status, const char * msg) {
Expand All @@ -86,7 +89,7 @@ int DownloadCB::end(void * user_cb_data, TransferStatus status, const char * msg
dbus_object->emitSignal(signal);
} catch (...) {
}
return 0;
return ReturnCode::OK;
}

int DownloadCB::mirror_failure(void * user_cb_data, const char * msg, const char * url, const char * metadata) {
Expand All @@ -98,7 +101,7 @@ int DownloadCB::mirror_failure(void * user_cb_data, const char * msg, const char
dbus_object->emitSignal(signal);
} catch (...) {
}
return 0;
return ReturnCode::OK;
}


Expand Down
12 changes: 12 additions & 0 deletions dnf5daemon-server/dbus/interfaces/org.rpm.dnf.v0.Goal.xml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ along with libdnf. If not, see <https://www.gnu.org/licenses/>.
<arg name="options" type="a{sv}" direction="in" />
</method>

<!--
cancel:
@success: true if the cancellation was sucessfully requested
@error_msg: error message if the cancellation was refused

Cancel the transaction that was initiated by `do_transaction()`. The transaction can only be canceled during the package download phase. Once the RPM transaction has begun, cancellation is no longer permitted.
-->
<method name="cancel">
<arg name="success" type="b" />
<arg name="error_msg" type="s" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set direction="out" for both of these, please. The default, when not set, is the arguments are input arguments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened #1679 for this (the change is part of it)

</method>

</interface>

</node>
40 changes: 40 additions & 0 deletions dnf5daemon-server/services/goal/goal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ void Goal::dbus_register() {
[this](sdbus::MethodCall call) -> void {
session.get_threads_manager().handle_method(*this, &Goal::do_transaction, call, session.session_locale);
});
dbus_object->registerMethod(
dnfdaemon::INTERFACE_GOAL,
"cancel",
"",
{},
"bs",
{"success", "error_msg"},
[this](sdbus::MethodCall call) -> void {
session.get_threads_manager().handle_method(*this, &Goal::cancel, call, session.session_locale);
});
}

sdbus::MethodReply Goal::resolve(sdbus::MethodCall & call) {
Expand Down Expand Up @@ -269,6 +279,7 @@ sdbus::MethodReply Goal::do_transaction(sdbus::MethodCall & call) {
if (!session.check_authorization(dnfdaemon::POLKIT_EXECUTE_RPM_TRANSACTION, call.getSender())) {
throw std::runtime_error("Not authorized");
}
session.set_cancel_download(Session::CancelDownload::NOT_REQUESTED);

// read options from dbus call
dnfdaemon::KeyValueMap options;
Expand All @@ -281,6 +292,7 @@ sdbus::MethodReply Goal::do_transaction(sdbus::MethodCall & call) {
// TODO(mblaha): signalize reboot?
} else {
session.download_transaction_packages();
session.set_cancel_download(Session::CancelDownload::NOT_ALLOWED);

std::string comment;
if (options.find("comment") != options.end()) {
Expand All @@ -306,3 +318,31 @@ sdbus::MethodReply Goal::do_transaction(sdbus::MethodCall & call) {
auto reply = call.createReply();
return reply;
}

sdbus::MethodReply Goal::cancel(sdbus::MethodCall & call) {
bool success{true};
std::string error_msg;

switch (session.get_cancel_download()) {
case Session::CancelDownload::NOT_REQUESTED:
session.set_cancel_download(Session::CancelDownload::REQUESTED);
break;
case Session::CancelDownload::REQUESTED:
success = false;
error_msg = "Cancellation was already requested.";
break;
case Session::CancelDownload::NOT_ALLOWED:
success = false;
error_msg = "Cancellation is not allowed after the RPM transaction has started.";
break;
case Session::CancelDownload::NOT_RUNNING:
success = false;
error_msg = "No transaction is running.";
break;
}

auto reply = call.createReply();
reply << success;
reply << error_msg;
return reply;
}
1 change: 1 addition & 0 deletions dnf5daemon-server/services/goal/goal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Goal : public IDbusSessionService {
sdbus::MethodReply get_transaction_problems_string(sdbus::MethodCall & call);
sdbus::MethodReply get_transaction_problems(sdbus::MethodCall & call);
sdbus::MethodReply do_transaction(sdbus::MethodCall & call);
sdbus::MethodReply cancel(sdbus::MethodCall & call);
};

#endif
1 change: 1 addition & 0 deletions dnf5daemon-server/session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ void Session::store_transaction_offline() {
std::filesystem::create_directories(dest_dir);
base->get_config().get_destdir_option().set(dest_dir);
download_transaction_packages();
set_cancel_download(Session::CancelDownload::NOT_ALLOWED);

const auto & offline_datadir = installroot / libdnf5::offline::DEFAULT_DATADIR.relative_path();
std::filesystem::create_directories(offline_datadir);
Expand Down
7 changes: 7 additions & 0 deletions dnf5daemon-server/session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class IDbusSessionService {

class Session {
public:
enum class CancelDownload { NOT_RUNNING, NOT_REQUESTED, REQUESTED, NOT_ALLOWED };
Session(
std::vector<std::unique_ptr<libdnf5::Logger>> && loggers,
sdbus::IConnection & connection,
Expand Down Expand Up @@ -93,6 +94,11 @@ class Session {
/// prepare the current transaction to run during the next reboot
void store_transaction_offline();

/// Getter for download cancel request flag.
CancelDownload get_cancel_download() { return cancel_download.load(); }
/// Setter for download cancel request flag.
void set_cancel_download(CancelDownload value) { cancel_download.store(value); }

private:
sdbus::IConnection & connection;
std::unique_ptr<libdnf5::Base> base;
Expand All @@ -110,6 +116,7 @@ class Session {
std::mutex key_import_mutex;
std::condition_variable key_import_condition;
std::map<std::string, KeyConfirmationStatus> key_import_status{}; // map key_id: confirmation status
std::atomic<CancelDownload> cancel_download{CancelDownload::NOT_RUNNING};
};

#endif
4 changes: 4 additions & 0 deletions include/libdnf5/repo/download_callbacks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class LIBDNF_API DownloadCallbacks {
/// Transfer status codes.
enum class TransferStatus { SUCCESSFUL, ALREADYEXISTS, ERROR };

/// Download callbacks return values.
/// RETURN_OK - all is fine, RETURN_ABORT - abort just the current download, RETURN_ERROR - abort all downloading
enum ReturnCode : int { OK = 0, ABORT = 1, ERROR = 2 };

DownloadCallbacks() = default;
DownloadCallbacks(const DownloadCallbacks &) = delete;
DownloadCallbacks(DownloadCallbacks &&) = delete;
Expand Down
6 changes: 3 additions & 3 deletions libdnf5/repo/download_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@ void * DownloadCallbacks::add_new_download(

int DownloadCallbacks::end(
[[maybe_unused]] void * user_cb_data, [[maybe_unused]] TransferStatus status, [[maybe_unused]] const char * msg) {
return 0;
return ReturnCode::OK;
}

int DownloadCallbacks::progress(
[[maybe_unused]] void * user_cb_data,
[[maybe_unused]] double total_to_download,
[[maybe_unused]] double downloaded) {
return 0;
return ReturnCode::OK;
}

int DownloadCallbacks::mirror_failure(
[[maybe_unused]] void * user_cb_data,
[[maybe_unused]] const char * msg,
[[maybe_unused]] const char * url,
[[maybe_unused]] const char * metadata) {
return 0;
return ReturnCode::OK;
}

void DownloadCallbacks::fastest_mirror(
Expand Down
Loading