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

mcache.h

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

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