#include <mcache.h>
Inheritance diagram for MediaServer:


Public Member Functions | |
| MediaServer () | |
| ~MediaServer () | |
| virtual AppData * | get_data (int &size, AppData *d) |
| void | log (const char *fmt,...) |
| int | id () const |
| virtual void | process_data (int size, AppData *d) |
| Process *& | target () |
| virtual void | send_data (int size, AppData *data=0) |
Protected Types | |
| typedef Queue< PrefInfo > | PrefInfoQ |
| typedef QueueElem< PrefInfo > | PrefInfoE |
Protected Member Functions | |
| virtual int | command (int argc, const char *const *argv) |
| MediaSegment | get_next_segment (MediaRequest *r, Application *&ci) |
| PrefInfoE * | find_prefinfo (PrefInfoQ *q, Application *conid) |
| PrefInfoQ * | get_piq (const char *pgname, HttpApp *client) |
| RegInfo * | get_reginfo (Application *app) |
| int | add_cnc (HttpApp *client, TcpApp *agt) |
| void | delete_cnc (HttpApp *client) |
| TcpApp * | lookup_cnc (HttpApp *client) |
| void | set_pagepool (ClientPagePool *pp) |
Protected Attributes | |
| Tcl_HashTable * | pref_ |
| Tcl_HashTable * | cmap_ |
| Tcl_HashTable * | tpa_ |
| int | id_ |
| ClientPagePool * | pool_ |
| Tcl_Channel | log_ |
| Process * | target_ |
|
|
Definition at line 445 of file mcache.h. Referenced by command(). |
|
|
|
|
|
Definition at line 1162 of file mcache.cc.
01162 : HttpServer() 01163 { 01164 pref_ = new Tcl_HashTable; 01165 Tcl_InitHashTable(pref_, 2); 01166 cmap_ = new Tcl_HashTable; 01167 Tcl_InitHashTable(cmap_, TCL_ONE_WORD_KEYS); 01168 } |
|
|
Definition at line 1170 of file mcache.cc. References cmap_, MediaSegmentList::destroy(), pref_, and MediaServer::PrefInfo::sl_.
01171 {
01172 Tcl_HashEntry *he;
01173 Tcl_HashSearch hs;
01174 if (pref_ != NULL) {
01175 for (he = Tcl_FirstHashEntry(pref_, &hs); he != NULL;
01176 he = Tcl_NextHashEntry(&hs)) {
01177 PrefInfo *pi = (PrefInfo*)Tcl_GetHashValue(he);
01178 pi->sl_->destroy();
01179 delete pi->sl_;
01180 }
01181 Tcl_DeleteHashTable(pref_);
01182 delete pref_;
01183 }
01184 if (cmap_ != NULL) {
01185 for (he = Tcl_FirstHashEntry(cmap_, &hs); he != NULL;
01186 he = Tcl_NextHashEntry(&hs))
01187 delete (RegInfo*)Tcl_GetHashValue(he);
01188 Tcl_DeleteHashTable(cmap_);
01189 delete cmap_;
01190 }
01191 }
|
Here is the call graph for this function:

|
||||||||||||
|
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 }
|
|
||||||||||||
|
Reimplemented from HttpApp. Definition at line 1315 of file mcache.cc. References MediaSegmentList::add(), MediaServer::RegInfo::client_, cmap_, HttpApp::command(), MediaServer::PrefInfo::conid_, QueueElem< T >::data(), MediaSegmentList::destroy(), Queue< T >::detach(), Queue< T >::enqueue(), ClientPagePool::enter_page(), find_prefinfo(), ClientPagePool::get_page(), HttpApp::id_, Queue< T >::is_empty(), MAX_LAYER, MEDIA, MediaServer::RegInfo::name_, HttpApp::pool_, pref_, PrefInfoE, MediaServer::PrefInfo::sl_, and ClientPage::type().
01316 {
01317 Tcl& tcl = Tcl::instance();
01318 if (argc == 3) {
01319 if (strcmp(argv[1], "is-media-page") == 0) {
01320 ClientPage *pg = pool_->get_page(argv[2]);
01321 if (pg && (pg->type() == MEDIA))
01322 tcl.result("1");
01323 else
01324 tcl.result("0");
01325 return TCL_OK;
01326 }
01327 } else if (argc == 5) {
01328 if (strcmp(argv[1], "stop-prefetching") == 0) {
01329 /*
01330 * <server> stop-prefetching <Client> <conid> <pagenum>
01331 */
01332 TclObject *a = TclObject::lookup(argv[2]);
01333 assert(a != NULL);
01334 int tmp[2];
01335 tmp[0] = (int)a;
01336 tmp[1] = atoi(argv[4]);
01337 Tcl_HashEntry *he =
01338 Tcl_FindHashEntry(pref_, (const char*)tmp);
01339 if (he == NULL) {
01340 tcl.add_errorf(
01341 "Server %d cannot stop prefetching!\n", id_);
01342 return TCL_ERROR;
01343 }
01344 a = TclObject::lookup(argv[3]);
01345 assert(a != NULL);
01346 PrefInfoQ *q = (PrefInfoQ*)Tcl_GetHashValue(he);
01347 PrefInfoE *pe = find_prefinfo(q, (Application*)a);
01348 assert(pe != NULL);
01349 PrefInfo *pi = pe->data();
01350 MediaSegmentList *p = pi->sl_;
01351 assert(p != NULL);
01352 for (int i = 0; i < MAX_LAYER; i++)
01353 p[i].destroy();
01354 delete []p;
01355 delete pi;
01356 q->detach(pe);
01357 delete pe;
01358 // If no more prefetching streams left for this client,
01359 // delete all the information.
01360 // Return 0 means that we still have prefetching
01361 // clients left, don't tear down the channel yet.
01362 // Otherwise return 1.
01363 int res = 0;
01364 if (q->is_empty()) {
01365 delete q;
01366 Tcl_DeleteHashEntry(he);
01367 res = 1;
01368 }
01369 tcl.resultf("%d", res);
01370 return (TCL_OK);
01371 } else if (strcmp(argv[1], "register-client") == 0) {
01372 // <cache> register-client <app> <client> <pageid>
01373 TclObject *a = TclObject::lookup(argv[2]);
01374 assert(a != NULL);
01375 int newEntry;
01376 Tcl_HashEntry *he = Tcl_CreateHashEntry(cmap_,
01377 (const char *)a, &newEntry);
01378 if (he == NULL) {
01379 tcl.add_errorf("cannot create hash entry");
01380 return TCL_ERROR;
01381 }
01382 if (!newEntry) {
01383 tcl.add_errorf("duplicate connection");
01384 return TCL_ERROR;
01385 }
01386 RegInfo *p = new RegInfo;
01387 p->client_ = (HttpApp*)TclObject::lookup(argv[3]);
01388 assert(p->client_ != NULL);
01389 strcpy(p->name_, argv[4]);
01390 Tcl_SetHashValue(he, (ClientData)p);
01391 return TCL_OK;
01392 } else if (strcmp(argv[1], "unregister-client") == 0) {
01393 // <cache> unregister-client <app> <client> <pageid>
01394 TclObject *a = TclObject::lookup(argv[2]);
01395 assert(a != NULL);
01396 Tcl_HashEntry *he =
01397 Tcl_FindHashEntry(cmap_, (const char*)a);
01398 if (he == NULL) {
01399 tcl.add_errorf("cannot find hash entry");
01400 return TCL_ERROR;
01401 }
01402 RegInfo *p = (RegInfo*)Tcl_GetHashValue(he);
01403 delete p;
01404 Tcl_DeleteHashEntry(he);
01405 return TCL_OK;
01406 }
01407 } else {
01408 if (strcmp(argv[1], "enter-page") == 0) {
01409 ClientPage *pg = pool_->enter_page(argc, argv);
01410 if (pg == NULL)
01411 return TCL_ERROR;
01412 if (pg->type() == MEDIA)
01413 ((MediaPage*)pg)->create();
01414 // Unlock the page after creation
01415 ((MediaPage*)pg)->unlock();
01416 return TCL_OK;
01417 } else if (strcmp(argv[1], "register-prefetch") == 0) {
01418 /*
01419 * <server> register-prefetch <client> <pagenum>
01420 * <conid> <layer> {<segments>}
01421 * Registers a list of segments to be prefetched by
01422 * <client>, where each <segment> is a pair of
01423 * (start, end). <pagenum> should be pageid without
01424 * preceding [server:] prefix.
01425 *
01426 * <conid> is the OTcl name of the original client
01427 * who requested the page. This is used for the cache
01428 * to get statistics about a particular connection.
01429 *
01430 * <client> is the requestor of the stream.
01431 */
01432 TclObject *a = TclObject::lookup(argv[2]);
01433 assert(a != NULL);
01434 int newEntry = 1;
01435 int tmp[2];
01436 tmp[0] = (int)a;
01437 tmp[1] = atoi(argv[3]);
01438 // Map <cache_ptr><conid> to a pref entry
01439 Tcl_HashEntry *he = Tcl_CreateHashEntry(pref_,
01440 (const char*)tmp, &newEntry);
01441 if (he == NULL) {
01442 fprintf(stderr, "Cannot create entry.\n");
01443 return TCL_ERROR;
01444 }
01445 PrefInfo *pi;
01446 PrefInfoE *pe;
01447 PrefInfoQ *q;
01448 MediaSegmentList *p;
01449 a = TclObject::lookup(argv[4]);
01450 if (newEntry) {
01451 q = new PrefInfoQ;
01452 Tcl_SetHashValue(he, (ClientData)q);
01453 pe = NULL;
01454 } else {
01455 q = (PrefInfoQ *)Tcl_GetHashValue(he);
01456 pe = find_prefinfo(q, (Application*)a);
01457 }
01458 if (pe == NULL) {
01459 pi = new PrefInfo;
01460 pi->conid_ = (Application*)a;
01461 p = pi->sl_ = new MediaSegmentList[MAX_LAYER];
01462 q->enqueue(new PrefInfoE(pi));
01463 } else {
01464 pi = pe->data();
01465 p = pi->sl_;
01466 }
01467 assert((pi != NULL) && (p != NULL));
01468 // Preempt all old requests because they
01469 // cannot reach the cache "in time"
01470 int layer = atoi(argv[5]);
01471 p[layer].destroy();
01472 // Add segments into prefetching list
01473 assert(argc % 2 == 0);
01474 for (int i = 6; i < argc; i+=2)
01475 p[layer].add(MediaSegment(atoi(argv[i]),
01476 atoi(argv[i+1])));
01477 return TCL_OK;
01478 }
01479 }
01480
01481 return HttpServer::command(argc, argv);
01482 }
|
Here is the call graph for this function:

