openMSX
FilePoolCore.hh
Go to the documentation of this file.
1#ifndef FILEPOOLCORE_HH
2#define FILEPOOLCORE_HH
3
4#include "FileOperations.hh"
5#include "ObjectPool.hh"
6#include "MemBuffer.hh"
7#include "SimpleHashSet.hh"
8#include "sha1.hh"
9#include "xxhash.hh"
10#include <cassert>
11#include <cstdint>
12#include <ctime>
13#include <functional>
14#include <string>
15#include <string_view>
16#include <vector>
17
18namespace openmsx {
19
20class File;
21
22enum class FileType {
23 NONE = 0,
24 SYSTEM_ROM = 1, ROM = 2, DISK = 4, TAPE = 8
25};
27 return static_cast<FileType>(int(x) | int(y));
28}
30 return static_cast<FileType>(int(x) & int(y));
31}
33 x = x | y;
34 return x;
35}
36
38{
39public:
40 struct Dir {
41 std::string_view path;
43 };
44 using Directories = std::vector<Dir>;
45
46public:
47 FilePoolCore(std::string fileCache,
48 std::function<Directories()> getDirectories,
49 std::function<void(std::string_view)> reportProgress);
51
56 [[nodiscard]] File getFile(FileType fileType, const Sha1Sum& sha1sum);
57
62 [[nodiscard]] Sha1Sum getSha1Sum(File& file);
63
68 void abort() { stop = true; }
69
70private:
71 struct ScanProgress {
72 uint64_t lastTime;
73 unsigned amountScanned;
74 };
75
76 struct Entry {
77 Entry(const Sha1Sum& s, time_t t, std::string_view f)
78 : filename(f), time(t), sum(s)
79 {
80 assert(time != Date::INVALID_TIME_T);
81 }
82 Entry(const Sha1Sum& s, const char* t, std::string_view f)
83 : filename(f), timeStr(t), sum(s)
84 {
85 assert(timeStr != nullptr);
86 }
87
88 [[nodiscard]] time_t getTime();
89 void setTime(time_t t);
90
91 // - At least one of 'timeStr' or 'time' is valid.
92 // - 'filename' and 'timeStr' are non-owning pointers.
93 std::string_view filename;
94 const char* timeStr = nullptr; // might be nullptr
95 time_t time = Date::INVALID_TIME_T;
96 Sha1Sum sum;
97 };
98
99 using Pool = ObjectPool<Entry>;
100 using Index = Pool::Index;
101 using Sha1Index = std::vector<Index>; // sorted on sha1sum
102
103 class FilenameIndexHelper {
104 public:
105 FilenameIndexHelper(const Pool& p) : pool(p) {}
106 [[nodiscard]] std::string_view get(std::string_view s) const { return s; }
107 [[nodiscard]] std::string_view get(Index idx) const { return pool[idx].filename; }
108 private:
109 const Pool& pool;
110 };
111 struct FilenameIndexHash : FilenameIndexHelper {
112 FilenameIndexHash(const Pool& p) : FilenameIndexHelper(p) {}
113 template<typename T> [[nodiscard]] auto operator()(T t) const {
114 XXHasher hasher;
115 return hasher(get(t));
116 }
117 };
118 struct FilenameIndexEqual : FilenameIndexHelper {
119 FilenameIndexEqual(const Pool& p) : FilenameIndexHelper(p) {}
120 template<typename T1, typename T2>
121 [[nodiscard]] bool operator()(T1 x, T2 y) const {
122 return get(x) == get(y);
123 }
124 };
125 // Hash indexed by filename, points to a full object in 'pool'
126 using FilenameIndex = SimpleHashSet<Index, Index(-1), FilenameIndexHash, FilenameIndexEqual>;
127
128private:
129 void insert(const Sha1Sum& sum, time_t time, const std::string& filename);
130 [[nodiscard]] Sha1Index::iterator getSha1Iterator(Index idx, Entry& entry);
131 void remove(Sha1Index::iterator it);
132 void remove(Index idx);
133 void remove(Index idx, Entry& entry);
134 bool adjustSha1(Sha1Index::iterator it, Entry& entry, const Sha1Sum& newSum);
135 bool adjustSha1(Index idx, Entry& entry, const Sha1Sum& newSum);
136
137 void readSha1sums();
138 void writeSha1sums();
139
140 [[nodiscard]] File getFromPool(const Sha1Sum& sha1sum);
141 [[nodiscard]] File scanDirectory(
142 const Sha1Sum& sha1sum,
143 const std::string& directory,
144 std::string_view poolPath,
145 ScanProgress& progress);
146 [[nodiscard]] File scanFile(
147 const Sha1Sum& sha1sum,
148 const std::string& filename,
149 const FileOperations::Stat& st,
150 std::string_view poolPath,
151 ScanProgress& progress);
152 [[nodiscard]] Sha1Sum calcSha1sum(File& file);
153 [[nodiscard]] std::pair<Index, Entry*> findInDatabase(std::string_view filename);
154
155private:
156 std::string fileCache; // path of the '.filecache' file.
157 std::function<Directories()> getDirectories;
158 std::function<void(std::string_view)> reportProgress;
159
160 MemBuffer<char> fileMem; // content of initial .filecache
161 std::vector<std::string> stringBuffer; // owns strings that are not in 'fileMem'
162
163 Pool pool; // the actual entries
164 Sha1Index sha1Index; // entries accessible via sha1, sorted on 'CompareSha1'
165 FilenameIndex filenameIndex{FilenameIndexHash(pool), FilenameIndexEqual(pool)}; // accessible via filename
166
167 bool stop = false; // abort long search (set via reportProgress callback)
168 bool needWrite = false; // dirty '.filecache'? write on exit
169
170 friend struct GetSha1;
171};
172
173} // namespace openmsx
174
175#endif
TclObject t
Sha1Sum getSha1Sum(File &file)
Calculate sha1sum for the given File object.
FilePoolCore(std::string fileCache, std::function< Directories()> getDirectories, std::function< void(std::string_view)> reportProgress)
Definition: FilePoolCore.cc:24
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
void abort()
This is only meaningful to call from within the 'reportProgress' callback (constructor parameter).
Definition: FilePoolCore.hh:68
std::vector< Dir > Directories
Definition: FilePoolCore.hh:44
This class represents the result of a sha1 calculation (a 160-bit value).
Definition: sha1.hh:23
constexpr time_t INVALID_TIME_T
Definition: Date.hh:11
uint64_t getTime()
Get current (real) time in us.
Definition: Timer.cc:7
This file implemented 3 utility functions:
Definition: Autofire.cc:9
FileType operator&(FileType x, FileType y)
Definition: FilePoolCore.hh:29
const T & get(const Event &event)
Definition: Event.hh:727
FileType & operator|=(FileType &x, FileType y)
Definition: FilePoolCore.hh:32
FileType operator|(FileType x, FileType y)
Definition: FilePoolCore.hh:26
auto sum(InputRange &&range, Proj proj={})
Definition: stl.hh:236