• Main Page
  • Classes
  • Files
  • File List

/Users/yzchen/ns/ns-allinone-2.33/ns-2.33/webcache/http-aux.h

00001 /*
00002  * Copyright (c) Xerox Corporation 1998. All rights reserved.
00003  *
00004  * This program is free software; you can redistribute it and/or modify it
00005  * under the terms of the GNU General Public License as published by the
00006  * Free Software Foundation; either version 2 of the License, or (at your
00007  * option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License along
00015  * with this program; if not, write to the Free Software Foundation, Inc.,
00016  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  *
00018  * Linking this file statically or dynamically with other modules is making
00019  * a combined work based on this file.  Thus, the terms and conditions of
00020  * the GNU General Public License cover the whole combination.
00021  *
00022  * In addition, as a special exception, the copyright holders of this file
00023  * give you permission to combine this file with free software programs or
00024  * libraries that are released under the GNU LGPL and with code included in
00025  * the standard release of ns-2 under the Apache 2.0 license or under
00026  * otherwise-compatible licenses with advertising requirements (or modified
00027  * versions of such code, with unchanged license).  You may copy and
00028  * distribute such a system following the terms of the GNU GPL for this
00029  * file and the licenses of the other code concerned, provided that you
00030  * include the source code of that other code when and as the GNU GPL
00031  * requires distribution of source code.
00032  *
00033  * Note that people who make modified versions of this file are not
00034  * obligated to grant this special exception for their modified versions;
00035  * it is their choice whether to do so.  The GNU General Public License
00036  * gives permission to release a modified version without this exception;
00037  * this exception also makes it possible to release a modified version
00038  * which carries forward this exception.
00039  *
00040  * $Header: /cvsroot/nsnam/ns-2/webcache/http-aux.h,v 1.17 2005/08/26 05:05:31 tomh Exp $
00041  */
00042 
00043 //
00044 // Auxiliary classes for HTTP multicast invalidation proxy cache
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; // How many lost HBs mean disconnection?
00058 const int HTTP_HBINTERVAL       = 60;// Heartbeat intervals (seconds)
00059 const int HTTP_UPDATEINTERVAL   = 5; // Delays to push/v1 (seconds)
00060 
00061 class HttpMInvalCache;
00062 
00063 // Used for caches to keep track of invalidations
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_; // 1 if an update is going to be sent soon
00112         int scount_;    // Times that an invalidation needs to be multicast
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_;    // The cache to be alerted
00165         int nbr_;               // Neighbor cache id
00166         double interval_;
00167 };
00168 
00169 
00170 // XXX ADU defined in app-connector.h
00171 
00172 const int HTTPDATA_COST         = 8;
00173 
00174 // User-level packets
00175 class HttpData : public AppData {
00176 private:
00177         int id_;        // ID of the sender
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 // HTTP data during normal request and response: containing a tcl command
00193 class HttpNormalData : public HttpData {
00194 private: 
00195         char *str_;
00196         int strlen_;
00197         int cost_;
00198 public:
00199         // XXX Whoever sends data should allocate memory to store the string.
00200         // Whoever receives this object should delete it to free the string.
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                 // Intentially use sizeof(int) instead of 2*sizeof(int)
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 // XXX assign cost to a constant so as to be more portable
00242 const int HTTPHBDATA_COST = 32;
00243 const int HTTP_MAXURLLEN = 20;
00244 
00245 // Struct used to pack invalidation records into packets
00246 class HttpHbData : public HttpData {
00247 protected:
00248         struct InvalRec {
00249                 char pg_[HTTP_MAXURLLEN];       // Maximum page id length
00250                 double mtime_;
00251                 // Used only to mark that this page will be send in the 
00252                 // next multicast update. The updating field in this agent 
00253                 // will only be set after it gets the real update.
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         // XXX byte cost to appear in trace file
00295         virtual int cost() const { 
00296                 // Minimum size 1 so that TCP will send a packet
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         // Pack page updates to be pushed to caches
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 // Message: server leave
00385 class HttpLeaveData : public HttpData {
00386 private:
00387         int num_;
00388         int* rec_; // array of server ids which are out of contact
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 // Auxliary class
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         // Maintaining neighbor cache timeout entries
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         // We cannot use template. :(((
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                 // We don't need a detach()
00472                 ServerEntry* gethead() { return head_; } // For iterations
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

Generated on Tue Aug 10 2010 16:16:09 for ns-2.33 by  doxygen 1.7.1