|
|
Definition at line 82 of file http.cc. References client, and HttpApp::tpa_. Referenced by HttpApp::command().
|
|
||||||||||||
|
Definition at line 446 of file mcache.h. References QueueElem< T >::data(), Queue< T >::getHead(), and QueueElem< T >::next(). Referenced by command().
00446 {
00447 for (PrefInfoE *e = q->getHead(); e != NULL; e = e->next())
00448 if (e->data()->conid_ == conid)
00449 return e;
00450 return NULL;
00451 }
|
Here is the call graph for this function:

|
||||||||||||
|
Reimplemented from HttpApp. Definition at line 1268 of file mcache.cc. References abort(), MediaSegment::datasize(), MediaSegment::end(), get_next_segment(), MediaSegment::is_last(), MediaSegment::is_pref(), MediaRequest::layer(), MEDIA_REQUEST, MEDIAREQ_CHECKSEG, MEDIAREQ_GETSEG, MediaRequest::name(), req, MediaRequest::request(), HttpMediaData::set_conid(), HttpMediaData::set_finish(), HttpMediaData::set_last(), HttpMediaData::set_pref(), and MediaSegment::start().
01269 {
01270 assert((req != NULL) && (req->type() == MEDIA_REQUEST));
01271 MediaRequest *r = (MediaRequest *)req;
01272 Application* conid = NULL;
01273
01274 if (r->request() == MEDIAREQ_GETSEG) {
01275 // Get a new data segment
01276 MediaSegment s2 = get_next_segment(r, conid);
01277 HttpMediaData *p;
01278 if (s2.datasize() == 0) {
01279 // No more data available for this layer, most likely
01280 // it's because this layer is finished.
01281 size = 0;
01282 p = new HttpMediaData(name(), r->name(),
01283 r->layer(), 0, 0);
01284 } else {
01285 size = s2.datasize();
01286 p = new HttpMediaData(name(), r->name(),
01287 r->layer(), s2.start(), s2.end());
01288 }
01289 if (s2.is_last()) {
01290 p->set_last();
01291 // Tear down the connection after we've sent the last
01292 // segment of the base layer and are requested again.
01293 if ((s2.datasize() == 0) && (r->layer() == 0))
01294 p->set_finish();
01295 }
01296 if (s2.is_pref()) {
01297 // Add connection id into returned data
01298 p->set_conid(conid);
01299 p->set_pref();
01300 }
01301 return p;
01302 } else if (r->request() == MEDIAREQ_CHECKSEG)
01303 // We don't need to return anything, so just NULL
01304 return NULL;
01305 else {
01306 fprintf(stderr,
01307 "MediaServer %s gets an unknown MediaRequest type %d\n",
01308 name(), r->request());
01309 abort();
01310 }
01311 /*NOTREACHED*/
01312 return NULL; // Make msvc happy
01313 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1194 of file mcache.cc. References MediaRequest::app(), MediaServer::RegInfo::client_, MediaServer::PrefInfo::conid_, QueueElem< T >::data(), MediaRequest::datasize(), MediaSegment::datasize(), Queue< T >::dequeue(), MediaSegment::end(), Queue< T >::enqueue(), MediaRequest::et(), MediaSegmentList::get_nextseg(), ClientPagePool::get_page(), get_piq(), get_reginfo(), Queue< T >::is_empty(), MediaRequest::layer(), MediaPage::layer_size(), MediaSegmentList::length(), MediaRequest::name(), MediaPage::next_overlap(), MediaPage::num_layer(), HttpApp::pool_, MediaSegment::set_end(), MediaRequest::set_layer(), MediaSegment::set_pref(), MediaSegment::set_start(), Queue< T >::size(), MediaServer::PrefInfo::sl_, MediaRequest::st(), and MediaSegment::start(). Referenced by get_data().
01195 {
01196 MediaPage* pg = (MediaPage*)pool_->get_page(r->name());
01197 assert(pg != NULL);
01198
01199 // XXX Extremely hacky way to map media app names to
01200 // HTTP connections. Should maintain another hash table for this.
01201 RegInfo *ri = get_reginfo(r->app());
01202 assert(ri != NULL);
01203 PrefInfoQ* q = get_piq(r->name(), ri->client_);
01204
01205 // We are not on the prefetching list, send a normal data segment
01206 if ((q == NULL) || (q->is_empty())) {
01207 MediaSegment s1(r->st(), r->et());
01208 return pg->next_overlap(r->layer(), s1);
01209 }
01210
01211 // Cycle through the prefetched segments that we need to send
01212 int found = 0;
01213 int searched = 0;
01214 PrefInfo *pi;
01215 while (!found) {
01216 PrefInfoE *pe = q->dequeue();
01217 pi = pe->data();
01218 q->enqueue(pe);
01219 // If there's a pending segment in any layer, send it
01220 for (int i = 0; i < pg->num_layer(); i++)
01221 if (pi->sl_[i].length() > 0)
01222 found = 1;
01223 // If no pending prefetched segments, return empty
01224 if (searched++ == q->size())
01225 return MediaSegment(0, 0);
01226 }
01227
01228 // Send a segment from the prefetching list. Only use the data size
01229 // included in the request.
01230 MediaSegmentList *p = pi->sl_;
01231 // Set return conid
01232 ci = pi->conid_;
01233
01234 // Find one available segment in prefetching list if there is none
01235 // in the given layer
01236 int l = r->layer(), i = 0;
01237 MediaSegment res;
01238 while ((res.datasize() == 0) && (i < pg->num_layer())) {
01239 // next() doesn't work. Need a method that returns the
01240 // *FIRST* non-empty segment which satisfies the size
01241 // constraint.
01242 res = p[l].get_nextseg(MediaSegment(0, r->datasize()));
01243 i++;
01244 l = (l+1) % pg->num_layer();
01245 }
01246 // XXX We must do boundary check of the prefetched segments to make
01247 // sure that the start and end offsets are valid!
01248 if (res.start() < 0)
01249 res.set_start(0);
01250 if (res.end() > pg->layer_size(l))
01251 res.set_end(pg->layer_size(l));
01252 if (res.datasize() > 0) {
01253 // XXX We may end up getting data from another layer!!
01254 l = (l-1+pg->num_layer()) % pg->num_layer();
01255 if (l != r->layer())
01256 r->set_layer(l);
01257 // We may not be able to get the specified data size, due
01258 // to arbitrary stream lengths
01259 //assert(res.datasize() == r->datasize());
01260 p[r->layer()].evict_head(r->datasize());
01261 }
01262 // Set the prefetching flag of this segment
01263 res.set_pref();
01264 return res;
01265 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 456 of file mcache.h. References client, HttpApp::id(), PageID::id_, pref_, and ClientPage::split_name(). Referenced by get_next_segment().
00456 {
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 }
|
Here is the call graph for this function:

|
|
Definition at line 468 of file mcache.h. References abort(), and cmap_. Referenced by get_next_segment().
00468 {
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 }
|
Here is the call graph for this function:

|
|
Definition at line 44 of file http.h. References HttpApp::id_. Referenced by HttpMInvalCache::add_cache(), HttpMInvalCache::add_nbr(), HttpMInvalCache::command(), get_piq(), ClientPagePool::invalidate_server(), and HttpMInvalCache::process_inv().
00044 { return id_; }
|
|
||||||||||||
|
Definition at line 356 of file http.cc. References HttpApp::id_, Scheduler::instance(), HttpApp::log_, BaseTrace::round(), and TIME_FORMAT. Referenced by MediaClient::command(), MediaCache::command(), HttpMInvalCache::command(), HttpYucInvalServer::command(), MediaClient::process_data(), MediaCache::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:

|
|
Definition at line 92 of file http.cc. References client, and HttpApp::tpa_. Referenced by HttpApp::command().
|
|
||||||||||||
|
Reimplemented from Process. Reimplemented in HttpMInvalCache, MediaCache, and MediaClient. Definition at line 372 of file http.cc. References abort(), HTTP_NORMAL, HttpNormalData::str(), and AppData::type(). Referenced by MediaClient::process_data(), MediaCache::process_data(), and HttpMInvalCache::process_data().
00373 {
00374 if (data == NULL)
00375 return;
00376
00377 switch (data->type()) {
00378 case HTTP_NORMAL: {
00379 HttpNormalData *tmp = (HttpNormalData*)data;
00380 Tcl::instance().eval(tmp->str());
00381 break;
00382 }
00383 default:
00384 fprintf(stderr, "Bad http invalidation data type %d\n",
00385 data->type());
00386 abort();
00387 break;
00388 }
00389 }
|
Here is the call graph for this function:

|
||||||||||||
|
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:

|
|
Definition at line 58 of file http.h. References HttpApp::pool_.
00058 { pool_ = pp; }
|
|
|
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_; }
|
|
|
Definition at line 454 of file mcache.h. Referenced by command(), get_reginfo(), MediaServer(), and ~MediaServer(). |
|
|
|
Definition at line 63 of file http.h. Referenced by HttpApp::command(), and HttpApp::log(). |
|
|
|
Definition at line 453 of file mcache.h. Referenced by command(), get_piq(), MediaServer(), and ~MediaServer(). |
|
|
Definition at line 113 of file ns-process.h. Referenced by HttpUInvalAgent::command(), Process::Process(), HttpUInvalAgent::process_data(), Process::send_data(), and Process::target(). |
|
|
Definition at line 60 of file http.h. Referenced by HttpApp::add_cnc(), HttpApp::delete_cnc(), HttpApp::HttpApp(), HttpApp::lookup_cnc(), and HttpApp::~HttpApp(). |
1.3.3