Index: webtraf.cc =================================================================== RCS file: /usr/src/mash/repository/vint/ns-2/webcache/webtraf.cc,v retrieving revision 1.5 diff -u -r1.5 webtraf.cc --- webtraf.cc 1999/12/03 21:11:46 1.5 +++ webtraf.cc 2000/04/12 17:07:22 @@ -26,7 +26,7 @@ // // Incorporation Polly's web traffic module into the PagePool framework // -// $Header: /usr/src/mash/repository/vint/ns-2/webcache/webtraf.cc,v 1.5 1999/12/03 21:11:46 haoboy Exp $ +// $Header: /usr/src/mash/repository/vint/ns-2/webcache/webtraf.cc,v 1.7 2000/02/24 02:18:22 haoboy Exp $ #include "config.h" #include @@ -47,10 +47,12 @@ id_(id), sess_(sess), nObj_(nObj), curObj_(0), dst_(dst) {} virtual ~WebPage() {} - void start() { - expire(); - schedNext(); + inline void start() { + // Call expire() and schedule the next one if needed + status_ = TIMER_PENDING; + handle(&event_); } + inline int id() const { return id_; } Node* dst() { return dst_; } private: @@ -60,17 +62,23 @@ (int)ceil(sess_->objSize()->value())); } virtual void handle(Event *e) { - TimerHandler::handle(e); - schedNext(); - } - void schedNext() { - // Schedule next timer - if (++curObj_ >= nObj_) { - // We are done with this page, tell parent to delete me + // XXX Note when curObj_ == nObj_, we still schedule the timer + // once, but we do not actually send out requests. This extra + // schedule is only meant to be a hint to wait for the last + // request to finish, then we will ask our parent to delete + // this page. +#if 0 + fprintf(stderr, "Session %d handling page %d obj %d\n", + sess_->id(), id_, curObj_); +#endif + if (curObj_ <= nObj_) { + // If this is not the last object, schedule the next + // one. Otherwise stop and tell session to delete me. + TimerHandler::handle(e); + curObj_++; + sched(sess_->interObj()->value()); + } else sess_->donePage((void*)this); - return; - } - sched(sess_->interObj()->value()); } int id_; WebTrafSession* sess_; @@ -92,7 +100,10 @@ donePage_, curPage_); abort(); } - + if (status_ != TIMER_IDLE) { + fprintf(stderr, "WebTrafSession must be idle when deleted.\n"); + abort(); + } if (rvInterPage_ != NULL) Tcl::instance().evalf("delete %s", rvInterPage_->name()); if (rvPageSize_ != NULL) @@ -105,6 +116,10 @@ void WebTrafSession::donePage(void* ClntData) { +#if 0 + fprintf(stderr, "Session %d done page %d\n", id_, + ((WebPage*)ClntData)->id()); +#endif delete (WebPage*)ClntData; // If all pages are done, tell my parent to delete myself if (++donePage_ >= nPage_) @@ -119,19 +134,23 @@ // Make sure page size is not 0! WebPage* pg = new WebPage(LASTPAGE_++, this, (int)ceil(rvPageSize_->value()), dst); +#if 0 + printf("Session %d starting page %d, curpage %d \n", + id_, LASTPAGE_-1, curPage_); +#endif pg->start(); } void WebTrafSession::handle(Event *e) { + // If I haven't scheduled all my pages, do the next one TimerHandler::handle(e); - // If I've scheduled all my pages, don't schedule it any more. - if (++curPage_ >= nPage_) - return; -#if 0 - printf("Session %d schedule next page %d\n", id_, LASTPAGE_); -#endif - sched(rvInterPage_->value()); + // XXX Notice before each page is done, it will schedule itself + // one more time, this makes sure that this session will not be + // deleted after the above call. Thus the following code will not + // be executed in the context of a deleted object. + if (++curPage_ < nPage_) + sched(rvInterPage_->value()); } // Launch a request for a particular object @@ -154,9 +173,9 @@ // Debug only // $numPacket_ $objectId_ $pageId_ $sessionId_ [$ns_ now] src dst #if 0 - printf("%d \t %d \t %d \t %d \t %g %d %d\n", size, obj, page, id_, - Scheduler::instance().clock(), - src_->address(), dst->address()); + printf("%d \t %d \t %d \t %d \t %g %d %d\n", size, obj, pg->id(), id_, + Scheduler::instance().clock(), + src_->address(), pg->dst()->address()); printf("** Tcp agents %d, Tcp sinks %d\n", mgr_->nTcp(),mgr_->nSink()); #endif } .