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