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

MediaCache Class Reference

#include <mcache.h>

Inheritance diagram for MediaCache:

Inheritance graph
[legend]
Collaboration diagram for MediaCache:

Collaboration graph
[legend]
List of all members.

Public Member Functions

 MediaCache ()
 ~MediaCache ()
virtual void process_data (int size, AppData *data)
virtual AppDataget_data (int &size, AppData *data)
void log (const char *fmt,...)
int id () const
Process *& target ()
virtual void send_data (int size, AppData *data=0)

Protected Types

enum  { NOPREF, ONLINE_PREF, OFFLINE_PREF }

Protected Member Functions

virtual int command (int argc, const char *const *argv)
MClientPagePoolmpool ()
int add_cnc (HttpApp *client, TcpApp *agt)
void delete_cnc (HttpApp *client)
TcpApplookup_cnc (HttpApp *client)
void set_pagepool (ClientPagePool *pp)

Protected Attributes

Tcl_HashTable * cmap_
enum MediaCache:: { ... }  pref_style_
Tcl_HashTable * tpa_
int id_
ClientPagePoolpool_
Tcl_Channel log_
Processtarget_

Member Enumeration Documentation

anonymous enum [protected]
 

Enumeration values:
NOPREF 
ONLINE_PREF 
OFFLINE_PREF 

Definition at line 297 of file mcache.h.


Constructor & Destructor Documentation

MediaCache::MediaCache  ) 
 

Definition at line 756 of file mcache.cc.

References cmap_.

00756                        : pref_style_(ONLINE_PREF)
00757 {
00758         cmap_ = new Tcl_HashTable;
00759         Tcl_InitHashTable(cmap_, TCL_ONE_WORD_KEYS);
00760 }

MediaCache::~MediaCache  ) 
 

Definition at line 762 of file mcache.cc.

References cmap_.

00763 {
00764         Tcl_HashEntry *he;
00765         Tcl_HashSearch hs;
00766         if (cmap_) {
00767                 for (he = Tcl_FirstHashEntry(cmap_, &hs);  he != NULL;
00768                      he = Tcl_NextHashEntry(&hs))
00769                         delete (RegInfo*)Tcl_GetHashValue(he);
00770                 Tcl_DeleteHashTable(cmap_);
00771                 delete cmap_;
00772         }
00773 }


Member Function Documentation

int HttpApp::add_cnc HttpApp client,
TcpApp agt
[protected, inherited]
 

Definition at line 69 of file http.cc.

References client, and HttpApp::tpa_.

Referenced by HttpApp::command().

00070 {
00071         int newEntry = 1;
00072         Tcl_HashEntry *he = Tcl_CreateHashEntry(tpa_, 
00073                                                 (const char *)client->id(),
00074                                                 &newEntry);
00075         if (he == NULL) 
00076                 return -1;
00077         if (newEntry)
00078                 Tcl_SetHashValue(he, (ClientData)agt);
00079         return 0;
00080 }

int MediaCache::command int  argc,
const char *const *  argv
[protected, virtual]
 

Reimplemented from HttpApp.

Definition at line 922 of file mcache.cc.

References MediaCache::RegInfo::client_, cmap_, HttpApp::command(), MediaCache::RegInfo::db_, MClientPagePool::dump_hclist(), MediaCache::RegInfo::eb_, MClientPagePool::fill_page(), ClientPagePool::get_page(), MClientPagePool::hc_update(), MediaCache::RegInfo::hl_, HttpApp::id_, HttpApp::log(), MEDIA, mpool(), MediaCache::RegInfo::name_, NOPREF, MediaPage::num_layer(), OFFLINE_PREF, ONLINE_PREF, MediaCache::RegInfo::pb_, pref_style_, MediaPage::print_layer(), MediaPage::tlock(), MediaPage::tunlock(), MediaPage::type(), ClientPage::type(), and MediaPage::unlock().

