Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / nel / src / gui / http_cache.cpp
blob245ffbe20bc79d437e9c87ec72b09e12831e9841
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2017 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "stdpch.h"
18 #include "nel/gui/http_cache.h"
20 using namespace std;
21 using namespace NLMISC;
23 #ifdef DEBUG_NEW
24 #define new DEBUG_NEW
25 #endif
27 #if defined(GCC_VERSION) && !defined(CLANG_VERSION) && defined(NL_ISO_CPP0X_AVAILABLE) && (GCC_VERSION <= 40804)
28 // hack to fix std::map::erase wrong return type (void instead of iterator in C++11) in GCC 4.8.4
29 #undef NL_ISO_CPP0X_AVAILABLE
30 #endif
32 namespace NLGUI
34 CHttpCache* CHttpCache::instance = NULL;
36 CHttpCache* CHttpCache::getInstance()
38 if (!instance)
40 instance = new CHttpCache();
43 return instance;
46 void CHttpCache::release()
48 delete instance;
49 instance = NULL;
52 CHttpCache::CHttpCache()
53 : _Initialized(false)
54 , _MaxObjects(100)
55 { };
57 CHttpCache::~CHttpCache()
59 flushCache();
62 void CHttpCache::setCacheIndex(const std::string& fname)
64 _IndexFilename = fname;
65 _Initialized = false;
68 CHttpCacheObject CHttpCache::lookup(const std::string& fname)
70 if (!_Initialized)
71 init();
73 if (_List.count(fname) > 0)
74 return _List[fname];
76 return CHttpCacheObject();
79 void CHttpCache::store(const std::string& fname, const CHttpCacheObject& data)
81 if (!_Initialized)
82 init();
84 _List[fname] = data;
87 void CHttpCache::init()
89 if (_Initialized)
90 return;
92 _Initialized = true;
94 if (_IndexFilename.empty() || !CFile::fileExists(_IndexFilename))
95 return;
97 CIFile in;
98 if (!in.open(_IndexFilename)) {
99 nlwarning("Unable to open %s for reading", _IndexFilename.c_str());
100 return;
103 serial(in);
106 void CHttpCacheObject::serial(NLMISC::IStream& f)
108 f.serialVersion(1);
109 f.serial(Expires);
110 f.serial(LastModified);
111 f.serial(Etag);
114 void CHttpCache::serial(NLMISC::IStream& f)
116 // saved state is ignored when version checks fail
117 try {
118 f.serialVersion(1);
120 // CacheIdx
121 f.serialCheck(NELID("hcaC"));
122 f.serialCheck(NELID("xdIe"));
124 if (f.isReading())
126 uint32 numFiles;
127 f.serial(numFiles);
129 _List.clear();
130 for (uint k = 0; k < numFiles; ++k)
132 std::string fname;
133 f.serial(fname);
135 CHttpCacheObject obj;
136 obj.serial(f);
138 _List[fname] = obj;
141 else
143 uint32 numFiles = _List.size();
144 f.serial(numFiles);
146 for (THttpCacheMap::iterator it = _List.begin(); it != _List.end(); ++it)
148 std::string fname(it->first);
149 f.serial(fname);
151 (*it).second.serial(f);
154 } catch (...) {
155 _List.clear();
156 nlwarning("Invalid cache index format (%s)", _IndexFilename.c_str());
157 return;
161 void CHttpCache::pruneCache()
163 if (_List.size() < _MaxObjects)
164 return;
166 size_t mustDrop = _List.size() - _MaxObjects;
168 time_t currentTime;
169 time(&currentTime);
171 // if we over object limit, then start removing expired objects
172 // this does not guarantee that max limit is reached
173 for (THttpCacheMap::iterator it = _List.begin(); it != _List.end();)
175 if (it->second.Expires <= currentTime)
177 #ifdef NL_ISO_CPP0X_AVAILABLE
178 it = _List.erase(it);
179 #else
180 THttpCacheMap::iterator itToErase = it++;
181 _List.erase(itToErase);
182 #endif
184 --mustDrop;
185 if (mustDrop == 0)
186 break;
188 else
190 ++it;
195 void CHttpCache::flushCache()
197 if (_IndexFilename.empty())
198 return;
200 pruneCache();
202 COFile out;
203 if (!out.open(_IndexFilename))
205 nlwarning("Unable to open %s for writing", _IndexFilename.c_str());
206 return;
209 serial(out);
210 out.close();