Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

http-aux.h

Go to the documentation of this file.
00001 // Copyright (c) Xerox Corporation 1998. All rights reserved.
00002 //
00003 // License is granted to copy, to use, and to make and to use derivative
00004 // works for research and evaluation purposes, provided that Xerox is
00005 // acknowledged in all documentation pertaining to any such copy or
00006 // derivative work. Xerox grants no other licenses expressed or
00007 // implied. The Xerox trade name should not be used in any advertising
00008 // without its written permission. 
00009 //
00010 // XEROX CORPORATION MAKES NO REPRESENTATIONS CONCERNING EITHER THE
00011 // MERCHANTABILITY OF THIS SOFTWARE OR THE SUITABILITY OF THIS SOFTWARE
00012 // FOR ANY PARTICULAR PURPOSE.  The software is provided "as is" without
00013 // express or implied warranty of any kind.
00014 //
00015 // These notices must be retained in any copies of any part of this
00016 // software. 
00017 //
00018 // Auxiliary classes for HTTP multicast invalidation proxy cache
00019 //
00020 // $Header: /nfs/jade/vint/CVSROOT/ns-2/webcache/http-aux.h,v 1.16 1999/09/08 20:27:37 haoboy Exp $
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; // How many lost HBs mean disconnection?
00033 const int HTTP_HBINTERVAL       = 60;// Heartbeat intervals (seconds)
00034 const int HTTP_UPDATEINTERVAL   = 5; // Delays to push/v1 (seconds)
00035 
00036 class HttpMInvalCache;
00037 
00038 // Used for caches to keep track of invalidations
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_; // 1 if an update is going to be sent soon
00087         int scount_;    // Times that an invalidation needs to be multicast
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_;    // The cache to be alerted
00140         int nbr_;               // Neighbor cache id
00141         double interval_;
00142 };
00143 
00144 
00145 // XXX ADU defined in app-connector.h
00146 
00147 const int HTTPDATA_COST         = 8;
00148 
00149 // User-level packets
00150 class HttpData : public AppData {
00151 private:
00152         int id_;        // ID of the sender
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 // HTTP data during normal request and response: containing a tcl command
00168 class HttpNormalData : public HttpData {
00169 private: 
00170         char *str_;
00171         int strlen_;
00172         int cost_;
00173 public:
00174         // XXX Whoever sends data should allocate memory to store the string.
00175         // Whoever receives this object should delete it to free the string.
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                 // Intentially use sizeof(int) instead of 2*sizeof(int)
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 // XXX assign cost to a constant so as to be more portable
00217 const int HTTPHBDATA_COST = 32;
00218 const int HTTP_MAXURLLEN = 20;
00219 
00220 // Struct used to pack invalidation records into packets
00221 class HttpHbData : public HttpData {
00222 protected:
00223         struct InvalRec {
00224                 char pg_[HTTP_MAXURLLEN];       // Maximum page id length
00225                 double mtime_;
00226                 // Used only to mark that this page will be send in the 
00227                 // next multicast update. The updating field in this agent 
00228                 // will only be set after it gets the real update.
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         // XXX byte cost to appear in trace file
00270         virtual int cost() const { 
00271                 // Minimum size 1 so that TCP will send a packet
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         // Pack page updates to be pushed to caches
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 // Message: server leave
00360 class HttpLeaveData : public HttpData {
00361 private:
00362         int num_;
00363         int* rec_; // array of server ids which are out of contact
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 // Auxliary class
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         // Maintaining neighbor cache timeout entries
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         // We cannot use template. :(((
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                 // We don't need a detach()
00447                 ServerEntry* gethead() { return head_; } // For iterations
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

Generated on Tue Apr 20 12:14:19 2004 for NS2.26SourcesOriginal by doxygen 1.3.3