blob: 65aa2db34468d41e3db86024d5929e9660db1d5b [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 Northrop6cca6c22023-02-08 20:23:13 -070035namespace android {
36
Jisun Lee88a1b762024-10-17 20:12:29 +090037constexpr uint32_t kMultifileBlobCacheVersion = 2;
Cody Northrop027f2422023-11-12 22:51:01 -070038constexpr char kMultifileBlobCacheStatusFile[] = "cache.status";
39
Cody Northrop6cca6c22023-02-08 20:23:13 -070040struct MultifileHeader {
Cody Northrop999db232023-02-27 17:02:50 -070041 uint32_t magic;
42 uint32_t crc;
Cody Northrop6cca6c22023-02-08 20:23:13 -070043 EGLsizeiANDROID keySize;
44 EGLsizeiANDROID valueSize;
45};
46
47struct MultifileEntryStats {
48 EGLsizeiANDROID valueSize;
49 size_t fileSize;
50 time_t accessTime;
51};
52
Cody Northrop027f2422023-11-12 22:51:01 -070053struct MultifileStatus {
54 uint32_t magic;
55 uint32_t crc;
56 uint32_t cacheVersion;
57 char buildId[PROP_VALUE_MAX];
58};
59
Cody Northrop6cca6c22023-02-08 20:23:13 -070060struct MultifileHotCache {
61 int entryFd;
62 uint8_t* entryBuffer;
63 size_t entrySize;
64};
65
66enum class TaskCommand {
67 Invalid = 0,
68 WriteToDisk,
69 Exit,
70};
71
72class DeferredTask {
73public:
74 DeferredTask(TaskCommand command)
75 : mCommand(command), mEntryHash(0), mBuffer(nullptr), mBufferSize(0) {}
76
77 TaskCommand getTaskCommand() { return mCommand; }
78
79 void initWriteToDisk(uint32_t entryHash, std::string fullPath, uint8_t* buffer,
80 size_t bufferSize) {
81 mCommand = TaskCommand::WriteToDisk;
82 mEntryHash = entryHash;
83 mFullPath = std::move(fullPath);
84 mBuffer = buffer;
85 mBufferSize = bufferSize;
86 }
87
88 uint32_t getEntryHash() { return mEntryHash; }
89 std::string& getFullPath() { return mFullPath; }
90 uint8_t* getBuffer() { return mBuffer; }
91 size_t getBufferSize() { return mBufferSize; };
92
93private:
94 TaskCommand mCommand;
95
96 // Parameters for WriteToDisk
97 uint32_t mEntryHash;
98 std::string mFullPath;
99 uint8_t* mBuffer;
100 size_t mBufferSize;
101};
102
103class MultifileBlobCache {
104public:
Cody Northrop5dbcfa72023-03-24 15:34:09 -0600105 MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
Cody Northropb5267032023-10-24 10:11:21 -0600106 size_t maxTotalEntries, const std::string& baseDir);
Cody Northrop6cca6c22023-02-08 20:23:13 -0700107 ~MultifileBlobCache();
108
109 void set(const void* key, EGLsizeiANDROID keySize, const void* value,
110 EGLsizeiANDROID valueSize);
111 EGLsizeiANDROID get(const void* key, EGLsizeiANDROID keySize, void* value,
112 EGLsizeiANDROID valueSize);
113
114 void finish();
115
116 size_t getTotalSize() const { return mTotalCacheSize; }
Cody Northropb5267032023-10-24 10:11:21 -0600117 size_t getTotalEntries() const { return mTotalCacheEntries; }
Cody Northrop6cca6c22023-02-08 20:23:13 -0700118
Cody Northrop027f2422023-11-12 22:51:01 -0700119 const std::string& getCurrentBuildId() const { return mBuildId; }
120 void setCurrentBuildId(const std::string& buildId) { mBuildId = buildId; }
121
122 uint32_t getCurrentCacheVersion() const { return mCacheVersion; }
123 void setCurrentCacheVersion(uint32_t cacheVersion) { mCacheVersion = cacheVersion; }
124
Cody Northrop6cca6c22023-02-08 20:23:13 -0700125private:
126 void trackEntry(uint32_t entryHash, EGLsizeiANDROID valueSize, size_t fileSize,
127 time_t accessTime);
128 bool contains(uint32_t entryHash) const;
129 bool removeEntry(uint32_t entryHash);
130 MultifileEntryStats getEntryStats(uint32_t entryHash);
131
Cody Northrop027f2422023-11-12 22:51:01 -0700132 bool createStatus(const std::string& baseDir);
133 bool checkStatus(const std::string& baseDir);
134
Cody Northrop6cca6c22023-02-08 20:23:13 -0700135 size_t getFileSize(uint32_t entryHash);
136 size_t getValueSize(uint32_t entryHash);
137
138 void increaseTotalCacheSize(size_t fileSize);
139 void decreaseTotalCacheSize(size_t fileSize);
140
141 bool addToHotCache(uint32_t entryHash, int fd, uint8_t* entryBufer, size_t entrySize);
142 bool removeFromHotCache(uint32_t entryHash);
143
Cody Northrop027f2422023-11-12 22:51:01 -0700144 bool clearCache();
Cody Northropf2588a82023-03-27 23:03:49 -0600145 void trimCache();
Cody Northropb5267032023-10-24 10:11:21 -0600146 bool applyLRU(size_t cacheSizeLimit, size_t cacheEntryLimit);
Cody Northrop6cca6c22023-02-08 20:23:13 -0700147
148 bool mInitialized;
149 std::string mMultifileDirName;
150
Cody Northrop027f2422023-11-12 22:51:01 -0700151 std::string mBuildId;
152 uint32_t mCacheVersion;
153
Cody Northrop6cca6c22023-02-08 20:23:13 -0700154 std::unordered_set<uint32_t> mEntries;
155 std::unordered_map<uint32_t, MultifileEntryStats> mEntryStats;
156 std::unordered_map<uint32_t, MultifileHotCache> mHotCache;
157
158 size_t mMaxKeySize;
159 size_t mMaxValueSize;
160 size_t mMaxTotalSize;
Cody Northropb5267032023-10-24 10:11:21 -0600161 size_t mMaxTotalEntries;
Cody Northrop6cca6c22023-02-08 20:23:13 -0700162 size_t mTotalCacheSize;
Cody Northropb5267032023-10-24 10:11:21 -0600163 size_t mTotalCacheEntries;
Cody Northrop6cca6c22023-02-08 20:23:13 -0700164 size_t mHotCacheLimit;
165 size_t mHotCacheEntryLimit;
166 size_t mHotCacheSize;
167
168 // Below are the components used for deferred writes
169
170 // Track whether we have pending writes for an entry
Cody Northropbe163732023-03-22 10:14:26 -0600171 std::mutex mDeferredWriteStatusMutex;
172 std::multimap<uint32_t, uint8_t*> mDeferredWrites GUARDED_BY(mDeferredWriteStatusMutex);
Cody Northrop6cca6c22023-02-08 20:23:13 -0700173
174 // Functions to work through tasks in the queue
175 void processTasks();
176 void processTasksImpl(bool* exitThread);
177 void processTask(DeferredTask& task);
178
179 // Used by main thread to create work for the worker thread
180 void queueTask(DeferredTask&& task);
181
182 // Used by main thread to wait for worker thread to complete all outstanding work.
183 void waitForWorkComplete();
184
185 std::thread mTaskThread;
186 std::queue<DeferredTask> mTasks;
187 std::mutex mWorkerMutex;
188
189 // This condition will block the worker thread until a task is queued
190 std::condition_variable mWorkAvailableCondition;
191
192 // This condition will block the main thread while the worker thread still has tasks
193 std::condition_variable mWorkerIdleCondition;
194
195 // This bool will track whether all tasks have been completed
196 bool mWorkerThreadIdle;
197};
198
199}; // namespace android
200
201#endif // ANDROID_MULTIFILE_BLOB_CACHE_H