xref: /aosp_15_r20/external/cronet/net/disk_cache/blockfile/rankings.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker // See net/disk_cache/disk_cache.h for the public interface.
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #ifndef NET_DISK_CACHE_BLOCKFILE_RANKINGS_H_
8*6777b538SAndroid Build Coastguard Worker #define NET_DISK_CACHE_BLOCKFILE_RANKINGS_H_
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <list>
11*6777b538SAndroid Build Coastguard Worker #include <memory>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include <array>
14*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/disk_cache/blockfile/addr.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/disk_cache/blockfile/mapped_file.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/disk_cache/blockfile/storage_block.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker namespace disk_cache {
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker class BackendImpl;
22*6777b538SAndroid Build Coastguard Worker struct LruData;
23*6777b538SAndroid Build Coastguard Worker struct RankingsNode;
24*6777b538SAndroid Build Coastguard Worker typedef StorageBlock<RankingsNode> CacheRankingsBlock;
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker // Type of crashes generated for the unit tests.
27*6777b538SAndroid Build Coastguard Worker enum RankCrashes {
28*6777b538SAndroid Build Coastguard Worker   NO_CRASH = 0,
29*6777b538SAndroid Build Coastguard Worker   INSERT_EMPTY_1,
30*6777b538SAndroid Build Coastguard Worker   INSERT_EMPTY_2,
31*6777b538SAndroid Build Coastguard Worker   INSERT_EMPTY_3,
32*6777b538SAndroid Build Coastguard Worker   INSERT_ONE_1,
33*6777b538SAndroid Build Coastguard Worker   INSERT_ONE_2,
34*6777b538SAndroid Build Coastguard Worker   INSERT_ONE_3,
35*6777b538SAndroid Build Coastguard Worker   INSERT_LOAD_1,
36*6777b538SAndroid Build Coastguard Worker   INSERT_LOAD_2,
37*6777b538SAndroid Build Coastguard Worker   REMOVE_ONE_1,
38*6777b538SAndroid Build Coastguard Worker   REMOVE_ONE_2,
39*6777b538SAndroid Build Coastguard Worker   REMOVE_ONE_3,
40*6777b538SAndroid Build Coastguard Worker   REMOVE_ONE_4,
41*6777b538SAndroid Build Coastguard Worker   REMOVE_HEAD_1,
42*6777b538SAndroid Build Coastguard Worker   REMOVE_HEAD_2,
43*6777b538SAndroid Build Coastguard Worker   REMOVE_HEAD_3,
44*6777b538SAndroid Build Coastguard Worker   REMOVE_HEAD_4,
45*6777b538SAndroid Build Coastguard Worker   REMOVE_TAIL_1,
46*6777b538SAndroid Build Coastguard Worker   REMOVE_TAIL_2,
47*6777b538SAndroid Build Coastguard Worker   REMOVE_TAIL_3,
48*6777b538SAndroid Build Coastguard Worker   REMOVE_LOAD_1,
49*6777b538SAndroid Build Coastguard Worker   REMOVE_LOAD_2,
50*6777b538SAndroid Build Coastguard Worker   REMOVE_LOAD_3,
51*6777b538SAndroid Build Coastguard Worker   MAX_CRASH
52*6777b538SAndroid Build Coastguard Worker };
53*6777b538SAndroid Build Coastguard Worker 
54*6777b538SAndroid Build Coastguard Worker // This class handles the ranking information for the cache.
55*6777b538SAndroid Build Coastguard Worker class Rankings {
56*6777b538SAndroid Build Coastguard Worker  public:
57*6777b538SAndroid Build Coastguard Worker   // Possible lists of entries.
58*6777b538SAndroid Build Coastguard Worker   enum List {
59*6777b538SAndroid Build Coastguard Worker     NO_USE = 0,   // List of entries that have not been reused.
60*6777b538SAndroid Build Coastguard Worker     LOW_USE,      // List of entries with low reuse.
61*6777b538SAndroid Build Coastguard Worker     HIGH_USE,     // List of entries with high reuse.
62*6777b538SAndroid Build Coastguard Worker     RESERVED,     // Reserved for future use.
63*6777b538SAndroid Build Coastguard Worker     DELETED,      // List of recently deleted or doomed entries.
64*6777b538SAndroid Build Coastguard Worker     LAST_ELEMENT
65*6777b538SAndroid Build Coastguard Worker   };
66*6777b538SAndroid Build Coastguard Worker 
67*6777b538SAndroid Build Coastguard Worker   // This class provides a specialized version of scoped_ptr, that calls
68*6777b538SAndroid Build Coastguard Worker   // Rankings whenever a CacheRankingsBlock is deleted, to keep track of cache
69*6777b538SAndroid Build Coastguard Worker   // iterators that may go stale.
70*6777b538SAndroid Build Coastguard Worker   class ScopedRankingsBlock : public std::unique_ptr<CacheRankingsBlock> {
71*6777b538SAndroid Build Coastguard Worker    public:
72*6777b538SAndroid Build Coastguard Worker     ScopedRankingsBlock();
73*6777b538SAndroid Build Coastguard Worker     explicit ScopedRankingsBlock(Rankings* rankings);
74*6777b538SAndroid Build Coastguard Worker     ScopedRankingsBlock(Rankings* rankings, CacheRankingsBlock* node);
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker     ScopedRankingsBlock(const ScopedRankingsBlock&) = delete;
77*6777b538SAndroid Build Coastguard Worker     ScopedRankingsBlock& operator=(const ScopedRankingsBlock&) = delete;
78*6777b538SAndroid Build Coastguard Worker 
~ScopedRankingsBlock()79*6777b538SAndroid Build Coastguard Worker     ~ScopedRankingsBlock() {
80*6777b538SAndroid Build Coastguard Worker       rankings_->FreeRankingsBlock(get());
81*6777b538SAndroid Build Coastguard Worker     }
82*6777b538SAndroid Build Coastguard Worker 
set_rankings(Rankings * rankings)83*6777b538SAndroid Build Coastguard Worker     void set_rankings(Rankings* rankings) {
84*6777b538SAndroid Build Coastguard Worker       rankings_ = rankings;
85*6777b538SAndroid Build Coastguard Worker     }
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker     // scoped_ptr::reset will delete the object.
88*6777b538SAndroid Build Coastguard Worker     void reset(CacheRankingsBlock* p = nullptr) {
89*6777b538SAndroid Build Coastguard Worker       if (p != get())
90*6777b538SAndroid Build Coastguard Worker         rankings_->FreeRankingsBlock(get());
91*6777b538SAndroid Build Coastguard Worker       std::unique_ptr<CacheRankingsBlock>::reset(p);
92*6777b538SAndroid Build Coastguard Worker     }
93*6777b538SAndroid Build Coastguard Worker 
94*6777b538SAndroid Build Coastguard Worker    private:
95*6777b538SAndroid Build Coastguard Worker     raw_ptr<Rankings> rankings_;
96*6777b538SAndroid Build Coastguard Worker   };
97*6777b538SAndroid Build Coastguard Worker 
98*6777b538SAndroid Build Coastguard Worker   // If we have multiple lists, we have to iterate through all at the same time.
99*6777b538SAndroid Build Coastguard Worker   // This structure keeps track of where we are on the iteration.
100*6777b538SAndroid Build Coastguard Worker   // TODO(https://crbug.com/1409814) refactor this struct to make it clearer
101*6777b538SAndroid Build Coastguard Worker   // this owns the `nodes`.
102*6777b538SAndroid Build Coastguard Worker   struct Iterator {
103*6777b538SAndroid Build Coastguard Worker     Iterator();
104*6777b538SAndroid Build Coastguard Worker     void Reset();
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker     // Which entry was returned to the user.
107*6777b538SAndroid Build Coastguard Worker     List list = List::NO_USE;
108*6777b538SAndroid Build Coastguard Worker     // Nodes on the first three lists.
109*6777b538SAndroid Build Coastguard Worker     std::array<CacheRankingsBlock*, 3> nodes = {nullptr, nullptr, nullptr};
110*6777b538SAndroid Build Coastguard Worker     raw_ptr<Rankings> my_rankings = nullptr;
111*6777b538SAndroid Build Coastguard Worker   };
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker   Rankings();
114*6777b538SAndroid Build Coastguard Worker 
115*6777b538SAndroid Build Coastguard Worker   Rankings(const Rankings&) = delete;
116*6777b538SAndroid Build Coastguard Worker   Rankings& operator=(const Rankings&) = delete;
117*6777b538SAndroid Build Coastguard Worker 
118*6777b538SAndroid Build Coastguard Worker   ~Rankings();
119*6777b538SAndroid Build Coastguard Worker 
120*6777b538SAndroid Build Coastguard Worker   bool Init(BackendImpl* backend, bool count_lists);
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker   // Restores original state, leaving the object ready for initialization.
123*6777b538SAndroid Build Coastguard Worker   void Reset();
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   // Inserts a given entry at the head of the queue.
126*6777b538SAndroid Build Coastguard Worker   void Insert(CacheRankingsBlock* node, bool modified, List list);
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker   // Removes a given entry from the LRU list. If |strict| is true, this method
129*6777b538SAndroid Build Coastguard Worker   // assumes that |node| is not pointed to by an active iterator. On the other
130*6777b538SAndroid Build Coastguard Worker   // hand, removing that restriction allows the current "head" of an iterator
131*6777b538SAndroid Build Coastguard Worker   // to be removed from the list (basically without control of the code that is
132*6777b538SAndroid Build Coastguard Worker   // performing the iteration), so it should be used with extra care.
133*6777b538SAndroid Build Coastguard Worker   void Remove(CacheRankingsBlock* node, List list, bool strict);
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker   // Moves a given entry to the head.
136*6777b538SAndroid Build Coastguard Worker   void UpdateRank(CacheRankingsBlock* node, bool modified, List list);
137*6777b538SAndroid Build Coastguard Worker 
138*6777b538SAndroid Build Coastguard Worker   // Iterates through the list.
139*6777b538SAndroid Build Coastguard Worker   CacheRankingsBlock* GetNext(CacheRankingsBlock* node, List list);
140*6777b538SAndroid Build Coastguard Worker   CacheRankingsBlock* GetPrev(CacheRankingsBlock* node, List list);
141*6777b538SAndroid Build Coastguard Worker   void FreeRankingsBlock(CacheRankingsBlock* node);
142*6777b538SAndroid Build Coastguard Worker 
143*6777b538SAndroid Build Coastguard Worker   // Controls tracking of nodes used for enumerations.
144*6777b538SAndroid Build Coastguard Worker   void TrackRankingsBlock(CacheRankingsBlock* node, bool start_tracking);
145*6777b538SAndroid Build Coastguard Worker 
146*6777b538SAndroid Build Coastguard Worker   // Peforms a simple self-check of the lists, and returns the number of items
147*6777b538SAndroid Build Coastguard Worker   // or an error code (negative value).
148*6777b538SAndroid Build Coastguard Worker   int SelfCheck();
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker   // Returns false if the entry is clearly invalid. from_list is true if the
151*6777b538SAndroid Build Coastguard Worker   // node comes from the LRU list.
152*6777b538SAndroid Build Coastguard Worker   bool SanityCheck(CacheRankingsBlock* node, bool from_list) const;
153*6777b538SAndroid Build Coastguard Worker   bool DataSanityCheck(CacheRankingsBlock* node, bool from_list) const;
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker   // Sets the |contents| field of |node| to |address|.
156*6777b538SAndroid Build Coastguard Worker   void SetContents(CacheRankingsBlock* node, CacheAddr address);
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker  private:
159*6777b538SAndroid Build Coastguard Worker   typedef std::pair<CacheAddr, CacheRankingsBlock*> IteratorPair;
160*6777b538SAndroid Build Coastguard Worker   typedef std::list<IteratorPair> IteratorList;
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker   void ReadHeads();
163*6777b538SAndroid Build Coastguard Worker   void ReadTails();
164*6777b538SAndroid Build Coastguard Worker   void WriteHead(List list);
165*6777b538SAndroid Build Coastguard Worker   void WriteTail(List list);
166*6777b538SAndroid Build Coastguard Worker 
167*6777b538SAndroid Build Coastguard Worker   // Gets the rankings information for a given rankings node. We may end up
168*6777b538SAndroid Build Coastguard Worker   // sharing the actual memory with a loaded entry, but we are not taking a
169*6777b538SAndroid Build Coastguard Worker   // reference to that entry, so |rankings| must be short lived.
170*6777b538SAndroid Build Coastguard Worker   bool GetRanking(CacheRankingsBlock* rankings);
171*6777b538SAndroid Build Coastguard Worker 
172*6777b538SAndroid Build Coastguard Worker   // Makes |rankings| suitable to live a long life.
173*6777b538SAndroid Build Coastguard Worker   void ConvertToLongLived(CacheRankingsBlock* rankings);
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker   // Finishes a list modification after a crash.
176*6777b538SAndroid Build Coastguard Worker   void CompleteTransaction();
177*6777b538SAndroid Build Coastguard Worker   void FinishInsert(CacheRankingsBlock* rankings);
178*6777b538SAndroid Build Coastguard Worker   void RevertRemove(CacheRankingsBlock* rankings);
179*6777b538SAndroid Build Coastguard Worker 
180*6777b538SAndroid Build Coastguard Worker   // Returns false if node is not properly linked. This method may change the
181*6777b538SAndroid Build Coastguard Worker   // provided |list| to reflect the list where this node is actually stored.
182*6777b538SAndroid Build Coastguard Worker   bool CheckLinks(CacheRankingsBlock* node, CacheRankingsBlock* prev,
183*6777b538SAndroid Build Coastguard Worker                   CacheRankingsBlock* next, List* list);
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker   // Checks the links between two consecutive nodes.
186*6777b538SAndroid Build Coastguard Worker   bool CheckSingleLink(CacheRankingsBlock* prev, CacheRankingsBlock* next);
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   // Peforms a simple check of the list, and returns the number of items or an
189*6777b538SAndroid Build Coastguard Worker   // error code (negative value).
190*6777b538SAndroid Build Coastguard Worker   int CheckList(List list);
191*6777b538SAndroid Build Coastguard Worker 
192*6777b538SAndroid Build Coastguard Worker   // Walks a list in the desired direction until the nodes |end1| or |end2| are
193*6777b538SAndroid Build Coastguard Worker   // reached. Returns an error code (0 on success), the number of items verified
194*6777b538SAndroid Build Coastguard Worker   // and the addresses of the last nodes visited.
195*6777b538SAndroid Build Coastguard Worker   int CheckListSection(List list, Addr end1, Addr end2, bool forward,
196*6777b538SAndroid Build Coastguard Worker                        Addr* last, Addr* second_last, int* num_items);
197*6777b538SAndroid Build Coastguard Worker 
198*6777b538SAndroid Build Coastguard Worker   // Returns true if addr is the head or tail of any list. When there is a
199*6777b538SAndroid Build Coastguard Worker   // match |list| will contain the list number for |addr|.
200*6777b538SAndroid Build Coastguard Worker   bool IsHead(CacheAddr addr, List* list) const;
201*6777b538SAndroid Build Coastguard Worker   bool IsTail(CacheAddr addr, List* list) const;
202*6777b538SAndroid Build Coastguard Worker 
203*6777b538SAndroid Build Coastguard Worker   // Updates the iterators whenever node is being changed.
204*6777b538SAndroid Build Coastguard Worker   void UpdateIterators(CacheRankingsBlock* node);
205*6777b538SAndroid Build Coastguard Worker 
206*6777b538SAndroid Build Coastguard Worker   // Updates the iterators when node at address |addr| is being removed to point
207*6777b538SAndroid Build Coastguard Worker   // to |next| instead.
208*6777b538SAndroid Build Coastguard Worker   void UpdateIteratorsForRemoved(CacheAddr addr, CacheRankingsBlock* next);
209*6777b538SAndroid Build Coastguard Worker 
210*6777b538SAndroid Build Coastguard Worker   // Keeps track of the number of entries on a list.
211*6777b538SAndroid Build Coastguard Worker   void IncrementCounter(List list);
212*6777b538SAndroid Build Coastguard Worker   void DecrementCounter(List list);
213*6777b538SAndroid Build Coastguard Worker 
214*6777b538SAndroid Build Coastguard Worker   bool init_ = false;
215*6777b538SAndroid Build Coastguard Worker   bool count_lists_;
216*6777b538SAndroid Build Coastguard Worker   Addr heads_[LAST_ELEMENT];
217*6777b538SAndroid Build Coastguard Worker   Addr tails_[LAST_ELEMENT];
218*6777b538SAndroid Build Coastguard Worker   raw_ptr<BackendImpl> backend_;
219*6777b538SAndroid Build Coastguard Worker 
220*6777b538SAndroid Build Coastguard Worker   // Data related to the LRU lists.
221*6777b538SAndroid Build Coastguard Worker   // May point to a mapped file's unmapped memory at destruction time.
222*6777b538SAndroid Build Coastguard Worker   raw_ptr<LruData, DisableDanglingPtrDetection> control_data_;
223*6777b538SAndroid Build Coastguard Worker 
224*6777b538SAndroid Build Coastguard Worker   IteratorList iterators_;
225*6777b538SAndroid Build Coastguard Worker };
226*6777b538SAndroid Build Coastguard Worker 
227*6777b538SAndroid Build Coastguard Worker }  // namespace disk_cache
228*6777b538SAndroid Build Coastguard Worker 
229*6777b538SAndroid Build Coastguard Worker #endif  // NET_DISK_CACHE_BLOCKFILE_RANKINGS_H_
230