⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcache.cc

📁 柯老师网站上找到的
💻 CC
📖 第 1 页 / 共 3 页
字号:
	abort();	return 0; // Make msvc happy}int MClientPagePool::repl_finegrain(ClientPage *, int size){	// Traverse through hit count table, evict segments from the tail	// of a layer with minimum hit counts	HitCount *h, *p;	int sz, totalsz = 0;	// Repeatedly evict pages/segments until get enough space	h = (HitCount*)hclist_.tail();	while (h != NULL) {		MediaPage *pg = (MediaPage *)h->page();		// XXX Don't touch locked pages		if (pg->is_tlocked() || pg->is_locked()) {			h = h->prev();			continue;		}		// Try to get "size" space by evicting other segments		sz = pg->evict_tail_segment(h->layer(), size);		// Decrease the cache used space		used_size_ -= sz;		totalsz += sz;		// If we have not got enough space, we must have got rid of 		// the entire layer		assert((sz == size) || 		       ((sz < size) && (pg->layer_size(h->layer()) == 0)));		// If we don't have anything of this layer left, get rid of 		// the hit count record. 		// XXX Must do this BEFORE removing the page		p = h;		h = h->prev();		if (pg->layer_size(p->layer()) == 0) {			// XXX Should NEVER delete a hit count record!!			// A hit count record is ONLY deleted when the page			// is deleted (evicted from cache: ~MediaPage())			hclist_.detach(p);			p->reset();		}		// Furthermore, if the page has nothing left, get rid of it		if (pg->realsize() == 0) {			// NOTE: we do not manually remove hit counts of 			// this page because if its realsize is 0, all 			// hit count records must have already been 			// detached from the page. 			char tmp[HTTP_MAXURLLEN];			pg->name(tmp);#if 0			fprintf(stderr, "At time %g, fine-grain evicted page %s\n",				Scheduler::instance().clock(), tmp);			fprintf(stderr, "Hit count list: \n");			hclist_.print();			fprintf(stderr,				"---------------------------------------\n\n");#endif			// Then the hit count record will be deleted in here			remove_page(tmp);		}		// If we've got enough space, return; otherwise continue		if (sz >= size)			return totalsz;		size -= sz;	// Evict to fill the rest	}	fprintf(stderr, "Cache replacement cannot get enough space.\n");	abort();	return 0; // Make msvc happy}// Clean all hit count record of a page regardless of whether it's in the // hit count list. Used when hclist_ is not used at all, e.g., by MediaClient.int MClientPagePool::force_remove(const char *name){	// XXX Bad hack. Needs to integrate this into ClientPagePool.	ClientPage *pg = (ClientPage*)get_page(name);	// We should not remove a non-existent page!!	assert(pg != NULL);	if (pg->type() == MEDIA) {		HitCount *p;		MediaPage *q = (MediaPage*)pg;		used_size_ -= q->realsize();		for (int i = 0; i < q->num_layer(); i++) {			p = q->get_hit_count(i);			hclist_.detach(p);		}	} else if (pg->type() == HTML)		used_size_ -= pg->size();	return ClientPagePool::remove_page(name);}int MClientPagePool::remove_page(const char *name){	// XXX Bad hack. Needs to integrate this into ClientPagePool.	ClientPage *pg = (ClientPage*)get_page(name);	// We should not remove a non-existent page!!	assert(pg != NULL);	if (pg->type() == MEDIA)		used_size_ -= ((MediaPage *)pg)->realsize();	else if (pg->type() == HTML)		used_size_ -= pg->size();	return ClientPagePool::remove_page(name);}//------------------------------------------------------------// MediaPagePool// Generate requests and pages for clients and servers //------------------------------------------------------------static class MediaPagePoolClass : public TclClass {public:        MediaPagePoolClass() : TclClass("PagePool/Media") {}        TclObject* create(int, const char*const*) {		return (new MediaPagePool());	}} class_mediapagepool_agent;MediaPagePool::MediaPagePool() : PagePool(){	size_ = NULL;	duration_ = 0;	layer_ = 1;}// For now, only one page, fixed size, fixed layerint MediaPagePool::command(int argc, const char*const* argv){	Tcl& tcl = Tcl::instance();	if (argc == 2) {		if (strcmp(argv[1], "get-poolsize") == 0) { 			tcl.resultf("%d", num_pages_);			return TCL_OK;		} else if (strcmp(argv[1], "get-start-time") == 0) {			tcl.resultf("%.17g", start_time_);			return TCL_OK;		} else if (strcmp(argv[1], "get-duration") == 0) {			tcl.resultf("%d", duration_);			return TCL_OK;		}	} else if (argc == 3) {		if (strcmp(argv[1], "gen-pageid") == 0) {			// Generating requested page id			if (rvReq_ == NULL) {				tcl.add_errorf("no page id ranvar.");				return TCL_ERROR;			}			int p = (int)rvReq_->value();			assert((p >= 0) && (p < num_pages_));			tcl.resultf("%d", p);			return TCL_OK;		} else if (strcmp(argv[1], "is-media-page") == 0) {			// XXX Currently all pages are media pages. Should			// be able to allow both normal pages and media pages			// in the future			tcl.result("1");			return TCL_OK;		} else if (strcmp(argv[1], "get-layer") == 0) {			// XXX Currently all pages have the same number of 			// layers. Should be able to change this in future.			tcl.resultf("%d", layer_); 			return TCL_OK;		} else if (strcmp(argv[1], "set-start-time") == 0) {			double st = strtod(argv[2], NULL);			start_time_ = st;			end_time_ = st + duration_;			return TCL_OK;		} else if (strcmp(argv[1], "set-duration") == 0) {			// XXX Need this info to set page mod time!!			duration_ = atoi(argv[2]);			end_time_ = start_time_ + duration_;			return TCL_OK;		} else if (strcmp(argv[1], "gen-init-modtime") == 0) {			// XXX We are not interested in page consistency here,			// so never change this page.			tcl.resultf("%d", -1);			return TCL_OK;		} else if (strcmp(argv[1], "gen-size") == 0) {			int pagenum = atoi(argv[2]);			if (pagenum >= num_pages_) {				tcl.add_errorf("Invalid page id %d", pagenum);				return TCL_ERROR;			}			tcl.resultf("%d", size_[pagenum]);			return TCL_OK;		} else if (strcmp(argv[1], "set-layer") == 0) {			layer_ = atoi(argv[2]);			return TCL_OK;		} else if (strcmp(argv[1], "set-num-pages") == 0) {			if (size_ != NULL) {				tcl.add_errorf("can't change number of pages");				return TCL_ERROR;			}			num_pages_ = atoi(argv[2]);			size_ = new int[num_pages_];			return TCL_OK;		} else if (strcmp(argv[1], "ranvar-req") == 0) {			rvReq_ = (RandomVariable*)TclObject::lookup(argv[2]);			return TCL_OK;		}	} else if (argc == 4) {		if (strcmp(argv[1], "gen-modtime") == 0) {			// This should never be called, because we never			// deals with page modifications!!			fprintf(stderr, "%s: gen-modtime called!\n", name());			abort();		} else if (strcmp(argv[1], "set-pagesize") == 0) {			// <pagepool> set-pagesize <pagenum> <size>			int pagenum = atoi(argv[2]);			if (pagenum >= num_pages_) {				tcl.add_errorf("Invalid page id %d", pagenum);				return TCL_ERROR;			}			size_[pagenum] = atoi(argv[3]);			return TCL_OK;		}	}	return PagePool::command(argc, argv);}//----------------------------------------------------------------------// PagePool that generates requests using the SURGE model//// Part of the code by Paul Barford (barford@cs.bu.edu).// Copyright (c) 1997 Trustees of Boston University//// Allow two options: (1) setting if all pages are media page or normal// HTTP pages; (2) average page size//----------------------------------------------------------------------//  static class SurgePagePoolClass : public TclClass {//  public://          SurgePagePoolClass() : TclClass("PagePool/Surge") {}//          TclObject* create(int, const char*const*) {//  		return (new SurgePagePool());//  	}//  } class_surgepagepool_agent;//  SurgePagePool::SurgePagePool() : PagePool()//  {//  }//----------------------------------------------------------------------// Multimedia web applications: cache, etc.//----------------------------------------------------------------------static class MediaCacheClass : public TclClass {public:	MediaCacheClass() : TclClass("Http/Cache/Media") {}	TclObject* create(int, const char*const*) {		return (new MediaCache());	}} class_mediacache;// By default we use online prefetchingMediaCache::MediaCache() : pref_style_(ONLINE_PREF){	cmap_ = new Tcl_HashTable;	Tcl_InitHashTable(cmap_, TCL_ONE_WORD_KEYS);}MediaCache::~MediaCache(){	Tcl_HashEntry *he;	Tcl_HashSearch hs;	if (cmap_) {		for (he = Tcl_FirstHashEntry(cmap_, &hs);  he != NULL;		     he = Tcl_NextHashEntry(&hs))			delete (RegInfo*)Tcl_GetHashValue(he);		Tcl_DeleteHashTable(cmap_);		delete cmap_;	}}AppData* MediaCache::get_data(int& size, AppData* req){	assert(req != NULL);	if (req->type() != MEDIA_REQUEST) {		return HttpApp::get_data(size, req);	}	MediaRequest *r = (MediaRequest *)req;	// Get statistics block for the requestor	Tcl_HashEntry *he = 		Tcl_FindHashEntry(cmap_, (const char *)(r->app()));	assert(he != NULL);	RegInfo *ri = (RegInfo *)Tcl_GetHashValue(he);	// Process request	if (r->request() == MEDIAREQ_GETSEG) {		// Get a new data segment		MediaPage* pg = (MediaPage*)pool_->get_page(r->name());		assert(pg != NULL);		MediaSegment s1(r->st(), r->et());		MediaSegment s2 = pg->next_overlap(r->layer(), s1);		HttpMediaData *p;		if (s2.datasize() == 0) {			// No more data available for this layer, allocate			// an ADU with data size 0 to signal the end			// of transmission for this layer			size = 0;			p = new HttpMediaData(name(), r->name(),					      r->layer(), 0, 0);		} else {			size = s2.datasize();			p = new HttpMediaData(name(), r->name(),					   r->layer(), s2.start(), s2.end());		}		// XXX If we are still receiving the stream, don't 		// ever say that this is the last segment. If the 		// page is not locked, it's still possible that we		// return a NULL segment because the requested one		// is not available. Don't set the 'LAST' flag in this 		// case.		if (s2.is_last()) {			p->set_last();			if (!pg->is_locked() && (s2.datasize() == 0) && 			    (r->layer() == 0)) 				p->set_finish();		}		//----------------------------------------		// Update statistics of this connection		//----------------------------------------		// Update the highest layer that this client has requested		if (ri->hl_ < r->layer())			ri->hl_ = r->layer();		if (size > 0) {			// Update total delivered bytes			ri->db_[r->layer()] += size;			// Update prefetched bytes that've been delivered			ri->eb_[r->layer()] += ri->pref_size(r->layer(), s2);		}		return p;	} else if (r->request() == MEDIAREQ_CHECKSEG) {		// If we are not doing online prefetching, return nothing		if (pref_style_ != ONLINE_PREF)			return NULL;		// Check the availability of a new data segment		// And refetch if it is not available		MediaPage* pg = (MediaPage*)pool_->get_page(r->name());		assert(pg != NULL);		if (pg->is_locked()) 			// If we are during the first retrieval, don't prefetch			return NULL;		MediaSegmentList ul = pg->is_available(r->layer(),				      MediaSegment(r->st(),r->et()));		if (ul.length() == 0)			// All segments are available			return NULL;		// Otherwise do prefetching on these "holes"		char *buf = ul.dump2buf();		Tcl::instance().evalf("%s pref-segment %s %s %d %s", name(), 				      r->app()->name(), r->name(), 				      r->layer(), buf);//  		log("E PREF p %s l %d %s\n", r->name(), r->layer(), buf);		delete []buf;		ul.destroy();		// Update the highest layer that this client has requested		Tcl_HashEntry *he = 			Tcl_FindHashEntry(cmap_, (const char *)(r->app()));		assert(he != NULL);		RegInfo *ri = (RegInfo *)Tcl_GetHashValue(he);		if (ri->hl_ < r->layer())			ri->hl_ = r->layer();		return NULL;	}			fprintf(stderr, 		"MediaCache %s gets an unknown MediaRequest type %d\n",		name(), r->request());	abort();	return NULL; // Make msvc happy}// Add received media segment into page poolvoid MediaCache::process_data(int size, AppData* data) {	switch (data->type()) {	case MEDIA_DATA: {		HttpMediaData* d = (HttpMediaData*)data;		// Cache this segment, do replacement if necessary		if (mpool()->add_segment(d->page(), d->layer(), 					 MediaSegment(*d)) == -1) {			fprintf(stderr, "MediaCache %s gets a segment for an "				"unknown page %s\n", name(), d->page());			abort();		}		if (d->is_pref()) {			// Update total prefetched bytes			Tcl_HashEntry *he = Tcl_FindHashEntry(cmap_, 						(const char*)(d->conid()));			// Client-cache-server disconnection procedure:			// (1) client disconnects from cache, then			// (2) cache disconnects from server and shuts down 			//     prefetching channel. 			// Therefore, after client disconnects, the cache 			// may still receive a few prefetched segments. 			// Ignore those because we no longer keep statistics			// about the torn-down connection.			if (he != NULL) {				RegInfo *ri = (RegInfo *)Tcl_GetHashValue(he);				ri->add_pref(d->layer(), MediaSegment(*d));				ri->pb_[d->layer()] += d->datasize();			}		}		// XXX debugging only#if 1  		log("E RSEG p %s l %d s %d e %d z %d f %d\n",   		    d->page(), d->layer(), d->st(), d->et(), d->datasize(),  		    d->is_pref());#endif		break;	} 	default:		HttpCache::process_data(size, data);	}}int MediaCache::command(int argc, const char*const* argv) {	Tcl& tcl = Tcl::instance();	if (argc == 2) {		if (strcmp(argv[1], "get-pref-style") == 0) {			switch (pref_style_) {			case NOPREF:				tcl.result("NOPREF");				break;			case ONLINE_PREF:				tcl.result("ONLINE_PREF");				break;			case OFFLINE_PREF:				tcl.result("OFFLINE_PREF");				break;			default:				fprintf(stderr, 					"Corrupted prefetching style %d", 					pref_style_);				return TCL_ERROR;			}			return TCL_OK;		}	} else if (argc == 3) {		if (strcmp(argv[1], "offline-complete") == 0) {			// Delete whatever segments in the given page, 			// make it complete. Used by offline prefetching			ClientPage *pg = mpool()->get_page(argv[2]);			if (pg == NULL)				// XXX It's possible that we've already kicked				// it out of the cache. Do nothing.				return TCL_OK;			assert(pg->type() == MEDIA);			assert(!((MediaPage*)pg)->is_locked());			mpool()->fill_page(argv[2]);			return TCL_OK;		} else if (strcmp(argv[1], "set-pref-style") == 0) {			// Set prefetching style			// <obj> set-pref-style <style>			//			// style can be: NOPREF, ONLINE_PREF, OFFLINE_PREF			if (strcmp(argv[2], "NOPREF") == 0) 				pref_style_ = NOPREF;			else if (strcmp(argv[2], "ONLINE_PREF") == 0) 				pref_style_ = ONLINE_PREF;			else if (strcmp(argv[2], "OFFLINE_PREF") == 0) 				pref_style_ = OFFLINE_PREF;			else {				fprintf(stderr, "Wrong prefetching style %s",					argv[2]);				return TCL_ERROR;			}			return TCL_OK;		} else if (strcmp(argv[1], "dump-page") == 0) {			// Dump segments of a given page			ClientPage *p=(ClientPage*)mpool()->get_page(argv[2]);			if (p->type() != MEDIA)				// Do nothing for non-media pages				return TCL_OK;			MediaPage *pg = (MediaPage *)p;			char *buf;			for (int i = 0; i < pg->num_layer(); i++) {				buf = pg->print_layer(i);				if (strlen(buf) > 0)					log("E SEGS p %s l %d %s\n", argv[2], 					    i, buf);				delete []buf;			}			return TCL_OK;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -