📄 pagepool.cc
字号:
// cache size here!! return 0;}int ClientPagePool::set_mtime(const char *name, double mt){ ClientPage *pg = (ClientPage *)get_page(name); if (pg == NULL) return -1; pg->mtime() = mt; return 0;}int ClientPagePool::get_mtime(const char *name, double& mt){ ClientPage *pg = (ClientPage *)get_page(name); if (pg == NULL) return -1; mt = pg->mtime(); return 0;}int ClientPagePool::set_etime(const char *name, double et){ ClientPage *pg = (ClientPage *)get_page(name); if (pg == NULL) return -1; pg->etime() = et; return 0;}int ClientPagePool::get_etime(const char *name, double& et){ ClientPage *pg = (ClientPage *)get_page(name); if (pg == NULL) return -1; et = pg->etime(); return 0;}int ClientPagePool::get_size(const char *name, int& size) { ClientPage *pg = (ClientPage *)get_page(name); if (pg == NULL) return -1; size = pg->size(); return 0;}int ClientPagePool::get_age(const char *name, double& age) { ClientPage *pg = (ClientPage *)get_page(name); if (pg == NULL) return -1; age = pg->age(); return 0;}void ClientPagePool::invalidate_server(int sid){ Tcl_HashEntry *he; Tcl_HashSearch hs; ClientPage *pg; int i; for (i = 0, he = Tcl_FirstHashEntry(namemap_, &hs); he != NULL; he = Tcl_NextHashEntry(&hs), i++) { pg = (ClientPage *) Tcl_GetHashValue(he); if (pg->server()->id() == sid) pg->server_down(); }}// Proxy traces. Request file format://// [<time> <clientID> <serverID> <URL_ID>]// i <Duration> <Number_of_unique_URLs>//// <time> is guaranteed to start from 0. It needs to be adjusted//// Page file format (sorted by access counts)// // <serverID> <URL_ID> <PageSize> <AccessCount>static class ProxyTracePagePoolClass : public TclClass {public: ProxyTracePagePoolClass() : TclClass("PagePool/ProxyTrace") {} TclObject* create(int, const char*const*) { return (new ProxyTracePagePool()); }} class_ProxyTracepagepool_agent;ProxyTracePagePool::ProxyTracePagePool() : rvDyn_(NULL), rvStatic_(NULL), br_(0), size_(NULL), reqfile_(NULL), req_(NULL), lastseq_(0){}ProxyTracePagePool::~ProxyTracePagePool(){ if (size_ != NULL) delete []size_; if (reqfile_ != NULL) fclose(reqfile_); if (req_ != NULL) { Tcl_DeleteHashTable(req_); delete req_; }}int ProxyTracePagePool::init_req(const char *fn) { reqfile_ = fopen(fn, "r"); if (reqfile_ == NULL) { fprintf(stderr, "ProxyTracePagePool: couldn't open trace file %s\n", fn); return TCL_ERROR; } // Discover information about the trace, e.g., number of pages, // start time, end time, etc. They should be available at the // first line of the trace file. return find_info();}int ProxyTracePagePool::find_info(){ // Read the last line of the file fseek(reqfile_, -128, SEEK_END); char buf[129]; if (fread(buf, 1, 128, reqfile_) != 128) { fprintf(stderr, "ProxyTracePagePool: cannot read file information\n"); return TCL_ERROR; } int i; // ignore the last RETURN buf[128] = 0; if (buf[127] == '\n') buf[127] = 0; for (i = 127; i >= 0; i--) if (buf[i] == '\n') { i++; break; } if (buf[i] != 'i') { fprintf(stderr, "ProxyTracePagePool: trace file doesn't contain statistics.\n"); abort(); } double len; sscanf(buf+i+1, "%lf %u", &len, &num_pages_); duration_ = (int)ceil(len);#if 0 printf("ProxyTracePagePool: duration %d pages %u\n", duration_, num_pages_);#endif rewind(reqfile_); return TCL_OK;}// Load page size info. Assuming request stream has already been loadedint ProxyTracePagePool::init_page(const char *fn){ FILE *fp = fopen(fn, "r"); if (fp == NULL) { fprintf(stderr, "ProxyTracePagePool: couldn't open trace file %s\n", fn); return TCL_ERROR; } if (size_ != NULL) delete []size_; int* p = new int[num_pages_]; size_ = p; for (int i = 0; i < num_pages_; i++, p++) fscanf(fp, "%*d %*d %d %*u\n", p); fclose(fp); return TCL_OK;}ProxyTracePagePool::ClientRequest* ProxyTracePagePool::load_req(int cid){ // Find out which client we are seeking Tcl_HashEntry *he; ClientRequest *p; int dummy; if ((he = Tcl_FindHashEntry(req_, (const char*)cid)) == NULL) { // New entry p = new ClientRequest(); p->seq_ = lastseq_++; he = Tcl_CreateHashEntry(req_, (const char*)cid, &dummy); Tcl_SetHashValue(he, (const char*)p); // Search from the beginning of file for this new client fseek(reqfile_, 0, SEEK_SET); } else { p = (ClientRequest*)Tcl_GetHashValue(he); if (p->nrt_ == -1) // No more requests for this client return p; // Clear EOF status fseek(reqfile_, p->fpos_, SEEK_SET); } // Looking for the next available request for this client double nrt; int ncid = -1, nurl; char buf[256]; while (fgets(buf, 256, reqfile_)) { if (isalpha(buf[0])) { // Last line, break; ncid = -1; break; } sscanf(buf, "%lf %d %*d %d\n", &nrt, &ncid, &nurl); if ((ncid % nclient_) == p->seq_) break; } if ((ncid % nclient_) != p->seq_) // Didn't find the next request for this client p->nrt_ = -1; else { p->nrt_ = nrt, p->nurl_ = nurl; p->nrt_ += start_time_; } p->fpos_ = ftell(reqfile_); return p;}// Provide a tcl interface compatible with MathPagePoolint ProxyTracePagePool::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 2) { if (strcmp(argv[1], "get-poolsize") == 0) { tcl.resultf("%u", 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 (strcmp(argv[1], "bimodal-ratio") == 0) { tcl.resultf("%g", br_ / 10); return TCL_OK; } } else if (argc == 3) { if (strcmp(argv[1], "set-client-num") == 0) { // Set the number of clients it'll access // Cannot be changed once set if (req_ != NULL) return TCL_ERROR; int num = atoi(argv[2]); req_ = new Tcl_HashTable; Tcl_InitHashTable(req_, TCL_ONE_WORD_KEYS); nclient_ = num; return TCL_OK; } else if (strcmp(argv[1], "gen-request") == 0) { // Use client id to get a corresponding request int id = atoi(argv[2]); ClientRequest *p = load_req(id); if ((p->nrt_ >= 0) && (p->nrt_ < Scheduler::instance().clock())) { // XXX Do NOT treat this as an error, also // do NOT disable further requests from this // client. fprintf(stderr, "%.17g: Wrong request time %g.\n", Scheduler::instance().clock(), p->nrt_); // XXX If it's a little bit older than current // time, let it be a little bit later than now p->nrt_ = Scheduler::instance().clock()+0.001; } tcl.resultf("%lf %d", p->nrt_ - Scheduler::instance().clock(), p->nurl_); return TCL_OK; } else if (strcmp(argv[1], "gen-size") == 0) { int id = atoi(argv[2]); if ((id < 0) || (id > num_pages_)) { tcl.result("PagePool: id out of range.\n"); return TCL_ERROR; } tcl.resultf("%d", size_[id]); return TCL_OK; } else if (strcmp(argv[1], "set-start-time") == 0) { start_time_ = strtod(argv[2], NULL); return TCL_OK; } else if (strcmp(argv[1], "bimodal-ratio") == 0) { // XXX Codes in Http/Server::gen-page{} also depends // on this dyn/static page algorithm. If this is // changed, that instproc must be changed too. // // percentage of dynamic pages. E.g., // if this ratio is 5, then page 0-4 is // dynamic, and page 4-99 is static, and so on. double ratio = strtod(argv[2], NULL); //br_ = (int)ceil(ratio*100); br_ = (int)ceil(ratio*10); return TCL_OK; } else if (strcmp(argv[1], "ranvar-dp") == 0) { // Page mod ranvar for dynamic pages rvDyn_ = (RandomVariable*)TclObject::lookup(argv[2]); return TCL_OK; } else if (strcmp(argv[1], "ranvar-sp") == 0) { // page mod ranvar for static pages rvStatic_= (RandomVariable*)TclObject::lookup(argv[2]); return TCL_OK; } else if (strcmp(argv[1], "set-reqfile") == 0) { return init_req(argv[2]); } else if (strcmp(argv[1], "set-pagefile") == 0) { return init_page(argv[2]); } else if (strcmp(argv[1], "gen-init-modtime") == 0) { int id = atoi(argv[2]) % 10; if (id >= br_) // Static page tcl.result("0"); else // Dynamic page tcl.resultf("%.17g", Scheduler::instance().clock()); return TCL_OK; } } else { if (strcmp(argv[1], "gen-modtime") == 0) { if ((rvDyn_ == 0) || (rvStatic_ == 0)) { tcl.add_errorf("%s: no page age generator", name_); return TCL_ERROR; } // int id = atoi(argv[2]) % 100; int id = atoi(argv[2]) % 10; double mt = strtod(argv[3], NULL); if (id >= br_) tcl.resultf("%.17g", mt + rvStatic_->value()); else tcl.resultf("%.17g", mt + rvDyn_->value()); return TCL_OK; } } return PagePool::command(argc, argv);}// Proxy trace with special method for page modificationstatic class EPAPagePoolClass : public TclClass {public: EPAPagePoolClass() : TclClass("PagePool/ProxyTrace/epa") {} TclObject* create(int, const char*const*) { return (new EPATracePagePool()); }} class_epapagepool_agent;int EPATracePagePool::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 2) { if (strcmp(argv[1], "pick-pagemod") == 0) { if (rvDyn_ == 0) { tcl.add_errorf("%s: no page age generator", name_); return (TCL_ERROR); } int j = (int)floor(rvDyn_->value()); //fprintf(stderr, "mod id = %d\n", j/br_*10 + j % br_); tcl.resultf("%d", j/br_*10 + j % br_); return TCL_OK; } } else if (argc == 3) { if (strcmp(argv[1], "ranvar-dp") == 0) { rvDyn_ = (RandomVariable*)TclObject::lookup(argv[2]); if (rvDyn_ == 0) { tcl.add_errorf("%s: no page age generator", name_); return (TCL_ERROR); } ((UniformRandomVariable*)rvDyn_)->setmin(0); ((UniformRandomVariable*)rvDyn_)->setmax(num_pages_/10*br_ + num_pages_%br_ - 1); return TCL_OK; } } else { if (strcmp(argv[1], "gen-modtime") == 0) { // Return a very large number tcl.resultf("%d", INT_MAX); return TCL_OK; } } return ProxyTracePagePool::command(argc, argv);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -