pagepool.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/pagepool.h,v 1.17 2005/09/18 23:33:35 tomh Exp $
00041  *
00042  */
00043 //
00044 // Definitions for class PagePool
00045 //
00046 
00047 #ifndef ns_pagepool_h
00048 #define ns_pagepool_h
00049 
00050 #include <stdio.h>
00051 #include <limits.h>
00052 #include <tcl.h>
00053 #include <ranvar.h>
00054 #include <tclcl.h>
00055 #include "config.h"
00056 
00057 enum WebPageType { HTML, MEDIA };
00058 
00059 class Page {
00060 public:
00061     Page(int size) : size_(size) {}
00062     virtual ~Page () {}
00063     int size() const { return size_; }
00064     int& id() { return id_; }
00065     virtual WebPageType type() const = 0;   // Page type: HTML or MEDIA
00066 
00067 protected:
00068     int size_;
00069     int id_;
00070 };
00071 
00072 class ServerPage : public Page {
00073 public:
00074     ServerPage(int size, int id) : Page(size) {
00075         id_ = id, mtime_ = NULL, num_mtime_ = 0;
00076     }
00077     virtual ~ServerPage() {
00078         if (mtime_ != NULL) 
00079             delete []mtime_;
00080     }
00081 
00082     virtual WebPageType type() const { return HTML; }
00083 
00084     int& size() { return size_; }
00085     int& mtime(int n) { return mtime_[n]; }
00086     int& num_mtime() { return num_mtime_; }
00087     void set_mtime(int *mt, int n);
00088 
00089 protected:
00090     int *mtime_;
00091     int num_mtime_;
00092 };
00093 
00094 class HttpApp;
00095 
00096 // Page states
00097 const int HTTP_PAGE_STATE_MASK  = 0x00FF;
00098 const int HTTP_ALL_PAGE_STATES  = 0x00ff; // all page states
00099 const int HTTP_VALID_PAGE   = 0x01; // Valid page
00100 const int HTTP_SERVER_DOWN  = 0x02; // Server is down. Don't know if 
00101                     // page is valid
00102 const int HTTP_VALID_HEADER = 0x04; // Only meta-data is valid
00103 const int HTTP_UNREAD_PAGE  = 0x08; // Unread valid page
00104 
00105 // Used only for server to manage its pages. A none-cacheable page won't be 
00106 // stored by caches and clients.
00107 const int HTTP_UNCACHEABLE  = 0x10; // Non-cacheable page
00108 
00109 // Page actions
00110 const int HTTP_PAGE_ACTION_MASK = 0xFF00; // Page action bit mask
00111 const int HTTP_MANDATORY_PUSH   = 0x1000; // If the page is mandatory pushed
00112 
00113 struct PageID {
00114     PageID() : s_(NULL), id_(0) {}
00115         PageID(int *buffer) {
00116             PageID *realBuffer = reinterpret_cast <PageID *> (buffer);
00117         s_ = realBuffer->s_;
00118         id_ = realBuffer->id_;
00119     }
00120     PageID(HttpApp *app, int id) {
00121         s_ = app;
00122         id_ = id;
00123     }
00124     HttpApp* s_;
00125     int id_;
00126 };
00127 
00128 class ClientPage : public Page {
00129 public:
00130     ClientPage(const char *n, int s, double mt, double et, double a);
00131     virtual ~ClientPage() {}
00132 
00133     virtual WebPageType type() const { return HTML; }
00134     virtual void print_info(char* buf);
00135 
00136     void name(char* buf);
00137     double& mtime() { return mtime_; }
00138     double& etime() { return etime_; }
00139     double& age() { return age_; }
00140     HttpApp* server() { return server_; }
00141 
00142     // Page becomes valid. Clear all other possible invalid bits
00143     void validate(double mtime) { 
00144         if (mtime_ >= mtime)
00145             abort(); // This shouldn't happen!
00146         // Clear server down bit
00147         clear_page_state(HTTP_SERVER_DOWN);
00148         set_page_state(HTTP_VALID_PAGE);
00149         mtime_ = mtime;
00150     }
00151     void invalidate(double mtime) { 
00152         if (mtime_ >= mtime)
00153             return;
00154         clear_page_state(HTTP_VALID_PAGE);
00155         clear_page_state(HTTP_VALID_HEADER);
00156         mtime_ = mtime;
00157     }
00158     int is_valid() const { 
00159         return (status_ & HTTP_VALID_PAGE);
00160     }
00161     int is_header_valid() const {
00162         return ((status_ & HTTP_VALID_PAGE) || 
00163             (status_ & HTTP_VALID_HEADER));
00164     }
00165     inline void set_valid_hdr() { 
00166         // XXX page invalid, but only header valid
00167         clear_page_state(HTTP_SERVER_DOWN);
00168         clear_page_state(HTTP_VALID_PAGE);
00169         set_page_state(HTTP_VALID_HEADER); 
00170     }
00171 
00172     inline void set_uncacheable() { 
00173         set_page_state(HTTP_UNCACHEABLE);
00174     }
00175     inline int is_uncacheable() {
00176         return (status_ & HTTP_UNCACHEABLE);
00177     }
00178 
00179     // Has nothing to do with valid/invalid/server_down etc. It can 
00180     // be combined with all other page status
00181     inline void set_unread() { 
00182         set_page_state(HTTP_UNREAD_PAGE); 
00183     }
00184     inline void set_read() { 
00185         clear_page_state(HTTP_UNREAD_PAGE);
00186     }
00187     inline int is_unread() { return (status_ & HTTP_UNREAD_PAGE); }
00188 
00189     inline int is_server_down() { return (status_ & HTTP_SERVER_DOWN); }
00190     inline void server_down() {
00191         // Set page as invalid
00192         // Don't change mtime, only change page status
00193         clear_page_state(HTTP_VALID_PAGE);
00194         clear_page_state(HTTP_VALID_HEADER);
00195         set_page_state(HTTP_SERVER_DOWN);
00196     }
00197 
00198     // Flags to indicate whether we want to do all push or selective push
00199     // If 0: selective push, otherwise all push
00200     static int PUSHALL_; 
00201     inline int& counter() { 
00202         if (PUSHALL_) counter_ = INT_MAX;
00203         return counter_;
00204     }
00205     inline int count_inval(int a, int th) { 
00206         if (PUSHALL_) 
00207             return INT_MAX;
00208         else {
00209             counter_ -= a; 
00210             if (counter_ < th) 
00211                 counter_ = th;
00212             return counter_; 
00213         }
00214     }
00215     inline int count_request(int b, int th) { 
00216         if (PUSHALL_) 
00217             return INT_MAX;
00218         else {
00219             counter_ += b; 
00220             if (counter_ > th) 
00221                 counter_ = th;
00222             return counter_; 
00223         }
00224     }
00225     inline void set_mpush(double time) { 
00226         set_page_action(HTTP_MANDATORY_PUSH), mpushTime_ = time; 
00227     }
00228     inline void clear_mpush() { clear_page_action(HTTP_MANDATORY_PUSH); }
00229     inline int is_mpush() { return status_ & HTTP_MANDATORY_PUSH; }
00230     inline double mpush_time() { return mpushTime_; }
00231 
00232     // Used to split page names into page identifiers
00233     static void split_name(const char* name, PageID& id);
00234     static void print_name(char* name, PageID& id);
00235 
00236 protected:
00237     void set_page_state(int state) {
00238         status_ |= state;
00239     }
00240     void clear_page_state(int state) {
00241         status_ = status_ & ~state;
00242     }
00243     void set_page_action(int action) {
00244         status_ |= action;
00245     }
00246     void clear_page_action(int action) {
00247         status_ = status_ & ~action;
00248     }
00249 
00250     HttpApp* server_;
00251     double age_;
00252     double mtime_;  // modification time
00253     double etime_;  // entry time
00254     int status_;    // VALID or INVALID
00255     int counter_;   // counter for invalidation & request
00256     double mpushTime_;
00257 };
00258 
00259 
00260 // Abstract page pool, used for interface only
00261 class PagePool : public TclObject {
00262 public: 
00263     PagePool() : num_pages_(0), start_time_(INT_MAX), end_time_(INT_MIN) {}
00264     int num_pages() const { return num_pages_; }
00265 protected:
00266     virtual int command(int argc, const char*const* argv);
00267     int num_pages_;
00268     double start_time_;
00269     double end_time_;
00270     int duration_;
00271 
00272     // Helper functions
00273     TclObject* lookup_obj(const char* name) {
00274         TclObject* obj = Tcl::instance().lookup(name);
00275         if (obj == NULL) 
00276             fprintf(stderr, "Bad object name %s\n", name);
00277         return obj;
00278     }
00279 };
00280 
00281 // Page pool based on real server traces
00282 
00283 const int TRACEPAGEPOOL_MAXBUF = 4096;
00284 
00285 // This trace must contain web page names and all of its modification times
00286 class TracePagePool : public PagePool {
00287 public:
00288     TracePagePool(const char *fn);
00289     virtual ~TracePagePool();
00290     virtual int command(int argc, const char*const* argv);
00291 
00292 protected:
00293     Tcl_HashTable *namemap_, *idmap_;
00294     RandomVariable *ranvar_;
00295 
00296     ServerPage* load_page(FILE *fp);
00297     void change_time();
00298     int add_page(const char* pgname, ServerPage *pg);
00299 
00300     ServerPage* get_page(int id);
00301 };
00302 
00303 // Page pool based on mathematical models of request and page 
00304 // modification patterns
00305 class MathPagePool : public PagePool {
00306 public:
00307     // XXX TBA: what should be here???
00308     MathPagePool() : rvSize_(0), rvAge_(0) { num_pages_ = 1; }
00309 
00310 protected:
00311     virtual int command(int argc, const char*const* argv);
00312     // Single page
00313     RandomVariable *rvSize_;
00314     RandomVariable *rvAge_;
00315 };
00316 
00317 // Assume one main page, which changes often, and multiple component pages
00318 class CompMathPagePool : public PagePool {
00319 public:
00320     CompMathPagePool();
00321 
00322 protected:
00323     virtual int command(int argc, const char*const* argv);
00324     RandomVariable *rvMainAge_;  // modtime for main page
00325     RandomVariable *rvCompAge_;  // modtime for component pages
00326     int main_size_, comp_size_;
00327 };
00328 
00329 class ClientPagePool : public PagePool {
00330 public:
00331     ClientPagePool();
00332     virtual ~ClientPagePool();
00333 
00334     virtual ClientPage* enter_page(int argc, const char*const* argv);
00335     virtual ClientPage* enter_metadata(int argc, const char*const* argv);
00336     virtual ClientPage* enter_page(const char *name, int size, double mt, 
00337                        double et, double age);
00338     virtual ClientPage* enter_metadata(const char *name, int size, 
00339                        double mt, double et, double age);
00340     virtual int remove_page(const char *name);
00341 
00342     void invalidate_server(int server_id);
00343 
00344     ClientPage* get_page(const char *name);
00345     int get_mtime(const char *name, double &mt);
00346     int set_mtime(const char *name, double mt);
00347     int exist_page(const char *name) { return (get_page(name) != NULL); }
00348     int get_size(const char *name, int &size);
00349     int get_age(const char *name, double &age);
00350     int get_etime(const char *name, double &et);
00351     int set_etime(const char *name, double et);
00352     int get_pageinfo(const char *name, char *buf);
00353 
00354     virtual int command(int argc, const char*const* argv);
00355 
00356 protected:
00357 
00358     int add_page(ClientPage *pg);
00359     Tcl_HashTable *namemap_;
00360 };
00361 
00362 // This is *not* designed for BU trace files. We should write a script to 
00363 // transform BU traces to a single trace file with the following format:
00364 //
00365 // <client id> <page id> <time> <size>
00366 //
00367 // Q: How would we deal with page size changes? 
00368 // What if simulated response time
00369 // is longer and a real client request for the same page happened before the 
00370 // simulated request completes? 
00371 
00372 class ProxyTracePagePool : public PagePool {
00373 public:
00374     ProxyTracePagePool();
00375 // : rvDyn_(NULL), rvStatic_(NULL), br_(0), 
00376 //      size_(NULL), reqfile_(NULL), req_(NULL), lastseq_(0)
00377 //      {}
00378     virtual ~ProxyTracePagePool();
00379     virtual int command(int argc, const char*const* argv);
00380 
00381 protected:
00382     // How would we handle different types of page modifications? How 
00383     // to integrate bimodal, and multi-modal distributions?
00384     int init_req(const char *fn);
00385     int init_page(const char *fn);
00386     int find_info();
00387 
00388     RandomVariable *rvDyn_, *rvStatic_;
00389     int br_;        // bimodal ratio
00390     int *size_;         // page sizes
00391     FILE *reqfile_;     // request stream of proxy trace
00392 
00393     struct ClientRequest {
00394         ClientRequest() : seq_(0), nrt_(0), nurl_(0), fpos_(0)
00395             {}
00396         int seq_;   // client sequence number, used to match 
00397                 // client ids in the trace file
00398         double nrt_;    // next request time
00399         int nurl_;  // next request url
00400         long fpos_; // position in file of its next request
00401     };
00402     Tcl_HashTable *req_;    // Requests table
00403     int nclient_, lastseq_;
00404     ClientRequest* load_req(int cid);
00405 };
00406 
00407 class EPATracePagePool : public ProxyTracePagePool {
00408 public:
00409     virtual int command(int argc, const char*const* argv);
00410 };
00411 
00412 #endif //ns_pagepool_h

Generated on Tue Mar 6 16:47:49 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6