00923 {
00924         Tcl& tcl = Tcl::instance();
00925         if (argc == 2) {
00926                 if (strcmp(argv[1], "get-pref-style") == 0) {
00927                         switch (pref_style_) {
00928                         case NOPREF:
00929                                 tcl.result("NOPREF");
00930                                 break;
00931                         case ONLINE_PREF:
00932                                 tcl.result("ONLINE_PREF");
00933                                 break;
00934                         case OFFLINE_PREF:
00935                                 tcl.result("OFFLINE_PREF");
00936                                 break;
00937                         default:
00938                                 fprintf(stderr, 
00939                                         "Corrupted prefetching style %d", 
00940                                         pref_style_);
00941                                 return TCL_ERROR;
00942                         }
00943                         return TCL_OK;
00944                 }
00945         } else if (argc == 3) {
00946                 if (strcmp(argv[1], "offline-complete") == 0) {
00947                         // Delete whatever segments in the given page, 
00948                         // make it complete. Used by offline prefetching
00949                         ClientPage *pg = mpool()->get_page(argv[2]);
00950                         if (pg == NULL)
00951                                 // XXX It's possible that we've already kicked
00952                                 // it out of the cache. Do nothing.
00953                                 return TCL_OK;
00954                         assert(pg->type() == MEDIA);
00955                         assert(!((MediaPage*)pg)->is_locked());
00956                         mpool()->fill_page(argv[2]);
00957                         return TCL_OK;
00958                 } else if (strcmp(argv[1], "set-pref-style") == 0) {
00959                         // Set prefetching style
00960                         // <obj> set-pref-style <style>
00961                         //
00962                         // style can be: NOPREF, ONLINE_PREF, OFFLINE_PREF
00963                         if (strcmp(argv[2], "NOPREF") == 0) 
00964                                 pref_style_ = NOPREF;
00965                         else if (strcmp(argv[2], "ONLINE_PREF") == 0) 
00966                                 pref_style_ = ONLINE_PREF;
00967                         else if (strcmp(argv[2], "OFFLINE_PREF") == 0) 
00968                                 pref_style_ = OFFLINE_PREF;
00969                         else {
00970                                 fprintf(stderr, "Wrong prefetching style %s",
00971                                         argv[2]);
00972                                 return TCL_ERROR;
00973                         }
00974                         return TCL_OK;
00975                 } else if (strcmp(argv[1], "dump-page") == 0) {
00976                         // Dump segments of a given page
00977                         ClientPage *p=(ClientPage*)mpool()->get_page(argv[2]);
00978                         if (p->type() != MEDIA)
00979                                 // Do nothing for non-media pages
00980                                 return TCL_OK;
00981                         MediaPage *pg = (MediaPage *)p;
00982                         char *buf;
00983                         for (int i = 0; i < pg->num_layer(); i++) {
00984                                 buf = pg->print_layer(i);
00985                                 if (strlen(buf) > 0)
00986                                         log("E SEGS p %s l %d %s\n", argv[2], 
00987                                             i, buf);
00988                                 delete []buf;
00989                         }
00990                         return TCL_OK;
00991                 } else if (strcmp(argv[1], "stream-received") == 0) {
00992                         // We've got the entire page, unlock it
00993                         MediaPage *pg = (MediaPage*)mpool()->get_page(argv[2]);
00994                         assert(pg != NULL);
00995                         pg->unlock();
00996                         // XXX Should we clear all "last" flag of segments??
00997 #ifdef MCACHE_DEBUG
00998                         // Printing out current buffer status of the page
00999                         char *buf;
01000                         for (int i = 0; i < pg->num_layer(); i++) {
01001                                 buf = pg->print_layer(i);
01002                                 log("E SEGS p %s l %d %s\n", argv[2], i, buf);
01003                                 delete []buf;
01004                         }
01005 #endif
01006                         // Show cache free size
01007                         log("E SIZ n %d z %d t %d\n", mpool()->num_pages(),
01008                             mpool()->usedsize(), mpool()->maxsize());
01009                         return TCL_OK;
01010                 }
01011         } else if (argc == 5) {
01012                 if (strcmp(argv[1], "register-client") == 0) {
01013                         // <server> register-client <app> <client> <pageid>
01014                         TclObject *a = TclObject::lookup(argv[2]);
01015                         assert(a != NULL);
01016                         int newEntry;
01017                         Tcl_HashEntry *he = Tcl_CreateHashEntry(cmap_, 
01018                                         (const char *)a, &newEntry);
01019                         if (he == NULL) {
01020                                 tcl.add_errorf("cannot create hash entry");
01021                                 return TCL_ERROR;
01022                         }
01023                         if (!newEntry) {
01024                                 tcl.add_errorf("duplicate connection");
01025                                 return TCL_ERROR;
01026                         }
01027                         RegInfo *p = new RegInfo;
01028                         p->client_ = (HttpApp*)TclObject::lookup(argv[3]);
01029                         assert(p->client_ != NULL);
01030                         strcpy(p->name_, argv[4]);
01031                         Tcl_SetHashValue(he, (ClientData)p);
01032 
01033                         // Lock the page while transmitting it to a client
01034                         MediaPage *pg = (MediaPage*)mpool()->get_page(argv[4]);
01035                         assert((pg != NULL) && (pg->type() == MEDIA));
01036                         pg->tlock();
01037 
01038                         return TCL_OK;
01039                 } else if (strcmp(argv[1], "unregister-client") == 0) {
01040                         // <server> unregister-client <app> <client> <pageid>
01041                         TclObject *a = TclObject::lookup(argv[2]);
01042                         assert(a != NULL);
01043                         Tcl_HashEntry *he = 
01044                                 Tcl_FindHashEntry(cmap_, (const char*)a);
01045                         if (he == NULL) {
01046                                 tcl.add_errorf("cannot find hash entry");
01047                                 return TCL_ERROR;
01048                         }
01049                         RegInfo *ri = (RegInfo*)Tcl_GetHashValue(he);
01050                         // Update hit count
01051                         mpool()->hc_update(argv[4], ri->hl_);
01052 #ifdef MCACHE_DEBUG
01053                         printf("Cache %d hit counts: \n", id_);
01054                         mpool()->dump_hclist();
01055 #endif
01056                         // Dump per-connection statistics
01057                         for (int i = 0; i <= ri->hl_; i++)
01058                                 log("E STAT p %s l %d d %d e %d p %d\n",
01059                                     ri->name_, i, ri->db_[i], ri->eb_[i], 
01060                                     ri->pb_[i]);
01061                         delete ri;
01062                         Tcl_DeleteHashEntry(he);
01063 
01064                         // Lock the page while transmitting it to a client
01065                         MediaPage *pg = (MediaPage*)mpool()->get_page(argv[4]);
01066                         assert((pg != NULL) && (pg->type() == MEDIA));
01067                         pg->tunlock();
01068 
01069                         return TCL_OK;
01070                 }
01071         }
01072 
01073         return HttpCache::command(argc, argv);
01074 }

Here is the call graph for this function:

void HttpApp::delete_cnc HttpApp client  )  [protected, inherited]
 

Definition at line 82 of file http.cc.

References client, and HttpApp::tpa_.

Referenced by HttpApp::command().

00083 {
00084         Tcl_HashEntry *he = Tcl_FindHashEntry(tpa_,(const char *)client->id());
00085         if (he != NULL) {
00086                 TcpApp *cnc = (TcpApp *)Tcl_GetHashValue(he);
00087                 Tcl_DeleteHashEntry(he);
00088                 delete cnc;
00089         }
00090 }

AppData * MediaCache::get_data int &  size,
AppData data
[virtual]
 

Reimplemented from HttpApp.

Definition at line 775 of file mcache.cc.

References abort(), MediaRequest::app(), cmap_, MediaSegment::datasize(), MediaCache::RegInfo::db_, MediaSegmentList::destroy(), MediaSegmentList::dump2buf(), MediaCache::RegInfo::eb_, MediaSegment::end(), MediaRequest::et(), HttpApp::get_data(), ClientPagePool::get_page(), MediaCache::RegInfo::hl_, MediaPage::is_available(), MediaSegment::is_last(), MediaPage::is_locked(), MediaRequest::layer(), MediaSegmentList::length(), MEDIA_REQUEST, MEDIAREQ_CHECKSEG, MEDIAREQ_GETSEG, MediaRequest::name(), MediaPage::next_overlap(), ONLINE_PREF, HttpApp::pool_, MediaCache::RegInfo::pref_size(), pref_style_, req, MediaRequest::request(), HttpMediaData::set_finish(), HttpMediaData::set_last(), MediaRequest::st(), and MediaSegment::start().

