// Copyright (C) 2019 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. #ifndef PREFETCHER_SESSION_H_ #define PREFETCHER_SESSION_H_ #include #include #include #include #include #include #include #include namespace iorap { namespace prefetcher { #ifndef READ_AHEAD_KIND #define READ_AHEAD_KIND 1 enum class ReadAheadKind : uint32_t { kFadvise = 0, kMmapLocked = 1, kMlock = 2, }; #endif class Session { public: virtual bool RegisterFilePath(size_t path_id, std::string_view file_path) = 0; virtual bool UnregisterFilePath(size_t path_id) = 0; // Immediately perform a readahead now. // Fadvise: the readahead will have been queued by the kernel. // MmapLocked/Mlock: the memory is pinned by the requested process. virtual bool ReadAhead(size_t path_id, ReadAheadKind kind, size_t length, size_t offset) = 0; // Cancels a readahead previously done. // The length/offset should match the call of ReadAhead. virtual bool UnreadAhead(size_t path_id, ReadAheadKind kind, size_t length, size_t offset) = 0; // Multi-line detailed dump, e.g. for dumpsys. // Single-line summary dump, e.g. for logcat. virtual void Dump(std::ostream& os, bool multiline) const = 0; // Process the FD for kCreateFdSession. // Assumes there's a compiled_trace.pb at the fd, calling this function // will immediately process it and execute any read-aheads. // // FD is borrowed only for the duration of the function call. virtual bool ProcessFd(int fd) = 0; // Get the session ID associated with this session. // Session IDs are distinct, they are not used for new sessions. virtual size_t SessionId() const = 0; // Get this session's description. // Only useful for logging/dumping. virtual const std::string& SessionDescription() const = 0; // Implicitly unregister any remaining file paths. // All read-aheads are also cancelled. virtual ~Session() {} protected: Session(); }; // Single-line summary dump of Session. std::ostream& operator<<(std::ostream&os, const Session& session); class SessionBase : public Session { public: virtual void Dump(std::ostream& os, bool multiline) const override; virtual ~SessionBase() {} virtual size_t SessionId() const override { return session_id_; } virtual const std::string& SessionDescription() const override { return description_; } virtual bool ProcessFd(int fd) override; protected: SessionBase(size_t session_id, std::string description); std::optional GetFilePath(size_t path_id) const; bool RemoveFilePath(size_t path_id); bool InsertFilePath(size_t path_id, std::string file_path); android::base::Timer timer_{}; private: // Note: Store filename for easier debugging and for dumping. std::unordered_map path_map_; size_t session_id_; std::string description_; }; // In-process session. class SessionDirect : public SessionBase { public: virtual bool RegisterFilePath(size_t path_id, std::string_view file_path) override; virtual bool UnregisterFilePath(size_t path_id) override; virtual bool ReadAhead(size_t path_id, ReadAheadKind kind, size_t length, size_t offset); virtual bool UnreadAhead(size_t path_id, ReadAheadKind kind, size_t length, size_t offset) override; virtual bool ProcessFd(int fd) override; virtual void Dump(std::ostream& os, bool multiline) const override; virtual ~SessionDirect(); SessionDirect(size_t session_id, std::string description) : SessionBase{session_id, std::move(description)} { } protected: struct Entry { size_t path_id; ReadAheadKind kind; size_t length; size_t offset; constexpr bool operator==(const Entry& other) const { return path_id == other.path_id && kind == other.kind && length == other.length && offset == other.offset; } constexpr bool operator!=(const Entry& other) const { return !(*this == other); } friend std::ostream& operator<<(std::ostream& os, const Entry& entry); }; struct EntryMapping { Entry entry; void* address; bool success; }; // bool EntryReadAhead(const Entry& entry) const; // bool EntryUnReadAhead(const Entry& entry) const; void UnmapWithoutErase(const EntryMapping& entry_mapping); std::optional GetFdForPath(size_t path_id); private: std::unordered_map> entry_list_map_; std::unordered_map path_fd_map_; public: friend std::ostream& operator<<(std::ostream& os, const SessionDirect::Entry& entry); }; std::ostream& operator<<(std::ostream& os, const SessionDirect::Entry& entry); class PrefetcherDaemon; // Out-of-process session. Requires prefetcher daemon. class SessionIndirect : public SessionBase { public: virtual bool RegisterFilePath(size_t path_id, std::string_view file_path) override; virtual bool UnregisterFilePath(size_t path_id) override; virtual bool ReadAhead(size_t path_id, ReadAheadKind kind, size_t length, size_t offset) override; virtual bool UnreadAhead(size_t path_id, ReadAheadKind kind, size_t length, size_t offset) override; virtual void Dump(std::ostream& os, bool multiline) const override; // Creates a new session indirectly. // Writes to daemon the new session command. SessionIndirect(size_t session_id, std::string description, std::shared_ptr daemon, bool send_command = true); // Destroys the current session. // Writes to daemon that the session is to be destroyed. virtual ~SessionIndirect(); protected: std::shared_ptr daemon_; }; // Out-of-process session. Requires prefetcher daemon. class SessionIndirectSocket : public SessionIndirect { public: // Creates a new session indirectly. // Writes to daemon the new session command. SessionIndirectSocket(size_t session_id, int fd, std::string description, std::shared_ptr daemon); // Destroys the current session. // Writes to daemon that the session is to be destroyed. virtual ~SessionIndirectSocket(); private: }; } // namespace prefetcher } // namespace iorap #endif