libdap++ Updated for version 3.8.2

HTTPCache.h

Go to the documentation of this file.
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