blob: 9a396f01c3a90cac6e0e2b756d5410b6c02cba1b [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 Northrop6cca6c22023-02-08 20:23:13 -070024#include <future>
25#include <map>
26#include <queue>
27#include <string>
28#include <thread>
29#include <unordered_map>
30#include <unordered_set>
31
Cody Northrop999db232023-02-27 17:02:50 -070032#include "FileBlobCache.h"
33
Cody Northrop6cca6c22023-02-08 20:23:13 -070034namespace android {
35
36struct MultifileHeader {
Cody Northrop999db232023-02-27 17:02:50 -070037 uint32_t magic;
38 uint32_t crc;
Cody Northrop6cca6c22023-02-08 20:23:13 -070039 EGLsizeiANDROID keySize;
40 EGLsizeiANDROID valueSize;
41};
42
43struct MultifileEntryStats {
44 EGLsizeiANDROID valueSize;
45 size_t fileSize;
46 time_t accessTime;
47};
48
49struct MultifileHotCache {
50 int entryFd;
51 uint8_t* entryBuffer;
52 size_t entrySize;
53};
54
55enum class TaskCommand {
56 Invalid = 0,
57 WriteToDisk,
58 Exit,
59};
60
61class DeferredTask {
62public:
63 DeferredTask(TaskCommand command)
64 : mCommand(command), mEntryHash(0), mBuffer(nullptr), mBufferSize(0) {}
65
66 TaskCommand getTaskCommand() { return mCommand; }
67
68 void initWriteToDisk(uint32_t entryHash, std::string fullPath, uint8_t* buffer,
69 size_t bufferSize) {
70 mCommand = TaskCommand::WriteToDisk;
71 mEntryHash = entryHash;
72 mFullPath = std::move(fullPath);
73 mBuffer = buffer;
74 mBufferSize = bufferSize;
75 }
76
77 uint32_t getEntryHash() { return mEntryHash; }
78 std::string& getFullPath() { return mFullPath; }
79 uint8_t* getBuffer() { return mBuffer; }
80 size_t getBufferSize() { return mBufferSize; };
81
82private:
83 TaskCommand mCommand;
84
85 // Parameters for WriteToDisk
86 uint32_t mEntryHash;
87 std::string mFullPath;
88 uint8_t* mBuffer;
89 size_t mBufferSize;
90};
91
92class MultifileBlobCache {
93public:
Cody Northrop5dbcfa72023-03-24 15:34:09 -060094 MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
Cody Northropb5267032023-10-24 10:11:21 -060095 size_t maxTotalEntries, const std::string& baseDir);
Cody Northrop6cca6c22023-02-08 20:23:13 -070096 ~MultifileBlobCache();
97
98 void set(const void* key, EGLsizeiANDROID keySize, const void* value,
99 EGLsizeiANDROID valueSize);
100 EGLsizeiANDROID get(const void* key, EGLsizeiANDROID keySize, void* value,
101 EGLsizeiANDROID valueSize);
102
103 void finish();
104
105 size_t getTotalSize() const { return mTotalCacheSize; }
Cody Northropb5267032023-10-24 10:11:21 -0600106 size_t getTotalEntries() const { return mTotalCacheEntries; }
Cody Northrop6cca6c22023-02-08 20:23:13 -0700107
108private:
109 void trackEntry(uint32_t entryHash, EGLsizeiANDROID valueSize, size_t fileSize,
110 time_t accessTime);
111 bool contains(uint32_t entryHash) const;
112 bool removeEntry(uint32_t entryHash);
113 MultifileEntryStats getEntryStats(uint32_t entryHash);
114
115 size_t getFileSize(uint32_t entryHash);
116 size_t getValueSize(uint32_t entryHash);
117
118 void increaseTotalCacheSize(size_t fileSize);
119 void decreaseTotalCacheSize(size_t fileSize);
120
121 bool addToHotCache(uint32_t entryHash, int fd, uint8_t* entryBufer, size_t entrySize);
122 bool removeFromHotCache(uint32_t entryHash);
123
Cody Northropf2588a82023-03-27 23:03:49 -0600124 void trimCache();
Cody Northropb5267032023-10-24 10:11:21 -0600125 bool applyLRU(size_t cacheSizeLimit, size_t cacheEntryLimit);
Cody Northrop6cca6c22023-02-08 20:23:13 -0700126
127 bool mInitialized;
128 std::string mMultifileDirName;
129
130 std::unordered_set<uint32_t> mEntries;
131 std::unordered_map<uint32_t, MultifileEntryStats> mEntryStats;
132 std::unordered_map<uint32_t, MultifileHotCache> mHotCache;
133
134 size_t mMaxKeySize;
135 size_t mMaxValueSize;
136 size_t mMaxTotalSize;
Cody Northropb5267032023-10-24 10:11:21 -0600137 size_t mMaxTotalEntries;
Cody Northrop6cca6c22023-02-08 20:23:13 -0700138 size_t mTotalCacheSize;
Cody Northropb5267032023-10-24 10:11:21 -0600139 size_t mTotalCacheEntries;
Cody Northrop6cca6c22023-02-08 20:23:13 -0700140 size_t mHotCacheLimit;
141 size_t mHotCacheEntryLimit;
142 size_t mHotCacheSize;
143
144 // Below are the components used for deferred writes
145
146 // Track whether we have pending writes for an entry
Cody Northropbe163732023-03-22 10:14:26 -0600147 std::mutex mDeferredWriteStatusMutex;
148 std::multimap<uint32_t, uint8_t*> mDeferredWrites GUARDED_BY(mDeferredWriteStatusMutex);
Cody Northrop6cca6c22023-02-08 20:23:13 -0700149
150 // Functions to work through tasks in the queue
151 void processTasks();
152 void processTasksImpl(bool* exitThread);
153 void processTask(DeferredTask& task);
154
155 // Used by main thread to create work for the worker thread
156 void queueTask(DeferredTask&& task);
157
158 // Used by main thread to wait for worker thread to complete all outstanding work.
159 void waitForWorkComplete();
160
161 std::thread mTaskThread;
162 std::queue<DeferredTask> mTasks;
163 std::mutex mWorkerMutex;
164
165 // This condition will block the worker thread until a task is queued
166 std::condition_variable mWorkAvailableCondition;
167
168 // This condition will block the main thread while the worker thread still has tasks
169 std::condition_variable mWorkerIdleCondition;
170
171 // This bool will track whether all tasks have been completed
172 bool mWorkerThreadIdle;
173};
174
175}; // namespace android
176
177#endif // ANDROID_MULTIFILE_BLOB_CACHE_H