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