📄 pagepool.cc
字号:
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) { // Single page tcl.result("0"); return TCL_OK; } else if (strcmp(argv[1], "gen-size") == 0) { if (rvSize_ == 0) { tcl.add_errorf("%s: no page size generator", name_); return TCL_ERROR; } int size = (int) rvSize_->value(); if (size == 0) // XXX do not allow page size 0, because TcpApp // doesn't behave correctly when sending 0 byte size = 1; tcl.resultf("%d", size); return TCL_OK; } else if (strcmp(argv[1], "ranvar-size") == 0) { rvSize_ = (RandomVariable*)TclObject::lookup(argv[2]); return TCL_OK; } else if (strcmp(argv[1], "ranvar-age") == 0) { rvAge_ = (RandomVariable*)TclObject::lookup(argv[2]); return TCL_OK; } else if (strcmp(argv[1], "set-start-time") == 0) { double st = strtod(argv[2], NULL); start_time_ = st; end_time_ += st; return TCL_OK; } else if (strcmp(argv[1], "gen-init-modtime") == 0) { tcl.resultf("%.17g", Scheduler::instance().clock()); return TCL_OK; } } else { if (strcmp(argv[1], "gen-modtime") == 0) { if (rvAge_ == 0) { tcl.add_errorf("%s: no page age generator", name_); return TCL_ERROR; } double mt = strtod(argv[3], NULL); tcl.resultf("%.17g", mt + rvAge_->value()); return TCL_OK; } } return PagePool::command(argc, argv);}// Assume one main page, which changes often, and multiple component pagesstatic class CompMathPagePoolClass : public TclClass {public: CompMathPagePoolClass() : TclClass("PagePool/CompMath") {} TclObject* create(int, const char*const*) { return (new CompMathPagePool()); }} class_compmathpagepool_agent;CompMathPagePool::CompMathPagePool(){ bind("num_pages_", &num_pages_); bind("main_size_", &main_size_); bind("comp_size_", &comp_size_);}int CompMathPagePool::command(int argc, const char *const* argv){ Tcl& tcl = Tcl::instance(); // Keep the same tcl interface as PagePool/Trace if (argc == 2) { if (strcmp(argv[1], "get-poolsize") == 0) { tcl.result("1"); 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) { // Main pageid, never return id of component pages tcl.result("0"); return TCL_OK; } else if (strcmp(argv[1], "gen-size") == 0) { int id = atoi(argv[2]); if (id == 0) tcl.resultf("%d", main_size_); else tcl.resultf("%d", comp_size_); return TCL_OK; } else if (strcmp(argv[1], "gen-obj-size") == 0) { tcl.resultf("%d", comp_size_); return (TCL_OK); } else if (strcmp(argv[1], "get-next-objs") == 0) { PageID id; ClientPage::split_name(argv[2], id); // If we want simultaneous requests of multiple // objects, return a list; otherwise return a single // pageid. for (int i = id.id_+1; i < num_pages_; i++) { tcl.resultf("%s %s:%d", tcl.result(), id.s_->name(), i); } return TCL_OK; } else if (strcmp(argv[1], "ranvar-main-age") == 0) { rvMainAge_ = (RandomVariable*)TclObject::lookup(argv[2]); return TCL_OK; } else if (strcmp(argv[1], "ranvar-obj-age") == 0) { rvCompAge_ = (RandomVariable*)TclObject::lookup(argv[2]); return TCL_OK; } else if (strcmp(argv[1], "set-start-time") == 0) { double st = strtod(argv[2], NULL); start_time_ = st; end_time_ += st; return TCL_OK; } else if (strcmp(argv[1], "gen-init-modtime") == 0) { tcl.resultf("%.17g", Scheduler::instance().clock()); return TCL_OK; } else if (strcmp(argv[1], "is-mainpage") == 0) { // Tell if the given page is a main page or an // embedded object. // XXX Here because we have only one page, so only // page id 0 is the main page. If we have multiple // pages, we need something else to do this. PageID t1; ClientPage::split_name(argv[2], t1); if (t1.id_ == 0) tcl.result("1"); else tcl.result("0"); return TCL_OK; } else if (strcmp(argv[1], "get-mainpage") == 0) { // Get the main page of an embedded object // XXX Should maintain a mapping between embedded // objects and main pages. It can be an algorithmic // one, e.g., using page id intervals. It's simple // here because we have only one page. PageID t1; ClientPage::split_name(argv[2], t1); tcl.resultf("%s:0", t1.s_->name()); return TCL_OK; } else if (strcmp(argv[1], "get-obj-num") == 0) { // Returns the number of embedded objects of the page // given in argv[1]. Here because we have only one // page, we return a fixed value. tcl.resultf("%d", num_pages_-1); return TCL_OK; } } else { // argc > 3 if (strcmp(argv[1], "gen-modtime") == 0) { int id = atoi(argv[2]); if (id == 0) { if (rvMainAge_ == 0) { tcl.add_errorf("%s: no page age generator", name_); return TCL_ERROR; } double mt = strtod(argv[3], NULL); tcl.resultf("%.17g", mt + rvMainAge_->value()); } else { if (rvCompAge_ == 0) { tcl.add_errorf("%s: no page age generator", name_); return TCL_ERROR; } double mt = atoi(argv[3]); tcl.resultf("%.17g", mt + rvCompAge_->value()); } return TCL_OK; } else if (strcmp(argv[1], "gen-obj-modtime") == 0) { if (rvCompAge_ == 0) { tcl.add_errorf("%s: no page age generator", name_); return TCL_ERROR; } double mt = atoi(argv[3]); tcl.resultf("%.17g", mt + rvCompAge_->value()); return TCL_OK; } } return PagePool::command(argc, argv);}static class ClientPagePoolClass : public TclClass {public: ClientPagePoolClass() : TclClass("PagePool/Client") {} TclObject* create(int, const char*const*) { return (new ClientPagePool()); }} class_clientpagepool_agent;ClientPagePool::ClientPagePool(){ namemap_ = new Tcl_HashTable; Tcl_InitHashTable(namemap_, 2);}ClientPagePool::~ClientPagePool(){ if (namemap_ != NULL) { Tcl_DeleteHashTable(namemap_); delete namemap_; }}// In case client/cache/server needs details, e.g., page listingint ClientPagePool::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 2) { if (strcmp(argv[1], "list-pages") == 0) { Tcl_HashEntry *he; Tcl_HashSearch hs; char *buf = new char[num_pages_*20]; char *p = buf; for (he = Tcl_FirstHashEntry(namemap_, &hs); he != NULL; he = Tcl_NextHashEntry(&hs)) { int* t2 = (int*)Tcl_GetHashKey(namemap_, he); PageID t1(t2);#ifdef NEED_SUNOS_PROTOS sprintf(p, "%s:%-d ", t1.s_->name(),t1.id_); p += strlen(p);#else p += sprintf(p,"%s:%-d ",t1.s_->name(),t1.id_);#endif } tcl.resultf("%s", buf); delete []buf; return TCL_OK; } } return PagePool::command(argc, argv);}ClientPage* ClientPagePool::get_page(const char *name){ PageID t1; void* t2[2]; ClientPage::split_name(name, t1); t2[0] = (void *)t1.s_; t2[1] = (void *)t1.id_; Tcl_HashEntry *he = Tcl_FindHashEntry(namemap_, (const char *)t2); if (he == NULL) return NULL; return (ClientPage *)Tcl_GetHashValue(he);}int ClientPagePool::get_pageinfo(const char *name, char *buf){ ClientPage *pg = get_page(name); if (pg == NULL) return -1; pg->print_info(buf); return 0;}ClientPage* ClientPagePool::enter_page(int argc, const char*const* argv){ double mt = -1, et, age = -1, noc = 0; int size = -1; for (int i = 3; i < argc; i+=2) { if (strcmp(argv[i], "modtime") == 0) mt = strtod(argv[i+1], NULL); else if (strcmp(argv[i], "size") == 0) size = atoi(argv[i+1]); else if (strcmp(argv[i], "age") == 0) age = strtod(argv[i+1], NULL); else if (strcmp(argv[i], "noc") == 0) // non-cacheable flag noc = 1; } // XXX allow mod time < 0 and age < 0!! if (size < 0) { fprintf(stderr, "PagePool %s: wrong information for page %s\n", name_, argv[2]); return NULL; } et = Scheduler::instance().clock(); ClientPage* pg = new ClientPage(argv[2], size, mt, et, age); if (add_page(pg) < 0) { delete pg; return NULL; } if (noc) pg->set_uncacheable(); return pg;}ClientPage* ClientPagePool::enter_page(const char *name, int size, double mt, double et, double age){ ClientPage* pg = new ClientPage(name, size, mt, et, age); if (add_page(pg) < 0) { delete pg; return NULL; } return pg;}// XXX We don't need parsing "noc" here because a non-cacheable// page won't be processed by a cache.ClientPage* ClientPagePool::enter_metadata(int argc, const char*const* argv){ ClientPage *pg = enter_page(argc, argv); if (pg != NULL) pg->set_valid_hdr(); return pg;}ClientPage* ClientPagePool::enter_metadata(const char *name, int size, double mt, double et, double age){ ClientPage *pg = enter_page(name, size, mt, et, age); if (pg != NULL) pg->set_valid_hdr(); return pg;}int ClientPagePool::add_page(ClientPage* pg){ if (pg == NULL) return -1; char buf[HTTP_MAXURLLEN]; pg->name(buf); PageID t1; void* t2[2]; ClientPage::split_name(buf, t1); t2[0] = (void *)t1.s_; t2[1] = (void *)t1.id_; int newEntry = 1; Tcl_HashEntry *he = Tcl_CreateHashEntry(namemap_, (const char *)t2, &newEntry); if (he == NULL) return -1; // XXX If cache replacement algorithm is added, should change // cache size here!! if (newEntry) { Tcl_SetHashValue(he, (ClientData)pg); num_pages_++; } else { // Replace the old one ClientPage *q = (ClientPage *)Tcl_GetHashValue(he); // XXX must copy the counter value pg->counter() = q->counter(); // XXX must copy the mpush values if (q->is_mpush()) pg->set_mpush(q->mpush_time()); Tcl_SetHashValue(he, (ClientData)pg); delete q; } return 0;}int ClientPagePool::remove_page(const char *name){ PageID t1; void* t2[2]; ClientPage::split_name(name, t1); t2[0] = (void *)t1.s_; t2[1] = (void *)t1.id_; // Find out which client we are seeking Tcl_HashEntry *he = Tcl_FindHashEntry(namemap_, (const char *)t2); if (he == NULL) return -1; ClientPage *pg = (ClientPage *)Tcl_GetHashValue(he); Tcl_DeleteHashEntry(he); delete pg; num_pages_--; // XXX If cache replacement algorithm is added, should change
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -