← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:09 2015

Filename/var/www/foswiki11/lib/Foswiki/Engine.pm
StatementsExecuted 44 statements in 1.89ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11153µs6.11msFoswiki::Engine::::__ANON__[:77]Foswiki::Engine::__ANON__[:77]
11147µs6.19msFoswiki::Engine::::prepareFoswiki::Engine::prepare
11138µs213µsFoswiki::Engine::::finalizeBodyFoswiki::Engine::finalizeBody
11136µs258µsFoswiki::Engine::::finalizeFoswiki::Engine::finalize
11115µs30µsFoswiki::Engine::::BEGIN@17Foswiki::Engine::BEGIN@17
11112µs28µsFoswiki::Engine::::BEGIN@20Foswiki::Engine::BEGIN@20
11110µs17µsFoswiki::Engine::::BEGIN@18Foswiki::Engine::BEGIN@18
11110µs10µsFoswiki::Engine::::newFoswiki::Engine::new
1119µs146µsFoswiki::Engine::::BEGIN@19Foswiki::Engine::BEGIN@19
1114µs4µsFoswiki::Engine::::BEGIN@21Foswiki::Engine::BEGIN@21
1113µs3µsFoswiki::Engine::::prepareWriteFoswiki::Engine::prepareWrite
1112µs2µsFoswiki::Engine::::finalizeUploadsFoswiki::Engine::finalizeUploads
1112µs2µsFoswiki::Engine::::prepareBodyFoswiki::Engine::prepareBody
1111µs1µsFoswiki::Engine::::prepareBodyParametersFoswiki::Engine::prepareBodyParameters
1111µs1µsFoswiki::Engine::::prepareUploadsFoswiki::Engine::prepareUploads
0000s0sFoswiki::Engine::::__ANON__[:122]Foswiki::Engine::__ANON__[:122]
0000s0sFoswiki::Engine::::__ANON__[:92]Foswiki::Engine::__ANON__[:92]
0000s0sFoswiki::Engine::::finalizeCookiesFoswiki::Engine::finalizeCookies
0000s0sFoswiki::Engine::::finalizeErrorFoswiki::Engine::finalizeError
0000s0sFoswiki::Engine::::finalizeHeadersFoswiki::Engine::finalizeHeaders
0000s0sFoswiki::Engine::::flushFoswiki::Engine::flush
0000s0sFoswiki::Engine::::prepareConnectionFoswiki::Engine::prepareConnection
0000s0sFoswiki::Engine::::prepareCookiesFoswiki::Engine::prepareCookies
0000s0sFoswiki::Engine::::prepareHeadersFoswiki::Engine::prepareHeaders
0000s0sFoswiki::Engine::::preparePathFoswiki::Engine::preparePath
0000s0sFoswiki::Engine::::prepareQueryParametersFoswiki::Engine::prepareQueryParameters
0000s0sFoswiki::Engine::::runFoswiki::Engine::run
0000s0sFoswiki::Engine::::writeFoswiki::Engine::write
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+!! package Foswiki::Engine
6
7The engine class is a singleton that implements details about Foswiki's
8execution mode. This is the base class and implements basic behavior.
9
10Each engine should inherits from this and overload methods necessary
11to achieve correct behavior.
12
13=cut
14
15package Foswiki::Engine;
16
17231µs246µs
# spent 30µs (15+16) within Foswiki::Engine::BEGIN@17 which was called: # once (15µs+16µs) by Foswiki::Engine::CLI::BEGIN@20 at line 17
use strict;
# spent 30µs making 1 call to Foswiki::Engine::BEGIN@17 # spent 16µs making 1 call to strict::import
18230µs223µs
# spent 17µs (10+6) within Foswiki::Engine::BEGIN@18 which was called: # once (10µs+6µs) by Foswiki::Engine::CLI::BEGIN@20 at line 18
use warnings;
# spent 17µs making 1 call to Foswiki::Engine::BEGIN@18 # spent 6µs making 1 call to warnings::import
19236µs2284µs
# spent 146µs (9+137) within Foswiki::Engine::BEGIN@19 which was called: # once (9µs+137µs) by Foswiki::Engine::CLI::BEGIN@20 at line 19
use Error qw( :try );
# spent 146µs making 1 call to Foswiki::Engine::BEGIN@19 # spent 137µs making 1 call to Error::import
20229µs244µs
# spent 28µs (12+16) within Foswiki::Engine::BEGIN@20 which was called: # once (12µs+16µs) by Foswiki::Engine::CLI::BEGIN@20 at line 20
use Assert;
# spent 28µs making 1 call to Foswiki::Engine::BEGIN@20 # spent 16µs making 1 call to Assert::import
2121.59ms14µs
# spent 4µs within Foswiki::Engine::BEGIN@21 which was called: # once (4µs+0s) by Foswiki::Engine::CLI::BEGIN@20 at line 21
use Scalar::Util ();
# spent 4µs making 1 call to Foswiki::Engine::BEGIN@21
22
23=begin TML
24
25---++ ClassMethod new() -> $engine
26
27Constructs an engine object.
28
29=cut
30
31
# spent 10µs within Foswiki::Engine::new which was called: # once (10µs+0s) by Foswiki::BEGIN@137 at line 1 of (eval 36)[/var/www/foswiki11/lib/Foswiki.pm:620]
sub new {
321700ns my $proto = shift;
331500ns my $class = ref($proto) || $proto;
341700ns my $this = {};
35111µs return bless $this, $class;
36}
37
38=begin TML
39
40---++ ObjectMethod run()
41
42Start point to Runtime Engines.
43
44=cut
45
46sub run {
47 my $this = shift;
48 my $req = $this->prepare();
49 if ( defined $req ) {
50 my $res = Foswiki::UI::handleRequest($req);
51 $this->finalize( $res, $req );
52 }
53}
54
55=begin TML
56
57---++ ObjectMethod prepare() -> $req
58
59Initialize a Foswiki::Request object by calling many preparation methods
60and returns it, or a status code in case of error.
61
62=cut
63
64
# spent 6.19ms (47µs+6.14) within Foswiki::Engine::prepare which was called: # once (47µs+6.14ms) by Foswiki::Engine::CLI::run at line 51 of /var/www/foswiki11/lib/Foswiki/Engine/CLI.pm
sub prepare {
651600ns my $this = shift;
661300ns my $req;
67
# spent 6.11ms (53µs+6.06) within Foswiki::Engine::__ANON__[/var/www/foswiki11/lib/Foswiki/Engine.pm:77] which was called: # once (53µs+6.06ms) by Error::subs::try at line 419 of Error.pm
try {
6814µs120µs $req = Foswiki::Request->new();
# spent 20µs making 1 call to Foswiki::Request::new
6913µs118µs $this->prepareConnection($req);
# spent 18µs making 1 call to Foswiki::Engine::CLI::prepareConnection
7012µs1111µs $this->prepareQueryParameters($req);
# spent 111µs making 1 call to Foswiki::Engine::CLI::prepareQueryParameters
7113µs111µs $this->prepareHeaders($req);
# spent 11µs making 1 call to Foswiki::Engine::CLI::prepareHeaders
7212µs11µs $this->prepareCookies($req);
# spent 1µs making 1 call to Foswiki::Engine::CLI::prepareCookies
7312µs15.89ms $this->preparePath($req);
# spent 5.89ms making 1 call to Foswiki::Engine::CLI::preparePath
7416µs12µs $this->prepareBody($req);
# spent 2µs making 1 call to Foswiki::Engine::prepareBody
7514µs11µs $this->prepareBodyParameters($req);
# spent 1µs making 1 call to Foswiki::Engine::prepareBodyParameters
7617µs11µs $this->prepareUploads($req);
# spent 1µs making 1 call to Foswiki::Engine::prepareUploads
77 }
78 catch Foswiki::EngineException with {
79 my $e = shift;
80 my $res = $e->{response};
81 unless ( defined $res ) {
82 $res = new Foswiki::Response();
83 $res->header( -type => 'text/html', -status => $e->{status} );
84 my $html = CGI::start_html( $e->{status} . ' Bad Request' );
85 $html .= CGI::h1( {}, 'Bad Request' );
86 $html .= CGI::p( {}, $e->{reason} );
87 $html .= CGI::end_html();
88 $res->print($html);
89 }
90 $this->finalizeError( $res, $req );
91 return $e->{status};
92 }
93 otherwise {
94 my $e = shift;
95 my $res = Foswiki::Response->new();
96 my $mess =
97 $e->can('stringify')
98 ? $e->stringify()
99 : 'Unknown ' . ref($e) . ' exception: ' . $@;
100 $res->header( -type => 'text/plain' );
101 if (DEBUG) {
102
103 # output the full message and stacktrace to the browser
104 $res->print($mess);
105 }
106 else {
107 print STDERR $mess;
108
109 # tell the browser where to look for more help
110 my $text =
111'Foswiki detected an internal error - please check your Foswiki logs and webserver logs for more information.'
112 . "\n\n";
113 $mess =~ s/ at .*$//s;
114
115 # cut out pathnames from public announcement
116 $mess =~ s#/[\w./]+#path#g;
117 $text .= $mess;
118 $res->print($text);
119 }
120 $this->finalizeError( $res, $req );
121 return 500; # Internal server error
122138µs46.14ms };
# spent 6.13ms making 1 call to Error::subs::try # spent 6µs making 1 call to Error::catch # spent 5µs making 1 call to Error::subs::otherwise # spent 2µs making 1 call to Error::subs::with
12314µs return $req;
124}
125
126=begin TML
127
128---++ ObjectMethod prepareConnection( $req )
129
130Abstract method, must be defined by inherited classes.
131 * =$req= - Foswiki::Request object to populate
132
133Should fill remoteAddr, method and secure fields of =$req= object.
134
135=cut
136
137sub prepareConnection { }
138
139=begin TML
140
141---++ ObjectMethod prepareQueryParameters( $req, $queryString )
142
143Should fill $req's query parameters field.
144
145This method populates $req as it should if given $queryString parameter.
146Subclasses may redefine this method and call SUPER with query string obtained.
147
148=cut
149
150sub prepareQueryParameters {
151 my ( $this, $req, $queryString ) = @_;
152 my @pairs = split /[&;]/, $queryString;
153 my ( $param, $value, %params, @plist );
154 foreach my $pair (@pairs) {
155 ( $param, $value ) = split( '=', $pair, 2 );
156
157 # url decode
158 if ( defined $value ) {
159 $value =~ tr/+/ /;
160 $value =~ s/%([0-9A-F]{2})/chr(hex($1))/gei;
161 }
162 if ( defined $param ) {
163 $param =~ tr/+/ /;
164 $param =~ s/%([0-9A-F]{2})/chr(hex($1))/gei;
165 push @{ $params{$param} }, $value;
166 push @plist, $param;
167 }
168 }
169 foreach my $param (@plist) {
170 $req->queryParam( $param, $params{$param} );
171 }
172}
173
174=begin TML
175
176---++ ObjectMethod prepareHeaders( $req )
177
178Abstract method, must be defined by inherited classes.
179 * =$req= - Foswiki::Request object to populate
180
181Should fill $req's headers and remoteUser fields.
182
183=cut
184
185sub prepareHeaders { }
186
187=begin TML
188
189---++ ObjectMethod preparePath( $req )
190
191Abstract method, must be defined by inherited classes.
192 * =$req= - Foswiki::Request object to populate
193
194Should fill $req's uri and pathInfo fields.
195
196=cut
197
198sub preparePath { }
199
200=begin TML
201
202---++ ObjectMethod prepareCookies( $req )
203
204 * =$req= - Foswiki::Request object to populate
205
206Should fill $req's cookie field. This method take cookie data from
207previously populated headers field and initializes from it. Maybe
208doesn't need to overload in children classes.
209
210=cut
211
212sub prepareCookies {
213 my ( $this, $req ) = @_;
214 eval { require CGI::Cookie };
215 throw Error::Simple($@) if $@;
216 $req->cookies( scalar CGI::Cookie->parse( $req->header('Cookie') ) )
217 if $req->header('Cookie');
218}
219
220=begin TML
221
222---++ ObjectMethod prepareBody( $req )
223
224Abstract method, must be defined by inherited classes.
225 * =$req= - Foswiki::Request object to populate
226
227Should perform any initialization tasks related to body processing.
228
229=cut
230
23115µs
# spent 2µs within Foswiki::Engine::prepareBody which was called: # once (2µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswiki11/lib/Foswiki/Engine.pm:77] at line 74
sub prepareBody { }
232
233=begin TML
234
235---++ ObjectMethod prepareBodyParameters( $req )
236
237Abstract method, must be defined by inherited classes.
238 * =$req= - Foswiki::Request object to populate
239
240Should fill $req's body parameters.
241
242=cut
243
24413µs
# spent 1µs within Foswiki::Engine::prepareBodyParameters which was called: # once (1µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswiki11/lib/Foswiki/Engine.pm:77] at line 75
sub prepareBodyParameters { }
245
246=begin TML
247
248---++ ObjectMethod prepareUploads( $req )
249
250Abstract method, must be defined by inherited classes.
251 * =$req= - Foswiki::Request object to populate
252
253Should fill $req's uploads field. Its a hashref whose keys are
254parameter names and values Foswiki::Request::Upload objects.
255
256=cut
257
25813µs
# spent 1µs within Foswiki::Engine::prepareUploads which was called: # once (1µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswiki11/lib/Foswiki/Engine.pm:77] at line 76
sub prepareUploads { }
259
260=begin TML
261
262---++ ObjectMethod finalize($res, $req)
263
264Finalizes the request by calling many methods to send response to client and
265take any appropriate finalize actions, such as delete temporary files.
266 * =$res= is the Foswiki::Response object
267 * =$req= it the Foswiki::Request object.
268
269=cut
270
271
# spent 258µs (36+222) within Foswiki::Engine::finalize which was called: # once (36µs+222µs) by Foswiki::Engine::CLI::run at line 54 of /var/www/foswiki11/lib/Foswiki/Engine/CLI.pm
sub finalize {
27212µs my ( $this, $res, $req ) = @_;
27317µs14µs if ( $res->outputHasStarted() ) {
# spent 4µs making 1 call to Foswiki::Response::outputHasStarted
274 $this->flush( $res, $req );
275 }
276 else {
27716µs12µs $this->finalizeUploads( $res, $req );
# spent 2µs making 1 call to Foswiki::Engine::finalizeUploads
27814µs13µs $this->finalizeHeaders( $res, $req );
# spent 3µs making 1 call to Foswiki::Engine::CLI::finalizeHeaders
27917µs1213µs $this->finalizeBody($res);
# spent 213µs making 1 call to Foswiki::Engine::finalizeBody
280 }
281}
282
283=begin TML
284
285---++ ObjectMethod finalizeUploads( $res, $req )
286
287Abstract method, must be defined by inherited classes.
288 * =$res= - Foswiki::Response object to get data from
289 * =$req= - Foswiki::Request object to get data from
290
291Should delete any temp files created in preparation phase.
292
293=cut
294
29516µs
# spent 2µs within Foswiki::Engine::finalizeUploads which was called: # once (2µs+0s) by Foswiki::Engine::finalize at line 277
sub finalizeUploads { }
296
297=begin TML
298
299---++ ObjectMethod finalizeError( $res, $req )
300
301Called if some engine especific error happens.
302
303 * =$res= - Foswiki::Response object to get data from
304 * =$req= - Foswiki::Request object to get data from
305
306=cut
307
308sub finalizeError {
309 my ( $this, $res, $req ) = @_;
310 $this->finalizeHeaders( $res, $req );
311 $this->finalizeBody( $res, $req );
312
313 # Item12590: prevent duplicated output by later call to finalize()
314 $res->body('');
315 $res->outputHasStarted(1);
316}
317
318=begin TML
319
320---++ ObjectMethod finalizeHeaders( $res, $req )
321
322Base method, must be redefined by inherited classes. For convenience
323this method deals with HEAD requests related stuff. Children classes
324should call SUPER.
325 * =$res= - Foswiki::Response object to get data from
326 * =$req= - Foswiki::Request object to get data from
327
328Should call finalizeCookies and then send $res' headers to client.
329
330=cut
331
332sub finalizeHeaders {
333 my ( $this, $res, $req ) = @_;
334 $this->finalizeCookies($res);
335 if ( $req && $req->method() && uc( $req->method() ) eq 'HEAD' ) {
336 $res->body('');
337 $res->deleteHeader('Content-Length');
338 }
339}
340
341=begin TML
342
343---++ ObjectMethod finalizeCookies( $res )
344
345 * =$res= - Foswiki::Response object to both get data from and populate
346
347Should populate $res' headers field with cookies, if any.
348
349=cut
350
351sub finalizeCookies {
352 my ( $this, $res ) = @_;
353
354 # SMELL: Review comment below, from CGI:
355 # if the user indicates an expiration time, then we need
356 # both an Expires and a Date header (so that the browser is
357 # uses OUR clock)
358 $res->pushHeader( 'Set-Cookie',
359 Scalar::Util::blessed $_
360 && $_->isa('CGI::Cookie') ? $_->as_string : $_ )
361 foreach $res->cookies;
362}
363
364=begin TML
365
366---++ ObjectMethod finalizeBody( $res, $req )
367
368 * =$res= - Foswiki::Response object to get data from
369 * =$req= - Foswiki::Request object to get data from
370
371Should send $res' body to client. This method calls =write()=
372as needed, sou engines should redefine that method insted of this one.
373
374=cut
375
376
# spent 213µs (38+175) within Foswiki::Engine::finalizeBody which was called: # once (38µs+175µs) by Foswiki::Engine::finalize at line 279
sub finalizeBody {
37711µs my ( $this, $res, $req ) = @_;
37813µs193µs my $body = $res->body;
# spent 93µs making 1 call to Foswiki::Response::body
3791300ns return unless defined $body;
38018µs13µs $this->prepareWrite($res);
# spent 3µs making 1 call to Foswiki::Engine::prepareWrite
381119µs16µs if ( Scalar::Util::blessed($body) && $body->can('read')
# spent 6µs making 1 call to Scalar::Util::blessed
382 or ref $body eq 'GLOB' )
383 {
384 while ( !eof $body ) {
385 read $body, my $buffer, 4096;
386 last unless $this->write($buffer);
387 }
388 close $body;
389 }
390 else {
39113µs173µs $this->write($body);
# spent 73µs making 1 call to Foswiki::Engine::CLI::write
392 }
393}
394
395=begin TML
396
397---++ flush($res, $req)
398
399Forces the response headers to be emitted if they haven't already been sent
400(note that this may in some circumstances result in cookies being missed)
401before flushing what is in the body so far.
402
403Before headers are sent, any Content-length is removed, as a call to
404flush is a statement that there's more to follow, but we don't know
405how much at this point.
406
407This function should be used with great care! It requires that the output
408headers are fully complete before it is first called. Once it *has* been
409called, the response object will refuse any modifications that would alter
410the header.
411
412=cut
413
414sub flush {
415 my ( $this, $res, $req ) = @_;
416
417 unless ( $res->outputHasStarted() ) {
418 $res->deleteHeader('Content-Length');
419 $this->finalizeUploads( $res, $req );
420 $this->finalizeHeaders( $res, $req );
421 $this->prepareWrite($res);
422 $res->outputHasStarted(1);
423 }
424
425 my $body = $res->body();
426
427 if ( Scalar::Util::blessed($body) || ref($body) eq 'GLOB' ) {
428 throw Foswiki::EngineException('Cannot flush non-text response body');
429 }
430
431 $this->write($body);
432 $res->body('');
433}
434
435=begin TML
436
437---++ ObjectMethod prepareWrite( $res )
438
439Abstract method, may be defined by inherited classes.
440 * =$res= - Foswiki::Response object to get data from
441
442Should perform any task needed before writing.
443That's ok if none needed ;-)
444
445=cut
446
44715µs
# spent 3µs within Foswiki::Engine::prepareWrite which was called: # once (3µs+0s) by Foswiki::Engine::finalizeBody at line 380
sub prepareWrite { }
448
449=begin TML
450
451---++ ObjectMethod write( $buffer )
452
453Abstract method, must be defined by inherited classes.
454 * =$buffer= - chunk of data to be sent
455
456Should send $buffer to client.
457
458=cut
459
460sub write {
461 ASSERT('Pure virtual method - should never be called');
462}
463
46413µs1;
465__END__