| // Copyright (C) 2023 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #pragma once |
| |
| #include <memory> |
| #include <queue> |
| #include <string> |
| #include <thread> |
| #include <vector> |
| |
| #include <android-base/unique_fd.h> |
| |
| namespace android { |
| namespace snapshot { |
| |
| class SnapshotHandler; |
| |
| class HandlerThread { |
| public: |
| explicit HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd); |
| |
| void FreeResources(); |
| const std::shared_ptr<SnapshotHandler>& snapuserd() const { return snapuserd_; } |
| std::thread& thread() { return thread_; } |
| |
| const std::string& misc_name() const { return misc_name_; } |
| bool ThreadTerminated() { return thread_terminated_; } |
| void SetThreadTerminated() { thread_terminated_ = true; } |
| |
| private: |
| std::thread thread_; |
| std::shared_ptr<SnapshotHandler> snapuserd_; |
| std::string misc_name_; |
| bool thread_terminated_ = false; |
| }; |
| |
| class ISnapshotHandlerManager { |
| public: |
| virtual ~ISnapshotHandlerManager() {} |
| |
| // Add a new snapshot handler but do not start serving requests yet. |
| virtual std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name, |
| const std::string& cow_device_path, |
| const std::string& backing_device, |
| const std::string& base_path_merge, |
| int num_worker_threads, bool use_iouring, |
| bool perform_verification) = 0; |
| |
| // Start serving requests on a snapshot handler. |
| virtual bool StartHandler(const std::string& misc_name) = 0; |
| |
| // Stop serving requests on a snapshot handler and remove it. |
| virtual bool DeleteHandler(const std::string& misc_name) = 0; |
| |
| // Begin merging blocks on the given snapshot handler. |
| virtual bool InitiateMerge(const std::string& misc_name) = 0; |
| |
| // Return a string containing a status code indicating the merge status |
| // on the handler. Returns empty on error. |
| virtual std::string GetMergeStatus(const std::string& misc_name) = 0; |
| |
| // Wait until all handlers have terminated. |
| virtual void JoinAllThreads() = 0; |
| |
| // Stop any in-progress merge threads. |
| virtual void TerminateMergeThreads() = 0; |
| |
| // Returns the merge progress across all merging snapshot handlers. |
| virtual double GetMergePercentage() = 0; |
| |
| // Returns whether all snapshots have verified. |
| virtual bool GetVerificationStatus() = 0; |
| }; |
| |
| class SnapshotHandlerManager final : public ISnapshotHandlerManager { |
| public: |
| SnapshotHandlerManager(); |
| std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name, |
| const std::string& cow_device_path, |
| const std::string& backing_device, |
| const std::string& base_path_merge, |
| int num_worker_threads, bool use_iouring, |
| bool perform_verification) override; |
| bool StartHandler(const std::string& misc_name) override; |
| bool DeleteHandler(const std::string& misc_name) override; |
| bool InitiateMerge(const std::string& misc_name) override; |
| std::string GetMergeStatus(const std::string& misc_name) override; |
| void JoinAllThreads() override; |
| void TerminateMergeThreads() override; |
| double GetMergePercentage() override; |
| bool GetVerificationStatus() override; |
| |
| private: |
| bool StartHandler(const std::shared_ptr<HandlerThread>& handler); |
| void RunThread(std::shared_ptr<HandlerThread> handler); |
| bool StartMerge(std::lock_guard<std::mutex>* proof_of_lock, |
| const std::shared_ptr<HandlerThread>& handler); |
| void MonitorMerge(); |
| void WakeupMonitorMergeThread(); |
| bool RemoveAndJoinHandler(const std::string& misc_name); |
| |
| // Find a HandlerThread within a lock. |
| using HandlerList = std::vector<std::shared_ptr<HandlerThread>>; |
| HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock, |
| const std::string& misc_name); |
| |
| std::mutex lock_; |
| HandlerList dm_users_; |
| |
| bool is_merge_monitor_started_ = false; |
| bool stop_monitor_merge_thread_ = false; |
| int active_merge_threads_ = 0; |
| int num_partitions_merge_complete_ = 0; |
| std::queue<std::shared_ptr<HandlerThread>> merge_handlers_; |
| android::base::unique_fd monitor_merge_event_fd_; |
| }; |
| |
| } // namespace snapshot |
| } // namespace android |