00776 {
00777         assert(req != NULL);
00778         if (req->type() != MEDIA_REQUEST) {
00779                 return HttpApp::get_data(size, req);
00780         }
00781 
00782         MediaRequest *r = (MediaRequest *)req;
00783 
00784         // Get statistics block for the requestor
00785         Tcl_HashEntry *he = 
00786                 Tcl_FindHashEntry(cmap_, (const char *)(r->app()));
00787         assert(he != NULL);
00788         RegInfo *ri = (RegInfo *)Tcl_GetHashValue(he);
00789 
00790         // Process request
00791         if (r->request() == MEDIAREQ_GETSEG) {
00792                 // Get a new data segment
00793                 MediaPage* pg = (MediaPage*)pool_->get_page(r->name());
00794                 assert(pg != NULL);
00795                 MediaSegment s1(r->st(), r->et());
00796                 MediaSegment s2 = pg->next_overlap(r->layer(), s1);
00797                 HttpMediaData *p;
00798                 if (s2.datasize() == 0) {
00799                         // No more data available for this layer, allocate
00800                         // an ADU with data size 0 to signal the end
00801                         // of transmission for this layer
00802                         size = 0;
00803                         p = new HttpMediaData(name(), r->name(),
00804                                               r->layer(), 0, 0);
00805                 } else {
00806                         size = s2.datasize();
00807                         p = new HttpMediaData(name(), r->name(),
00808                                            r->layer(), s2.start(), s2.end());
00809                 }
00810                 // XXX If we are still receiving the stream, don't 
00811                 // ever say that this is the last segment. If the 
00812                 // page is not locked, it's still possible that we
00813                 // return a NULL segment because the requested one
00814                 // is not available. Don't set the 'LAST' flag in this 
00815                 // case.
00816                 if (s2.is_last()) {
00817                         p->set_last();
00818                         if (!pg->is_locked() && (s2.datasize() == 0) && 
00819                             (r->layer() == 0)) 
00820                                 p->set_finish();
00821                 }
00822 
00823                 //----------------------------------------
00824                 // Update statistics of this connection
00825                 //----------------------------------------
00826                 // Update the highest layer that this client has requested
00827                 if (ri->hl_ < r->layer())
00828                         ri->hl_ = r->layer();
00829                 if (size > 0) {
00830                         // Update total delivered bytes
00831                         ri->db_[r->layer()] += size;
00832                         // Update prefetched bytes that've been delivered
00833                         ri->eb_[r->layer()] += ri->pref_size(r->layer(), s2);
00834                 }
00835                 return p;
00836         } else if (r->request() == MEDIAREQ_CHECKSEG) {
00837                 // If we are not doing online prefetching, return nothing
00838                 if (pref_style_ != ONLINE_PREF)
00839                         return NULL;
00840                 // Check the availability of a new data segment
00841                 // And refetch if it is not available
00842                 MediaPage* pg = (MediaPage*)pool_->get_page(r->name());
00843                 assert(pg != NULL);
00844                 if (pg->is_locked()) 
00845                         // If we are during the first retrieval, don't prefetch
00846                         return NULL;
00847                 MediaSegmentList ul = pg->is_available(r->layer(),
00848                                       MediaSegment(r->st(),r->et()));
00849                 if (ul.length() == 0)
00850                         // All segments are available
00851                         return NULL;
00852                 // Otherwise do prefetching on these "holes"
00853                 char *buf = ul.dump2buf();
00854                 Tcl::instance().evalf("%s pref-segment %s %s %d %s", name(), 
00855                                       r->app()->name(), r->name(), 
00856                                       r->layer(), buf);
00857 //              log("E PREF p %s l %d %s\n", r->name(), r->layer(), buf);
00858                 delete []buf;
00859                 ul.destroy();
00860 
00861                 // Update the highest layer that this client has requested
00862                 Tcl_HashEntry *he = 
00863                         Tcl_FindHashEntry(cmap_, (const char *)(r->app()));
00864                 assert(he != NULL);
00865                 RegInfo *ri = (RegInfo *)Tcl_GetHashValue(he);
00866                 if (ri->hl_ < r->layer())
00867                         ri->hl_ = r->layer();
00868                 return NULL;
00869         }
00870                 
00871         fprintf(stderr, 
00872                 "MediaCache %s gets an unknown MediaRequest type %d\n",
00873                 name(), r->request());
00874         abort();
00875         return NULL; // Make msvc happy
00876 }

