http-aux.h

Go to the documentation of this file.
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: /nfs/jade/vint/CVSROOT/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 Mar 6 16:47:45 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6