Add a subsession switch callback to dir backend 53/320153/4
authorMichal Bloch <m.bloch@samsung.com>
Mon, 24 Feb 2025 14:15:38 +0000 (15:15 +0100)
committerMichal Bloch <m.bloch@samsung.com>
Thu, 27 Feb 2025 15:28:11 +0000 (16:28 +0100)
Change-Id: I83bd27940fe61c6ac6b3a45be9e784db5b4535eb

src/service/src/dir_backend.hpp
src/service/src/dir_backend_regular_dir.cpp
src/service/src/dir_backend_regular_dir.hpp
src/service/src/fs_helpers.cpp
src/service/src/fs_helpers.hpp
src/service/src/main.cpp

index af6a89e63baae58c59d56eee6ef736add0291506..ce9b8d6c7810d54baca0308c276e509bb5e83841 100644 (file)
@@ -4,4 +4,6 @@
 
 struct DirBackend {
        virtual void RemoveSubsession (const std::filesystem::path& subsession_path) const = 0;
+       virtual void SwitchSubsessionAway (const std::filesystem::path& subsession_path) const = 0;
+       virtual void SwitchSubsessionInto (const std::filesystem::path& subsession_path) const = 0;
 };
index cdc7b94ddde52a8bd1efdfadfeaeef8684db56a2..39db809cdc39dd80bc7422de9b7abd16a1c5b3da 100644 (file)
@@ -44,3 +44,11 @@ void DirBackendRegularDir::RemoveSubsession (const fs::path& subsession_path) co
        fs::rename(subsession_path, tmp_subsession_path);
        fs::remove_all(tmp_subsession_path);
 }
+
+void DirBackendRegularDir::SwitchSubsessionAway (const std::filesystem::path& subsession_path) const
+{
+}
+
+void DirBackendRegularDir::SwitchSubsessionInto (const std::filesystem::path& subsession_path) const
+{
+}
index 1290a2ba9d11cc5ef00bd6a34919567f4f67a79d..39c49df2d66c59586ac64a65a5e4fc98e576f605 100644 (file)
@@ -4,4 +4,6 @@
 
 struct DirBackendRegularDir : public DirBackend {
        void RemoveSubsession (const std::filesystem::path& subsession_path) const override;
+       void SwitchSubsessionAway (const std::filesystem::path& subsession_path) const override;
+       void SwitchSubsessionInto (const std::filesystem::path& subsession_path) const override;
 };
index c2e349d40deee42b8da8775ef166cfcd708636a7..138370e6f4fb2b6f3349ea0d2f8dff6420cd692c 100644 (file)
@@ -252,6 +252,33 @@ static const DirBackend& GetBackendOfSubsession(const fs::path& path)
        return dbrd;
 }
 
+bool switch_user_subsession(const int session_uid, const std::string_view prev_subsession, const std::string_view next_subsession)
+{
+       /* We switch into next first, and only then switch away from prev. This is so
+        * that we are never in an intermediate "no session" state which is important
+        * for robustness (consider the case where Away succeeds and Into fails). */
+
+       try {
+               const auto next_subsession_path = fs::path(get_main_dir_by_user_id(session_uid)) / next_subsession;
+               const DirBackend& next_backend = GetBackendOfSubsession(next_subsession_path);
+               next_backend.SwitchSubsessionInto(next_subsession_path);
+       } catch (const std::exception &ex) {
+               LOGE("Logic exception %s\nwhile switching into subsession [session_uid=%d subsession_id=%s]", ex.what(), session_uid, next_subsession.data());
+               return false;
+       }
+
+       try {
+               const auto prev_subsession_path = fs::path(get_main_dir_by_user_id(session_uid)) / prev_subsession;
+               const DirBackend& prev_backend = GetBackendOfSubsession(prev_subsession_path);
+               prev_backend.SwitchSubsessionAway(prev_subsession_path);
+       } catch (const std::exception &ex) {
+               LOGE("Logic exception %s\nwhile switching away from user subsession [session_uid=%d subsession_id=%s]", ex.what(), session_uid, prev_subsession.data());
+               // fallthrough and return true, the new subsession was mounted after all
+       }
+
+       return true;
+}
+
 void remove_user_subsession(const int session_uid, const std::string_view subsession_id)
 {
        try {
index 2a0800b1cb94ab74d09665128fec531867f3b3f6..acdc7838086a9a085b5e90ceefaa745be56741d3 100644 (file)
@@ -9,6 +9,7 @@
 bool subsession_exists(const int session_uid, const std::string_view subsession_id);
 void add_user_subsession(const int session_uid, const std::string_view subsession_id);
 void remove_user_subsession(const int session_uid, const std::string_view subsession_id);
+bool switch_user_subsession(const int session_uid, const std::string_view prev_subsession, const std::string_view next_subsession);
 std::vector<std::string> get_user_list(const int session_uid);
 
 constexpr static std::string_view main_dir_name  = "subsession";
index fcc1c110d076af030fe5308d25ac91cded5b223b..7b03c8d82e3690d5418f36b218b6ffc2f6c67c46 100644 (file)
@@ -245,6 +245,12 @@ struct sessiond_context {
                                vals_to_g_variant(session_uid, switch_id, prev_subsession_id, next_subsession_id), &err))
                        g_error_throw(err, "Failed to emit a signal: ");
 
+               if (!switch_user_subsession(session_uid, prev_subsession_id, next_subsession_id)) {
+                       g_dbus_method_invocation_return_dbus_error(invocation,
+                               get_dbus_error_mapping(SUBSESSION_ERROR_IO_ERROR), "Failed to switch away from previous subsession");
+                       return;
+               }
+
                last_subsession_per_session[session_uid] = next_subsession_id;
 
                wait_switch.try_emplace(session_uid, session_uid, connection, "SwitchUserCompleted");