Here is the call graph for this function:

int HttpApp::id  )  const [inline, inherited]
 

Definition at line 44 of file http.h.

References HttpApp::id_.

Referenced by HttpMInvalCache::add_cache(), HttpMInvalCache::add_nbr(), HttpMInvalCache::command(), MediaServer::get_piq(), ClientPagePool::invalidate_server(), and HttpMInvalCache::process_inv().

00044 { return id_; }

void HttpApp::log const char *  fmt,
... 
[inherited]
 

Definition at line 356 of file http.cc.

References HttpApp::id_, Scheduler::instance(), HttpApp::log_, BaseTrace::round(), and TIME_FORMAT.

Referenced by MediaClient::command(), command(), HttpMInvalCache::command(), HttpYucInvalServer::command(), MediaClient::process_data(), process_data(), HttpMInvalCache::process_inv(), and HttpMInvalCache::recv_upd().

00357 {
00358         // Don't do anything if we don't have a log file.
00359         if (log_ == 0) 
00360                 return;
00361 
00362         char buf[10240], *p;
00363         sprintf(buf, TIME_FORMAT" i %d ", 
00364                 BaseTrace::round(Scheduler::instance().clock()), id_);
00365         p = &(buf[strlen(buf)]);
00366         va_list ap;
00367         va_start(ap, fmt);
00368         vsprintf(p, fmt, ap);
00369         Tcl_Write(log_, buf, strlen(buf));
00370 }

Here is the call graph for this function:

TcpApp * HttpApp::lookup_cnc HttpApp client  )  [protected, inherited]
 

Definition at line 92 of file http.cc.

References client, and HttpApp::tpa_.

Referenced by HttpApp::command().

00093 {
00094         Tcl_HashEntry *he = 
00095                 Tcl_FindHashEntry(tpa_, (const char *)client->id());
00096         if (he == NULL)
00097                 return NULL;
00098         return (TcpApp *)Tcl_GetHashValue(he);
00099 }

MClientPagePool* MediaCache::mpool  )  [inline, protected]
 

Definition at line 259 of file mcache.h.

References HttpApp::pool_.

Referenced by command(), and process_data().

00259 { return (MClientPagePool *)pool_; }

void MediaCache::process_data int  size,
AppData data
[virtual]
 

Reimplemented from HttpApp.

Definition at line 879 of file mcache.cc.

References abort(), MediaCache::RegInfo::add_pref(), MClientPagePool::add_segment(), cmap_, HttpMediaData::conid(), HttpMediaData::datasize(), HttpMediaData::et(), HttpMediaData::is_pref(), HttpMediaData::layer(), HttpApp::log(), MEDIA_DATA, mpool(), HttpMediaData::page(), MediaCache::RegInfo::pb_, HttpApp::process_data(), HttpMediaData::st(), and AppData::type().

00880 {
00881         switch (data->type()) {
00882         case MEDIA_DATA: {
00883                 HttpMediaData* d = (HttpMediaData*)data;
00884                 // Cache this segment, do replacement if necessary
00885                 if (mpool()->add_segment(d->page(), d->layer(), 
00886                                          MediaSegment(*d)) == -1) {
00887                         fprintf(stderr, "MediaCache %s gets a segment for an "
00888                                 "unknown page %s\n", name(), d->page());
00889                         abort();
00890                 }
00891                 if (d->is_pref()) {
00892                         // Update total prefetched bytes
00893                         Tcl_HashEntry *he = Tcl_FindHashEntry(cmap_, 
00894                                                 (const char*)(d->conid()));
00895                         // Client-cache-server disconnection procedure:
00896                         // (1) client disconnects from cache, then
00897                         // (2) cache disconnects from server and shuts down 
00898                         //     prefetching channel. 
00899                         // Therefore, after client disconnects, the cache 
00900                         // may still receive a few prefetched segments. 
00901                         // Ignore those because we no longer keep statistics
00902                         // about the torn-down connection.
00903                         if (he != NULL) {
00904                                 RegInfo *ri = (RegInfo *)Tcl_GetHashValue(he);
00905                                 ri->add_pref(d->layer(), MediaSegment(*d));
00906                                 ri->pb_[d->layer()] += d->datasize();
00907                         }
00908                 }
00909                 // XXX debugging only
00910 #if 1
00911                 log("E RSEG p %s l %d s %d e %d z %d f %d\n", 
00912                     d->page(), d->layer(), d->st(), d->et(), d->datasize(),
00913                     d->is_pref());
00914 #endif
00915                 break;
00916         } 
00917         default:
00918                 HttpCache::process_data(size, data);
00919         }
00920 }

