libdap++  Updated for version 3.12.0
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 <pthread.h>
30 
31 #ifdef WIN32
32 #include <io.h> // stat for win32? 09/05/02 jhrg
33 #endif
34 
35 #include <string>
36 #include <vector>
37 #include <map>
38 
39 #ifndef _http_cache_table_h
40 #include "HTTPCacheTable.h"
41 #endif
42 
43 #ifndef _error_h
44 #include "Error.h"
45 #endif
46 
47 #ifndef _internalerr_h
48 #include "InternalErr.h"
49 #endif
50 
51 #ifndef _debug_h
52 #include "debug.h"
53 #endif
54 
55 // The private method HTTPCache::write_body() could, at one time, throw
56 // ResponseTooBig to signal that while writing a response body it was found
57 // to be bigger than the max_entry_size property. But I bagged that; the
58 // garbage collection methods remove entries larger than max_entry_size. It
59 // might be that a really big entry belongs in the cache so long as it
60 // doesn't push other entries out. 10/07/02 jhrg
61 #ifndef _response_too_big_err_h
62 #include "ResponseTooBigErr.h"
63 #endif
64 
65 #ifndef _http_cache_disconnected_mode_h
67 #endif
68 
69 #ifndef _signal_handler_registered_err_h
71 #endif
72 
73 using namespace std;
74 
75 namespace libdap
76 {
77 
78 // This function is exported so the test code can use it too.
79 bool is_hop_by_hop_header(const string &header);
80 
133 {
134 private:
135  string d_cache_root;
136  FILE *d_locked_open_file; // Lock for single process use.
137 
138  bool d_cache_enabled;
139  bool d_cache_protected;
140  CacheDisconnectedMode d_cache_disconnected;
141  bool d_expire_ignored;
142  bool d_always_validate;
143 
144  unsigned long d_total_size; // How much can we store?
145  unsigned long d_folder_size; // How much of that is meta data?
146  unsigned long d_gc_buffer; // How much memory needed as buffer?
147  unsigned long d_max_entry_size; // Max individual entry size.
148  int d_default_expiration;
149 
150  vector<string> d_cache_control;
151  // these are values read from a request-directive Cache-Control header.
152  // Not to be confused with values read from the response or a cached
153  // response (e.g., CacheEntry has a max_age field, too). These fields are
154  // set when the set_cache_control method is called.
155  time_t d_max_age;
156  time_t d_max_stale; // -1: not set, 0:any response, >0 max time.
157  time_t d_min_fresh;
158 
159  // Lock non-const methods (also ones that use the STL).
160  pthread_mutex_t d_cache_mutex;
161 
162  HTTPCacheTable *d_http_cache_table;
163 
164  // d_open_files is used by the interrupt handler to clean up
165  vector<string> d_open_files;
166 
167  static HTTPCache *_instance;
168 
169  friend class HTTPCacheTest; // Unit tests
171 
172  // Private methods
173  HTTPCache(const HTTPCache &) {
174  throw InternalErr(__FILE__, __LINE__, "Unimplemented");
175  }
176  HTTPCache() {
177  throw InternalErr(__FILE__, __LINE__, "Unimplemented");
178  }
179  HTTPCache &operator=(const HTTPCache &) {
180  throw InternalErr(__FILE__, __LINE__, "Unimplemented");
181  }
182 
183  HTTPCache(string cache_root, bool force);
184 
185  static void delete_instance(); // Run by atexit (hence static)
186 
187  void set_cache_root(const string &root = "");
188  void create_cache_root(const string &cache_root);
189 
190  // These will go away when the cache can be used by multiple processes.
191  bool get_single_user_lock(bool force = false);
192  void release_single_user_lock();
193 
194  bool is_url_in_cache(const string &url);
195 
196  // I made these four methods so they could be tested by HTTPCacheTest.
197  // Otherwise they would be static functions. jhrg 10/01/02
198  void write_metadata(const string &cachename, const vector<string> &headers);
199  void read_metadata(const string &cachename, vector<string> &headers);
200  int write_body(const string &cachename, const FILE *src);
201  FILE *open_body(const string &cachename);
202 
203  bool stopGC() const;
204  bool startGC() const;
205 
206  void perform_garbage_collection();
207  void too_big_gc();
208  void expired_gc();
209  void hits_gc();
210 
211 public:
212  static HTTPCache *instance(const string &cache_root, bool force = false);
213  virtual ~HTTPCache();
214 
215  string get_cache_root() const;
216 
217  void set_cache_enabled(bool mode);
218  bool is_cache_enabled() const;
219 
220  void set_cache_disconnected(CacheDisconnectedMode mode);
221  CacheDisconnectedMode get_cache_disconnected() const;
222 
223  void set_expire_ignored(bool mode);
224  bool is_expire_ignored() const;
225 
226  void set_max_size(unsigned long size);
227  unsigned long get_max_size() const;
228 
229  void set_max_entry_size(unsigned long size);
230  unsigned long get_max_entry_size() const;
231 
232  void set_default_expiration(int exp_time);
233  int get_default_expiration() const;
234 
235  void set_always_validate(bool validate);
236  bool get_always_validate() const;
237 
238  void set_cache_control(const vector<string> &cc);
239  vector<string> get_cache_control();
240 
242  DBG(cerr << "Locking interface... ");
243  LOCK(&d_cache_mutex);
244  DBGN(cerr << "Done" << endl);
245  }
247  DBG(cerr << "Unlocking interface... " );
248  UNLOCK(&d_cache_mutex);
249  DBGN(cerr << "Done" << endl);
250  }
251 
252  // This must lock for writing
253  bool cache_response(const string &url, time_t request_time,
254  const vector<string> &headers, const FILE *body);
255  void update_response(const string &url, time_t request_time,
256  const vector<string> &headers);
257 
258  // This is separate from get_cached_response() because often an invalid
259  // cache entry just needs a header update. That is best left to the HTTP
260  // Connection code.
261  bool is_url_valid(const string &url);
262 
263  // Lock these for reading
264  vector<string> get_conditional_request_headers(const string &url);
265  FILE *get_cached_response(const string &url, vector<string> &headers,
266  string &cacheName);
267  FILE *get_cached_response(const string &url, vector<string> &headers);
268  FILE *get_cached_response(const string &url);
269 
270  void release_cached_response(FILE *response);
271 
272  void purge_cache();
273 };
274 
275 } // namespace libdap
276 
277 #endif // _http_cache_h