diff options
author | 2023-11-12 22:51:01 -0700 | |
---|---|---|
committer | 2023-11-14 14:27:30 -0700 | |
commit | 027f242a66832c14d2894098c128bbee41103647 (patch) | |
tree | 4f91946d24c3af40d1213456c47dc448b78ee1b9 | |
parent | b5267034cbf2b8eafcae4d76aac57fd0460a1cc5 (diff) |
EGL Multifile Blobcache: Add status file
Add a status file that contains the cache version and
platform build ID. On future startups, if those values
don't match, clear the cache.
This alleviates a problem on driver updates, which cause
all new queries to miss, creating new entires, filling the
cache. For apps with many small entries, the start up
time has become a problem.
Test: libEGL_test, EGL_test, ANGLE trace tests, apps
Bug: b/295051628
Bug: b/310535559
Change-Id: I17b91fb6c994237fb5c2a220db4f23050d45742b
-rw-r--r-- | opengl/libs/EGL/MultifileBlobCache.cpp | 203 | ||||
-rw-r--r-- | opengl/libs/EGL/MultifileBlobCache.h | 24 | ||||
-rw-r--r-- | opengl/libs/EGL/MultifileBlobCache_test.cpp | 218 | ||||
-rw-r--r-- | opengl/tests/EGLTest/egl_cache_test.cpp | 11 |
4 files changed, 443 insertions, 13 deletions
diff --git a/opengl/libs/EGL/MultifileBlobCache.cpp b/opengl/libs/EGL/MultifileBlobCache.cpp index 13a5e7baa7..9905210014 100644 --- a/opengl/libs/EGL/MultifileBlobCache.cpp +++ b/opengl/libs/EGL/MultifileBlobCache.cpp @@ -18,6 +18,7 @@ #include "MultifileBlobCache.h" +#include <android-base/properties.h> #include <dirent.h> #include <fcntl.h> #include <inttypes.h> @@ -64,6 +65,7 @@ namespace android { MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize, size_t maxTotalEntries, const std::string& baseDir) : mInitialized(false), + mCacheVersion(0), mMaxKeySize(maxKeySize), mMaxValueSize(maxValueSize), mMaxTotalSize(maxTotalSize), @@ -78,6 +80,26 @@ MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, s return; } + // Set the cache version, override if debug value set + mCacheVersion = kMultifileBlobCacheVersion; + int debugCacheVersion = base::GetIntProperty("debug.egl.blobcache.cache_version", -1); + if (debugCacheVersion >= 0) { + ALOGV("INIT: Using %u as cacheVersion instead of %u", debugCacheVersion, mCacheVersion); + mCacheVersion = debugCacheVersion; + } + + // Set the platform build ID, override if debug value set + mBuildId = base::GetProperty("ro.build.id", ""); + std::string debugBuildId = base::GetProperty("debug.egl.blobcache.build_id", ""); + if (!debugBuildId.empty()) { + ALOGV("INIT: Using %s as buildId instead of %s", debugBuildId.c_str(), mBuildId.c_str()); + if (debugBuildId.length() > PROP_VALUE_MAX) { + ALOGV("INIT: debugBuildId is too long (%zu), reduce it to %u", debugBuildId.length(), + PROP_VALUE_MAX); + } + mBuildId = debugBuildId; + } + // Establish the name of our multifile directory mMultifileDirName = baseDir + ".multifile"; @@ -95,14 +117,30 @@ MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, s mTaskThread = std::thread(&MultifileBlobCache::processTasks, this); // See if the dir exists, and initialize using its contents + bool statusGood = false; + + // Check that our cacheVersion and buildId match struct stat st; if (stat(mMultifileDirName.c_str(), &st) == 0) { + if (checkStatus(mMultifileDirName.c_str())) { + statusGood = true; + } else { + ALOGV("INIT: Cache status has changed, clearing the cache"); + if (!clearCache()) { + ALOGE("INIT: Unable to clear cache"); + return; + } + } + } + + if (statusGood) { // Read all the files and gather details, then preload their contents DIR* dir; struct dirent* entry; if ((dir = opendir(mMultifileDirName.c_str())) != nullptr) { while ((entry = readdir(dir)) != nullptr) { - if (entry->d_name == "."s || entry->d_name == ".."s) { + if (entry->d_name == "."s || entry->d_name == ".."s || + strcmp(entry->d_name, kMultifileBlobCacheStatusFile) == 0) { continue; } @@ -125,7 +163,8 @@ MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, s if (st.st_size <= 0 || st.st_atime <= 0) { ALOGE("INIT: Entry %u has invalid stats! Removing.", entryHash); if (remove(fullPath.c_str()) != 0) { - ALOGE("Error removing %s: %s", fullPath.c_str(), std::strerror(errno)); + ALOGE("INIT: Error removing %s: %s", fullPath.c_str(), + std::strerror(errno)); } continue; } @@ -142,7 +181,7 @@ MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, s MultifileHeader header; size_t result = read(fd, static_cast<void*>(&header), sizeof(MultifileHeader)); if (result != sizeof(MultifileHeader)) { - ALOGE("Error reading MultifileHeader from cache entry (%s): %s", + ALOGE("INIT: Error reading MultifileHeader from cache entry (%s): %s", fullPath.c_str(), std::strerror(errno)); close(fd); return; @@ -152,7 +191,8 @@ MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, s if (header.magic != kMultifileMagic) { ALOGE("INIT: Entry %u has bad magic (%u)! Removing.", entryHash, header.magic); if (remove(fullPath.c_str()) != 0) { - ALOGE("Error removing %s: %s", fullPath.c_str(), std::strerror(errno)); + ALOGE("INIT: Error removing %s: %s", fullPath.c_str(), + std::strerror(errno)); } close(fd); continue; @@ -177,7 +217,7 @@ MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, s if (header.crc != crc32c(mappedEntry + sizeof(MultifileHeader), fileSize - sizeof(MultifileHeader))) { - ALOGE("INIT: Entry %u failed CRC check! Removing.", entryHash); + ALOGV("INIT: Entry %u failed CRC check! Removing.", entryHash); if (remove(fullPath.c_str()) != 0) { ALOGE("Error removing %s: %s", fullPath.c_str(), std::strerror(errno)); } @@ -186,11 +226,12 @@ MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, s // If the cache entry is damaged or no good, remove it if (header.keySize <= 0 || header.valueSize <= 0) { - ALOGE("INIT: Entry %u has a bad header keySize (%lu) or valueSize (%lu), " + ALOGV("INIT: Entry %u has a bad header keySize (%lu) or valueSize (%lu), " "removing.", entryHash, header.keySize, header.valueSize); if (remove(fullPath.c_str()) != 0) { - ALOGE("Error removing %s: %s", fullPath.c_str(), std::strerror(errno)); + ALOGE("INIT: Error removing %s: %s", fullPath.c_str(), + std::strerror(errno)); } continue; } @@ -228,9 +269,17 @@ MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, s // If the multifile directory does not exist, create it and start from scratch if (mkdir(mMultifileDirName.c_str(), 0755) != 0 && (errno != EEXIST)) { ALOGE("Unable to create directory (%s), errno (%i)", mMultifileDirName.c_str(), errno); + return; + } + + // Create new status file + if (!createStatus(mMultifileDirName.c_str())) { + ALOGE("INIT: Failed to create status file!"); + return; } } + ALOGV("INIT: Multifile BlobCache initialization succeeded"); mInitialized = true; } @@ -471,6 +520,112 @@ void MultifileBlobCache::finish() { } } +bool MultifileBlobCache::createStatus(const std::string& baseDir) { + // Populate the status struct + struct MultifileStatus status; + memset(&status, 0, sizeof(status)); + status.magic = kMultifileMagic; + status.cacheVersion = mCacheVersion; + + // Copy the buildId string in, up to our allocated space + strncpy(status.buildId, mBuildId.c_str(), + mBuildId.length() > PROP_VALUE_MAX ? PROP_VALUE_MAX : mBuildId.length()); + + // Finally update the crc, using cacheVersion and everything the follows + status.crc = + crc32c(reinterpret_cast<uint8_t*>(&status) + offsetof(MultifileStatus, cacheVersion), + sizeof(status) - offsetof(MultifileStatus, cacheVersion)); + + // Create the status file + std::string cacheStatus = baseDir + "/" + kMultifileBlobCacheStatusFile; + int fd = open(cacheStatus.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); + if (fd == -1) { + ALOGE("STATUS(CREATE): Unable to create status file: %s, error: %s", cacheStatus.c_str(), + std::strerror(errno)); + return false; + } + + // Write the buffer contents to disk + ssize_t result = write(fd, &status, sizeof(status)); + close(fd); + if (result != sizeof(status)) { + ALOGE("STATUS(CREATE): Error writing cache status file: %s, error %s", cacheStatus.c_str(), + std::strerror(errno)); + return false; + } + + ALOGV("STATUS(CREATE): Created status file: %s", cacheStatus.c_str()); + return true; +} + +bool MultifileBlobCache::checkStatus(const std::string& baseDir) { + std::string cacheStatus = baseDir + "/" + kMultifileBlobCacheStatusFile; + + // Does status exist + struct stat st; + if (stat(cacheStatus.c_str(), &st) != 0) { + ALOGV("STATUS(CHECK): Status file (%s) missing", cacheStatus.c_str()); + return false; + } + + // If the status entry is damaged or no good, remove it + if (st.st_size <= 0 || st.st_atime <= 0) { + ALOGE("STATUS(CHECK): Cache status has invalid stats!"); + return false; + } + + // Open the file so we can read its header + int fd = open(cacheStatus.c_str(), O_RDONLY); + if (fd == -1) { + ALOGE("STATUS(CHECK): Cache error - failed to open cacheStatus: %s, error: %s", + cacheStatus.c_str(), std::strerror(errno)); + return false; + } + + // Read in the status header + MultifileStatus status; + size_t result = read(fd, static_cast<void*>(&status), sizeof(MultifileStatus)); + close(fd); + if (result != sizeof(MultifileStatus)) { + ALOGE("STATUS(CHECK): Error reading cache status (%s): %s", cacheStatus.c_str(), + std::strerror(errno)); + return false; + } + + // Verify header magic + if (status.magic != kMultifileMagic) { + ALOGE("STATUS(CHECK): Cache status has bad magic (%u)!", status.magic); + return false; + } + + // Ensure we have a good CRC + if (status.crc != + crc32c(reinterpret_cast<uint8_t*>(&status) + offsetof(MultifileStatus, cacheVersion), + sizeof(status) - offsetof(MultifileStatus, cacheVersion))) { + ALOGE("STATUS(CHECK): Cache status failed CRC check!"); + return false; + } + + // Check cacheVersion + if (status.cacheVersion != mCacheVersion) { + ALOGV("STATUS(CHECK): Cache version has changed! old(%u) new(%u)", status.cacheVersion, + mCacheVersion); + return false; + } + + // Check buildId + if (strcmp(status.buildId, mBuildId.c_str()) != 0) { + ALOGV("STATUS(CHECK): BuildId has changed! old(%s) new(%s)", status.buildId, + mBuildId.c_str()); + return false; + } + + // All checks passed! + ALOGV("STATUS(CHECK): Status file is good! cacheVersion(%u), buildId(%s) file(%s)", + status.cacheVersion, status.buildId, cacheStatus.c_str()); + return true; +} + void MultifileBlobCache::trackEntry(uint32_t entryHash, EGLsizeiANDROID valueSize, size_t fileSize, time_t accessTime) { mEntries.insert(entryHash); @@ -606,6 +761,40 @@ bool MultifileBlobCache::applyLRU(size_t cacheSizeLimit, size_t cacheEntryLimit) return false; } +// Clear the cache by removing all entries and deleting the directory +bool MultifileBlobCache::clearCache() { + DIR* dir; + struct dirent* entry; + dir = opendir(mMultifileDirName.c_str()); + if (dir == nullptr) { + ALOGE("CLEAR: Unable to open multifile dir: %s", mMultifileDirName.c_str()); + return false; + } + + // Delete all entries and the status file + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_name == "."s || entry->d_name == ".."s) { + continue; + } + + std::string entryName = entry->d_name; + std::string fullPath = mMultifileDirName + "/" + entryName; + if (remove(fullPath.c_str()) != 0) { + ALOGE("CLEAR: Error removing %s: %s", fullPath.c_str(), std::strerror(errno)); + return false; + } + } + + // Delete the directory + if (remove(mMultifileDirName.c_str()) != 0) { + ALOGE("CLEAR: Error removing %s: %s", mMultifileDirName.c_str(), std::strerror(errno)); + return false; + } + + ALOGV("CLEAR: Cleared the multifile blobcache"); + return true; +} + // When removing files, what fraction of the overall limit should be reached when removing files // A divisor of two will decrease the cache to 50%, four to 25% and so on // We use the same limit to manage size and entry count diff --git a/opengl/libs/EGL/MultifileBlobCache.h b/opengl/libs/EGL/MultifileBlobCache.h index 9a396f01c3..18566c2892 100644 --- a/opengl/libs/EGL/MultifileBlobCache.h +++ b/opengl/libs/EGL/MultifileBlobCache.h @@ -21,6 +21,7 @@ #include <EGL/eglext.h> #include <android-base/thread_annotations.h> +#include <cutils/properties.h> #include <future> #include <map> #include <queue> @@ -33,6 +34,9 @@ namespace android { +constexpr uint32_t kMultifileBlobCacheVersion = 1; +constexpr char kMultifileBlobCacheStatusFile[] = "cache.status"; + struct MultifileHeader { uint32_t magic; uint32_t crc; @@ -46,6 +50,13 @@ struct MultifileEntryStats { time_t accessTime; }; +struct MultifileStatus { + uint32_t magic; + uint32_t crc; + uint32_t cacheVersion; + char buildId[PROP_VALUE_MAX]; +}; + struct MultifileHotCache { int entryFd; uint8_t* entryBuffer; @@ -105,6 +116,12 @@ public: size_t getTotalSize() const { return mTotalCacheSize; } size_t getTotalEntries() const { return mTotalCacheEntries; } + const std::string& getCurrentBuildId() const { return mBuildId; } + void setCurrentBuildId(const std::string& buildId) { mBuildId = buildId; } + + uint32_t getCurrentCacheVersion() const { return mCacheVersion; } + void setCurrentCacheVersion(uint32_t cacheVersion) { mCacheVersion = cacheVersion; } + private: void trackEntry(uint32_t entryHash, EGLsizeiANDROID valueSize, size_t fileSize, time_t accessTime); @@ -112,6 +129,9 @@ private: bool removeEntry(uint32_t entryHash); MultifileEntryStats getEntryStats(uint32_t entryHash); + bool createStatus(const std::string& baseDir); + bool checkStatus(const std::string& baseDir); + size_t getFileSize(uint32_t entryHash); size_t getValueSize(uint32_t entryHash); @@ -121,12 +141,16 @@ private: bool addToHotCache(uint32_t entryHash, int fd, uint8_t* entryBufer, size_t entrySize); bool removeFromHotCache(uint32_t entryHash); + bool clearCache(); void trimCache(); bool applyLRU(size_t cacheSizeLimit, size_t cacheEntryLimit); bool mInitialized; std::string mMultifileDirName; + std::string mBuildId; + uint32_t mCacheVersion; + std::unordered_set<uint32_t> mEntries; std::unordered_map<uint32_t, MultifileEntryStats> mEntryStats; std::unordered_map<uint32_t, MultifileHotCache> mHotCache; diff --git a/opengl/libs/EGL/MultifileBlobCache_test.cpp b/opengl/libs/EGL/MultifileBlobCache_test.cpp index 8e27f5a738..90a0f1ee06 100644 --- a/opengl/libs/EGL/MultifileBlobCache_test.cpp +++ b/opengl/libs/EGL/MultifileBlobCache_test.cpp @@ -16,13 +16,17 @@ #include "MultifileBlobCache.h" +#include <android-base/properties.h> #include <android-base/test_utils.h> #include <fcntl.h> #include <gtest/gtest.h> #include <stdio.h> +#include <fstream> #include <memory> +using namespace std::literals; + namespace android { template <typename T> @@ -36,19 +40,35 @@ constexpr size_t kMaxTotalEntries = 64; class MultifileBlobCacheTest : public ::testing::Test { protected: virtual void SetUp() { + clearProperties(); mTempFile.reset(new TemporaryFile()); mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries, &mTempFile->path[0])); } - virtual void TearDown() { mMBC.reset(); } + virtual void TearDown() { + clearProperties(); + mMBC.reset(); + } int getFileDescriptorCount(); + std::vector<std::string> getCacheEntries(); + + void clearProperties(); std::unique_ptr<TemporaryFile> mTempFile; std::unique_ptr<MultifileBlobCache> mMBC; }; +void MultifileBlobCacheTest::clearProperties() { + // Clear any debug properties used in the tests + base::SetProperty("debug.egl.blobcache.cache_version", ""); + base::WaitForProperty("debug.egl.blobcache.cache_version", ""); + + base::SetProperty("debug.egl.blobcache.build_id", ""); + base::WaitForProperty("debug.egl.blobcache.build_id", ""); +} + TEST_F(MultifileBlobCacheTest, CacheSingleValueSucceeds) { unsigned char buf[4] = {0xee, 0xee, 0xee, 0xee}; mMBC->set("abcd", 4, "efgh", 4); @@ -287,4 +307,200 @@ TEST_F(MultifileBlobCacheTest, EnsureFileDescriptorsClosed) { ASSERT_LT(getFileDescriptorCount(), kMaxTotalEntries / 2); } +std::vector<std::string> MultifileBlobCacheTest::getCacheEntries() { + std::string cachePath = &mTempFile->path[0]; + std::string multifileDirName = cachePath + ".multifile"; + std::vector<std::string> cacheEntries; + + struct stat info; + if (stat(multifileDirName.c_str(), &info) == 0) { + // We have a multifile dir. Skip the status file and return the only entry. + DIR* dir; + struct dirent* entry; + if ((dir = opendir(multifileDirName.c_str())) != nullptr) { + while ((entry = readdir(dir)) != nullptr) { + if (entry->d_name == "."s || entry->d_name == ".."s) { + continue; + } + if (strcmp(entry->d_name, kMultifileBlobCacheStatusFile) == 0) { + continue; + } + cacheEntries.push_back(multifileDirName + "/" + entry->d_name); + } + } else { + printf("Unable to open %s, error: %s\n", multifileDirName.c_str(), + std::strerror(errno)); + } + } else { + printf("Unable to stat %s, error: %s\n", multifileDirName.c_str(), std::strerror(errno)); + } + + return cacheEntries; +} + +TEST_F(MultifileBlobCacheTest, CacheContainsStatus) { + struct stat info; + std::stringstream statusFile; + statusFile << &mTempFile->path[0] << ".multifile/" << kMultifileBlobCacheStatusFile; + + // After INIT, cache should have a status + ASSERT_TRUE(stat(statusFile.str().c_str(), &info) == 0); + + // Set one entry + mMBC->set("abcd", 4, "efgh", 4); + + // Close the cache so everything writes out + mMBC->finish(); + mMBC.reset(); + + // Ensure status lives after closing the cache + ASSERT_TRUE(stat(statusFile.str().c_str(), &info) == 0); + + // Open the cache again + mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries, + &mTempFile->path[0])); + + // Ensure we still have a status + ASSERT_TRUE(stat(statusFile.str().c_str(), &info) == 0); +} + +// Verify missing cache status file causes cache the be cleared +TEST_F(MultifileBlobCacheTest, MissingCacheStatusClears) { + // Set one entry + mMBC->set("abcd", 4, "efgh", 4); + + // Close the cache so everything writes out + mMBC->finish(); + mMBC.reset(); + + // Ensure there is one cache entry + ASSERT_EQ(getCacheEntries().size(), 1); + + // Delete the status file + std::stringstream statusFile; + statusFile << &mTempFile->path[0] << ".multifile/" << kMultifileBlobCacheStatusFile; + remove(statusFile.str().c_str()); + + // Open the cache again and ensure no cache hits + mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries, + &mTempFile->path[0])); + + // Ensure we have no entries + ASSERT_EQ(getCacheEntries().size(), 0); +} + +// Verify modified cache status file BEGIN causes cache to be cleared +TEST_F(MultifileBlobCacheTest, ModifiedCacheStatusBeginClears) { + // Set one entry + mMBC->set("abcd", 4, "efgh", 4); + + // Close the cache so everything writes out + mMBC->finish(); + mMBC.reset(); + + // Ensure there is one cache entry + ASSERT_EQ(getCacheEntries().size(), 1); + + // Modify the status file + std::stringstream statusFile; + statusFile << &mTempFile->path[0] << ".multifile/" << kMultifileBlobCacheStatusFile; + + // Stomp on the beginning of the cache file + const char* stomp = "BADF00D"; + std::fstream fs(statusFile.str()); + fs.seekp(0, std::ios_base::beg); + fs.write(stomp, strlen(stomp)); + fs.flush(); + fs.close(); + + // Open the cache again and ensure no cache hits + mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries, + &mTempFile->path[0])); + + // Ensure we have no entries + ASSERT_EQ(getCacheEntries().size(), 0); +} + +// Verify modified cache status file END causes cache to be cleared +TEST_F(MultifileBlobCacheTest, ModifiedCacheStatusEndClears) { + // Set one entry + mMBC->set("abcd", 4, "efgh", 4); + + // Close the cache so everything writes out + mMBC->finish(); + mMBC.reset(); + + // Ensure there is one cache entry + ASSERT_EQ(getCacheEntries().size(), 1); + + // Modify the status file + std::stringstream statusFile; + statusFile << &mTempFile->path[0] << ".multifile/" << kMultifileBlobCacheStatusFile; + + // Stomp on the END of the cache status file, modifying its contents + const char* stomp = "BADF00D"; + std::fstream fs(statusFile.str()); + fs.seekp(-strlen(stomp), std::ios_base::end); + fs.write(stomp, strlen(stomp)); + fs.flush(); + fs.close(); + + // Open the cache again and ensure no cache hits + mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries, + &mTempFile->path[0])); + + // Ensure we have no entries + ASSERT_EQ(getCacheEntries().size(), 0); +} + +// Verify mismatched cacheVersion causes cache to be cleared +TEST_F(MultifileBlobCacheTest, MismatchedCacheVersionClears) { + // Set one entry + mMBC->set("abcd", 4, "efgh", 4); + + // Close the cache so everything writes out + mMBC->finish(); + mMBC.reset(); + + // Ensure there is one cache entry + ASSERT_EQ(getCacheEntries().size(), 1); + + // Set a debug cacheVersion + std::string newCacheVersion = std::to_string(kMultifileBlobCacheVersion + 1); + ASSERT_TRUE(base::SetProperty("debug.egl.blobcache.cache_version", newCacheVersion.c_str())); + ASSERT_TRUE( + base::WaitForProperty("debug.egl.blobcache.cache_version", newCacheVersion.c_str())); + + // Open the cache again and ensure no cache hits + mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries, + &mTempFile->path[0])); + + // Ensure we have no entries + ASSERT_EQ(getCacheEntries().size(), 0); +} + +// Verify mismatched buildId causes cache to be cleared +TEST_F(MultifileBlobCacheTest, MismatchedBuildIdClears) { + // Set one entry + mMBC->set("abcd", 4, "efgh", 4); + + // Close the cache so everything writes out + mMBC->finish(); + mMBC.reset(); + + // Ensure there is one cache entry + ASSERT_EQ(getCacheEntries().size(), 1); + + // Set a debug buildId + base::SetProperty("debug.egl.blobcache.build_id", "foo"); + base::WaitForProperty("debug.egl.blobcache.build_id", "foo"); + + // Open the cache again and ensure no cache hits + mMBC.reset(new MultifileBlobCache(kMaxKeySize, kMaxValueSize, kMaxTotalSize, kMaxTotalEntries, + &mTempFile->path[0])); + + // Ensure we have no entries + ASSERT_EQ(getCacheEntries().size(), 0); +} + } // namespace android diff --git a/opengl/tests/EGLTest/egl_cache_test.cpp b/opengl/tests/EGLTest/egl_cache_test.cpp index f81c68f66e..ce5818229a 100644 --- a/opengl/tests/EGLTest/egl_cache_test.cpp +++ b/opengl/tests/EGLTest/egl_cache_test.cpp @@ -114,25 +114,26 @@ std::string EGLCacheTest::getCachefileName() { struct stat info; if (stat(multifileDirName.c_str(), &info) == 0) { // Ensure we only have one file to manage - int realFileCount = 0; + int entryFileCount = 0; - // We have a multifile dir. Return the only real file in it. + // We have a multifile dir. Return the only entry file in it. DIR* dir; struct dirent* entry; if ((dir = opendir(multifileDirName.c_str())) != nullptr) { while ((entry = readdir(dir)) != nullptr) { - if (entry->d_name == "."s || entry->d_name == ".."s) { + if (entry->d_name == "."s || entry->d_name == ".."s || + strcmp(entry->d_name, kMultifileBlobCacheStatusFile) == 0) { continue; } cachefileName = multifileDirName + "/" + entry->d_name; - realFileCount++; + entryFileCount++; } } else { printf("Unable to open %s, error: %s\n", multifileDirName.c_str(), std::strerror(errno)); } - if (realFileCount != 1) { + if (entryFileCount != 1) { // If there was more than one real file in the directory, this // violates test assumptions cachefileName = ""; |