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