libdap Updated for version 3.21.1
libdap4 is an implementation of OPeNDAP's DAP protocol.
HTTPCache.h
Go to the documentation of this file.
1
2// -*- mode: c++; c-basic-offset:4 -*-
3
4// This file is part of libdap, A C++ implementation of the OPeNDAP Data
5// Access Protocol.
6
7// Copyright (c) 2002,2008 OPeNDAP, Inc.
8// Author: James Gallagher <jgallagher@opendap.org>
9//
10// This library is free software; you can redistribute it and/or
11// modify it under the terms of the GNU Lesser General Public
12// License as published by the Free Software Foundation; either
13// version 2.1 of the License, or (at your option) any later version.
14//
15// This library is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18// Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23//
24// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25
26#ifndef _http_cache_h
27#define _http_cache_h
28
29#include <iostream>
30#include <memory>
31#include <mutex>
32#include <string>
33#include <vector>
34
36
37#define DUMP_FREQUENCY (10) // Dump index every x loads
38
39#define NO_LM_EXPIRATION (24 * 3600) // 24 hours
40
41#define MEGA (0x100000L)
42#define CACHE_TOTAL_SIZE (20) // Default cache size is 20M
43#define CACHE_FOLDER_PCT (10) // 10% of cache size for meta info etc.
44#define CACHE_GC_PCT (10) // 10% of cache size free after GC
45#define MIN_CACHE_TOTAL_SIZE (5) // 5M Min cache size
46#define MAX_CACHE_ENTRY_SIZE (3) // 3M Max size of single cached entry
47
48namespace libdap {
49
50class HTTPCacheTable;
51
52// This function is exported so the test code can use it too.
53bool is_hop_by_hop_header(const std::string &header);
54
106class HTTPCache {
107private:
108 std::string d_cache_root;
109 int d_cache_lock_fd = -1; // Lock for multiprocess use.
110 std::string d_cache_lock_file;
111
112 bool d_cache_enabled = false;
113 bool d_cache_protected = false;
114 CacheDisconnectedMode d_cache_disconnected = DISCONNECT_NONE;
115 bool d_expire_ignored = false;
116 bool d_always_validate = false;
117
118 unsigned long d_total_size = CACHE_TOTAL_SIZE * MEGA; // How much can we store?
119 unsigned long d_folder_size = CACHE_TOTAL_SIZE / CACHE_FOLDER_PCT; // How much of that is metadata?
120 unsigned long d_gc_buffer = CACHE_TOTAL_SIZE / CACHE_GC_PCT; // How much memory needed as buffer?
121 unsigned long d_max_entry_size = MAX_CACHE_ENTRY_SIZE * MEGA; // Max individual entry size.
122 int d_default_expiration = NO_LM_EXPIRATION;
123
124 std::vector<std::string> d_cache_control;
125 // these are values read from a request-directive Cache-Control header.
126 // Not to be confused with values read from the response or a cached
127 // response (e.g., CacheEntry has a max_age field, too). These fields are
128 // set when the set_cache_control method is called.
129 time_t d_max_age = -1;
130 time_t d_max_stale = -1; // -1: not set, 0:any response, >0 max time.
131 time_t d_min_fresh = -1;
132
133 // Lock non-const methods (also ones that use the STL).
134 std::mutex d_cache_mutex;
135
136 HTTPCacheTable *d_http_cache_table = nullptr;
137
138 // d_open_files is used by the interrupt handler to clean up
139 std::vector<std::string> d_open_files;
140
141 void set_cache_root(const std::string &root = "");
142
143 void create_cache_root(const std::string &cache_root) const;
144
145 int m_initialize_cache_lock(const std::string &cache_lock) const;
146
147 static void m_lock_cache_write(int fd);
148
149 static void m_lock_cache_read(int fd);
150
151 static void m_unlock_cache(int fd);
152
153 static void m_exclusive_to_shared_lock(int fd);
154
155 bool is_url_in_cache(const std::string &url);
156
157 // I made these four methods, so they could be tested by HTTPCacheTest.
158 // Otherwise, they would be static functions. jhrg 10/01/02
159 void write_metadata(const std::string &cachename, const std::vector<std::string> &headers);
160
161 void read_metadata(const std::string &cachename, std::vector<std::string> &headers) const;
162
163 int write_body(const std::string &cachename, const FILE *src);
164
165 FILE *open_body(const std::string &cachename);
166
167 bool stopGC() const;
168
169 bool startGC() const;
170
171 void perform_garbage_collection();
172
173 void too_big_gc();
174
175 void expired_gc();
176
177 void hits_gc();
178
179 explicit HTTPCache(const std::string &cache_root);
180
181 friend class HTTPCacheTest; // Unit tests
182 friend class HTTPConnectTest;
183
193 class mp_lock_guard {
194 public:
195 enum class operation { read, write };
196
197 private:
198 int d_fd;
199 bool d_locked = false;
200 bool d_released = false; // Use this so instances can go out of scope without releasing the lock.
201 operation d_op;
202
203 public:
204 mp_lock_guard() = delete;
205
206 mp_lock_guard(const mp_lock_guard &) = delete;
207
208 mp_lock_guard &operator=(const mp_lock_guard &) = delete;
209
210 mp_lock_guard(int fd, operation op) : d_fd(fd), d_op(op) {
211 try {
212 if (d_op == operation::write)
213 HTTPCache::m_lock_cache_write(d_fd);
214 else
215 HTTPCache::m_lock_cache_read(d_fd);
216 d_locked = true;
217 } catch (const std::exception &e) {
218 d_locked = false;
219 // Log this case.
220 std::cerr << "mp_lock_guard::mp_lock_guard() - Failed to lock the cache (" << e.what() << ")."
221 << std::endl;
222 }
223 }
224
225 ~mp_lock_guard() {
226 try {
227 if (!d_released && d_locked) {
228 HTTPCache::m_unlock_cache(d_fd);
229 }
230 } catch (const std::exception &e) {
231 // Log this case.
232 std::cerr << "mp_lock_guard::~mp_lock_guard() - Failed to release the cache lock (" << e.what() << ")."
233 << std::endl;
234 }
235 }
236
237 void release() { d_released = true; }
238 };
239
240public:
241 // Delete the copy constructor and assignment operator to prevent copying
242 HTTPCache() = delete;
243 HTTPCache(const HTTPCache &) = delete;
244 HTTPCache &operator=(const HTTPCache &) = delete;
245
246 virtual ~HTTPCache();
247
268
269 static HTTPCache *instance(const std::string &cache_root = "") {
270 // Create a local static object the first time the function is called
271 static HTTPCache instance(cache_root);
272 return &instance;
273 }
274
275 std::string get_cache_root() const;
276
277 void set_cache_enabled(bool mode);
278
279 bool is_cache_enabled() const;
280
282
284
285 void set_expire_ignored(bool mode);
286
287 bool is_expire_ignored() const;
288
289 void set_max_size(unsigned long size);
290
291 unsigned long get_max_size() const;
292
293 void set_max_entry_size(unsigned long size);
294
295 unsigned long get_max_entry_size() const;
296
297 void set_default_expiration(int exp_time);
298
299 int get_default_expiration() const;
300
301 void set_always_validate(bool validate);
302
303 bool get_always_validate() const;
304
305 void set_cache_control(const std::vector<std::string> &cc);
306
307 std::vector<std::string> get_cache_control() const;
308
309 // This must lock for writing
310 bool cache_response(const std::string &url, time_t request_time, const std::vector<std::string> &headers,
311 const FILE *body);
312
313 void update_response(const std::string &url, time_t request_time, const std::vector<std::string> &headers);
314
315 // This is separate from get_cached_response() because often an invalid
316 // cache entry just needs a header update. That is best left to the HTTP
317 // Connection code.
318 bool is_url_valid(const std::string &url);
319
320 // Lock these for reading
321 std::vector<std::string> get_conditional_request_headers(const std::string &url);
322
323 FILE *get_cached_response(const std::string &url, std::vector<std::string> &headers, std::string &cacheName);
324
325 FILE *get_cached_response(const std::string &url, std::vector<std::string> &headers);
326
327 FILE *get_cached_response(const std::string &url);
328
329 void release_cached_response(FILE *response);
330
331 void purge_cache();
332};
333
334} // namespace libdap
335
336#endif // _http_cache_h
#define CACHE_GC_PCT
Definition HTTPCache.h:44
#define MEGA
Definition HTTPCache.h:41
#define MAX_CACHE_ENTRY_SIZE
Definition HTTPCache.h:46
#define CACHE_FOLDER_PCT
Definition HTTPCache.h:43
#define CACHE_TOTAL_SIZE
Definition HTTPCache.h:42
#define NO_LM_EXPIRATION
Definition HTTPCache.h:39
CacheDisconnectedMode get_cache_disconnected() const
Definition HTTPCache.cc:519
void set_expire_ignored(bool mode)
Definition HTTPCache.cc:529
void set_default_expiration(int exp_time)
Definition HTTPCache.cc:612
bool is_url_valid(const std::string &url)
std::vector< std::string > get_conditional_request_headers(const std::string &url)
Definition HTTPCache.cc:973
std::string get_cache_root() const
Definition HTTPCache.cc:414
void set_cache_disconnected(CacheDisconnectedMode mode)
Definition HTTPCache.cc:511
void release_cached_response(FILE *response)
HTTPCache & operator=(const HTTPCache &)=delete
static HTTPCache * instance(const std::string &cache_root="")
Definition HTTPCache.h:269
HTTPCache(const HTTPCache &)=delete
unsigned long get_max_entry_size() const
Definition HTTPCache.cc:600
void set_cache_enabled(bool mode)
Definition HTTPCache.cc:491
FILE * get_cached_response(const std::string &url, std::vector< std::string > &headers, std::string &cacheName)
friend class HTTPCacheTest
Definition HTTPCache.h:181
unsigned long get_max_size() const
Definition HTTPCache.cc:572
bool cache_response(const std::string &url, time_t request_time, const std::vector< std::string > &headers, const FILE *body)
Definition HTTPCache.cc:898
std::vector< std::string > get_cache_control() const
Definition HTTPCache.cc:682
void set_max_entry_size(unsigned long size)
Definition HTTPCache.cc:582
bool get_always_validate() const
Definition HTTPCache.cc:631
friend class HTTPConnectTest
Definition HTTPCache.h:182
int get_default_expiration() const
Definition HTTPCache.cc:620
void set_always_validate(bool validate)
Definition HTTPCache.cc:626
void update_response(const std::string &url, time_t request_time, const std::vector< std::string > &headers)
void set_max_size(unsigned long size)
Definition HTTPCache.cc:555
bool is_expire_ignored() const
Definition HTTPCache.cc:538
void set_cache_control(const std::vector< std::string > &cc)
Definition HTTPCache.cc:649
virtual ~HTTPCache()
Definition HTTPCache.cc:124
bool is_cache_enabled() const
Definition HTTPCache.cc:499
Lock the cache for writing. Implements RAII for the multi-process write lock for the cache.
top level DAP object to house generic methods
Definition AISConnect.cc:30
bool is_hop_by_hop_header(const string &header)
Definition HTTPCache.cc:715