Skip to content

Commit

Permalink
dnfdaemon: API to cancel current running transaction
Browse files Browse the repository at this point in the history
New API `Goal.cancel()` cancels 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.
  • Loading branch information
m-blaha authored and jan-kolarik committed Sep 4, 2024
1 parent 7f11f86 commit 4926fc5
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 0 deletions.
3 changes: 3 additions & 0 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 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" />
</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

0 comments on commit 4926fc5

Please sign in to comment.