File: persistent_cache_collection.h

package info (click to toggle)
chromium 144.0.7559.109-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 5,915,868 kB
  • sloc: cpp: 35,866,215; ansic: 7,599,035; javascript: 3,623,761; python: 1,639,407; xml: 833,084; asm: 716,173; pascal: 185,323; sh: 88,763; perl: 88,699; objc: 79,984; sql: 58,217; cs: 42,430; fortran: 24,101; makefile: 20,747; tcl: 15,277; php: 14,022; yacc: 9,059; ruby: 7,553; awk: 3,720; lisp: 3,233; lex: 1,330; ada: 727; jsp: 228; sed: 36
file content (175 lines) | stat: -rw-r--r-- 7,347 bytes parent folder | download | duplicates (5)
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
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_PERSISTENT_CACHE_PERSISTENT_CACHE_COLLECTION_H_
#define COMPONENTS_PERSISTENT_CACHE_PERSISTENT_CACHE_COLLECTION_H_

#include <stdint.h>

#include <memory>
#include <optional>
#include <string>
#include <string_view>

#include "base/component_export.h"
#include "base/containers/lru_cache.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/sequence_checker.h"
#include "base/thread_annotations.h"
#include "base/types/expected.h"
#include "components/persistent_cache/backend.h"
#include "components/persistent_cache/backend_storage.h"
#include "components/persistent_cache/buffer_provider.h"
#include "components/persistent_cache/entry_metadata.h"

namespace persistent_cache {

struct PendingBackend;
class PersistentCache;

// Use PersistentCacheCollection to seamlessly access multiple PersistentCache
// instances. For example when used instead of double-keying with backends that
// use disk storage this can result in smaller separated files. Unlike
// PersistentCache itself PersistentCacheCollection is not thread-safe in any
// way.
//
// Example:
//    PersistentCacheCollection collection(temp_dir.GetPath(), 4096);
//    collection.Insert("first_cache_id", "key", value_span);
//    collection.Insert("second_cache_id","key", value_span);
//    ASSIGN_OR_RETURN(auto entry, collection->Find("first_cache_id", "key"),
//      [](persistent_cache::TransactionError error) {
//        // Translate error to return type here.
//      });
//
// Use PersistentCacheCollection to store and retrieve key-value pairs from
// multiple `PersistentCache`s which are created just-in-time.
//
// PersistentCaches stored in the collection can be shared through exported
// parameters but cannot keep being used after they are evicted from the
// collection. PersistentCacheCollection ensures this doesn't happen by
// automatically abandoning caches when evicted.
class COMPONENT_EXPORT(PERSISTENT_CACHE) PersistentCacheCollection {
 public:
  static constexpr size_t kDefaultLruCacheCapacity = 100;

  // Constructs an instance that will use the default storage backend for file
  // management within `top_directory`.
  PersistentCacheCollection(base::FilePath top_directory,
                            int64_t target_footprint,
                            size_t lru_capacity = kDefaultLruCacheCapacity);

  // Constructs an instance that will use `storage_delegate` for file management
  // within `top_directory`.
  PersistentCacheCollection(
      base::FilePath top_directory,
      int64_t target_footprint,
      std::unique_ptr<BackendStorage::Delegate> storage_delegate,
      size_t lru_capacity = kDefaultLruCacheCapacity);

  PersistentCacheCollection(const PersistentCacheCollection&) = delete;
  PersistentCacheCollection& operator=(const PersistentCacheCollection&) =
      delete;
  ~PersistentCacheCollection();

  // Pass-through to PersistentCache functions that first select the correct
  // cache. `cache_id` must be a US-ASCII string consisting more-or-less of
  // lower-case letters, numbers, and select punctuation; see
  // `BaseNameFromCacheId()` below for gory details.
  base::expected<std::optional<EntryMetadata>, TransactionError> Find(
      const std::string& cache_id,
      std::string_view key,
      BufferProvider buffer_provider);

