http-agent.tcl
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:22k
源码类别:

通讯编程

开发平台:

Visual C++

  1. # Copyright (c) Xerox Corporation 1998. All rights reserved.
  2. #
  3. # This program is free software; you can redistribute it and/or modify it
  4. # under the terms of the GNU General Public License as published by the
  5. # Free Software Foundation; either version 2 of the License, or (at your
  6. # option) any later version.
  7. # This program is distributed in the hope that it will be useful, but
  8. # WITHOUT ANY WARRANTY; without even the implied warranty of
  9. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10. # General Public License for more details.
  11. # You should have received a copy of the GNU General Public License along
  12. # with this program; if not, write to the Free Software Foundation, Inc.,
  13. # 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  14. # Linking this file statically or dynamically with other modules is making
  15. # a combined work based on this file.  Thus, the terms and conditions of
  16. # the GNU General Public License cover the whole combination.
  17. # In addition, as a special exception, the copyright holders of this file
  18. # give you permission to combine this file with free software programs or
  19. # libraries that are released under the GNU LGPL and with code included in
  20. # the standard release of ns-2 under the Apache 2.0 license or under
  21. # otherwise-compatible licenses with advertising requirements (or modified
  22. # versions of such code, with unchanged license).  You may copy and
  23. # distribute such a system following the terms of the GNU GPL for this
  24. # file and the licenses of the other code concerned, provided that you
  25. # include the source code of that other code when and as the GNU GPL
  26. # requires distribution of source code.
  27. # Note that people who make modified versions of this file are not
  28. # obligated to grant this special exception for their modified versions;
  29. # it is their choice whether to do so.  The GNU General Public License
  30. # gives permission to release a modified version without this exception;
  31. # this exception also makes it possible to release a modified version
  32. # which carries forward this exception.
  33. #
  34. # HTTP agents: server, client, cache
  35. #
  36. # $Header: /cvsroot/nsnam/ns-2/tcl/webcache/http-agent.tcl,v 1.11 2005/08/26 05:05:30 tomh Exp $
  37. Http set id_ 0 ;# required by TclCL
  38. # Type of Tcp agent. Can be SimpleTcp or FullTcp
  39. # Default should be set to FullTcp, in case for inadvertent bites. :(
  40. Http set TRANSPORT_ FullTcp
  41. Http set HB_FID_ 40
  42. Http set PINV_FID_ 41
  43. # XXX invalidation message size should be proportional to the number of
  44. # invalidations inside the message
  45. Http set INVSize_ 43 ;# unicast invalidation
  46. Http set REQSize_ 43 ;# Request
  47. Http set REFSize_ 50 ;# Refetch request
  48. Http set IMSSize_ 50 ;# If-Modified-Since
  49. Http set JOINSize_ 10 ;# Server join/leave
  50. Http set HBSize_ 1 ;# Used by Http/Server/Inval only
  51. Http set PFSize_ 1 ;# Pro forma
  52. Http set NTFSize_ 10 ;# Request Notification
  53. Http set MPUSize_ 10 ;# Mandatory push request
  54. Http/Server set id_ 0
  55. Http/Server/Inval set id_ 0
  56. Http/Server/Inval/Yuc set hb_interval_ 60
  57. Http/Server/Inval/Yuc set enable_upd_ 0
  58. Http/Server/Inval/Yuc set Ca_ 1
  59. Http/Server/Inval/Yuc set Cb_ 4
  60. Http/Server/Inval/Yuc set push_thresh_ 4
  61. Http/Server/Inval/Yuc set push_low_bound_ 0
  62. Http/Server/Inval/Yuc set push_high_bound_ 8
  63. Http/Cache set id_ 0
  64. Http/Cache/Inval set id_ 0
  65. Http/Cache/Inval/Mcast set hb_interval_ 60
  66. Http/Cache/Inval/Mcast set upd_interval_ 5
  67. Http/Cache/Inval/Mcast set enable_upd_ 0
  68. Http/Cache/Inval/Mcast set Ca_ 1
  69. Http/Cache/Inval/Mcast set Cb_ 4
  70. Http/Cache/Inval/Mcast set push_thresh_ 4
  71. Http/Cache/Inval/Mcast set push_low_bound_ 0
  72. Http/Cache/Inval/Mcast set push_high_bound_ 8
  73. Http/Cache/Inval/Mcast/Perc set direct_request_ 0
  74. PagePool/CompMath set num_pages_ 1
  75. PagePool/CompMath set main_size_ 1024
  76. PagePool/CompMath set comp_size_ 10240
  77. # Transport protocol used for multimedia connections
  78. Http set MEDIA_TRANSPORT_ RAP
  79. # Application-level handler for multimedia connections. 
  80. # Currently there are two available:
  81. # - MediaApp: simply extract data from packets and pass it to cache
  82. # - QA: do quality adaptation
  83. Http set MEDIA_APP_ MediaApp
  84. # 1K per multimedia segment
  85. Application/MediaApp set segmentSize_ 1024
  86. Application/MediaApp set MAX_LAYER_ 10
  87. # Constants related to quality adaptation
  88. Application/MediaApp/QA set LAYERBW_ 2500 ;# Byte per-second
  89. Application/MediaApp/QA set MAXACTIVELAYERS_ 10
  90. Application/MediaApp/QA set SRTTWEIGHT_ 0.95
  91. Application/MediaApp/QA set SMOOTHFACTOR_ 4
  92. Application/MediaApp/QA set MAXBKOFF_ 100
  93. Application/MediaApp/QA set debug_output_ 0
  94. # Prefetching lookahead SRTT 200ms
  95. Application/MediaApp/QA set pref_srtt_ 0.6
  96. # 100M buffer size at cache/server/client
  97. PagePool/Client/Media set max_size_ 104857600 
  98. Http instproc init { ns node } {
  99. $self next
  100. $self instvar ns_ node_ id_ pool_
  101. set ns_ $ns
  102. set node_ $node
  103. $self set id_ [$node_ id]
  104. set pool_ [$self create-pagepool]
  105. }
  106. Http instproc create-pagepool {} {
  107. set pool [new PagePool/Client]
  108. $self set-pagepool $pool
  109. return $pool
  110. }
  111. Http instproc addr {} {
  112. $self instvar node_ 
  113. return [$node_ node-addr]
  114. }
  115. Http set fid_ -1
  116. Http instproc getfid {} {
  117. $self instvar fid_
  118. set fid_ [Http set fid_]
  119. Http set fid_ [incr fid_]
  120. }
  121. Http instproc get-mpusize {} {
  122. return [Http set MPUSize_]
  123. }
  124. Http instproc get-ntfsize {} {
  125. return [Http set NTFSize_]
  126. }
  127. Http instproc get-pfsize {} {
  128. return [Http set PFSize_]
  129. }
  130. Http instproc get-hbsize {} {
  131. return [Http set HBSize_]
  132. }
  133. Http instproc get-imssize {} {
  134. return [Http set IMSSize_]
  135. }
  136. Http instproc get-invsize {} {
  137. return [Http set INVSize_]
  138. }
  139. # Generate request packet size. Should be constant because it's small
  140. Http instproc get-reqsize {} {
  141. return [Http set REQSize_]
  142. }
  143. Http instproc get-refsize {} {
  144. return [Http set REFSize_]
  145. }
  146. Http instproc get-joinsize {} {
  147. return [Http set JOINSize_]
  148. }
  149. # At startup, connect to a server, the server may be a cache
  150. Http instproc connect { server } {
  151. Http instvar TRANSPORT_
  152. $self instvar ns_ slist_ node_ fid_ id_
  153. lappend slist_ $server
  154. set tcp [new Agent/TCP/$TRANSPORT_]
  155. $tcp set fid_ [$self getfid]
  156. $ns_ attach-agent $node_ $tcp
  157. set ret [$server alloc-connection $self $fid_]
  158. set snk [$ret agent]
  159. $ns_ connect $tcp $snk
  160. #$tcp set dst_ [$snk set addr_]
  161. $tcp set window_ 100
  162. # Use a wrapper to implement application data transfer
  163. set wrapper [new Application/TcpApp $tcp]
  164. $self cmd connect $server $wrapper
  165. $wrapper connect $ret
  166. #puts "HttpApp $id_ connected to server [$server id]"
  167. }
  168. Http instproc stat { name } {
  169. $self instvar stat_
  170. return $stat_($name)
  171. }
  172. # Used for mandatory push refreshments
  173. Http/Client set hb_interval_ 60
  174. Http/Client instproc init args {
  175. eval $self next $args
  176. $self instvar node_ stat_
  177. $node_ color "SteelBlue"
  178. array set stat_ [list req-num 0 stale-num 0 stale-time 0 rep-time 0 
  179. rt-min 987654321 rt-max 0 st-min 987654321 st-max 0]
  180. }
  181. # XXX Assume that it's always client disconnects from server, not vice versa
  182. Http/Client instproc disconnect { server } {
  183. $self instvar ns_ slist_ 
  184. set pos [lsearch $slist_ $server]
  185. if {$pos >= 0} {
  186. lreplace $slist_ $pos $pos
  187. } else { 
  188. error "Http::disconnect: not connected to $server"
  189. }
  190. # Cleanup of all pending requests and states
  191. $self instvar ns_ node_ cache_
  192. $self stop-session $server
  193. # XXX Is this the right behavior? Should we wait for FIN etc.?
  194. set tcp [[$self get-cnc $server] agent]
  195. $self cmd disconnect $server
  196. $server disconnect $self
  197. $tcp proc done {} "$ns_ detach-agent $node_ $tcp; delete $tcp"
  198. $tcp close
  199. }
  200. # Meta-data to be sent in a request
  201. # XXX pageid should always be given from the users, because client may 
  202. # connect to a cache, hence it doesn't know the server name.
  203. Http/Client instproc send-request { server type pageid args } {
  204. $self instvar ns_ pending_  ;# unansewered requests
  205. # XXX Do not set pending states for an non-existent connection
  206. if ![$self cmd is-connected $server] {
  207. return
  208. }
  209. if ![info exists pending_($pageid)] { 
  210. # XXX Actually we should use set, because only one request
  211. # is allowed for a page simultaneously
  212. lappend pending_($pageid) [$ns_ now]
  213. } else {
  214. # If the page is being requested, do not send another request
  215. return
  216. }
  217. set size [$self get-reqsize]
  218. $self send $server $size 
  219.     "$server get-request $self $type $pageid size $size [join $args]"
  220. $self evTrace C GET p $pageid s [$server id] z $size
  221. $self instvar stat_ simStartTime_
  222. if [info exists simStartTime_] {
  223. incr stat_(req-num)
  224. }
  225. $self mark-request $pageid
  226. }
  227. Http/Client instproc mark-request { pageid } {
  228. # Nam state coloring
  229. $self instvar node_ marks_ ns_
  230. $node_ add-mark $pageid:[$ns_ now] "purple"
  231. lappend marks_($pageid) $pageid:[$ns_ now]
  232. }
  233. # The reason that "type" is here is for Http/Cache to work. Client doesn't 
  234. # check the reason of the response
  235. Http/Client instproc get-response-GET { server pageid args } {
  236. $self instvar pending_ id_ ns_ stat_ simStartTime_
  237. if ![info exists pending_($pageid)] {
  238. error "Client $id_: Unrequested response page $pageid from server [$server id]"
  239. }
  240. array set data $args
  241. # Check stale hits
  242. set origsvr [lindex [split $pageid :] 0]
  243. set modtime [$origsvr get-modtime $pageid]
  244. set reqtime [lindex $pending_($pageid) 0]
  245. set reqrtt [expr [$ns_ now] - $reqtime]
  246. #
  247. # XXX If a stale hit occurs because a page is modified during the RTT
  248. # of the request, we should *NOT* consider it a stale hit. We 
  249. # implement it by ignoring all stale hits whose modification time is
  250. # larger than the request time. 
  251. #
  252. if {$modtime > $data(modtime)} {
  253. # Staleness is the time from now to the time it's last modified
  254. set tmp [$origsvr stale-time $pageid $data(modtime)]
  255. if {$tmp > $reqrtt/2} {
  256. # We have a real stale hit
  257. $self evTrace C STA p $pageid s [$origsvr id] l $tmp
  258. if [info exists simStartTime_] {
  259. incr stat_(stale-num)
  260. set stat_(stale-time) [expr 
  261. $stat_(stale-time) + $tmp]
  262. if {$stat_(st-min) > $tmp} {
  263. set stat_(st-min) $tmp
  264. }
  265. if {$stat_(st-max) < $tmp} {
  266. set stat_(st-max) $tmp
  267. }
  268. }
  269. }
  270. }
  271. # Assume this response is for the very first request we've sent. 
  272. # Because we'll average the response time at the end, which 
  273. # request this response actually corresponds to doesn't matter.
  274. $self evTrace C RCV p $pageid s [$server id] l $reqrtt z $data(size)
  275. if [info exists simStartTime_] {
  276. set stat_(rep-time) [expr $stat_(rep-time) + $reqrtt]
  277. if {$stat_(rt-min) > $reqrtt} {
  278. set stat_(rt-min) $reqrtt
  279. }
  280. if {$stat_(rt-max) < $reqrtt} {
  281. set stat_(rt-max) $reqrtt
  282. }
  283. }
  284. set pending_($pageid) [lreplace $pending_($pageid) 0 0]
  285. if {[llength $pending_($pageid)] == 0} {
  286. unset pending_($pageid)
  287. }
  288. $self mark-response $pageid
  289. }
  290. Http/Client instproc mark-response { pageid } {
  291. $self instvar node_ marks_ ns_
  292. set mk [lindex $marks_($pageid) 0]
  293. $node_ delete-mark $mk
  294. set marks_($pageid) [lreplace $marks_($pageid) 0 0]
  295. }
  296. Http/Client instproc get-response-REF { server pageid args } {
  297. eval $self get-response-GET $server $pageid $args
  298. }
  299. Http/Client instproc get-response-IMS { server pageid args } {
  300. eval $self get-response-GET $server $pageid $args
  301. }
  302. # Generate the time when next request will occur
  303. # It's either a TracePagePool or a MathPagePool
  304. #
  305. # XXX both TracePagePool and MathPagePool should share the same C++ 
  306. # interface and OTcl interface
  307. Http/Client instproc set-page-generator { pagepool } {
  308. $self instvar pgtr_  ;# Page generator
  309. set pgtr_ $pagepool
  310. }
  311. Http/Client instproc set-interval-generator { ranvar } {
  312. $self instvar rvInterPage_
  313. set rvInterPage_ $ranvar
  314. }
  315. # XXX PagePool::gen-pageid{} *MUST* precede gen-req-itvl{}, because the 
  316. # former may responsible for loading a new page from the trace file if 
  317. # PagePool/ProxyTrace is used
  318. Http/Client instproc gen-request {} {
  319. $self instvar pgtr_ rvInterPage_ id_
  320. if ![info exists pgtr_] {
  321. error "Http/Client requires a page generator (pgtr_)!"
  322. }
  323. # XXX 
  324. # rvInterPage_ should only be set when PagePool/ProxyTrace is 
  325. # *NOT* used
  326. if [info exists rvInterPage_] {
  327. return [list [$rvInterPage_ value] [$pgtr_ gen-pageid $id_]]
  328. } else {
  329. return [$pgtr_ gen-request $id_]
  330. }
  331. }
  332. Http/Client instproc next-request { server pageid } {
  333. $self instvar ns_ cache_ nextreq_
  334. if [info exists cache_] {
  335. $self send-request $cache_ GET $pageid
  336. } else {
  337. $self send-request $server GET $pageid
  338. }
  339. # Prepare for the next request
  340. set req [$self gen-request]
  341. set pageid $server:[lindex $req 1]
  342. set itvl [lindex $req 0]
  343. if {$itvl >= 0} {
  344. set nextreq_([$server id]) [$ns_ at [expr [$ns_ now] + $itvl] 
  345. "$self next-request $server $pageid"]
  346. } ;# otherwise it's the end of the request stream 
  347. }
  348. Http/Client instproc set-cache { cache } {
  349. $self instvar cache_
  350. set cache_ $cache
  351. }
  352. # Assuming everything is setup, this function starts sending requests
  353. # Sending a request to $cache, the original page should come from $server
  354. #
  355. # Populate a cache with all available pages
  356. # XXX how would we distribute pages spatially when we have a hierarchy 
  357. # of caches? Or, how would we distribute client requests spatially?
  358. # It should be used in single client, single cache and single server case
  359. # *ONLY*.
  360. Http/Client instproc start-session { cache server } {
  361. $self instvar ns_ cache_ simStartTime_
  362. $self instvar simStartTime_ pgtr_
  363. set simStartTime_ [$ns_ now]
  364. if [info exists pgtr_] {
  365. if {[$pgtr_ get-start-time] > $simStartTime_} {
  366. $pgtr_ set-start-time $simStartTime_
  367. }
  368. }
  369. #puts "Client [$self id] starts request session at [$ns_ now]"
  370. set cache_ $cache
  371. # The first time invocation we don't send out a request 
  372. # immediately. Instead, we find out when will the first
  373. # request happen, then schedule it using next-request{}
  374. # Then every time next-request{} is called later, it
  375. # sends out a request and schedule the next.
  376. set req [$self gen-request]
  377. set pageid $server:[lindex $req 1]
  378. set itvl [lindex $req 0]
  379. if {$itvl >= 0} {
  380. $ns_ at [expr [$ns_ now] + $itvl] 
  381. "$self next-request $server $pageid"
  382. } ;# otherwise it's the end of the request stream 
  383. }
  384. # Stop sending further requests, and clean all pending requests
  385. Http/Client instproc stop-session { server } {
  386. $self instvar ns_ nextreq_ pending_ cache_
  387. set sid [$server id]
  388. # Clean up all pending requests
  389. if [info exists nextreq_($sid)] {
  390. $ns_ cancel $nextreq_($sid)
  391. }
  392. if {![info exists pending_]} {
  393. return
  394. }
  395. # XXX If a client either connects to a *SINGLE* cache 
  396. # or a *SINGLE* server, then we remove all pending requests 
  397. # when we are disconnected. 
  398. if {[info exists cache_] && ($server == $cache_)} {
  399. unset pending_
  400. } else {
  401. # Only remove pending requests related to $server
  402. foreach p [array names pending_] {
  403. if {$server == [lindex [split $p :] 0]} {
  404. unset pending_($p)
  405. }
  406. }
  407. }
  408. }
  409. Http/Client instproc populate { cache server } {
  410. $self instvar pgtr_ curpage_ status_ ns_
  411. if ![info exists status_] {
  412. set status_ "POPULATE"
  413. set curpage_ 0
  414. }
  415. if [info exists pgtr_] {
  416. # Populate cache with all pages incrementally
  417. if {$curpage_ < [$pgtr_ get-poolsize]} {
  418. $self send-request $cache GET $server:$curpage_
  419. incr curpage_
  420. $ns_ at [expr [$ns_ now] + 1] 
  421. "$self populate $cache $server"
  422. # if {$curpage_ % 1000 == 0} {
  423. # puts "Client [$self id] populated $curpage_"
  424. # }
  425. return
  426. }
  427. }
  428. # Start sending requests
  429. $ns_ at [expr [$ns_ now] + 10] "$self start-session $cache $server"
  430. }
  431. Http/Client instproc start { cache server } {
  432. $self instvar cache_
  433. set cache_ $cache
  434. $self populate $cache $server
  435. }
  436. Http/Client instproc request-mpush { page } {
  437. $self instvar mpush_refresh_ ns_ cache_
  438. $self send $cache_ [$self get-mpusize] 
  439. "$cache_ request-mpush $page"
  440. Http/Client instvar hb_interval_
  441. set mpush_refresh_($page) [$ns_ at [expr [$ns_ now] + $hb_interval_] 
  442. "$self send-refresh-mpush $page"]
  443. }
  444. Http/Client instproc send-refresh-mpush { page } {
  445. $self instvar mpush_refresh_ ns_ cache_
  446. $self send $cache_ [$self get-mpusize] "$cache_ refresh-mpush $page"
  447. #puts "[$ns_ now]: Client [$self id] send mpush refresh"
  448. Http/Client instvar hb_interval_
  449. set mpush_refresh_($page) [$ns_ at [expr [$ns_ now] + $hb_interval_] 
  450. "$self send-refresh-mpush $page"]
  451. }
  452. # XXX We use explicit teardown. 
  453. Http/Client instproc stop-mpush { page } {
  454. $self instvar mpush_refresh_ ns_ cache_
  455. if [info exists mpush_refresh_($page)] {
  456. # Stop sending the periodic refreshment
  457. $ns_ cancel $mpush_refresh_($page)
  458. #puts "[$ns_ now]: Client [$self id] stops mpush"
  459. } else {
  460. error "no mpush to cancel!"
  461. }
  462. # Send explicit message up to tear down
  463. $self send $cache_ [$self get-mpusize] "$cache_ stop-mpush $page"
  464. }
  465. #----------------------------------------------------------------------
  466. # Client which is capable of handling compound pages
  467. #----------------------------------------------------------------------
  468. Class Http/Client/Compound -superclass Http/Client
  469. Http/Client/Compound instproc set-interobj-generator { ranvar } {
  470. $self instvar rvInterObj_
  471. set rvInterObj_ $ranvar
  472. }
  473. # Generate next page request and the number of embedded objects for 
  474. # this page. 
  475. # Use rvInterPage_ to generate interval between pages (inactive OFF), and 
  476. # use rvInterObj_ to generate interval between embedded objects (active OFF)
  477. Http/Client/Compound instproc next-request { server pageid } {
  478. # First schedule next page request
  479. eval $self next $server $pageid
  480. }
  481. # Request the next embedded object(s)
  482. Http/Client/Compound instproc next-obj { server args } {
  483. $self instvar pgtr_ cache_ req_objs_ ns_ rvInterObj_
  484. if ![llength $args] {
  485. # No requests to make
  486. return
  487. }
  488. if [info exists cache_] {
  489. set dest $cache_
  490. } else {
  491. set dest $server
  492. }
  493. set pageid [lindex $args 0]
  494. set mpgid [$pgtr_ get-mainpage $pageid] ;# main page id
  495. set max 0
  496. set origsvr [lindex [split $pageid :] 0]
  497. foreach pageid $args {
  498. set id [lindex [split $pageid :] 1]
  499. if {$max < $id} {
  500. set max $id
  501. }
  502. incr req_objs_($mpgid) -1
  503. $self send-request $dest GET $pageid
  504. }
  505. if {$req_objs_($mpgid) <= 0} {
  506. # We have requested all objects for this page, done.
  507. return
  508. }
  509. # Schedule next requests. Assuming we get embedded objects according
  510. # to the ascending order of their page id
  511. set objid [join [$pgtr_ get-next-objs $origsvr:$max]]
  512. puts "At [$ns_ now], client [$self id] get objs $objid"
  513. if [info exists rvInterObj_] {
  514. $ns_ at [expr [$ns_ now] + [$rvInterObj_ value]] 
  515. "$self next-obj $server $objid"
  516. } else {
  517. $self next-obj $server $objid
  518. }
  519. }
  520. # XXX We need to override get-response-GET because we need to recompute
  521. #     the RCV time, and the STA time, etc. 
  522. # XXX Allow only *ONE* compound page.
  523. Http/Client/Compound instproc get-response-GET { server pageid args } {
  524. $self instvar pending_ id_ ns_ recv_objs_ max_stale_ stat_ 
  525. simStartTime_ pgtr_
  526. if ![info exists pending_($pageid)] {
  527. error "Client $id_: Unrequested response page $pageid from server/cache [$server id]"
  528. }
  529. # Check if this is the main page
  530. if [$pgtr_ is-mainpage $pageid] {
  531. set mpgid $pageid
  532. # Get all the embedded objects, do "active OFF" delay 
  533. # if available
  534. $self instvar req_objs_ recv_objs_ rvInterObj_
  535. # Objects that are to be received
  536. set recv_objs_($pageid) [$pgtr_ get-obj-num $pageid] 
  537. # Objects that have been requested
  538. set req_objs_($pageid) $recv_objs_($pageid) 
  539. set objid [join [$pgtr_ get-next-objs $pageid]]
  540. if [info exists rvInterObj_] {
  541. $ns_ at [expr [$ns_ now] + [$rvInterObj_ value]] 
  542. "$self next-obj $server $objid"
  543. } else {
  544. eval $self next-obj $server $objid
  545. }
  546. } else {
  547. # Main page id
  548. set mpgid [$pgtr_ get-mainpage $pageid]
  549. }
  550. array set data $args
  551. # Check stale hits and record maximum stale hit time
  552. set origsvr [lindex [split $pageid :] 0]
  553. set modtime [$origsvr get-modtime $pageid]
  554. set reqtime [lindex $pending_($pageid) 0]
  555. set reqrtt [expr [$ns_ now] - $reqtime]
  556. # XXX If a stale hit occurs because a page is modified during the RTT
  557. # of the request, we should *NOT* consider it a stale hit. We 
  558. # implement it by ignoring all stale hits whose modification time is
  559. # larger than the request time. 
  560. #
  561. # See Http/Client::get-response-GET{}
  562. if {$modtime > $data(modtime)} {
  563. $self instvar ns_
  564. # Staleness is the time from now to the time it's last modified
  565. set tmp [$origsvr stale-time $pageid $data(modtime)]
  566. if {$tmp > $reqrtt/2} {
  567. if ![info exists max_stale_($mpgid)] {
  568. set max_stale_($mpgid) $tmp
  569. } elseif {$max_stale_($mpgid) < $tmp} {
  570. set max_stale_($mpgid) $tmp
  571. }
  572. }
  573. }
  574. # Wait for the embedded objects if this is a main page
  575. if [$pgtr_ is-mainpage $pageid] {
  576. return
  577. }
  578. # Delete pending record of all embedded objects, but not the main page;
  579. # we need it later to compute the response time, etc.
  580. # XXX assuming only one request per object
  581. $self evTrace C RCV p $pageid s [$server id] l $reqrtt z $data(size)
  582. unset pending_($pageid)
  583. # Check if we have any pending embedded objects
  584. incr recv_objs_($mpgid) -1
  585. if {$recv_objs_($mpgid) > 0} {
  586. # We are waiting for more objects to come
  587. return
  588. }
  589. # Now we've received all objects
  590. $self instvar pgtr_
  591. # Record response time for the entire compound page
  592. set reqtime [lindex $pending_($mpgid) 0]
  593. $self evTrace C RCV p $mpgid s [$origsvr id] l 
  594. [expr [$ns_ now] - $reqtime] z $data(size)
  595. # We are done with this page
  596. unset pending_($mpgid)
  597. if [info exists simStartTime_] {
  598. set tmp [expr [$ns_ now] - $reqtime]
  599. set stat_(rep-time) [expr $stat_(rep-time) + $tmp]
  600. if {$stat_(rt-min) > $tmp} {
  601. set stat_(rt-min) $tmp
  602. }
  603. if {$stat_(rt-max) < $tmp} {
  604. set stat_(rt-max) $tmp
  605. }
  606. unset tmp
  607. }
  608. if [info exists max_stale_($mpgid)] {
  609. $self evTrace C STA p $mpgid s [$origsvr id] 
  610. l $max_stale_($mpgid)
  611. if [info exists simStartTime_] {
  612. incr stat_(stale-num)
  613. set stat_(stale-time) [expr 
  614. $stat_(stale-time) + $max_stale_($mpgid)]
  615. if {$stat_(st-min) > $max_stale_($mpgid)} {
  616. set stat_(st-min) $max_stale_($mpgid)
  617. }
  618. if {$stat_(st-max) < $max_stale_($mpgid)} {
  619. set stat_(st-max) $max_stale_($mpgid)
  620. }
  621. }
  622. unset max_stale_($mpgid)
  623. }
  624. $self mark-response $mpgid
  625. }
  626. Http/Client/Compound instproc mark-request { pageid } {
  627. set id [lindex [split $pageid :] end]
  628. if {$id == 0} {
  629. $self next $pageid
  630. }
  631. }