• Main Page
  • Classes
  • Files
  • File List

/Users/yzchen/ns/ns-allinone-2.33/ns-2.33/webcache/mcache.h

00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
00002 
00003 /*
00004  * mcache.h
00005  * Copyright (C) 1997 by the University of Southern California
00006  * $Id: mcache.h,v 1.8 2005/09/18 23:33:35 tomh Exp $
00007  *
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License,
00010  * version 2, as published by the Free Software Foundation.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License along
00018  * with this program; if not, write to the Free Software Foundation, Inc.,
00019  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00020  *
00021  *
00022  * The copyright of this module includes the following
00023  * linking-with-specific-other-licenses addition:
00024  *
00025  * In addition, as a special exception, the copyright holders of
00026  * this module give you permission to combine (via static or
00027  * dynamic linking) this module with free software programs or
00028  * libraries that are released under the GNU LGPL and with code
00029  * included in the standard release of ns-2 under the Apache 2.0
00030  * license or under otherwise-compatible licenses with advertising
00031  * requirements (or modified versions of such code, with unchanged
00032  * license).  You may copy and distribute such a system following the
00033  * terms of the GNU GPL for this module and the licenses of the
00034  * other code concerned, provided that you include the source code of
00035  * that other code when and as the GNU GPL requires distribution of
00036  * source code.
00037  *
00038  * Note that people who make modified versions of this module
00039  * are not obligated to grant this special exception for their
00040  * modified versions; it is their choice whether to do so.  The GNU
00041  * General Public License gives permission to release a modified
00042  * version without this exception; this exception also makes it
00043  * possible to release a modified version which carries forward this
00044  * exception.
00045  *
00046  */
00047 
00048 //
00049 // Multimedia caches
00050 // 
00051 // $Header: /cvsroot/nsnam/ns-2/webcache/mcache.h,v 1.8 2005/09/18 23:33:35 tomh Exp $
00052 
00053 #ifndef ns_mcache_h
00054 #define ns_mcache_h
00055 
00056 #include "config.h"
00057 #include "agent.h"
00058 #include "pagepool.h"
00059 #include "http.h"
00060 #include "rap/media-app.h"
00061 
00062 
00063 //----------------------------------------------------------------------
00064 // Priority list for hit counts at each layer
00065 //----------------------------------------------------------------------
00066 class HitCount : public DoubleListElem {
00067 public:
00068         HitCount(ClientPage *pg, short layer) : 
00069                 DoubleListElem(), pg_(pg), layer_(layer), hc_(0) {}
00070 
00071         void update(float hc) { hc_ += hc; }
00072         float hc() { return hc_; }
00073         void reset() { hc_ = 0; }
00074         ClientPage* page() { return pg_; }
00075         short layer() { return layer_; }
00076 
00077         HitCount* next() { return (HitCount *)DoubleListElem::next(); }
00078         HitCount* prev() { return (HitCount *)DoubleListElem::prev(); }
00079 
00080 private:
00081         ClientPage* pg_;        // page
00082         short layer_;           // layer id
00083         float hc_;              // hit count
00084 };
00085 
00086 class HitCountList : public DoubleList {
00087 public:
00088         HitCountList() : DoubleList() {}
00089 
00090         void update(HitCount *h);       // Update layer hit count
00091         void add(HitCount *h);          // Add a new layer
00092 
00093         HitCount* detach_tail() {
00094                 HitCount* tmp = (HitCount *)tail_;
00095                 if (tmp) {
00096                         tail_ = tail_->prev();
00097                         tmp->detach();
00098                 }
00099                 return tmp;
00100         }
00101 
00102         // Debug only
00103         void print();
00104         void check_integrity(); 
00105 };
00106 
00107 
00108 
00109 //----------------------------------------------------------------------
00110 // Multimedia web objects
00111 //----------------------------------------------------------------------
00112 class MediaPage : public ClientPage {
00113 public:
00114         MediaPage(const char *n, int s, double mt, double et, double a, int l);
00115         virtual ~MediaPage();
00116 
00117         virtual WebPageType type() const { return MEDIA; }
00118         virtual void print_info(char *buf);
00119         int num_layer() const { return num_layer_; }
00120 
00121         HitCount* get_hit_count(int layer) { 
00122                 assert((layer >= 0) && (layer < num_layer_));
00123                 return hc_[layer]; 
00124         }
00125         void hit_layer(int layer) {
00126                 assert((layer >= 0) && (layer < num_layer_));
00127                 hc_[layer]->update((double)(layer_[layer].length()*num_layer_)
00128                                    / (double)size_); 
00129         }
00130 
00131         int layer_size(int layer) { 
00132                 assert((layer >= 0) && (layer < num_layer_));
00133                 return layer_[layer].length();
00134         }
00135         void add_segment(int layer, const MediaSegment& s);
00136         int evict_tail_segment(int layer, int size);
00137 
00138         void add_layer(int layer) {
00139                 assert((layer >= 0) && (layer < num_layer_));
00140                 num_layer_ = (num_layer_ < layer) ? layer : num_layer_;
00141         }
00142         char* print_layer(int layer) {
00143                 assert((layer >= 0) && (layer < num_layer_));
00144                 return layer_[layer].dump2buf();
00145         }
00146         MediaSegmentList is_available(int layer, const MediaSegment& s) {
00147                 assert((layer >= 0) && (layer < MAX_LAYER));
00148                 return layer_[layer].check_holes(s);
00149         }
00150         // Return a media segment which is the closest one after 's'.
00151         // Used by MediaApps to request data.
00152         // Do NOT check if layer >= num_layer_. If it's empty, 
00153         // an empty MediaSegment will be returned. 
00154         MediaSegment next_available(int layer, const MediaSegment& s) {
00155                 assert((layer >= 0) && (layer < MAX_LAYER));
00156                 return layer_[layer].get_nextseg(s);
00157         }
00158         MediaSegment next_overlap(int layer, const MediaSegment& s) {
00159                 assert((layer >= 0) && (layer < MAX_LAYER));
00160                 MediaSegment s1 = layer_[layer].get_nextseg(s);
00161                 if ((s1.end() <= s.start()) || (s1.start() >= s.end())) {
00162                         MediaSegment s;
00163                         if (s1.is_last())
00164                                 s.set_last();
00165                         return s;
00166                 } else
00167                         return s1;
00168         }
00169 
00170         enum {FETCHLOCK = 1, XMITLOCK = 2};
00171 
00172         // 1st type of lock: it is being fetched from the server
00173         void lock() { locked_ |= FETCHLOCK; }
00174         void unlock() { locked_ &= ~FETCHLOCK; }
00175         int is_locked() { return (locked_ & FETCHLOCK); }
00176         // 2nd type of lock: it is being transmitted to a client
00177         void tlock() { locked_ |= XMITLOCK; }
00178         void tunlock() { locked_ &= ~XMITLOCK; }
00179         int is_tlocked() { return (locked_ & XMITLOCK); }
00180 
00181         // Whether all layers are marked as "completed"
00182         int is_complete(); 
00183         // Set all layers as "completed"
00184         void set_complete();
00185 
00186         // Given the number of layers, evenly distribute the size among all
00187         // layers and create all segments.
00188         void create();
00189         int realsize() const { return realsize_; }
00190 
00191 protected:
00192         void set_complete_layer(int layer) {
00193                 flags_[layer] = 1;
00194         }
00195         int is_complete_layer(int layer) {
00196                 return flags_[layer] == 1; 
00197         }
00198 
00199         MediaSegmentList layer_[MAX_LAYER];
00200         int flags_[MAX_LAYER]; // If 1, marks the layer as completed
00201         HitCount* hc_[MAX_LAYER];
00202         int num_layer_; 
00203         int locked_;  // If 1, then no segment can be replaced
00204         int realsize_; // The size of stream data in this page.
00205 };
00206 
00207 // XXX Later we should add a generic replacement algorithm hook into 
00208 // ClientPagePool. But now we'll leave it there and get this media 
00209 // page pool work first. 
00210 
00211 // ClientPagePool enhanced with support for multimedia objects, and 
00212 // with replacement algorithms
00213 class MClientPagePool : public ClientPagePool {
00214 public:
00215         MClientPagePool();
00216 
00217         virtual ClientPage* enter_page(int argc, const char*const* argv);
00218         virtual int remove_page(const char *name);
00219         virtual int force_remove(const char *name);
00220 
00221         int add_segment(const char *name, int layer, const MediaSegment& s);
00222         void hc_update(const char *name, int max_layer);
00223 
00224         int maxsize() { return max_size_; }
00225         int usedsize() { return used_size_; }
00226 
00227         void fill_page(const char* pgname);
00228 
00229         // Debug only
00230         void dump_hclist() { hclist_.print(); }
00231 
00232 protected:
00233         virtual int command(int argc, const char*const* argv);
00234         virtual int cache_replace(ClientPage* page, int size);
00235 
00236         // Fine-grain replacement
00237         int repl_finegrain(ClientPage* p, int size);
00238         int repl_atomic(ClientPage* p, int size);
00239 
00240         // XXX Should change to quad_t, or use MB as unit
00241         int max_size_;          // PagePool size
00242         int used_size_;         // Available space size
00243         HitCountList hclist_; 
00244         // Replacement style
00245         enum { FINEGRAIN, ATOMIC } repl_style_;
00246 };
00247 
00248 // Provide page data and generate requests for servers and clients
00249 class MediaPagePool : public PagePool {
00250 public:
00251         MediaPagePool();
00252 protected:
00253         virtual int command(int argc, const char*const* argv);
00254         int layer_;     // Number of layers of pages
00255         int *size_;     // Page sizes
00256         RandomVariable *rvReq_;
00257 };
00258 
00259 
00260 
00261 //--------------------
00262 // Multimedia caches
00263 //--------------------
00264 
00265 // Plain multimedia cache, which can interface with RapAgent
00266 class MediaCache : public HttpCache {
00267 public:
00268         MediaCache();
00269         ~MediaCache();
00270 
00271         // Handle app-specific data in C++
00272         virtual void process_data(int size, AppData* data);
00273         // Handle data request from RAP
00274         virtual AppData* get_data(int& size, AppData* data);
00275 
00276 protected:
00277         virtual int command(int argc, const char*const* argv);
00278 
00279         // Do we need to maintain links to MediaApp?? I doubt not
00280         // MediaApp* mapp_; // An array of incoming/outgoing RAP agents
00281         MClientPagePool* mpool() { return (MClientPagePool *)pool_; }
00282 
00283         // Information and statistics related to clients
00284         struct RegInfo {
00285                 RegInfo() : client_(NULL), hl_(-1) {
00286                         memset(pb_, 0, sizeof(unsigned int)*MAX_LAYER);
00287                         memset(db_, 0, sizeof(unsigned int)*MAX_LAYER);
00288                         memset(eb_, 0, sizeof(unsigned int)*MAX_LAYER);
00289                 }
00290                 ~RegInfo() {
00291                         for (int i = 0; i < MAX_LAYER; i++)
00292                                 pref_[i].destroy();
00293                 }
00294 
00295                 char name_[20];
00296                 HttpApp* client_;
00297                 int hl_;                // Highest layer this client has asked
00298                 // Prefetched bytes
00299                 unsigned int pb_[MAX_LAYER]; 
00300                 // Prefetched bytes that were delivered
00301                 unsigned int eb_[MAX_LAYER];
00302                 // Total delivered bytes
00303                 unsigned int db_[MAX_LAYER];
00304                 MediaSegmentList pref_[MAX_LAYER];
00305 
00306                 // Return the number of prefetched bytes in the given segment
00307                 void add_pref(int layer, const MediaSegment& s) {
00308                         assert((layer >= 0) && (layer < MAX_LAYER));
00309                         pref_[layer].add(s);
00310                 }
00311                 int pref_size(int layer, const MediaSegment &s) const { 
00312                         assert((layer >= 0) && (layer < MAX_LAYER));
00313                         return pref_[layer].overlap_size(s);
00314                 }
00315         };
00316         Tcl_HashTable *cmap_;   // client map
00317 
00318         // Prefetching/No-prefetching/Offline-prefetching flag
00319         enum {NOPREF, ONLINE_PREF, OFFLINE_PREF} pref_style_;
00320 };
00321 
00322 
00323 //----------------------------------------------------------------------
00324 // Multimedia web client
00325 //----------------------------------------------------------------------
00326 class MediaClient : public HttpClient {
00327 public:
00328         MediaClient() : HttpClient() {}
00329         virtual void process_data(int size, AppData* data);
00330         virtual int command(int argc, const char*const* argv);
00331 private:
00332         MClientPagePool* mpool() { return (MClientPagePool *)pool_; }
00333 };
00334 
00335 
00336 
00337 // Helper data structure
00338 
00339 template <class T> class Queue; // forward declaration
00340 
00341 template <class T> class QueueElem {
00342 public:
00343         QueueElem(T* d) : next_(0), data_(d) {}
00344 
00345         QueueElem<T>* next() const { return next_; }
00346         T* data() const { return data_; }
00347         void detachData() { data_ = NULL; }
00348         void append(QueueElem<T>* e) {
00349                 e->next_ = next_;
00350                 next_ = e;
00351         }
00352 
00353 protected:
00354         QueueElem<T>* next_;
00355         T* data_;
00356         friend class Queue<T>; 
00357 };
00358 
00359 template <class T> class Queue {
00360 public:
00361         Queue() : head_(0), tail_(0), size_(0) {}
00362         virtual ~Queue() {
00363                 QueueElem<T> *p = head_, *q;
00364                 while (p != NULL) {
00365                         q = p;
00366                         p = p->next();
00367                         delete q;
00368                 }
00369                 head_ = NULL;
00370         }
00371         virtual void reset() {
00372                 QueueElem<T> *p = head_, *q;
00373                 while (p != NULL) {
00374                         q = p;
00375                         p = p->next();
00376                         delete q;
00377                 }
00378                 head_ = NULL;
00379         }
00380         virtual void destroy() {
00381                 QueueElem<T> *p = head_, *q;
00382                 while (p != NULL) {
00383                         q = p;
00384                         p = p->next();
00385                         delete q->data();
00386                         delete q;
00387                 }
00388                 head_ = NULL;
00389         }
00390 
00391         void enqueue(QueueElem<T> *e) {
00392                 if (tail_ == 0)
00393                         head_ = tail_ = e;
00394                 else {
00395                         tail_->append(e);
00396                         tail_ = e;
00397                 }
00398                 size_++;
00399         }
00400         QueueElem<T>* dequeue() {
00401                 QueueElem<T> *p = head_;
00402                 if (head_ != 0) 
00403                         head_ = head_->next();
00404                 if (head_ == 0)
00405                         tail_ = 0;
00406                 p->next_ = 0;
00407                 size_--;
00408                 if (size_ == 0) 
00409                         assert((head_ == 0) && (tail_ == 0));
00410                 return p;
00411         }
00412         void detach(QueueElem<T>* e) {
00413                 assert(head_ != 0);
00414                 if (head_ == e) {
00415                         dequeue();
00416                         return;
00417                 }
00418                 QueueElem<T> *p = head_;
00419                 while (p != NULL) {
00420                         if (p->next_ != e)
00421                                 p = p->next_;
00422                         else
00423                                 break;
00424                 }
00425                 assert(p != NULL);
00426                 p->next_ = e->next_;
00427                 if (tail_ == e)
00428                         tail_ = p;
00429                 size_--;
00430                 if (size_ == 0) 
00431                         assert((head_ == 0) && (tail_ == 0));
00432         }
00433         QueueElem<T>* getHead() { return head_; }
00434         int is_empty() const { return (size_ == 0); }
00435         int size() const { return size_; }
00436 
00437 protected:
00438         QueueElem<T> *head_, *tail_;
00439         int size_;
00440 };
00441 
00442 
00443 
00444 //----------------------------------------------------------------------
00445 // Multimedia server
00446 //----------------------------------------------------------------------
00447 class MediaServer : public HttpServer {
00448 public:
00449         MediaServer();
00450         ~MediaServer();
00451         virtual AppData* get_data(int& size, AppData* d);
00452 
00453 protected:
00454         virtual int command(int argc, const char*const* argv);
00455         MediaSegment get_next_segment(MediaRequest *r, Application*& ci);
00456 
00457         // Prefetching list
00458         struct RegInfo {
00459                 char name_[20];
00460                 HttpApp* client_;
00461         };
00462         struct PrefInfo {
00463                 MediaSegmentList* sl_;
00464                 Application* conid_;
00465         };
00466         typedef Queue<PrefInfo> PrefInfoQ;
00467         typedef QueueElem<PrefInfo> PrefInfoE;
00468         PrefInfoE* find_prefinfo(PrefInfoQ* q, Application* conid) {
00469                 for (PrefInfoE *e = q->getHead(); e != NULL; e = e->next())
00470                         if (e->data()->conid_ == conid)
00471                                 return e;
00472                 return NULL;
00473         }
00474 
00475         Tcl_HashTable *pref_; // Mapping <cache>:<pagenum> to PrefInfoQ
00476         Tcl_HashTable *cmap_; // Mapping MediaApps to clients
00477 
00478         PrefInfoQ* get_piq(const char* pgname, HttpApp* client) {
00479                 PageID id;
00480                 ClientPage::split_name(pgname, id);
00481                 id.s_ = client;
00482                 Tcl_HashEntry* he = 
00483                         Tcl_FindHashEntry(pref_, (const char*)&id);
00484                 if (he == NULL) 
00485                         return NULL;
00486                 return (PrefInfoQ*)Tcl_GetHashValue(he);
00487         }
00488         RegInfo* get_reginfo(Application* app) {
00489                 Tcl_HashEntry *he = 
00490                         Tcl_FindHashEntry(cmap_, (const char *)app);
00491                 if (he == NULL) {
00492                         fprintf(stderr, "Unknown connection!\n");
00493                         abort();
00494                 } 
00495                 return (RegInfo *)Tcl_GetHashValue(he);
00496         }
00497 };
00498 
00499 
00500 #endif // ns_mcache_h

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