00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef _http_cache_table_h
00027 #define _http_cache_table_h
00028
00029
00030
00031 #include <pthread.h>
00032
00033 #ifdef WIN32
00034 #include <io.h>
00035 #endif
00036
00037 #include <string>
00038 #include <vector>
00039 #include <map>
00040
00041 #ifndef _error_h
00042 #include "Error.h"
00043 #endif
00044
00045 #ifndef _internalerr_h
00046 #include "InternalErr.h"
00047 #endif
00048
00049 #ifndef _debug_h
00050 #include "debug.h"
00051 #endif
00052
00053 #define LOCK(m) pthread_mutex_lock((m))
00054 #define TRYLOCK(m) pthread_mutex_trylock((m))
00055 #define UNLOCK(m) pthread_mutex_unlock((m))
00056 #define INIT(m) pthread_mutex_init((m), 0)
00057 #define DESTROY(m) pthread_mutex_destroy((m))
00058
00059 using namespace std;
00060
00061 namespace libdap
00062 {
00063
00064 int get_hash(const string &url);
00065
00081 class HTTPCacheTable {
00082 public:
00094 struct CacheEntry
00095 {
00096 private:
00097 string url;
00098 int hash;
00099 int hits;
00100 string cachename;
00101
00102 string etag;
00103 time_t lm;
00104 time_t expires;
00105 time_t date;
00106 time_t age;
00107 time_t max_age;
00108
00109 unsigned long size;
00110 bool range;
00111
00112 time_t freshness_lifetime;
00113 time_t response_time;
00114 time_t corrected_initial_age;
00115
00116 bool must_revalidate;
00117 bool no_cache;
00118
00119 int readers;
00120 pthread_mutex_t d_response_lock;
00121 pthread_mutex_t d_response_write_lock;
00122
00123
00124 friend class HTTPCacheTable;
00125 friend class HTTPCacheTest;
00126
00127
00128 friend class DeleteCacheEntry;
00129 friend class WriteOneCacheEntry;
00130 friend class DeleteExpired;
00131 friend class DeleteByHits;
00132 friend class DeleteBySize;
00133
00134 public:
00135 string get_cachename() {
00136 return cachename;
00137 }
00138 string get_etag() {
00139 return etag;
00140 }
00141 time_t get_lm() {
00142 return lm;
00143 }
00144 time_t get_expires() {
00145 return expires;
00146 }
00147 time_t get_max_age() {
00148 return max_age;
00149 }
00150 void set_size(unsigned long sz) {
00151 size = sz;
00152 }
00153 time_t get_freshness_lifetime() {
00154 return freshness_lifetime;
00155 }
00156 time_t get_response_time() {
00157 return response_time;
00158 }
00159 time_t get_corrected_initial_age() {
00160 return corrected_initial_age;
00161 }
00162 bool get_must_revalidate() {
00163 return must_revalidate;
00164 }
00165 void set_no_cache(bool state) {
00166 no_cache = state;
00167 }
00168 bool is_no_cache() { return no_cache; }
00169
00170 void lock_read_response() {
00171 DBG(cerr << "Try locking read response... (" << hex << &d_response_lock << dec << ") ");
00172 int status = TRYLOCK(&d_response_lock);
00173 if (status != 0 ) {
00174
00175 LOCK(&d_response_write_lock);
00176 UNLOCK(&d_response_write_lock);
00177 }
00178 DBGN(cerr << "Done" << endl);
00179 readers++;
00180 }
00181
00182 void unlock_read_response() {
00183 readers--;
00184 if (readers == 0) {
00185 DBG(cerr << "Unlocking read response... (" << hex << &d_response_lock << dec << ") ");
00186 UNLOCK(&d_response_lock);
00187 DBGN(cerr << "Done" << endl);
00188 }
00189 }
00190
00191 void lock_write_response() {
00192 DBG(cerr << "locking write response... (" << hex << &d_response_lock << dec << ") ");
00193 LOCK(&d_response_lock);
00194 LOCK(&d_response_write_lock);
00195 DBGN(cerr << "Done" << endl);
00196 }
00197
00198 void unlock_write_response() {
00199 DBG(cerr << "Unlocking write response... (" << hex << &d_response_lock << dec << ") ");
00200 UNLOCK(&d_response_write_lock);
00201 UNLOCK(&d_response_lock);
00202 DBGN(cerr << "Done" << endl);
00203 }
00204
00205 CacheEntry() :
00206 url(""), hash(-1), hits(0), cachename(""), etag(""), lm(-1),
00207 expires(-1), date(-1), age(-1), max_age(-1), size(0),
00208 range(false), freshness_lifetime(0), response_time(0),
00209 corrected_initial_age(0), must_revalidate(false),
00210 no_cache(false), readers(0) {
00211 INIT(&d_response_lock);
00212 INIT(&d_response_write_lock);
00213 }
00214 CacheEntry(const string &u) :
00215 url(u), hash(-1), hits(0), cachename(""), etag(""), lm(-1),
00216 expires(-1), date(-1), age(-1), max_age(-1), size(0),
00217 range(false), freshness_lifetime(0), response_time(0),
00218 corrected_initial_age(0), must_revalidate(false),
00219 no_cache(false), readers(0) {
00220 INIT(&d_response_lock);
00221 INIT(&d_response_write_lock);
00222 hash = get_hash(url);
00223 }
00224 };
00225
00226
00227
00228
00229
00230
00231 typedef vector<CacheEntry *> CacheEntries;
00232 typedef CacheEntries::iterator CacheEntriesIter;
00233
00234 typedef CacheEntries **CacheTable;
00235
00236 friend class HTTPCacheTest;
00237
00238 private:
00239 CacheTable d_cache_table;
00240
00241 string d_cache_root;
00242 unsigned int d_block_size;
00243 unsigned long d_current_size;
00244
00245 string d_cache_index;
00246 int d_new_entries;
00247
00248 map<FILE *, HTTPCacheTable::CacheEntry *> d_locked_entries;
00249
00250
00251 HTTPCacheTable(const HTTPCacheTable &) {
00252 throw InternalErr(__FILE__, __LINE__, "unimplemented");
00253 }
00254
00255 HTTPCacheTable &operator=(const HTTPCacheTable &) {
00256 throw InternalErr(__FILE__, __LINE__, "unimplemented");
00257 }
00258
00259 HTTPCacheTable() {
00260 throw InternalErr(__FILE__, __LINE__, "unimplemented");
00261 }
00262
00263 CacheTable &get_cache_table() { return d_cache_table; }
00264 CacheEntry *get_locked_entry_from_cache_table(int hash, const string &url);
00265
00266 public:
00267 HTTPCacheTable(const string &cache_root, int block_size);
00268 ~HTTPCacheTable();
00269
00271 unsigned long get_current_size() const { return d_current_size; }
00272 void set_current_size(unsigned long sz) { d_current_size = sz; }
00273
00274 unsigned int get_block_size() const { return d_block_size; }
00275 void set_block_size(unsigned int sz) { d_block_size = sz; }
00276
00277 int get_new_entries() const { return d_new_entries; }
00278 void increment_new_entries() { ++d_new_entries; }
00279
00280 string get_cache_root() { return d_cache_root; }
00281 void set_cache_root(const string &cr) { d_cache_root = cr; }
00283
00284 void delete_expired_entries(time_t time = 0);
00285 void delete_by_hits(int hits);
00286 void delete_by_size(unsigned int size);
00287 void delete_all_entries();
00288
00289 bool cache_index_delete();
00290 bool cache_index_read();
00291 CacheEntry *cache_index_parse_line(const char *line);
00292 void cache_index_write();
00293
00294 string create_hash_directory(int hash);
00295 void create_location(CacheEntry *entry);
00296
00297 void add_entry_to_cache_table(CacheEntry *entry);
00298 void remove_cache_entry(HTTPCacheTable::CacheEntry *entry);
00299
00300 void remove_entry_from_cache_table(const string &url);
00301 CacheEntry *get_locked_entry_from_cache_table(const string &url);
00302 CacheEntry *get_write_locked_entry_from_cache_table(const string &url);
00303
00304 void calculate_time(HTTPCacheTable::CacheEntry *entry,
00305 int default_expiration, time_t request_time);
00306 void parse_headers(HTTPCacheTable::CacheEntry *entry,
00307 unsigned long max_entry_size, const vector<string> &headers);
00308
00309
00310 void bind_entry_to_data(CacheEntry *entry, FILE *body);
00311 void uncouple_entry_from_data(FILE *body);
00312 bool is_locked_read_responses();
00313 };
00314
00315 }
00316 #endif