Bridges-C++ 3.5.0-dev1
Bridges(C++ API)
Loading...
Searching...
No Matches
Cache.h
Go to the documentation of this file.
1#ifndef CACHE_H
2#define CACHE_H
3
4#ifndef _WIN32
5#include <unistd.h>
6#endif
7#ifdef _WIN32
8#include <direct.h>
9#endif
10
11#if __cplusplus >= 201703L
12#include <filesystem>
13#endif
14
15namespace bridges {
16
17 class CacheException : public std::exception {
18 const char* whatmsg;
19 public:
20
21 CacheException(const char* what_msg = "")
22 : std::exception(), whatmsg(what_msg) {
23
24 }
25
26 virtual const char* what() const noexcept {
27 return whatmsg;
28 }
29
30 };
31
32 class Cache {
33 public:
34 virtual bool inCache(const std::string & docName) noexcept(false) = 0;
35 virtual std::string getDoc (const std::string & docName) noexcept(false) = 0;
36 //store content under docname
37 virtual void putDoc (const std::string & docName,
38 const std::string & content) noexcept(false) = 0;
39 };
40
53 class SimpleCache : public Cache {
54 private:
55 std::string cacheDir;
56
57 std::string getFilename(const std::string & docName) {
58 return cacheDir + "/" + docName; //TODO: bad things can happen if docName contains / or .. or stuff like that
59
60 }
61
62 //return whether s is a directory (true) or does not exist (false). all other cases are exception
63 bool directoryExist(const std::string &s) {
64 struct stat buffer;
65 int ret = stat (s.c_str(), &buffer);
66
67 if (ret == 0) { //file exist
68 if ((buffer.st_mode & S_IFMT) == S_IFDIR) { //Not using S_ISDIR because VS2017 does not support it.
69 return true;
70 }
71 else {
72 throw CacheException("Expect directory"); //s exist but is not a directory
73 }
74 }
75
76 return false;
77 }
78
79 //make a directory called s or throw an exception
80 static void makeDirectory (const std::string &s) {
81#if __cplusplus >= 201703L
82 //C++17 support
83
84 //we can use std::filesystem::create_directories to make the directories recursively.
85
86 bool ret = std::filesystem::create_directories(s);
87 if (!ret)
88 throw CacheException("error in makeDirectory");
89
90#else
91 //No C++17 support. So no std::filesystem support
92 //So forgo recursive creation. Probably not worth the cost of writing the code.
93#ifndef _WIN32
94 int ret = mkdir(s.c_str(), 0700);
95#endif
96#ifdef _WIN32
97 int ret = _mkdir(s.c_str());
98#endif
99
100 if (ret != 0)
101 throw CacheException("error in makeDirectory");
102
103#endif
104
105 }
106
107 public:
109 //According to XDG, you should put the cache data in
110 //$XDG_CACHE_HOME and if not defined in $HOME/.cache
111 //However, MS Windows does not set $HOME. So we
112 //use $LOCALAPPDATA as if it was $HOME.
113 //
114 //So we put the data in $XDG_CACHE_HOME/bridges_data/cxx
115 //
116 //Finally, one can overide everything by setting $FORCE_BRIDGES_CACHEDIR
117
118 char * home = getenv("HOME"); // a reasonable location on unixes
119 if (home == nullptr)
120 home = getenv("LOCALAPPDATA"); // a reasonnable location on windowses
121
122 if (home != nullptr)
123 cacheDir += std::string(home) + "/.cache/";
124
125 //override the directory of the cache if is set
126 char* xdg_cache_home = getenv("XDG_CACHE_HOME");
127 if (xdg_cache_home != nullptr)
128 cacheDir = std::string(xdg_cache_home) + "/";
129
130 cacheDir += "bridges_data/cxx/";
131 //probably should check directory existence here, but exception in constructors are weird.
132
133 //override the directory of the cache if FORCE_BRIDGES_CACHEDIR is set
134 char* forcedir = getenv("FORCE_BRIDGES_CACHEDIR");
135 if (forcedir != nullptr)
136 cacheDir = std::string(forcedir) + "/";
137 }
138
139 virtual ~SimpleCache() = default;
140
141 //is docName in the cache
142 virtual bool inCache(const std::string & docName) noexcept(false) override {
143 std::string filename = getFilename(docName);
144
145 std::ifstream in(filename);
146
147 return in.is_open();
148 }
149
150 //return the content of docName which is in the cache
151 virtual std::string getDoc (const std::string & docName) noexcept(false) override {
152 std::string filename = getFilename(docName);
153
154 std::ifstream in(filename);
155
156 if (!in.good() || !(in.is_open()))
157 throw CacheException("Can't open file to read");
158
159 std::string contents;
160 in.seekg(0, std::ios::end);
161 contents.resize(in.tellg());
162 in.seekg(0, std::ios::beg);
163 in.read(&contents[0], contents.size());
164 if (! (in.good()))
165 throw CacheException("Error while reading cache document");
166 in.close();
167 return (contents);
168
169 }
170
171 //store content under docname
172 virtual void putDoc (const std::string & docName,
173 const std::string & content) noexcept(false) override {
174 if (!directoryExist(cacheDir))
175 makeDirectory(cacheDir);
176
177 std::string filename = getFilename(docName);
178
179 std::ofstream out(filename);
180 if (!out.good() || !(out.is_open()))
181 throw CacheException("can't open file to store");
182
183 out << content.c_str(); //this assumes string isn't binary
184 if (!out.good() || !(out.is_open()))
185 throw CacheException("error while writing cache document");
186
187 }
188
193 bool evict(const std::string& docName) {
194 string f = cacheDir;
195 f.append(docName);
196
197 return std::remove(f.c_str()) == 0;
198 }
199 };
200
201 class lruCache : public Cache {
202
203 int maxCache;
204 std::vector<std::string> v;
205 SimpleCache ca;
206 public:
207 lruCache(int maxFileNumber = 30)
208 : maxCache(maxFileNumber) {
209 }
210
211 virtual ~lruCache() = default;
212
213 virtual std::string getDoc (const std::string& hash_value) override { //returns LRU vector from cache file
214 string content;
215 getLRU();
216 content = ca.getDoc(hash_value);
217 updateLRU(hash_value);
218 saveLRU();
219 return content;
220 }
221
222 virtual bool inCache(const std::string& hash_value) override {
223 if (ca.inCache(hash_value)) {
224 return true;
225 }
226 return false;
227 }
228
229 virtual void putDoc(const std::string& hash_value, const std::string& content) override { //puts hash value at front of LRU vector
230 getLRU();
231 ca.putDoc(hash_value, content);
232 updateLRU(hash_value);
233
234 //checks size of vector and pops lru off
235 if (v.size() >= maxCache + 1) { // keeps maxCache local maps
236 if (ca.evict(v[v.size() - 1]))
237 v.pop_back();
238 }
239 saveLRU();
240 return;
241 }
242
243 private:
244 void updateLRU(std::string hash_value) {
245 for (auto it = v.begin(); it != v.end(); ) {
246 if (*it == hash_value) {
247 v.erase(it); //removes old hash vlaue location in vector
248 break;
249 }
250 else {
251 ++it;
252 }
253 }
254 v.insert(v.begin(), hash_value); //puts hash value in the front of the vector
255 return;
256 }
257 void getLRU() {
258 v.clear();
259 if (ca.inCache("lru")) {
260 string vector_string = ca.getDoc("lru"); //Imported LRU
261 std::istringstream ss(vector_string);
262 std::string token;
263 //Parses string and turns it into vector
264 while (std::getline(ss, token, ',')) {
265 v.push_back(token);
266 }
267 }
268 return;
269 }
270
271 void saveLRU() {
272 //Saves the vector to file
273 string out_vector;
274 int x = 0;
275 for (auto s : v) {
276 if (x == 0) { //prevents , from being first character
277 out_vector = s;
278 x++;
279 }
280 else {
281 out_vector = out_vector + "," + s;
282 }
283 }
284 ca.putDoc("lru", out_vector);
285 }
286 };
287}
288
289#endif
Definition Cache.h:17
CacheException(const char *what_msg="")
Definition Cache.h:21
virtual const char * what() const noexcept
Definition Cache.h:26
Definition Cache.h:32
virtual std::string getDoc(const std::string &docName) noexcept(false)=0
virtual bool inCache(const std::string &docName) noexcept(false)=0
virtual void putDoc(const std::string &docName, const std::string &content) noexcept(false)=0
object managing a disk cache for which ever purpose needed.
Definition Cache.h:53
bool evict(const std::string &docName)
evicts a document from the cache
Definition Cache.h:193
virtual ~SimpleCache()=default
virtual void putDoc(const std::string &docName, const std::string &content) noexcept(false) override
Definition Cache.h:172
virtual std::string getDoc(const std::string &docName) noexcept(false) override
Definition Cache.h:151
virtual bool inCache(const std::string &docName) noexcept(false) override
Definition Cache.h:142
SimpleCache()
Definition Cache.h:108
Definition Cache.h:201
virtual void putDoc(const std::string &hash_value, const std::string &content) override
Definition Cache.h:229
lruCache(int maxFileNumber=30)
Definition Cache.h:207
virtual bool inCache(const std::string &hash_value) override
Definition Cache.h:222
virtual ~lruCache()=default
virtual std::string getDoc(const std::string &hash_value) override
Definition Cache.h:213
Support for drawing Bar charts.
Definition alltypes.h:4