  base::expected<void, TransactionError> Insert(
      const std::string& cache_id,
      std::string_view key,
      base::span<const uint8_t> content,
      EntryMetadata metadata = EntryMetadata{});

  // Deletes all files used by the collection, including any present on-disk
  // that are not actively in-use.
  void DeleteAllFiles();

  // Returns a pending backend for an independent read-only connection to the
  // persistent cache at `cache_id`, or nothing if the cache's backend is not
  // operating or the params cannot be exported.
  std::optional<PendingBackend> ShareReadOnlyConnection(
      const std::string& cache_id);

  // Returns a pending backend for an independent read-write connection to the
  // cache at `cache_id`, or nothing if the cache's backend is not operating or
  // the params cannot be exported.
  std::optional<PendingBackend> ShareReadWriteConnection(
      const std::string& cache_id);

 private:
  using PersistentCacheLRUMap =
      base::HashingLRUCache<std::string, std::unique_ptr<PersistentCache>>;

  friend class PersistentCacheCollectionTest;
  FRIEND_TEST_ALL_PREFIXES(PersistentCacheCollectionTest, BaseNameFromCacheId);
  FRIEND_TEST_ALL_PREFIXES(PersistentCacheCollectionTest,
                           FullAllowedCharacterSetHandled);
  FRIEND_TEST_ALL_PREFIXES(PersistentCacheCollectionTest, RetrievalAfterClear);
  FRIEND_TEST_ALL_PREFIXES(PersistentCacheCollectionTest,
                           InstancesAbandonnedOnClear);
  FRIEND_TEST_ALL_PREFIXES(PersistentCacheCollectionTest,
                           EvictWhileLockedDeletesFiles);

  // Abandon `cache` associated with `cache_id` in the LRU cache.
  void AbandonCache(const std::string& cache_id,
                    PersistentCache* persistent_cache)
      VALID_CONTEXT_REQUIRED(sequence_checker_);

  // To be called on receiving a transaction error from the cache at `cache_id`.
  TransactionError HandleTransactionError(const std::string& cache_id,
                                          TransactionError error);

  // Deletes files in the instance's directory from oldest to newest until the
  // instance is using no more than 90% of its target footprint.
  void ReduceFootPrint();

  // Returns the PersistentCache for `cache_id`, creating it if needed. Returns
  // nullptr if creation fails.
  PersistentCache* GetOrCreateCache(const std::string& cache_id);

  // Clears out the LRU map for testing.
  void Clear();

  // Returns the basename of the file(s) used by a backend given a cache id. An
  // extension MUST be added to a returned basename before use. Returns an empty
  // path if `cache_id` contains any character that does not match the following
  // regular expression (where '\' escapes the character it precedes):
  // "[\n !\"#$&'()*+,\-./0-9:;<=>?@[\\\]_a-z|~]". In other words, `cache_id`
  // must be a subset of US-ASCII consisting of newline, space, numbers,
  // lower-case letters, and select punctuation.
  static base::FilePath BaseNameFromCacheId(const std::string& cache_id);

  // Returns a string holding all valid characters for a cache id.
  static std::string GetAllAllowedCharactersInCacheIds();

  // Must outlive `persistent_caches_`.
  BackendStorage backend_storage_ GUARDED_BY_CONTEXT(sequence_checker_);

  // Desired maximum disk footprint for the cache collection in bytes.
  const int64_t target_footprint_;
  const size_t lru_capacity_;

  PersistentCacheLRUMap persistent_caches_
      GUARDED_BY_CONTEXT(sequence_checker_);

  // Running tally of how many bytes can be inserted before a footprint
  // reduction is triggered.
  int64_t bytes_until_footprint_reduction_
      GUARDED_BY_CONTEXT(sequence_checker_);

  SEQUENCE_CHECKER(sequence_checker_);
};

}  // namespace persistent_cache

#endif  // COMPONENTS_PERSISTENT_CACHE_PERSISTENT_CACHE_COLLECTION_H_