1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_IPC_HOST_GPU_DISK_CACHE_H_
#define GPU_IPC_HOST_GPU_DISK_CACHE_H_
#include <stdint.h>
#include <string>
#include <unordered_map>
#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "base/files/file_path.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "gpu/ipc/common/gpu_disk_cache_type.h"
#include "net/base/completion_once_callback.h"
#include "net/disk_cache/disk_cache.h"
namespace gpu {
class GpuDiskCacheFactory;
class GpuDiskCacheEntry;
class GpuDiskCacheReadHelper;
class GpuDiskCacheClearHelper;
// GpuDiskCache is the interface to the on disk cache for the GPU process.
class GpuDiskCache : public base::RefCounted<GpuDiskCache> {
public:
using BlobLoadedCallback =
base::RepeatingCallback<void(const std::string&, const std::string&)>;
GpuDiskCache(const GpuDiskCache&) = delete;
GpuDiskCache& operator=(const GpuDiskCache&) = delete;
// Store the |blob| into the cache under |key|.
void Cache(const std::string& key, const std::string& blob);
// Clear a range of entries. This supports unbounded deletes in either
// direction by using null Time values for either |begin_time| or |end_time|.
// The return value is a net error code. If this method returns
// ERR_IO_PENDING, the |completion_callback| will be invoked when the
// operation completes.
int Clear(base::Time begin_time,
base::Time end_time,
net::CompletionOnceCallback completion_callback);
// Sets a callback for when the cache is available. If the cache is
// already available the callback will not be called and net::OK is returned.
// If the callback is set net::ERR_IO_PENDING is returned and the callback
// will be executed when the cache is available.
int SetAvailableCallback(net::CompletionOnceCallback callback);
// Returns the element count synchronously if available, or
// net::ERR_IO_PENDING for asynchronous completion via `callback`. Returns
// net::ERR_FAILED if the cache is not yet available.
int32_t Size(net::CompletionOnceCallback callback);
// Set a callback notification for when all current entries have been
// written to the cache.
// The return value is a net error code. If this method returns
// ERR_IO_PENDING, the |callback| will be invoked when all entries have
// been written to the cache.
int SetCacheCompleteCallback(net::CompletionOnceCallback callback);
private:
friend class base::RefCounted<GpuDiskCache>;
friend class GpuDiskCacheEntry;
friend class GpuDiskCacheReadHelper;
friend class GpuDiskCacheFactory;
GpuDiskCache(GpuDiskCacheFactory* factory,
const base::FilePath& cache_path,
const BlobLoadedCallback& blob_loaded_cb,
base::OnceClosure cache_destroyed_cb);
~GpuDiskCache();
void Init();
void CacheCreatedCallback(disk_cache::BackendResult rv);
disk_cache::Backend* backend() { return backend_.get(); }
void EntryComplete(GpuDiskCacheEntry* entry);
void ReadComplete();
raw_ptr<GpuDiskCacheFactory> factory_;
bool cache_available_ = false;
base::FilePath cache_path_;
bool is_initialized_ = false;
net::CompletionOnceCallback available_callback_;
net::CompletionOnceCallback cache_complete_callback_;
BlobLoadedCallback blob_loaded_cb_;
base::OnceClosure cache_destroyed_cb_;
std::unique_ptr<disk_cache::Backend> backend_;
std::unique_ptr<GpuDiskCacheReadHelper> helper_;
std::unordered_map<GpuDiskCacheEntry*, std::unique_ptr<GpuDiskCacheEntry>>
entries_;
};
// GpuDiskCacheFactory maintains a cache of GpuDiskCache objects so we only
// create one per profile directory.
class GpuDiskCacheFactory {
public:
using HandleToPathMap = base::flat_map<GpuDiskCacheHandle, base::FilePath>;
using BlobLoadedForCacheCallback = base::RepeatingCallback<
void(const GpuDiskCacheHandle&, const std::string&, const std::string&)>;
using CacheDestroyedCallback =
base::OnceCallback<void(const GpuDiskCacheHandle&)>;
// Constructor allows passing in reserved handles and their corresponding
// paths.
explicit GpuDiskCacheFactory(
const HandleToPathMap& reserved_handles = HandleToPathMap());
GpuDiskCacheFactory(const GpuDiskCacheFactory&) = delete;
GpuDiskCacheFactory& operator=(const GpuDiskCacheFactory&) = delete;
~GpuDiskCacheFactory();
// Clear the given gpu disk |cache|. This supports unbounded deletes in
// either direction by using null Time values for either |begin_time| or
// |end_time|. The |callback| will be executed when the clear is complete.
void ClearByCache(scoped_refptr<GpuDiskCache> cache,
base::Time begin_time,
base::Time end_time,
base::OnceClosure callback);
// Clear the gpu disk cache for the given |path|. This supports unbounded
// deletes in either direction by using null Time values for either
// |begin_time| or |end_time|. The |callback| will be executed when the
// clear is complete.
void ClearByPath(const base::FilePath& path,
base::Time begin_time,
base::Time end_time,
base::OnceClosure callback);
// Looks up a |path| and returns a cache handle for it (registering it if
// necessary) for the given |type|.
GpuDiskCacheHandle GetCacheHandle(GpuDiskCacheType type,
const base::FilePath& path);
// Releases the cache's handle (or at least one count of it). When a cache
// handle's number of refs goes to 0, we can cull it from from the map. If the
// handle is a reserved handle, nothing happens because we do not cull
// reserved handles.
void ReleaseCacheHandle(GpuDiskCache* cache);
// Retrieve the gpu disk cache with the given |handle| if the handle has an
// associated path. Returns nullptr if there is no associated path or the
// cache was never explicitly created.
scoped_refptr<GpuDiskCache> Get(const GpuDiskCacheHandle& handle);
// Creates an non-existing gpu cache given a handle that was previously
// registered via GetCacheHandle. Returns nullptr if there was no associated
// path.
scoped_refptr<GpuDiskCache> Create(
const GpuDiskCacheHandle& handle,
const BlobLoadedForCacheCallback& blob_loaded_cb = base::DoNothing(),
CacheDestroyedCallback cache_destroyed_cb = base::DoNothing());
// Set the provided |cache| into the cache map for the given |path|.
void AddToCache(const base::FilePath& path, GpuDiskCache* cache);
// Remove the provided |path| from our cache map.
void RemoveFromCache(const base::FilePath& path);
private:
friend class GpuDiskCacheClearHelper;
scoped_refptr<GpuDiskCache> GetOrCreateByPath(
const base::FilePath& path,
const GpuDiskCache::BlobLoadedCallback& blob_loaded_cb =
base::DoNothing(),
base::OnceClosure cache_destroyed_cb = base::DoNothing());
void CacheCleared(GpuDiskCache* cache);
THREAD_CHECKER(thread_checker_);
// Implementation of bi-directional mapping from path to handle and handle to
// path for both way lookup. Entries in these maps are removed when the last
// scoped_ptr of the respective cache is destroyed, unless the handle is a
// special reserved handle, in which case we do not remove the entry.
HandleToPathMap handle_to_path_map_;
using PathToHandleMap =
base::flat_map<base::FilePath, gpu::GpuDiskCacheHandle>;
PathToHandleMap path_to_handle_map_;
// Map that essentially ref-counts the number of times that a handle is
// re-used. This is important since it allows us to cull the bi-directional
// mappings above when we no longer need them. Handle ref-count is incremented
// each time it is returned in GetCacheHandle, and decremented/removed in
// ReleaseCacheHandle. Note that this does not apply for reserved handles
// which we never cull.
using HandleRefCounts = base::flat_map<GpuDiskCacheHandle, uint32_t>;
HandleRefCounts handle_ref_counts_;
using PathToCacheMap =
base::flat_map<base::FilePath, raw_ptr<GpuDiskCache, CtnExperimental>>;
PathToCacheMap gpu_cache_map_;
using ClearHelperQueue =
base::queue<std::unique_ptr<GpuDiskCacheClearHelper>>;
using CacheToClearHelperQueueMap =
base::flat_map<GpuDiskCache*, ClearHelperQueue>;
CacheToClearHelperQueueMap gpu_clear_map_;
// Handles are all int32_t types underneath so we can allocate them all via
// this incrementing internal counter.
int32_t next_available_handle_ = 0;
};
} // namespace gpu
#endif // GPU_IPC_HOST_GPU_DISK_CACHE_H_
|