webtraf.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:19k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
  2. //
  3. /*
  4.  * webtraf.cc
  5.  * Copyright (C) 1999 by the University of Southern California
  6.  * $Id: webtraf.cc,v 1.30 2005/09/18 23:33:35 tomh Exp $
  7.  *
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License,
  10.  * version 2, as published by the Free Software Foundation.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License along
  18.  * with this program; if not, write to the Free Software Foundation, Inc.,
  19.  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  20.  *
  21.  *
  22.  * The copyright of this module includes the following
  23.  * linking-with-specific-other-licenses addition:
  24.  *
  25.  * In addition, as a special exception, the copyright holders of
  26.  * this module give you permission to combine (via static or
  27.  * dynamic linking) this module with free software programs or
  28.  * libraries that are released under the GNU LGPL and with code
  29.  * included in the standard release of ns-2 under the Apache 2.0
  30.  * license or under otherwise-compatible licenses with advertising
  31.  * requirements (or modified versions of such code, with unchanged
  32.  * license).  You may copy and distribute such a system following the
  33.  * terms of the GNU GPL for this module and the licenses of the
  34.  * other code concerned, provided that you include the source code of
  35.  * that other code when and as the GNU GPL requires distribution of
  36.  * source code.
  37.  *
  38.  * Note that people who make modified versions of this module
  39.  * are not obligated to grant this special exception for their
  40.  * modified versions; it is their choice whether to do so.  The GNU
  41.  * General Public License gives permission to release a modified
  42.  * version without this exception; this exception also makes it
  43.  * possible to release a modified version which carries forward this
  44.  * exception.
  45.  *
  46.  */
  47. //
  48. // Incorporation Polly's web traffic module into the PagePool framework
  49. //
  50. // $Header: /cvsroot/nsnam/ns-2/webcache/webtraf.cc,v 1.30 2005/09/18 23:33:35 tomh Exp $
  51. #include "config.h"
  52. #include <tclcl.h>
  53. #include <iostream>
  54. #include "node.h"
  55. #include "pagepool.h"
  56. #include "webtraf.h"
  57. // Data structures that are specific to this web traffic model and 
  58. // should not be used outside this file.
  59. //
  60. // - WebTrafPage
  61. // - WebTrafObject
  62. class WebPage : public TimerHandler {
  63. public:
  64. WebPage(int id, WebTrafSession* sess, int nObj, Node* dst) :
  65. id_(id), sess_(sess), nObj_(nObj), curObj_(0), doneObj_(0),
  66. dst_(dst) {}
  67. virtual ~WebPage() {}
  68. inline void start() {
  69. // Call expire() and schedule the next one if needed
  70. status_ = TIMER_PENDING;
  71. handle(&event_);
  72. }
  73. inline int id() const { return id_; }
  74. Node* dst() { return dst_; }
  75. void doneObject() {
  76. if (++doneObj_ >= nObj_) {
  77. //printf("doneObject: %g %d %d n", Scheduler::instance().clock(), doneObj_, nObj_);
  78. sess_->donePage((void*)this);
  79. }
  80. }
  81. inline int curObj() const { return curObj_; }
  82. inline int doneObj() const { return doneObj_; }
  83. private:
  84. virtual void expire(Event* = 0) {
  85. // Launch a request. Make sure size is not 0!
  86. if (curObj_ >= nObj_) 
  87. return;
  88. sess_->launchReq(this, LASTOBJ_++, 
  89.  (int)ceil(sess_->objSize()->value()));
  90. if (sess_->mgr()->isdebug())
  91. printf("Session %d launched page %d obj %dn",
  92.        sess_->id(), id_, curObj_);
  93. }
  94. virtual void handle(Event *e) {
  95. // XXX Note when curObj_ == nObj_, we still schedule the timer
  96. // once, but we do not actually send out requests. This extra
  97. // schedule is only meant to be a hint to wait for the last
  98. // request to finish, then we will ask our parent to delete
  99. // this page.
  100. // if (curObj_ <= nObj_) {
  101. //
  102. // Polly Huang: Wed Nov 21 18:18:51 CET 2001
  103. // With explicit doneObject() upcalls from the tcl
  104. // space, we don't need to play this trick anymore.
  105. if (curObj_ < nObj_) {
  106. // If this is not the last object, schedule the next 
  107. // one. Otherwise stop and tell session to delete me.
  108. TimerHandler::handle(e);
  109. curObj_++;
  110. // Kun-chan Lan: Mon Feb 11 10:12:27 PST 2002
  111. // Don't schedule another one when curObj_ = nObj_
  112. // otherwise the page might already have been deleted
  113. // before the next one is up and cause seg fault
  114. // in the case of larger interObj()->value()
  115. // sched(sess_->interObj()->value());
  116. if (curObj_ < nObj_) sched(sess_->interObj()->value());
  117. }
  118. }
  119. int id_;
  120. WebTrafSession* sess_;
  121. int nObj_, curObj_, doneObj_;
  122. Node* dst_;
  123. static int LASTOBJ_;
  124. };
  125. int WebPage::LASTOBJ_ = 1;
  126. int WebTrafSession::LASTPAGE_ = 1;
  127. // Constructor
  128. WebTrafSession::WebTrafSession(WebTrafPool *mgr, Node *src, int np, int id, int ftcp_, int recycle_p) : 
  129. rvInterPage_(NULL), rvPageSize_(NULL),
  130. rvInterObj_(NULL), rvObjSize_(NULL), 
  131. mgr_(mgr), src_(src), nPage_(np), curPage_(0), donePage_(0),
  132. id_(id), interPageOption_(1), fulltcp_(0) {
  133. fulltcp_ = ftcp_;
  134. recycle_page_ = recycle_p;
  135. }
  136. // XXX Must delete this after all pages are done!!
  137. WebTrafSession::~WebTrafSession() 
  138. {
  139. if (donePage_ != curPage_) {
  140. fprintf(stderr, "done pages %d != all pages %dn",
  141. donePage_, curPage_);
  142. abort();
  143. }
  144. if (status_ != TIMER_IDLE) {
  145. fprintf(stderr, "WebTrafSession must be idle when deleted.n");
  146. abort();
  147. }
  148. // Recycle the objects of page level attributes if needed
  149. // Reuse these objects may save memory for large simulations--xuanc
  150. if (recycle_page_) {
  151. if (rvInterPage_ != NULL)
  152. Tcl::instance().evalf("delete %s", rvInterPage_->name());
  153. if (rvPageSize_ != NULL)
  154. Tcl::instance().evalf("delete %s", rvPageSize_->name());
  155. if (rvInterObj_ != NULL)
  156. Tcl::instance().evalf("delete %s", rvInterObj_->name());
  157. if (rvObjSize_ != NULL)
  158. Tcl::instance().evalf("delete %s", rvObjSize_->name());
  159. }
  160. }
  161. void WebTrafSession::donePage(void* ClntData) 
  162. {
  163. WebPage* pg = (WebPage*)ClntData;
  164. if (mgr_->isdebug()) 
  165. printf("Session %d done page %dn", id_, pg->id());
  166. if (pg->doneObj() != pg->curObj()) {
  167. fprintf(stderr, "done objects %d != all objects %dn",
  168. pg->doneObj(), pg->curObj());
  169. abort();
  170. }
  171. delete pg;
  172. // If all pages are done, tell my parent to delete myself
  173. //
  174. if (++donePage_ >= nPage_)
  175. mgr_->doneSession(id_);
  176. else if (interPageOption_) {
  177. // Polly Huang: Wed Nov 21 18:23:30 CET 2001
  178. // add inter-page time option
  179. // inter-page time = end of a page to the start of the next
  180. sched(rvInterPage_->value());
  181. // printf("donePage: %g %d %dn", Scheduler::instance().clock(), donePage_, curPage_);
  182. }
  183. }
  184. // Launch the current page
  185. void WebTrafSession::expire(Event *)
  186. {
  187. // Pick destination for this page
  188. Node* dst = mgr_->pickdst();
  189. // Make sure page size is not 0!
  190. WebPage* pg = new WebPage(LASTPAGE_++, this, 
  191.   (int)ceil(rvPageSize_->value()), dst);
  192. if (mgr_->isdebug())
  193. printf("Session %d starting page %d, curpage %dn", 
  194.        id_, LASTPAGE_-1, curPage_);
  195. pg->start();
  196. }
  197. void WebTrafSession::handle(Event *e)
  198. {
  199. // If I haven't scheduled all my pages, do the next one
  200. TimerHandler::handle(e);
  201. ++curPage_;
  202. // XXX Notice before each page is done, it will schedule itself 
  203. // one more time, this makes sure that this session will not be
  204. // deleted after the above call. Thus the following code will not
  205. // be executed in the context of a deleted object. 
  206. //
  207. // Polly Huang: Wed Nov 21 18:23:30 CET 2001
  208. // add inter-page time option
  209. // inter-page time = inter-page-start time
  210. // If the interPageOption_ is not set, the XXX Notice above applies.
  211. if (!interPageOption_) {
  212. if (curPage_ < nPage_) {
  213. sched(rvInterPage_->value());
  214. // printf("schedule: %g %d %dn", Scheduler::instance().clock(), donePage_, curPage_);
  215. }
  216. }
  217. }
  218. // Launch a request for a particular object
  219. void WebTrafSession::launchReq(void* ClntData, int obj, int size) {
  220. mgr_->launchReq(src_, ClntData, obj, size);
  221. }
  222. static class WebTrafPoolClass : public TclClass {
  223. public:
  224.         WebTrafPoolClass() : TclClass("PagePool/WebTraf") { 
  225. }
  226.         TclObject* create(int, const char*const*) {
  227. return (new WebTrafPool());
  228. }
  229. } class_webtrafpool;
  230. WebTrafPool::~WebTrafPool()
  231. {
  232. if (session_ != NULL) {
  233. for (int i = 0; i < nSession_; i++)
  234. delete session_[i];
  235. delete []session_;
  236. }
  237. if (server_ != NULL)
  238. delete []server_;
  239. if (client_ != NULL)
  240. delete []client_;
  241. // XXX Destroy tcpPool_ and sinkPool_ ?
  242. }
  243. void WebTrafPool::delay_bind_init_all()
  244. {
  245. delay_bind_init_one("debug_");
  246. PagePool::delay_bind_init_all();
  247. }
  248. int WebTrafPool::delay_bind_dispatch(const char *varName,const char *localName,
  249.      TclObject *tracer)
  250. {
  251. if (delay_bind_bool(varName, localName, "debug_", &debug_, tracer)) 
  252. return TCL_OK;
  253. return PagePool::delay_bind_dispatch(varName, localName, tracer);
  254. }
  255. // By default we use constant request interval and page size
  256. WebTrafPool::WebTrafPool() : 
  257. session_(NULL), nServer_(0), server_(NULL), nClient_(0), client_(NULL),
  258. nTcp_(0), nSink_(0), fulltcp_(0), recycle_page_(0)
  259. {
  260. bind("fulltcp_", &fulltcp_);
  261. bind("recycle_page_", &recycle_page_);
  262. bind("dont_recycle_", &dont_recycle_);
  263. // Debo
  264. asimflag_=0;
  265. LIST_INIT(&tcpPool_);
  266. LIST_INIT(&sinkPool_);
  267. dbTcp_a = dbTcp_r = dbTcp_cr = 0;
  268. }
  269. TcpAgent* WebTrafPool::picktcp()
  270. {
  271. TcpAgent* a = (TcpAgent*)detachHead(&tcpPool_);
  272. if (a == NULL) {
  273. Tcl& tcl = Tcl::instance();
  274. tcl.evalf("%s alloc-tcp", name());
  275. a = (TcpAgent*)lookup_obj(tcl.result());
  276. if (a == NULL) {
  277. fprintf(stderr, "Failed to allocate a TCP agentn");
  278. abort();
  279. }
  280. } else 
  281. nTcp_--;
  282. //printf("A# %dn", dbTcp_a++);
  283. return a;
  284. }
  285. TcpSink* WebTrafPool::picksink()
  286. {
  287. TcpSink* a = (TcpSink*)detachHead(&sinkPool_);
  288. if (a == NULL) {
  289. Tcl& tcl = Tcl::instance();
  290. tcl.evalf("%s alloc-tcp-sink", name());
  291. a = (TcpSink*)lookup_obj(tcl.result());
  292. if (a == NULL) {
  293. fprintf(stderr, "Failed to allocate a TCP sinkn");
  294. abort();
  295. }
  296. } else 
  297. nSink_--;
  298. return a;
  299. }
  300. Node* WebTrafPool::picksrc() {
  301. int n = int(floor(Random::uniform(0, nClient_)));
  302. assert((n >= 0) && (n < nClient_));
  303. return client_[n];
  304. }
  305. Node* WebTrafPool::pickdst() {
  306. int n = int(floor(Random::uniform(0, nServer_)));
  307. assert((n >= 0) && (n < nServer_));
  308. return(server_[n].get_node());
  309. }
  310. // pick end points for a new TCP connection
  311. void WebTrafPool::pick_ep(TcpAgent** tcp, Agent** snk) {
  312. // Choose source
  313. *tcp = picktcp();
  314. // Choose destination
  315. if (fulltcp_) {
  316. *snk = picktcp();
  317. } else {
  318. *snk = picksink();
  319. }
  320. }
  321. // Launch a request for a particular object
  322. void WebTrafPool::launchReq(Node *src_, void* ClntData, int obj, int size) {
  323. TcpAgent *ctcp;
  324. Agent *csnk;
  325. // Allocation new TCP connections for both directions
  326. pick_ep(&ctcp, &csnk);
  327. WebPage* pg = (WebPage*)ClntData;
  328. // Setup TCP connection and done
  329. Tcl::instance().evalf("%s launch-req %d %d %s %s %s %s %d %d", 
  330.       name(), obj, pg->id(),
  331.       src_->name(), pg->dst()->name(),
  332.       ctcp->name(), csnk->name(), size, ClntData);
  333. // Debug only
  334. // $numPacket_ $objectId_ $pageId_ $sessionId_ [$ns_ now] src dst
  335. #if 0
  336. printf("%d t %d t %d t %d t %g %d %dn", size, obj, pg->id(), id_,
  337.        Scheduler::instance().clock(), 
  338.        src_->address(), pg->dst()->address());
  339. printf("** Tcp agents %d, Tcp sinks %dn", nTcp(),nSink());
  340. #endif
  341. }
  342. // Launch a request for a particular object
  343. void WebTrafPool::launchResp(int obj_id, Node *svr_, Node *clnt_, Agent *tcp, Agent* snk, int size, void *ClntData) {
  344. int pid;
  345. pid = obj_id;
  346. // Get webpage (client data) if any
  347. if (ClntData) {
  348. WebPage* pg = (WebPage*)ClntData;
  349. pid = pg->id();
  350. }
  351. // Setup TCP connection and done
  352. Tcl::instance().evalf("%s launch-resp %d %d %s %s %s %s %d %d", 
  353.       name(), obj_id, pid, svr_->name(), clnt_->name(),
  354.       tcp->name(), snk->name(), size, ClntData);
  355. // Debug only
  356. // $numPacket_ $objectId_ $pageId_ $sessionId_ [$ns_ now] src dst
  357. #if 0
  358. printf("%d t %d t %d t %d t %g %d %dn", size, obj, pg->id(), id_,
  359.        Scheduler::instance().clock(), 
  360.        src_->address(), pg->dst()->address());
  361. printf("** Tcp agents %d, Tcp sinks %dn", nTcp(),nSink());
  362. #endif
  363. }
  364. // Given sever's node id, find server
  365. int WebTrafPool::find_server(int sid) {
  366. int n = 0;
  367. while (server_[n].get_nid() != sid && n < nServer_) {
  368. n++;
  369. }
  370. return(n);
  371. }
  372. int WebTrafPool::command(int argc, const char*const* argv) {
  373. // Debojyoti Dutta ... for asim
  374. if (argc == 2){
  375. if (strcmp(argv[1], "use-asim") == 0) {
  376. asimflag_ = 1;
  377. //Tcl::instance().evalf("puts "Here"");
  378. return (TCL_OK);
  379. }
  380. else if (argc == 3) {
  381. if (strcmp(argv[1], "set-num-session") == 0) {
  382. if (session_ != NULL) {
  383. for (int i = 0; i < nSession_; i++) 
  384. delete session_[i];
  385. delete []session_;
  386. }
  387. nSession_ = atoi(argv[2]);
  388. session_ = new WebTrafSession*[nSession_];
  389. memset(session_, 0, sizeof(WebTrafSession*)*nSession_);
  390. return (TCL_OK);
  391. } else if (strcmp(argv[1], "set-num-server") == 0) {
  392. nServer_ = atoi(argv[2]);
  393. if (server_ != NULL) 
  394. delete []server_;
  395. server_ = new WebServer[nServer_];
  396. for (int i = 0; i < nServer_; i++) {
  397. server_[i] = WebServer(this);
  398. };
  399. return (TCL_OK);
  400. } else if (strcmp(argv[1], "set-num-client") == 0) {
  401. nClient_ = atoi(argv[2]);
  402. if (client_ != NULL) 
  403. delete []client_;
  404. client_ = new Node*[nClient_];
  405. return (TCL_OK);
  406. } else if (strcmp(argv[1], "set-interPageOption") == 0) {
  407. int option = atoi(argv[2]);
  408. if (session_ != NULL) {
  409. for (int i = 0; i < nSession_; i++) {
  410. WebTrafSession* p = session_[i];
  411. p->set_interPageOption(option);
  412. }
  413. }
  414. return (TCL_OK);
  415. } else if (strcmp(argv[1], "doneObj") == 0) {
  416. WebPage* p = (WebPage*)atol(argv[2]);
  417. // printf("doneObj for Page id: %dn", p->id());
  418. p->doneObject();
  419. return (TCL_OK);
  420. } else if (strcmp(argv[1], "set-server-mode") == 0) {
  421. // <obj> set-server-mode <mode>
  422. int mode = atoi(argv[2]);
  423. for (int n = 0; n < nServer_; n++) {
  424. server_[n].set_mode(mode);
  425. }
  426. return (TCL_OK);
  427. } else if (strcmp(argv[1], "set-server-rate") == 0) {
  428. // <obj> set-server-rate <rate> 
  429. int rate = atoi(argv[2]);
  430. for (int n = 0; n < nServer_; n++) {
  431. server_[n].set_rate(rate);
  432. }
  433. return (TCL_OK);
  434. } else if (strcmp(argv[1], "set-server-qlimit") == 0) {
  435. // <obj> set-server-qlimit <qlimit> 
  436. int qlimit = atoi(argv[2]);
  437. for (int n = 0; n < nServer_; n++) {
  438. server_[n].set_queue_limit(qlimit);
  439. }
  440. return (TCL_OK);
  441. }
  442. } else if (argc == 4) {
  443. if (strcmp(argv[1], "set-server") == 0) {
  444. Node* s = (Node*)lookup_obj(argv[3]);
  445. if (s == NULL)
  446. return (TCL_ERROR);
  447. int n = atoi(argv[2]);
  448. if (n >= nServer_) {
  449. fprintf(stderr, "Wrong server index %dn", n);
  450. return TCL_ERROR;
  451. }
  452. server_[n].set_node(s);
  453. return (TCL_OK);
  454. } else if (strcmp(argv[1], "set-client") == 0) {
  455. Node* c = (Node*)lookup_obj(argv[3]);
  456. if (c == NULL)
  457. return (TCL_ERROR);
  458. int n = atoi(argv[2]);
  459. if (n >= nClient_) {
  460. fprintf(stderr, "Wrong client index %dn", n);
  461. return TCL_ERROR;
  462. }
  463. client_[n] = c;
  464. return (TCL_OK);
  465. } else if (strcmp(argv[1], "recycle") == 0) {
  466. // <obj> recycle <tcp> <sink>
  467. //
  468. // Recycle a TCP source/sink pair
  469. Agent* tcp = (Agent*)lookup_obj(argv[2]);
  470. Agent* snk = (Agent*)lookup_obj(argv[3]);
  471. if ((tcp == NULL) || (snk == NULL))
  472. return (TCL_ERROR);
  473. if (fulltcp_) {
  474. delete tcp;
  475. delete snk;
  476. } else if (!dont_recycle_) {
  477. // PS: hmm.. who deletes the agents?
  478. // PS: plain delete doesn't seem to work
  479. // Recyle both tcp and sink objects
  480. nTcp_++;
  481. // XXX TBA: recycle tcp agents
  482. insertAgent(&tcpPool_, tcp);
  483. nSink_++;
  484. insertAgent(&sinkPool_, snk);
  485. //printf("R# %dn", dbTcp_r++);
  486. }
  487. return (TCL_OK);
  488. } else if (strcmp(argv[1], "set-server-rate") == 0) {
  489. // <obj> set_rate <server> <size> 
  490. int sid = atoi(argv[2]);
  491. int rate = atoi(argv[3]);
  492. int n = find_server(sid);
  493. if (n >= nServer_) 
  494. return (TCL_ERROR);
  495. server_[n].set_rate(rate);
  496. return (TCL_OK);
  497. } else if (strcmp(argv[1], "set-server-mode") == 0) {
  498. // <obj> set-mode <server> <mode>
  499. int sid = atoi(argv[2]);
  500. int mode = atoi(argv[3]);
  501. int n = find_server(sid);
  502. if (n >= nServer_) 
  503. return (TCL_ERROR);
  504. server_[n].set_mode(mode);
  505. return (TCL_OK);
  506. } else if (strcmp(argv[1], "set-server-qlimit") == 0) {
  507. // <obj> set-server-qlimit <server> <qlimit>
  508. int sid = atoi(argv[2]);
  509. int qlimit = atoi(argv[3]);
  510. int n = find_server(sid);
  511. if (n >= nServer_) 
  512. return (TCL_ERROR);
  513. server_[n].set_queue_limit(qlimit);
  514. return (TCL_OK);
  515. } else if (argc == 9) {
  516. if (strcmp(argv[1], "create-session") == 0) {
  517. // <obj> create-session <session_index>
  518. //   <pages_per_sess> <launch_time>
  519. //   <inter_page_rv> <page_size_rv>
  520. //   <inter_obj_rv> <obj_size_rv>
  521. int n = atoi(argv[2]);
  522. if ((n < 0)||(n >= nSession_)||(session_[n] != NULL)) {
  523. fprintf(stderr,"Invalid session index %dn",n);
  524. return (TCL_ERROR);
  525. }
  526. int npg = (int)strtod(argv[3], NULL);
  527. double lt = strtod(argv[4], NULL);
  528. WebTrafSession* p = 
  529. new WebTrafSession(this, picksrc(), npg, n, fulltcp_, recycle_page_);
  530. int res = lookup_rv(p->interPage(), argv[5]);
  531. res = (res == TCL_OK) ? 
  532. lookup_rv(p->pageSize(), argv[6]) : TCL_ERROR;
  533. res = (res == TCL_OK) ? 
  534. lookup_rv(p->interObj(), argv[7]) : TCL_ERROR;
  535. res = (res == TCL_OK) ? 
  536. lookup_rv(p->objSize(), argv[8]) : TCL_ERROR;
  537. if (res == TCL_ERROR) {
  538. delete p;
  539. fprintf(stderr, "Invalid random variablen");
  540. return (TCL_ERROR);
  541. }
  542. p->sched(lt);
  543. session_[n] = p;
  544. // Debojyoti added this for asim
  545. if(asimflag_){ // Asim stuff. Added by Debojyoti Dutta
  546. // Assumptions exist 
  547. //Tcl::instance().evalf("puts "Here"");
  548. double lambda = (1/(p->interPage())->avg())/(nServer_*nClient_);
  549. double mu = ((p->objSize())->value());
  550. //Tcl::instance().evalf("puts "Here"");
  551. for (int i=0; i<nServer_; i++){
  552. for(int j=0; j<nClient_; j++){
  553. // Set up short flows info for asim
  554. Tcl::instance().evalf("%s add2asim %d %d %lf %lf", this->name(),server_[i].get_nid(),client_[j]->nodeid(),lambda, mu);
  555. }
  556. }
  557. //Tcl::instance().evalf("puts "Here""); 
  558. }
  559. return (TCL_OK);
  560. } else if (strcmp(argv[1], "job_arrival") == 0) {
  561. //$self job_arrival $id $clnt $svr $tcp $snk $size $pobj
  562. int obj_id = atoi(argv[2]);
  563. Node* clnt_ = (Node*)lookup_obj(argv[3]);
  564. Node* svr_ = (Node*)lookup_obj(argv[4]);
  565. // TCP source and sink pair
  566. Agent* tcp = (Agent*)lookup_obj(argv[5]);
  567. Agent* snk = (Agent*)lookup_obj(argv[6]);
  568. int size = atoi(argv[7]);
  569. void* data = (void *)atol(argv[8]);
  570. int sid = svr_->nodeid();
  571. int n = find_server(sid);
  572. if (n >= nServer_) 
  573. return (TCL_ERROR);
  574. double delay = server_[n].job_arrival(obj_id, clnt_, tcp, snk, size, data);
  575. Tcl::instance().resultf("%f", delay);
  576. return (TCL_OK);
  577. }
  578. }
  579. return PagePool::command(argc, argv);
  580. }