1 // Copyright (C) 2019 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef PREFETCHER_SESSION_H_ 16 #define PREFETCHER_SESSION_H_ 17 18 #include <android-base/chrono_utils.h> 19 #include <android-base/unique_fd.h> 20 21 #include <optional> 22 #include <memory> 23 #include <string> 24 #include <string_view> 25 #include <unordered_map> 26 #include <vector> 27 28 namespace iorap { 29 namespace prefetcher { 30 31 #ifndef READ_AHEAD_KIND 32 #define READ_AHEAD_KIND 1 33 enum class ReadAheadKind : uint32_t { 34 kFadvise = 0, 35 kMmapLocked = 1, 36 kMlock = 2, 37 }; 38 #endif 39 40 class Session { 41 public: 42 virtual bool RegisterFilePath(size_t path_id, std::string_view file_path) = 0; 43 virtual bool UnregisterFilePath(size_t path_id) = 0; 44 45 // Immediately perform a readahead now. 46 // Fadvise: the readahead will have been queued by the kernel. 47 // MmapLocked/Mlock: the memory is pinned by the requested process. 48 virtual bool ReadAhead(size_t path_id, ReadAheadKind kind, size_t length, size_t offset) = 0; 49 50 // Cancels a readahead previously done. 51 // The length/offset should match the call of ReadAhead. 52 virtual bool UnreadAhead(size_t path_id, ReadAheadKind kind, size_t length, size_t offset) = 0; 53 54 // Multi-line detailed dump, e.g. for dumpsys. 55 // Single-line summary dump, e.g. for logcat. 56 virtual void Dump(std::ostream& os, bool multiline) const = 0; 57 58 // Process the FD for kCreateFdSession. 59 // Assumes there's a compiled_trace.pb at the fd, calling this function 60 // will immediately process it and execute any read-aheads. 61 // 62 // FD is borrowed only for the duration of the function call. 63 virtual bool ProcessFd(int fd) = 0; 64 65 // Get the session ID associated with this session. 66 // Session IDs are distinct, they are not used for new sessions. 67 virtual size_t SessionId() const = 0; 68 69 // Get this session's description. 70 // Only useful for logging/dumping. 71 virtual const std::string& SessionDescription() const = 0; 72 73 // Implicitly unregister any remaining file paths. 74 // All read-aheads are also cancelled. ~Session()75 virtual ~Session() {} 76 77 protected: 78 Session(); 79 }; 80 81 // Single-line summary dump of Session. 82 std::ostream& operator<<(std::ostream&os, const Session& session); 83 84 class SessionBase : public Session { 85 public: 86 virtual void Dump(std::ostream& os, bool multiline) const override; ~SessionBase()87 virtual ~SessionBase() {} 88 SessionId()89 virtual size_t SessionId() const override { 90 return session_id_; 91 } 92 SessionDescription()93 virtual const std::string& SessionDescription() const override { 94 return description_; 95 } 96 97 virtual bool ProcessFd(int fd) override; 98 99 protected: 100 SessionBase(size_t session_id, std::string description); 101 std::optional<std::string_view> GetFilePath(size_t path_id) const; 102 bool RemoveFilePath(size_t path_id); 103 bool InsertFilePath(size_t path_id, std::string file_path); 104 105 android::base::Timer timer_{}; 106 private: 107 // Note: Store filename for easier debugging and for dumping. 108 std::unordered_map</*path_id*/size_t, std::string> path_map_; 109 size_t session_id_; 110 std::string description_; 111 }; 112 113 // In-process session. 114 class SessionDirect : public SessionBase { 115 public: 116 virtual bool RegisterFilePath(size_t path_id, std::string_view file_path) override; 117 118 virtual bool UnregisterFilePath(size_t path_id) override; 119 virtual bool ReadAhead(size_t path_id, 120 ReadAheadKind kind, 121 size_t length, 122 size_t offset); 123 124 virtual bool UnreadAhead(size_t path_id, 125 ReadAheadKind kind, 126 size_t length, 127 size_t offset) override; 128 129 virtual bool ProcessFd(int fd) override; 130 131 virtual void Dump(std::ostream& os, bool multiline) const override; 132 133 virtual ~SessionDirect(); 134 SessionDirect(size_t session_id,std::string description)135 SessionDirect(size_t session_id, std::string description) 136 : SessionBase{session_id, std::move(description)} { 137 } 138 protected: 139 struct Entry { 140 size_t path_id; 141 ReadAheadKind kind; 142 size_t length; 143 size_t offset; 144 145 constexpr bool operator==(const Entry& other) const { 146 return path_id == other.path_id && 147 kind == other.kind && 148 length == other.length && 149 offset == other.offset; 150 } 151 constexpr bool operator!=(const Entry& other) const { 152 return !(*this == other); 153 } 154 155 friend std::ostream& operator<<(std::ostream& os, const Entry& entry); 156 }; 157 158 struct EntryMapping { 159 Entry entry; 160 void* address; 161 bool success; 162 }; 163 164 // bool EntryReadAhead(const Entry& entry) const; 165 // bool EntryUnReadAhead(const Entry& entry) const; 166 167 void UnmapWithoutErase(const EntryMapping& entry_mapping); 168 std::optional<android::base::unique_fd*> GetFdForPath(size_t path_id); 169 170 private: 171 std::unordered_map</*path_id*/size_t, std::vector<EntryMapping>> entry_list_map_; 172 std::unordered_map</*path_id*/size_t, android::base::unique_fd> path_fd_map_; 173 174 public: 175 friend std::ostream& operator<<(std::ostream& os, const SessionDirect::Entry& entry); 176 }; 177 178 std::ostream& operator<<(std::ostream& os, const SessionDirect::Entry& entry); 179 180 class PrefetcherDaemon; 181 182 // Out-of-process session. Requires prefetcher daemon. 183 class SessionIndirect : public SessionBase { 184 public: 185 virtual bool RegisterFilePath(size_t path_id, std::string_view file_path) override; 186 187 virtual bool UnregisterFilePath(size_t path_id) override; 188 virtual bool ReadAhead(size_t path_id, 189 ReadAheadKind kind, 190 size_t length, 191 size_t offset) override; 192 193 virtual bool UnreadAhead(size_t path_id, 194 ReadAheadKind kind, 195 size_t length, 196 size_t offset) override; 197 198 virtual void Dump(std::ostream& os, bool multiline) const override; 199 200 // Creates a new session indirectly. 201 // Writes to daemon the new session command. 202 SessionIndirect(size_t session_id, 203 std::string description, 204 std::shared_ptr<PrefetcherDaemon> daemon, 205 bool send_command = true); 206 207 // Destroys the current session. 208 // Writes to daemon that the session is to be destroyed. 209 virtual ~SessionIndirect(); 210 211 protected: 212 std::shared_ptr<PrefetcherDaemon> daemon_; 213 }; 214 215 // Out-of-process session. Requires prefetcher daemon. 216 class SessionIndirectSocket : public SessionIndirect { 217 public: 218 // Creates a new session indirectly. 219 // Writes to daemon the new session command. 220 SessionIndirectSocket(size_t session_id, 221 int fd, 222 std::string description, 223 std::shared_ptr<PrefetcherDaemon> daemon); 224 // Destroys the current session. 225 // Writes to daemon that the session is to be destroyed. 226 virtual ~SessionIndirectSocket(); 227 228 private: 229 }; 230 231 232 } // namespace prefetcher 233 } // namespace iorap 234 235 #endif 236 237