File: prefetch_cache.h

package info (click to toggle)
chromium 145.0.7632.159-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,976,224 kB
  • sloc: cpp: 36,198,469; ansic: 7,634,080; javascript: 3,564,060; python: 1,649,622; xml: 838,470; asm: 717,087; pascal: 185,708; sh: 88,786; perl: 88,718; objc: 79,984; sql: 59,811; cs: 42,452; fortran: 24,101; makefile: 21,144; tcl: 15,277; php: 14,022; yacc: 9,066; ruby: 7,553; awk: 3,720; lisp: 3,233; lex: 1,328; ada: 727; jsp: 228; sed: 36
file content (183 lines) | stat: -rw-r--r-- 7,295 bytes parent folder | download | duplicates (6)
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
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef SERVICES_NETWORK_PREFETCH_CACHE_H_
#define SERVICES_NETWORK_PREFETCH_CACHE_H_

#include <map>
#include <set>
#include <utility>

#include "base/component_export.h"
#include "base/containers/linked_list.h"
#include "base/containers/queue.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/network_isolation_key.h"
#include "url/gurl.h"

namespace net {
class NetworkIsolationKey;
}  // namespace net

namespace network {

class PrefetchURLLoaderClient;
struct ResourceRequest;

// PrefetchCache implements caching of PrefetchURLLoaderClient objects for
// NetworkContexts. There is at most one created per NetworkContext.
class COMPONENT_EXPORT(NETWORK_SERVICE) PrefetchCache final {
 public:
  // The maximum age a prefetch is permitted to live for without being claimed
  // by a render process.
  // TODO(crbug.com/342445996): Allow this to be set dynamically by a feature
  // param.
  static constexpr auto kMaxAge = base::Minutes(5);

  // If several prefetches are created close together, it is wasteful to wake up
  // once for each one, so permit prefetches that have reached
  // `kMaxAge` - `kExpirySlack` to also be expired.
  // TODO(crbug.com/342445996): Allow this to be set dynamically by a feature
  // param.
  static constexpr auto kExpirySlack = base::Seconds(1);

  PrefetchCache();

  PrefetchCache(const PrefetchCache&) = delete;
  PrefetchCache& operator=(const PrefetchCache&) = delete;

  ~PrefetchCache();

  // Instantiates and inserts a new PrefetchURLLoaderClient. If a matching
  // request (same NIK and URL) already exists in the cache, returns nullptr.
  // The returned PrefetchURLLoaderClient is owned by this object. The returned
  // pointer is safe to use synchronously as long as nothing calls Erase() on
  // it, but it should not be used again after returning to the run loop as it
  // might be deleted asynchronously.
  PrefetchURLLoaderClient* Emplace(const ResourceRequest& request);

  // Finds a PrefetchURLLoaderClient matching `nik` and `url`. Returns nullptr
  // if nothing is found. As with Emplace(), the returned pointer should only be
  // used synchronously.
  PrefetchURLLoaderClient* Lookup(const net::NetworkIsolationKey& nik,
                                  const GURL& url);

  // Prevents `client` from being returned by future calls to Lookup() and
  // permits a new request with the same key to be created by Emplace().
  // `client` must exist in the cache.
  void Consume(PrefetchURLLoaderClient* client);

  // Removes `client` from the cache and deletes it. `client` must have been
  // created by Emplace() and not already erased.
  void Erase(PrefetchURLLoaderClient* client);

  // Erases `client` after `kEraseGraceTime` has expired. The purpose is to
  // permit a new transaction from a renderer to reach the HttpCache code before
  // this client is erased, so that it can take over the cache lock if possible,
  // avoiding the entry being truncated.
  //
  // This is a temporary feature to maximise the chances of reusing the disk
  // cache entry when the feature kNetworkContextPrefetchUseMatches is not
  // enabled.
  //
  // TODO(crbug.com/342445996): Remove this method and associated code after
  // kNetworkContextPrefetchUseMatches has been permanently enabled.
  void DelayedErase(PrefetchURLLoaderClient* client);

 private:
  // This is not a std::list because we want to be able to remove an item from
  // the cache by pointer.
  using ListType = base::LinkedList<PrefetchURLLoaderClient>;

  // The references in the KeyType point inside the PrefetchURLLoaderClient that
  // is the value of the map, so they are guaranteed to be valid.
  using KeyType = std::pair<const net::NetworkIsolationKey&, const GURL&>;

  // The value_type of the map is const to reduce the risk of accidentally
  // changing it, since the key's references point into the value.
  using MapType = std::map<KeyType, const raw_ptr<PrefetchURLLoaderClient>>;

  using ClientStorage = std::set<std::unique_ptr<PrefetchURLLoaderClient>,
                                 base::UniquePtrComparator>;

  struct PendingErasure {
    // The client is referred to by its key rather than a pointer, so that there
    // is no dangling reference if something else erases the client first.
    net::NetworkIsolationKey nik;
    GURL url;
    base::TimeTicks erase_time;
  };

  using EraseQueue = base::queue<PendingErasure>;

  // Deletes any expired cache entries and then restarts the timer if needed.
  void OnTimer();

  // Deletes anything in `delayed_erase_queue_` that is due for deletion, and
  // then schedules another call if the queue is still non-empty.
  void DoDelayedErases();

  // Removes and deletes the oldest entry from the cache.
  void EraseOldest();

  // Removes an entry from the cache without deleting it. `client` must be in
  // the cache.
  void RemoveFromCache(PrefetchURLLoaderClient* client);

  // Removes `client` from `client_storage_`, deleting it. `client` must exist.
  void EraseFromStorage(PrefetchURLLoaderClient* client);

  // Starts the timer to fire when the next cache entry will expire. `now`
  // should be the current time. It is optional because some callers have it
  // handy and some don't.
  void StartTimer(base::TimeTicks now = base::TimeTicks::Now());

  // Schedules a task to call DoDelayedErases() the next time something in
  // `delayed_erase_queue_` needs to be erased. `now` should be the return value
  // from a recent call to `base::TimeTicks::Now()`.
  void SchedulePendingErases(base::TimeTicks now);

  // Performing a find() on `map_` is sufficiently messy that it's worth
  // encapsulating in a separate method.
  MapType::iterator FindInMap(const net::NetworkIsolationKey& nik,
                              const GURL& url);

  // Storage for all the PrefetchURLLoaderClients created by this object,
  // regardless if Consume() has been called for them or not. `list_` and `map_`
  // contain references into these objects, so must be destroyed first.
  ClientStorage client_storage_;

  // The PrefetchURLLoaderClients are stored in a list to permit deletion and
  // finding the oldest in O(1) time. `list_.head()` is the oldest item and
  // `list_.tail()` is the newest. `list_` does not own the objects. They are
  // owned by `client_storage_`.
  ListType list_;

  // They are referenced from a map, permitting O(log N) lookup.
  MapType map_;

  // Timer. If `list_` is non-empty, it is set to go off when the oldest item in
  // `list_` will expire.
  base::OneShotTimer expiry_timer_;

  // Queue for DelayedErase(). Entries will be deleted when their `erase_time`
  // is reached.
  EraseQueue delayed_erase_queue_;

  // Initialized from kNetworkContextPrefetchMaxLoaders feature flag.
  const size_t max_size_;

  // Initialized from "erase_grace_time" parameter to "NetworkContextPrefetch"
  // feature.
  const base::TimeDelta erase_grace_time_;

  base::WeakPtrFactory<PrefetchCache> weak_factory_{this};
};

}  // namespace network

#endif  // SERVICES_NETWORK_PREFETCH_CACHE_H_