#ifndef NET_DISK_CACHE_BLOCKFILE_RANKINGS_H_
#define NET_DISK_CACHE_BLOCKFILE_RANKINGS_H_
#include <list>
#include <memory>
#include <array>
#include "base/memory/raw_ptr.h"
#include "net/disk_cache/blockfile/addr.h"
#include "net/disk_cache/blockfile/mapped_file.h"
#include "net/disk_cache/blockfile/storage_block.h"
namespace disk_cache {
class BackendImpl;
struct LruData;
struct RankingsNode;
typedef StorageBlock<RankingsNode> CacheRankingsBlock;
enum RankCrashes {
NO_CRASH = 0,
INSERT_EMPTY_1,
INSERT_EMPTY_2,
INSERT_EMPTY_3,
INSERT_ONE_1,
INSERT_ONE_2,
INSERT_ONE_3,
INSERT_LOAD_1,
INSERT_LOAD_2,
REMOVE_ONE_1,
REMOVE_ONE_2,
REMOVE_ONE_3,
REMOVE_ONE_4,
REMOVE_HEAD_1,
REMOVE_HEAD_2,
REMOVE_HEAD_3,
REMOVE_HEAD_4,
REMOVE_TAIL_1,
REMOVE_TAIL_2,
REMOVE_TAIL_3,
REMOVE_LOAD_1,
REMOVE_LOAD_2,
REMOVE_LOAD_3,
MAX_CRASH
};
class Rankings {
public:
enum List {
NO_USE = 0,
LOW_USE,
HIGH_USE,
RESERVED,
DELETED,
LAST_ELEMENT
};
class ScopedRankingsBlock : public std::unique_ptr<CacheRankingsBlock> {
public:
ScopedRankingsBlock();
explicit ScopedRankingsBlock(Rankings* rankings);
ScopedRankingsBlock(Rankings* rankings, CacheRankingsBlock* node);
ScopedRankingsBlock(const ScopedRankingsBlock&) = delete;
ScopedRankingsBlock& operator=(const ScopedRankingsBlock&) = delete;
~ScopedRankingsBlock();
void set_rankings(Rankings* rankings) {
rankings_ = rankings;
}
void reset(CacheRankingsBlock* p = nullptr);
private:
raw_ptr<Rankings> rankings_;
};
struct Iterator {
Iterator();
void Reset();
List list = List::NO_USE;
std::array<CacheRankingsBlock*, 3> nodes = {nullptr, nullptr, nullptr};
raw_ptr<Rankings> my_rankings = nullptr;
};
Rankings();
Rankings(const Rankings&) = delete;
Rankings& operator=(const Rankings&) = delete;
~Rankings();
bool Init(BackendImpl* backend, bool count_lists);
void Reset();
void Insert(CacheRankingsBlock* node, List list);
void Remove(CacheRankingsBlock* node, List list, bool strict);
void UpdateRank(CacheRankingsBlock* node, List list);
CacheRankingsBlock* GetNext(CacheRankingsBlock* node, List list);
CacheRankingsBlock* GetPrev(CacheRankingsBlock* node, List list);
void FreeRankingsBlock(CacheRankingsBlock* node);
void TrackRankingsBlock(CacheRankingsBlock* node, bool start_tracking);
int SelfCheck();
bool SanityCheck(CacheRankingsBlock* node, bool from_list) const;
bool DataSanityCheck(CacheRankingsBlock* node, bool from_list) const;
void SetContents(CacheRankingsBlock* node, CacheAddr address);
private:
typedef std::pair<CacheAddr, CacheRankingsBlock*> IteratorPair;
typedef std::list<IteratorPair> IteratorList;
void ReadHeads();
void ReadTails();
void WriteHead(List list);
void WriteTail(List list);
bool GetRanking(CacheRankingsBlock* rankings);
void ConvertToLongLived(CacheRankingsBlock* rankings);
void CompleteTransaction();
void FinishInsert(CacheRankingsBlock* rankings);
void RevertRemove(CacheRankingsBlock* rankings);
bool CheckLinks(CacheRankingsBlock* node, CacheRankingsBlock* prev,
CacheRankingsBlock* next, List* list);
bool CheckSingleLink(CacheRankingsBlock* prev, CacheRankingsBlock* next);
int CheckList(List list);
int CheckListSection(List list, Addr end1, Addr end2, bool forward,
Addr* last, Addr* second_last, int* num_items);
bool IsHead(CacheAddr addr, List* list) const;
bool IsTail(CacheAddr addr, List* list) const;
void UpdateIterators(CacheRankingsBlock* node);
void UpdateIteratorsForRemoved(CacheAddr addr, CacheRankingsBlock* next);
void IncrementCounter(List list);
void DecrementCounter(List list);
bool init_ = false;
bool count_lists_;
std::array<Addr, LAST_ELEMENT> heads_;
std::array<Addr, LAST_ELEMENT> tails_;
raw_ptr<BackendImpl> backend_;
raw_ptr<LruData, DisableDanglingPtrDetection> control_data_;
IteratorList iterators_;
};
}
#endif