libdap++ Updated for version 3.8.2
|
00001 00002 // -*- mode: c++; c-basic-offset:4 -*- 00003 00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00005 // Access Protocol. 00006 00007 // Copyright (c) 2002,2008 OPeNDAP, Inc. 00008 // Author: James Gallagher <jgallagher@opendap.org> 00009 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 #ifndef _http_cache_h 00027 #define _http_cache_h 00028 00029 #include <pthread.h> 00030 00031 #ifdef WIN32 00032 #include <io.h> // stat for win32? 09/05/02 jhrg 00033 #endif 00034 00035 #include <string> 00036 #include <vector> 00037 #include <map> 00038 00039 #ifndef _http_cache_table_h 00040 #include "HTTPCacheTable.h" 00041 #endif 00042 00043 #ifndef _error_h 00044 #include "Error.h" 00045 #endif 00046 00047 #ifndef _internalerr_h 00048 #include "InternalErr.h" 00049 #endif 00050 00051 #ifndef _debug_h 00052 #include "debug.h" 00053 #endif 00054 00055 // The private method HTTPCache::write_body() could, at one time, throw 00056 // ResponseTooBig to signal that while writing a response body it was found 00057 // to be bigger than the max_entry_size property. But I bagged that; the 00058 // garbage collection methods remove entries larger than max_entry_size. It 00059 // might be that a really big entry belongs in the cache so long as it 00060 // doesn't push other entries out. 10/07/02 jhrg 00061 #ifndef _response_too_big_err_h 00062 #include "ResponseTooBigErr.h" 00063 #endif 00064 00065 #ifndef _http_cache_disconnected_mode_h 00066 #include "HTTPCacheDisconnectedMode.h" 00067 #endif 00068 00069 #ifndef _signal_handler_registered_err_h 00070 #include "SignalHandlerRegisteredErr.h" 00071 #endif 00072 00073 #define LOCK(m) pthread_mutex_lock((m)) 00074 #define TRYLOCK(m) pthread_mutex_trylock((m)) 00075 #define UNLOCK(m) pthread_mutex_unlock((m)) 00076 #define INIT(m) pthread_mutex_init((m), 0) 00077 #define DESTROY(m) pthread_mutex_destroy((m)) 00078 00079 using namespace std; 00080 00081 namespace libdap 00082 { 00083 00084 // This function is exported so the test code can use it too. 00085 bool is_hop_by_hop_header(const string &header); 00086 00138 class HTTPCache 00139 { 00140 private: 00141 string d_cache_root; 00142 FILE *d_locked_open_file; // Lock for single process use. 00143 00144 bool d_cache_enabled; 00145 bool d_cache_protected; 00146 CacheDisconnectedMode d_cache_disconnected; 00147 bool d_expire_ignored; 00148 bool d_always_validate; 00149 00150 unsigned long d_total_size; // How much can we store? 00151 unsigned long d_folder_size; // How much of that is meta data? 00152 unsigned long d_gc_buffer; // How much memory needed as buffer? 00153 unsigned long d_max_entry_size; // Max individual entry size. 00154 int d_default_expiration; 00155 00156 vector<string> d_cache_control; 00157 // these are values read from a request-directive Cache-Control header. 00158 // Not to be confused with values read from the response or a cached 00159 // response (e.g., CacheEntry has a max_age field, too). These fields are 00160 // set when the set_cache_control method is called. 00161 time_t d_max_age; 00162 time_t d_max_stale; // -1: not set, 0:any response, >0 max time. 00163 time_t d_min_fresh; 00164 00165 // Lock non-const methods (also ones that use the STL). 00166 pthread_mutex_t d_cache_mutex; 00167 00168 HTTPCacheTable *d_http_cache_table; 00169 00170 // d_open_files is used by the interrupt handler to clean up 00171 vector<string> d_open_files; 00172 00173 static HTTPCache *_instance; 00174 00175 friend class HTTPCacheTest; // Unit tests 00176 friend class HTTPCacheInterruptHandler; 00177 00178 // Private methods 00179 HTTPCache(const HTTPCache &) { 00180 throw InternalErr(__FILE__, __LINE__, "Unimplemented"); 00181 } 00182 HTTPCache() { 00183 throw InternalErr(__FILE__, __LINE__, "Unimplemented"); 00184 } 00185 HTTPCache &operator=(const HTTPCache &) { 00186 throw InternalErr(__FILE__, __LINE__, "Unimplemented"); 00187 } 00188 00189 HTTPCache(string cache_root, bool force); 00190 00191 static void delete_instance(); // Run by atexit (hence static) 00192 00193 void set_cache_root(const string &root = ""); 00194 void create_cache_root(const string &cache_root); 00195 00196 // These will go away when the cache can be used by multiple processes. 00197 bool get_single_user_lock(bool force = false); 00198 void release_single_user_lock(); 00199 00200 bool is_url_in_cache(const string &url); 00201 00202 // I made these four methods so they could be tested by HTTPCacheTest. 00203 // Otherwise they would be static functions. jhrg 10/01/02 00204 void write_metadata(const string &cachename, const vector<string> &headers); 00205 void read_metadata(const string &cachename, vector<string> &headers); 00206 int write_body(const string &cachename, const FILE *src); 00207 FILE *open_body(const string &cachename); 00208 00209 bool stopGC() const; 00210 bool startGC() const; 00211 00212 void perform_garbage_collection(); 00213 void too_big_gc(); 00214 void expired_gc(); 00215 void hits_gc(); 00216 00217 public: 00218 static HTTPCache *instance(const string &cache_root, bool force = false); 00219 virtual ~HTTPCache(); 00220 00221 string get_cache_root() const; 00222 00223 void set_cache_enabled(bool mode); 00224 bool is_cache_enabled() const; 00225 00226 void set_cache_disconnected(CacheDisconnectedMode mode); 00227 CacheDisconnectedMode get_cache_disconnected() const; 00228 00229 void set_expire_ignored(bool mode); 00230 bool is_expire_ignored() const; 00231 00232 void set_max_size(unsigned long size); 00233 unsigned long get_max_size() const; 00234 00235 void set_max_entry_size(unsigned long size); 00236 unsigned long get_max_entry_size() const; 00237 00238 void set_default_expiration(int exp_time); 00239 int get_default_expiration() const; 00240 00241 void set_always_validate(bool validate); 00242 bool get_always_validate() const; 00243 00244 void set_cache_control(const vector<string> &cc); 00245 vector<string> get_cache_control(); 00246 00247 void lock_cache_interface() { 00248 DBG(cerr << "Locking interface... "); 00249 LOCK(&d_cache_mutex); 00250 DBGN(cerr << "Done" << endl); 00251 } 00252 void unlock_cache_interface() { 00253 DBG(cerr << "Unlocking interface... " ); 00254 UNLOCK(&d_cache_mutex); 00255 DBGN(cerr << "Done" << endl); 00256 } 00257 00258 // This must lock for writing 00259 bool cache_response(const string &url, time_t request_time, 00260 const vector<string> &headers, const FILE *body); 00261 void update_response(const string &url, time_t request_time, 00262 const vector<string> &headers); 00263 00264 // This is separate from get_cached_response() because often an invalid 00265 // cache entry just needs a header update. That is best left to the HTTP 00266 // Connection code. 00267 bool is_url_valid(const string &url); 00268 00269 // Lock these for reading 00270 vector<string> get_conditional_request_headers(const string &url); 00271 FILE *get_cached_response(const string &url, vector<string> &headers, 00272 string &cacheName); 00273 FILE *get_cached_response(const string &url, vector<string> &headers); 00274 FILE *get_cached_response(const string &url); 00275 00276 void release_cached_response(FILE *response); 00277 00278 void purge_cache(); 00279 }; 00280 00281 } // namespace libdap 00282 00283 #endif // _http_cache_h