00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef ns_http_aux_h
00023 #define ns_http_aux_h
00024
00025 #include <tclcl.h>
00026
00027 #include "random.h"
00028 #include "ns-process.h"
00029 #include "pagepool.h"
00030 #include "timer-handler.h"
00031
00032 const int HTTP_HBEXPIRE_COUNT = 5;
00033 const int HTTP_HBINTERVAL = 60;
00034 const int HTTP_UPDATEINTERVAL = 5;
00035
00036 class HttpMInvalCache;
00037
00038
00039 class InvalidationRec {
00040 public:
00041 InvalidationRec(const char *pid, double mtime, char updating = 0) {
00042 pg_ = new char[strlen(pid) + 1];
00043 strcpy(pg_, pid);
00044 mtime_ = mtime;
00045 scount_ = HTTP_HBEXPIRE_COUNT;
00046 updating_ = updating;
00047 next_ = 0, prev_ = 0;
00048 }
00049 virtual ~InvalidationRec() {
00050 delete []pg_;
00051 }
00052
00053 const char* pg() const { return pg_; }
00054 double mtime() const { return mtime_; }
00055 char updating() const { return updating_; }
00056 int scount() const { return scount_; }
00057 InvalidationRec* next() { return next_; }
00058
00059 void reset(double mtime) {
00060 scount_ = HTTP_HBEXPIRE_COUNT;
00061 mtime_ = mtime;
00062 }
00063 int dec_scount() { return --scount_; }
00064 void set_updating() { updating_ = 1; }
00065 void clear_updating() { updating_ = 0; }
00066
00067 void insert(InvalidationRec **head) {
00068 next_ = *head;
00069 if (next_ != 0)
00070 next_->prev_ = &next_;
00071 prev_ = head;
00072 *head = this;
00073 }
00074 void detach() {
00075 if (prev_ != 0)
00076 *prev_ = next_;
00077 if (next_ != 0)
00078 next_->prev_ = prev_;
00079 }
00080
00081 friend class HttpMInvalCache;
00082
00083 protected:
00084 char *pg_;
00085 double mtime_;
00086 char updating_;
00087 int scount_;
00088 InvalidationRec *next_;
00089 InvalidationRec **prev_;
00090 };
00091
00092 class HBTimer : public TimerHandler {
00093 public:
00094 HBTimer(HttpMInvalCache *a, double interval) : TimerHandler() {
00095 a_ = a, interval_ = interval;
00096 }
00097 void set_interval(double interval) { interval_ = interval; }
00098 double get_interval() const { return interval_; }
00099 double next_interval() {
00100 return interval_ * (1 + Random::uniform(-0.1,0.1));
00101 }
00102 void sched() { TimerHandler::sched(interval_); }
00103 void resched() {
00104 TimerHandler::resched(next_interval());
00105 }
00106 protected:
00107 virtual void expire(Event *e);
00108 virtual void handle(Event *e) {
00109 TimerHandler::handle(e);
00110 resched();
00111 }
00112 HttpMInvalCache *a_;
00113 double interval_;
00114 };
00115
00116 class PushTimer : public TimerHandler {
00117 public:
00118 PushTimer(HttpMInvalCache *a, double itv) :
00119 TimerHandler(), a_(a), interval_(itv) {}
00120 void set_interval(double itv) { interval_ = itv; }
00121 double get_interval() const { return interval_; }
00122 void sched() {
00123 TimerHandler::sched(interval_);
00124 }
00125 protected:
00126 virtual void expire(Event *e);
00127 HttpMInvalCache *a_;
00128 double interval_;
00129 };
00130
00131 class LivenessTimer : public TimerHandler {
00132 public:
00133 LivenessTimer(HttpMInvalCache *a, double itv, int nbr) :
00134 TimerHandler(), a_(a), nbr_(nbr), interval_(itv) {}
00135 void sched() { TimerHandler::sched(interval_); }
00136 void resched() { TimerHandler::resched(interval_); }
00137 protected:
00138 virtual void expire(Event *e);
00139 HttpMInvalCache *a_;
00140 int nbr_;
00141 double interval_;
00142 };
00143
00144
00145
00146
00147 const int HTTPDATA_COST = 8;
00148
00149
00150 class HttpData : public AppData {
00151 private:
00152 int id_;
00153
00154 public:
00155 HttpData() : AppData(HTTP_DATA) {}
00156 HttpData(AppDataType t, int d) : AppData(t) { id_ = d; }
00157 HttpData(HttpData& d) : AppData(d) { id_ = d.id_; }
00158
00159 inline int& id() { return id_; }
00160 virtual int size() const { return sizeof(HttpData); }
00161 virtual int cost() const { return HTTPDATA_COST; }
00162 virtual AppData* copy() { return (new HttpData(*this)); }
00163 };
00164
00165
00166
00167
00168 class HttpNormalData : public HttpData {
00169 private:
00170 char *str_;
00171 int strlen_;
00172 int cost_;
00173 public:
00174
00175
00176 HttpNormalData(int id, int cost, const char *str) :
00177 HttpData(HTTP_NORMAL, id) {
00178 if ((str == NULL) || (*str == 0))
00179 strlen_ = 0;
00180 else
00181 strlen_ = strlen(str) + 1;
00182 if (strlen_ > 0) {
00183 str_ = new char[strlen_];
00184 strcpy(str_, str);
00185 } else
00186 str_ = NULL;
00187 cost_ = cost;
00188 }
00189 HttpNormalData(HttpNormalData& d) : HttpData(d) {
00190 cost_ = d.cost_;
00191 strlen_ = d.strlen_;
00192 if (strlen_ > 0) {
00193 str_ = new char[strlen_];
00194 strcpy(str_, d.str_);
00195 } else
00196 str_ = NULL;
00197 }
00198 virtual ~HttpNormalData() {
00199 if (str_ != NULL)
00200 delete []str_;
00201 }
00202
00203 virtual int size() const {
00204
00205 return (sizeof(HttpData)+sizeof(int)+strlen_);
00206 }
00207 virtual int cost() const { return cost_; }
00208 char* str() const { return str_; }
00209 virtual AppData* copy() {
00210 return (new HttpNormalData(*this));
00211 }
00212 };
00213
00214
00215
00216
00217 const int HTTPHBDATA_COST = 32;
00218 const int HTTP_MAXURLLEN = 20;
00219
00220
00221 class HttpHbData : public HttpData {
00222 protected:
00223 struct InvalRec {
00224 char pg_[HTTP_MAXURLLEN];
00225 double mtime_;
00226
00227
00228
00229 int updating_;
00230 void copy(InvalidationRec *v) {
00231 strcpy(pg_, v->pg());
00232 mtime_ = v->mtime();
00233 updating_ = v->updating();
00234 }
00235 InvalidationRec* copyto() {
00236 return (new InvalidationRec(pg_, mtime_, updating_));
00237 }
00238 };
00239
00240 private:
00241 int num_inv_;
00242 InvalRec* inv_rec_;
00243 inline InvalRec* inv_rec() { return inv_rec_; }
00244
00245 public:
00246 HttpHbData(int id, int n) :
00247 HttpData(HTTP_INVALIDATION, id), num_inv_(n) {
00248 if (num_inv_ > 0)
00249 inv_rec_ = new InvalRec[num_inv_];
00250 else
00251 inv_rec_ = NULL;
00252 }
00253 HttpHbData(HttpHbData& d) : HttpData(d) {
00254 num_inv_ = d.num_inv_;
00255 if (num_inv_ > 0) {
00256 inv_rec_ = new InvalRec[num_inv_];
00257 memcpy(inv_rec_, d.inv_rec_,num_inv_*sizeof(InvalRec));
00258 } else
00259 inv_rec_ = NULL;
00260 }
00261 virtual ~HttpHbData() {
00262 if (inv_rec_ != NULL)
00263 delete []inv_rec_;
00264 }
00265
00266 virtual int size() const {
00267 return HttpData::size() + num_inv_*sizeof(InvalRec);
00268 }
00269
00270 virtual int cost() const {
00271
00272 return (num_inv_ == 0) ? 1 : (num_inv_*HTTPHBDATA_COST);
00273 }
00274 virtual AppData* copy() {
00275 return (new HttpHbData(*this));
00276 }
00277
00278 inline int& num_inv() { return num_inv_; }
00279 inline void add(int i, InvalidationRec *r) {
00280 inv_rec()[i].copy(r);
00281 }
00282 inline char* rec_pg(int i) { return inv_rec()[i].pg_; }
00283 inline double& rec_mtime(int i) { return inv_rec()[i].mtime_; }
00284 void extract(InvalidationRec*& ivlist);
00285 };
00286
00287
00288
00289 class HttpUpdateData : public HttpData {
00290 protected:
00291
00292 struct PageRec {
00293 char pg_[HTTP_MAXURLLEN];
00294 double mtime_;
00295 double age_;
00296 int size_;
00297 void copy(ClientPage *p) {
00298 p->name(pg_);
00299 mtime_ = p->mtime();
00300 age_ = p->age();
00301 size_ = p->size();
00302 }
00303 };
00304 private:
00305 int num_;
00306 int pgsize_;
00307 PageRec *rec_;
00308 inline PageRec* rec() { return rec_; }
00309 public:
00310 HttpUpdateData(int id, int n) : HttpData(HTTP_UPDATE, id) {
00311 num_ = n;
00312 pgsize_ = 0;
00313 if (num_ > 0)
00314 rec_ = new PageRec[num_];
00315 else
00316 rec_ = NULL;
00317 }
00318 HttpUpdateData(HttpUpdateData& d) : HttpData(d) {
00319 num_ = d.num_;
00320 pgsize_ = d.pgsize_;
00321 if (num_ > 0) {
00322 rec_ = new PageRec[num_];
00323 memcpy(rec_, d.rec_, num_*sizeof(PageRec));
00324 } else
00325 rec_ = NULL;
00326 }
00327 virtual ~HttpUpdateData() {
00328 if (rec_ != NULL)
00329 delete []rec_;
00330 }
00331
00332 virtual int size() const {
00333 return HttpData::size() + 2*sizeof(int)+num_*sizeof(PageRec);
00334 }
00335 virtual int cost() const { return pgsize_; }
00336 virtual AppData* copy() {
00337 return (new HttpUpdateData(*this));
00338 }
00339
00340 inline int num() const { return num_; }
00341 inline int pgsize() const { return pgsize_; }
00342
00343 inline void set_pgsize(int s) { pgsize_ = s; }
00344 inline void add(int i, ClientPage *p) {
00345 rec()[i].copy(p);
00346 pgsize_ += p->size();
00347 }
00348
00349 inline char* rec_page(int i) { return rec()[i].pg_; }
00350 inline int& rec_size(int i) { return rec()[i].size_; }
00351 inline double& rec_age(int i) { return rec()[i].age_; }
00352 inline double& rec_mtime(int i) { return rec()[i].mtime_; }
00353 };
00354
00355
00356
00357 const int HTTPLEAVE_COST = 4;
00358
00359
00360 class HttpLeaveData : public HttpData {
00361 private:
00362 int num_;
00363 int* rec_;
00364 inline int* rec() { return rec_; }
00365 public:
00366 HttpLeaveData(int id, int n) : HttpData(HTTP_LEAVE, id) {
00367 num_ = n;
00368 if (num_ > 0)
00369 rec_ = new int[num_];
00370 else
00371 rec_ = NULL;
00372 }
00373 HttpLeaveData(HttpLeaveData& d) : HttpData(d) {
00374 num_ = d.num_;
00375 if (num_ > 0) {
00376 rec_ = new int[num_];
00377 memcpy(rec_, d.rec_, num_*sizeof(int));
00378 } else
00379 rec_ = NULL;
00380 }
00381 virtual ~HttpLeaveData() {
00382 if (rec_ != NULL)
00383 delete []rec_;
00384 }
00385
00386 virtual int size() const {
00387 return HttpData::size() + (num_+1)*sizeof(int);
00388 }
00389 virtual int cost() const { return num_*HTTPLEAVE_COST; }
00390 virtual AppData* copy() {
00391 return (new HttpLeaveData(*this));
00392 }
00393
00394 inline int num() const { return num_; }
00395 inline void add(int i, int id) {
00396 rec()[i] = id;
00397 }
00398 inline int rec_id(int i) { return rec()[i]; }
00399 };
00400
00401
00402
00403 class NeighborCache {
00404 public:
00405 NeighborCache(HttpMInvalCache*c, double t, LivenessTimer *timer) :
00406 cache_(c), time_(t), down_(0), timer_(timer) {}
00407 ~NeighborCache();
00408
00409 double time() { return time_; }
00410 void reset_timer(double time) {
00411 time_ = time, timer_->resched();
00412 }
00413 int is_down() { return down_; }
00414 void down() { down_ = 1; }
00415 void up() { down_ = 0; }
00416 int num() const { return sl_.num(); }
00417 HttpMInvalCache* cache() { return cache_; }
00418 void pack_leave(HttpLeaveData&);
00419 int is_server_down(int sid);
00420 void server_down(int sid);
00421 void server_up(int sid);
00422 void invalidate(HttpMInvalCache *c);
00423 void add_server(int sid);
00424
00425
00426 struct ServerEntry {
00427 ServerEntry(int sid) : server_(sid), next_(NULL), down_(0) {}
00428 int server() { return server_; }
00429 ServerEntry* next() { return next_; }
00430 int is_down() { return down_; }
00431 void down() { down_ = 1; }
00432 void up() { down_ = 0; }
00433
00434 int server_;
00435 ServerEntry *next_;
00436 int down_;
00437 };
00438
00439 struct ServerList {
00440 ServerList() : head_(NULL), num_(0) {}
00441 void insert(ServerEntry *s) {
00442 s->next_ = head_;
00443 head_ = s;
00444 num_++;
00445 }
00446
00447 ServerEntry* gethead() { return head_; }
00448 int num() const { return num_; }
00449 ServerEntry *head_;
00450 int num_;
00451 };
00452
00453 protected:
00454 HttpMInvalCache* cache_;
00455 double time_;
00456 int down_;
00457 ServerList sl_;
00458 LivenessTimer *timer_;
00459 };
00460
00461 #endif // ns_http_aux_h