Here is the call graph for this function:

virtual void Process::send_data int  size,
AppData data = 0
[inline, virtual, inherited]
 

Definition at line 106 of file ns-process.h.

References Process::process_data(), and Process::target_.

Referenced by TcpApp::process_data(), and MediaApp::process_data().

00106                                                             {
00107                 if (target_)
00108                         target_->process_data(size, data);
00109         }

Here is the call graph for this function:

void HttpApp::set_pagepool ClientPagePool pp  )  [inline, protected, inherited]
 

Definition at line 58 of file http.h.

References HttpApp::pool_.

00058 { pool_ = pp; }

Process*& Process::target  )  [inline, inherited]
 

Definition at line 97 of file ns-process.h.

References Process::target_.

Referenced by QA::check_availability(), Process::command(), HttpApp::command(), MediaApp::get_data(), QA::output(), and TcpApp::process_data().

00097 { return target_; }


Member Data Documentation

Tcl_HashTable* MediaCache::cmap_ [protected]
 

Definition at line 294 of file mcache.h.

Referenced by command(), get_data(), MediaCache(), process_data(), and ~MediaCache().

int HttpApp::id_ [protected, inherited]
 

Definition at line 61 of file http.h.

Referenced by HttpMInvalCache::check_sstate(), MediaServer::command(), command(), HttpPercInvalCache::command(), HttpMInvalCache::command(), HttpYucInvalServer::command(), HttpApp::command(), HttpMInvalCache::handle_node_failure(), HttpApp::HttpApp(), HttpApp::id(), HttpApp::log(), HttpMInvalCache::pack_heartbeat(), HttpYucInvalServer::pack_heartbeat(), HttpMInvalCache::pack_upd(), HttpMInvalCache::recv_heartbeat(), HttpMInvalCache::recv_leave(), and HttpMInvalCache::recv_upd().

Tcl_Channel HttpApp::log_ [protected, inherited]
 

Definition at line 63 of file http.h.

Referenced by HttpApp::command(), and HttpApp::log().

ClientPagePool* HttpApp::pool_ [protected, inherited]
 

Definition at line 62 of file http.h.

Referenced by MediaServer::command(), HttpPercInvalCache::command(), HttpMInvalCache::command(), HttpYucInvalServer::command(), HttpApp::command(), get_data(), MediaServer::get_next_segment(), HttpMInvalCache::invalidate_server(), MediaClient::mpool(), mpool(), HttpMInvalCache::process_inv(), HttpMInvalCache::recv_leave(), HttpMInvalCache::recv_upd(), and HttpApp::set_pagepool().

enum { ... } MediaCache::pref_style_ [protected]
 

Referenced by command(), and get_data().

Process* Process::target_ [protected, inherited]
 

Definition at line 113 of file ns-process.h.

Referenced by HttpUInvalAgent::command(), Process::Process(), HttpUInvalAgent::process_data(), Process::send_data(), and Process::target().

Tcl_HashTable* HttpApp::tpa_ [protected, inherited]
 

Definition at line 60 of file http.h.

Referenced by HttpApp::add_cnc(), HttpApp::delete_cnc(), HttpApp::HttpApp(), HttpApp::lookup_cnc(), and HttpApp::~HttpApp().


The documentation for this class was generated from the following files:
Generated on Tue Apr 20 12:59:45 2004 for NS2.26SourcesOriginal by doxygen 1.3.3