util/disk_cache: Support combined foz ro and non-foz rw caches

Mesa utilizes only one type of cache at a time. This patch enables support
for combined reading from read-only Fossilize cache + non-foz read-write
caches.

From now on, a non-foz read-write caches will first try to retrieve data
from a read-only foz cache if new MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ
environment variable is set to true, otherwise the caching behaviour is
unchanged. The new flag has no effect when MESA_DISK_CACHE_SINGLE_FILE=1,
i.e. when the single-file foz cache is used.

This change allows us to ship a prebuilt RO caches for a certain
applications, while the rest of applications will benefit from the
regular RW caching that supports cache-size limitation. This feature
will be used by ChromeOS.

Usage example #1:

MESA_DISK_CACHE_DATABASE=0
MESA_DISK_CACHE_SINGLE_FILE=0
MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ=1
MESA_DISK_CACHE_READ_ONLY_FOZ_DBS=rocache1,rocache2

Usage example #2:

MESA_DISK_CACHE_DATABASE=1
MESA_DISK_CACHE_SINGLE_FILE=0
MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ=1
MESA_DISK_CACHE_READ_ONLY_FOZ_DBS=rocache1,rocache2

Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18551>
This commit is contained in:
Dmitry Osipenko
2022-09-12 00:32:30 +03:00
committed by Marge Bot
parent 75dae4f8e3
commit 32fe60e8c4
4 changed files with 215 additions and 18 deletions
+166
View File
@@ -773,3 +773,169 @@ TEST_F(Cache, Database)
EXPECT_EQ(err, 0) << "Removing " CACHE_TEST_TMP " again";
#endif
}
TEST_F(Cache, Combined)
{
const char *driver_id = "make_check";
char blob[] = "This is a RO blob";
uint8_t dummy_key[20] = { 0 };
uint8_t blob_key[20];
char foz_rw_idx_file[1024];
char foz_ro_idx_file[1024];
char foz_rw_file[1024];
char foz_ro_file[1024];
char *result;
size_t size;
#ifndef ENABLE_SHADER_CACHE
GTEST_SKIP() << "ENABLE_SHADER_CACHE not defined.";
#else
setenv("MESA_DISK_CACHE_SINGLE_FILE", "true", 1);
setenv("MESA_DISK_CACHE_DATABASE", "false", 1);
#ifdef SHADER_CACHE_DISABLE_BY_DEFAULT
setenv("MESA_SHADER_CACHE_DISABLE", "false", 1);
#endif /* SHADER_CACHE_DISABLE_BY_DEFAULT */
/* Enable Fossilize read-write cache. */
setenv("MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ", "true", 1);
test_disk_cache_create(mem_ctx, CACHE_DIR_NAME_SF, driver_id);
/* Create Fossilize writable cache. */
struct disk_cache *cache_sf_wr = disk_cache_create("combined_test",
driver_id, 0);
disk_cache_compute_key(cache_sf_wr, blob, sizeof(blob), blob_key);
/* Ensure that disk_cache_get returns nothing before anything is added. */
result = (char *) disk_cache_get(cache_sf_wr, blob_key, &size);
EXPECT_EQ(result, nullptr) << "disk_cache_get with non-existent item (pointer)";
EXPECT_EQ(size, 0) << "disk_cache_get with non-existent item (size)";
/* Put blob entry to the cache. */
disk_cache_put(cache_sf_wr, blob_key, blob, sizeof(blob), NULL);
disk_cache_wait_for_idle(cache_sf_wr);
result = (char *) disk_cache_get(cache_sf_wr, blob_key, &size);
EXPECT_STREQ(blob, result) << "disk_cache_get of existing item (pointer)";
EXPECT_EQ(size, sizeof(blob)) << "disk_cache_get of existing item (size)";
free(result);
/* Rename file foz_cache.foz -> ro_cache.foz */
sprintf(foz_rw_file, "%s/foz_cache.foz", cache_sf_wr->path);
sprintf(foz_ro_file, "%s/ro_cache.foz", cache_sf_wr->path);
EXPECT_EQ(rename(foz_rw_file, foz_ro_file), 0) << "foz_cache.foz renaming failed";
/* Rename file foz_cache_idx.foz -> ro_cache_idx.foz */
sprintf(foz_rw_idx_file, "%s/foz_cache_idx.foz", cache_sf_wr->path);
sprintf(foz_ro_idx_file, "%s/ro_cache_idx.foz", cache_sf_wr->path);
EXPECT_EQ(rename(foz_rw_idx_file, foz_ro_idx_file), 0) << "foz_cache_idx.foz renaming failed";
disk_cache_destroy(cache_sf_wr);
/* Disable Fossilize read-write cache. */
setenv("MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ", "false", 1);
/* Set up Fossilize read-only cache. */
setenv("MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ", "true", 1);
setenv("MESA_DISK_CACHE_READ_ONLY_FOZ_DBS", "ro_cache", 1);
/* Create FOZ cache that fetches the RO cache. Note that this produces
* empty RW cache files. */
struct disk_cache *cache_sf_ro = disk_cache_create("combined_test",
driver_id, 0);
/* Blob entry must present because it shall be retrieved from the
* ro_cache.foz */
result = (char *) disk_cache_get(cache_sf_ro, blob_key, &size);
EXPECT_STREQ(blob, result) << "disk_cache_get of existing item (pointer)";
EXPECT_EQ(size, sizeof(blob)) << "disk_cache_get of existing item (size)";
free(result);
disk_cache_destroy(cache_sf_ro);
/* Remove empty FOZ RW cache files created above. We only need RO cache. */
EXPECT_EQ(unlink(foz_rw_file), 0);
EXPECT_EQ(unlink(foz_rw_idx_file), 0);
setenv("MESA_DISK_CACHE_SINGLE_FILE", "false", 1);
setenv("MESA_DISK_CACHE_DATABASE", "true", 1);
/* Create MESA-DB cache with enabled retrieval from the read-only
* cache. */
struct disk_cache *cache_mesa_db = disk_cache_create("combined_test",
driver_id, 0);
/* Dummy entry must not present in any of the caches. Foz cache
* reloads index if cache entry is missing. This is a sanity-check
* for foz_read_entry(), it should work properly with a disabled
* FOZ RW cache. */
result = (char *) disk_cache_get(cache_mesa_db, dummy_key, &size);
EXPECT_EQ(result, nullptr) << "disk_cache_get with non-existent item (pointer)";
EXPECT_EQ(size, 0) << "disk_cache_get with non-existent item (size)";
/* Blob entry must present because it shall be retrieved from the
* read-only cache. */
result = (char *) disk_cache_get(cache_mesa_db, blob_key, &size);
EXPECT_STREQ(blob, result) << "disk_cache_get of existing item (pointer)";
EXPECT_EQ(size, sizeof(blob)) << "disk_cache_get of existing item (size)";
free(result);
disk_cache_destroy(cache_mesa_db);
/* Disable read-only cache. */
setenv("MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ", "false", 1);
/* Create MESA-DB cache with disabled retrieval from the read-only
* cache. */
cache_mesa_db = disk_cache_create("combined_test", driver_id, 0);
/* Blob entry must not present in the cache because we disable the
* read-only cache. */
result = (char *) disk_cache_get(cache_mesa_db, blob_key, &size);
EXPECT_EQ(result, nullptr) << "disk_cache_get with non-existent item (pointer)";
EXPECT_EQ(size, 0) << "disk_cache_get with non-existent item (size)";
disk_cache_destroy(cache_mesa_db);
/* Create default multi-file cache. */
setenv("MESA_DISK_CACHE_DATABASE", "false", 1);
/* Enable read-only cache. */
setenv("MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ", "true", 1);
/* Create multi-file cache with enabled retrieval from the
* read-only cache. */
struct disk_cache *cache_multifile = disk_cache_create("combined_test",
driver_id, 0);
/* Blob entry must present because it shall be retrieved from the
* read-only cache. */
result = (char *) disk_cache_get(cache_multifile, blob_key, &size);
EXPECT_STREQ(blob, result) << "disk_cache_get of existing item (pointer)";
EXPECT_EQ(size, sizeof(blob)) << "disk_cache_get of existing item (size)";
free(result);
disk_cache_destroy(cache_multifile);
/* Disable read-only cache. */
setenv("MESA_DISK_CACHE_COMBINE_RW_WITH_RO_FOZ", "false", 1);
unsetenv("MESA_DISK_CACHE_READ_ONLY_FOZ_DBS");
/* Create multi-file cache with disabled retrieval from the
* read-only cache. */
cache_multifile = disk_cache_create("combined_test", driver_id, 0);
/* Blob entry must not present in the cache because we disabled the
* read-only cache. */
result = (char *) disk_cache_get(cache_multifile, blob_key, &size);
EXPECT_EQ(result, nullptr) << "disk_cache_get with non-existent item (pointer)";
EXPECT_EQ(size, 0) << "disk_cache_get with non-existent item (size)";
disk_cache_destroy(cache_multifile);
int err = rmrf_local(CACHE_TEST_TMP);
EXPECT_EQ(err, 0) << "Removing " CACHE_TEST_TMP " again";
#endif
}