blob: fe477bc76ab9a01b01767f76048fcdc133022a61 [file] [log] [blame]
Cody Northrop6cca6c22023-02-08 20:23:13 -07001/*
2 ** Copyright 2022, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17#ifndef ANDROID_MULTIFILE_BLOB_CACHE_H
18#define ANDROID_MULTIFILE_BLOB_CACHE_H
19
20#include <EGL/egl.h>
21#include <EGL/eglext.h>
22
Cody Northropbe163732023-03-22 10:14:26 -060023#include <android-base/thread_annotations.h>
Cody Northrop027f2422023-11-12 22:51:01 -070024#include <cutils/properties.h>
Cody Northrop6cca6c22023-02-08 20:23:13 -070025#include <future>
26#include <map>
27#include <queue>
28#include <string>
29#include <thread>
30#include <unordered_map>
31#include <unordered_set>
32
Cody Northrop999db232023-02-27 17:02:50 -070033#include "FileBlobCache.h"
34
Cody Northrop4ee63862024-11-19 22:41:23 -070035#include <com_android_graphics_egl_flags.h>
36
37using namespace com::android::graphics::egl;
38
Cody Northrop6cca6c22023-02-08 20:23:13 -070039namespace android {
40
Jisun Lee88a1b762024-10-17 20:12:29 +090041constexpr uint32_t kMultifileBlobCacheVersion = 2;
Cody Northrop027f2422023-11-12 22:51:01 -070042constexpr char kMultifileBlobCacheStatusFile[] = "cache.status";
43
Cody Northrop6cca6c22023-02-08 20:23:13 -070044struct MultifileHeader {
Cody Northrop999db232023-02-27 17:02:50 -070045 uint32_t magic;
46 uint32_t crc;
Cody Northrop6cca6c22023-02-08 20:23:13 -070047 EGLsizeiANDROID keySize;
48 EGLsizeiANDROID valueSize;
49};
50
51struct MultifileEntryStats {
52 EGLsizeiANDROID valueSize;
53 size_t fileSize;
54 time_t accessTime;
55};
56
Cody Northrop027f2422023-11-12 22:51:01 -070057struct MultifileStatus {
58 uint32_t magic;
59 uint32_t crc;
60 uint32_t cacheVersion;
61 char buildId[PROP_VALUE_MAX];
62};
63
Cody Northrop6cca6c22023-02-08 20:23:13 -070064struct MultifileHotCache {
65 int entryFd;
66 uint8_t* entryBuffer;
67 size_t entrySize;
68};
69
70enum class TaskCommand {
71 Invalid = 0,
72 WriteToDisk,
73 Exit,
74};
75
76class DeferredTask {
77public:
78 DeferredTask(TaskCommand command)
79 : mCommand(command), mEntryHash(0), mBuffer(nullptr), mBufferSize(0) {}
80
81 TaskCommand getTaskCommand() { return mCommand; }
82
83 void initWriteToDisk(uint32_t entryHash, std::string fullPath, uint8_t* buffer,
84 size_t bufferSize) {
85 mCommand = TaskCommand::WriteToDisk;
86 mEntryHash = entryHash;
87 mFullPath = std::move(fullPath);
88 mBuffer = buffer;
89 mBufferSize = bufferSize;
90 }
91
92 uint32_t getEntryHash() { return mEntryHash; }
93 std::string& getFullPath() { return mFullPath; }
94 uint8_t* getBuffer() { return mBuffer; }
95 size_t getBufferSize() { return mBufferSize; };
96
97private:
98 TaskCommand mCommand;
99
100 // Parameters for WriteToDisk
101 uint32_t mEntryHash;
102 std::string mFullPath;
103 uint8_t* mBuffer;
104 size_t mBufferSize;
105};
106
107class MultifileBlobCache {
108public:
Cody Northrop5dbcfa72023-03-24 15:34:09 -0600109 MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
Cody Northropb5267032023-10-24 10:11:21 -0600110 size_t maxTotalEntries, const std::string& baseDir);
Cody Northrop6cca6c22023-02-08 20:23:13 -0700111 ~MultifileBlobCache();
112
113 void set(const void* key, EGLsizeiANDROID keySize, const void* value,
114 EGLsizeiANDROID valueSize);
115 EGLsizeiANDROID get(const void* key, EGLsizeiANDROID keySize, void* value,
116 EGLsizeiANDROID valueSize);
117
118 void finish();
119
120 size_t getTotalSize() const { return mTotalCacheSize; }
Cody Northropb5267032023-10-24 10:11:21 -0600121 size_t getTotalEntries() const { return mTotalCacheEntries; }
Cody Northrop6cca6c22023-02-08 20:23:13 -0700122
Cody Northrop027f2422023-11-12 22:51:01 -0700123 const std::string& getCurrentBuildId() const { return mBuildId; }
124 void setCurrentBuildId(const std::string& buildId) { mBuildId = buildId; }
125
126 uint32_t getCurrentCacheVersion() const { return mCacheVersion; }
127 void setCurrentCacheVersion(uint32_t cacheVersion) { mCacheVersion = cacheVersion; }
128
Cody Northrop6cca6c22023-02-08 20:23:13 -0700129private:
130 void trackEntry(uint32_t entryHash, EGLsizeiANDROID valueSize, size_t fileSize,
131 time_t accessTime);
132 bool contains(uint32_t entryHash) const;
133 bool removeEntry(uint32_t entryHash);
134 MultifileEntryStats getEntryStats(uint32_t entryHash);
135
Cody Northrop027f2422023-11-12 22:51:01 -0700136 bool createStatus(const std::string& baseDir);
137 bool checkStatus(const std::string& baseDir);
138
Cody Northrop6cca6c22023-02-08 20:23:13 -0700139 size_t getFileSize(uint32_t entryHash);
140 size_t getValueSize(uint32_t entryHash);
141
142 void increaseTotalCacheSize(size_t fileSize);
143 void decreaseTotalCacheSize(size_t fileSize);
144
145 bool addToHotCache(uint32_t entryHash, int fd, uint8_t* entryBufer, size_t entrySize);
146 bool removeFromHotCache(uint32_t entryHash);
147
Cody Northrop027f2422023-11-12 22:51:01 -0700148 bool clearCache();
Cody Northropf2588a82023-03-27 23:03:49 -0600149 void trimCache();
Cody Northropb5267032023-10-24 10:11:21 -0600150 bool applyLRU(size_t cacheSizeLimit, size_t cacheEntryLimit);
Cody Northrop6cca6c22023-02-08 20:23:13 -0700151
152 bool mInitialized;
153 std::string mMultifileDirName;
154
Cody Northrop027f2422023-11-12 22:51:01 -0700155 std::string mBuildId;
156 uint32_t mCacheVersion;
157
Cody Northrop6cca6c22023-02-08 20:23:13 -0700158 std::unordered_set<uint32_t> mEntries;
159 std::unordered_map<uint32_t, MultifileEntryStats> mEntryStats;
160 std::unordered_map<uint32_t, MultifileHotCache> mHotCache;
161
162 size_t mMaxKeySize;
163 size_t mMaxValueSize;
164 size_t mMaxTotalSize;
Cody Northropb5267032023-10-24 10:11:21 -0600165 size_t mMaxTotalEntries;
Cody Northrop6cca6c22023-02-08 20:23:13 -0700166 size_t mTotalCacheSize;
Cody Northropb5267032023-10-24 10:11:21 -0600167 size_t mTotalCacheEntries;
Cody Northrop6cca6c22023-02-08 20:23:13 -0700168 size_t mHotCacheLimit;
169 size_t mHotCacheEntryLimit;
170 size_t mHotCacheSize;
171
172 // Below are the components used for deferred writes
173
174 // Track whether we have pending writes for an entry
Cody Northropbe163732023-03-22 10:14:26 -0600175 std::mutex mDeferredWriteStatusMutex;
176 std::multimap<uint32_t, uint8_t*> mDeferredWrites GUARDED_BY(mDeferredWriteStatusMutex);
Cody Northrop6cca6c22023-02-08 20:23:13 -0700177
178 // Functions to work through tasks in the queue
179 void processTasks();
180 void processTasksImpl(bool* exitThread);
181 void processTask(DeferredTask& task);
182
183 // Used by main thread to create work for the worker thread
184 void queueTask(DeferredTask&& task);
185
186 // Used by main thread to wait for worker thread to complete all outstanding work.
187 void waitForWorkComplete();
188
189 std::thread mTaskThread;
190 std::queue<DeferredTask> mTasks;
191 std::mutex mWorkerMutex;
192
193 // This condition will block the worker thread until a task is queued
194 std::condition_variable mWorkAvailableCondition;
195
196 // This condition will block the main thread while the worker thread still has tasks
197 std::condition_variable mWorkerIdleCondition;
198
199 // This bool will track whether all tasks have been completed
200 bool mWorkerThreadIdle;
201};
202
203}; // namespace android
204
205#endif // ANDROID_MULTIFILE_BLOB_CACHE_H