← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 18:42:36 2015
Reported on Fri Jul 31 18:48:13 2015

Filename/var/www/foswikidev/core/lib/Foswiki/Engine.pm
StatementsExecuted 46 statements in 1.69ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
11152µs315µsFoswiki::Engine::::prepareFoswiki::Engine::prepare
11143µs236µsFoswiki::Engine::::__ANON__[:110]Foswiki::Engine::__ANON__[:110]
11139µs1.18msFoswiki::Engine::::finalizeBodyFoswiki::Engine::finalizeBody
11139µs1.22msFoswiki::Engine::::finalizeFoswiki::Engine::finalize
11113µs26µsFoswiki::Engine::::BEGIN@17Foswiki::Engine::BEGIN@17
11110µs14µsFoswiki::Engine::::BEGIN@18Foswiki::Engine::BEGIN@18
11110µs32µsFoswiki::Engine::::BEGIN@20Foswiki::Engine::BEGIN@20
1119µs9µsFoswiki::Engine::::newFoswiki::Engine::new
1118µs149µsFoswiki::Engine::::BEGIN@19Foswiki::Engine::BEGIN@19
1114µs4µsFoswiki::Engine::::prepareWriteFoswiki::Engine::prepareWrite
1114µs4µsFoswiki::Engine::::BEGIN@21Foswiki::Engine::BEGIN@21
1114µs4µsFoswiki::Engine::::BEGIN@23Foswiki::Engine::BEGIN@23
1112µs2µsFoswiki::Engine::::prepareBodyFoswiki::Engine::prepareBody
1112µs2µsFoswiki::Engine::::prepareBodyParametersFoswiki::Engine::prepareBodyParameters
1111µs1µsFoswiki::Engine::::finalizeUploadsFoswiki::Engine::finalizeUploads
1111µs1µsFoswiki::Engine::::prepareUploadsFoswiki::Engine::prepareUploads
0000s0sFoswiki::Engine::::__ANON__[:125]Foswiki::Engine::__ANON__[:125]
0000s0sFoswiki::Engine::::__ANON__[:155]Foswiki::Engine::__ANON__[:155]
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
17233µs238µs
# spent 26µs (13+12) within Foswiki::Engine::BEGIN@17 which was called: # once (13µs+12µs) by Foswiki::Engine::CLI::BEGIN@20 at line 17
use strict;
# spent 26µs making 1 call to Foswiki::Engine::BEGIN@17 # spent 12µs making 1 call to strict::import
18228µs219µs
# spent 14µs (10+4) within Foswiki::Engine::BEGIN@18 which was called: # once (10µs+4µs) by Foswiki::Engine::CLI::BEGIN@20 at line 18
use warnings;
# spent 14µs making 1 call to Foswiki::Engine::BEGIN@18 # spent 4µs making 1 call to warnings::import
19230µs2290µs
# spent 149µs (8+141) within Foswiki::Engine::BEGIN@19 which was called: # once (8µs+141µs) by Foswiki::Engine::CLI::BEGIN@20 at line 19
use Error qw( :try );
# spent 149µs making 1 call to Foswiki::Engine::BEGIN@19 # spent 141µs making 1 call to Error::import
20225µs255µs
# spent 32µs (10+22) within Foswiki::Engine::BEGIN@20 which was called: # once (10µs+22µs) by Foswiki::Engine::CLI::BEGIN@20 at line 20
use Assert;
# spent 32µs making 1 call to Foswiki::Engine::BEGIN@20 # spent 22µs making 1 call to Exporter::import
21247µs14µ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
# spent 4µs within Foswiki::Engine::BEGIN@23 which was called: # once (4µs+0s) by Foswiki::Engine::CLI::BEGIN@20 at line 28
BEGIN {
2414µs if ( $Foswiki::cfg{UseLocale} ) {
25 require locale;
26 import locale();
27 }
2811.35ms14µs}
# spent 4µs making 1 call to Foswiki::Engine::BEGIN@23
29
30=begin TML
31
32---++ ClassMethod new() -> $engine
33
34Constructs an engine object.
35
36=cut
37
38
# spent 9µs within Foswiki::Engine::new which was called: # once (9µs+0s) by Foswiki::BEGIN@176 at line 1 of (eval 100)[/var/www/foswikidev/core/lib/Foswiki.pm:632]
sub new {
391700ns my $proto = shift;
401500ns my $class = ref($proto) || $proto;
411600ns my $this = {};
4219µs return bless $this, $class;
43}
44
45=begin TML
46
47---++ ObjectMethod run()
48
49Start point to Runtime Engines.
50
51=cut
52
53sub run {
54 my $this = shift;
55 my $req = $this->prepare();
56 if ( ref($req) ) {
57 my $res = Foswiki::UI::handleRequest($req);
58 $this->finalize( $res, $req );
59 }
60}
61
62=begin TML
63
64---++ ObjectMethod prepare() -> $req
65
66Initialize a Foswiki::Request object by calling many preparation methods
67and returns it, or a status code in case of error.
68
69=cut
70
71
# spent 315µs (52+263) within Foswiki::Engine::prepare which was called: # once (52µs+263µs) by Foswiki::Engine::CLI::run at line 58 of /var/www/foswikidev/core/lib/Foswiki/Engine/CLI.pm
sub prepare {
721700ns my $this = shift;
731300ns my $req;
74
7512µs if ( $Foswiki::cfg{Store}{overrideUmask} && $Foswiki::cfg{OS} ne 'WINDOWS' )
76 {
77
78# Note: The addition of zero is required to force dirPermission and filePermission
79# to be numeric. Without the additition, certain values of the permissions cause
80# runtime errors about illegal characters in subtraction. "and" with 777 to prevent
81# sticky-bits from breaking the umask.
82 my $oldUmask = umask(
83 (
84 oct(777) - (
85 (
86 $Foswiki::cfg{Store}{dirPermission} + 0 |
87 $Foswiki::cfg{Store}{filePermission} + 0
88 )
89 ) & oct(777)
90 )
91 );
92
93#my $umask = sprintf('%04o', umask() );
94#$oldUmask = sprintf('%04o', $oldUmask );
95#my $dirPerm = sprintf('%04o', $Foswiki::cfg{Store}{dirPermission}+0 );
96#my $filePerm = sprintf('%04o', $Foswiki::cfg{Store}{filePermission}+0 );
97#print STDERR " ENGINE changes $oldUmask to $umask from $dirPerm and $filePerm \n";
98 }
99
100
# spent 236µs (43+193) within Foswiki::Engine::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Engine.pm:110] which was called: # once (43µs+193µs) by Error::subs::try at line 419 of Error.pm
try {
10114µs138µs $req = Foswiki::Request->new();
# spent 38µs making 1 call to Foswiki::Request::new
10212µs116µs $this->prepareConnection($req);
# spent 16µs making 1 call to Foswiki::Engine::CLI::prepareConnection
10312µs1108µs $this->prepareQueryParameters($req);
# spent 108µs making 1 call to Foswiki::Engine::CLI::prepareQueryParameters
10413µs111µs $this->prepareHeaders($req);
# spent 11µs making 1 call to Foswiki::Engine::CLI::prepareHeaders
10512µs1900ns $this->prepareCookies($req);
# spent 900ns making 1 call to Foswiki::Engine::CLI::prepareCookies
10612µs115µs $this->preparePath($req);
# spent 15µs making 1 call to Foswiki::Engine::CLI::preparePath
10715µs12µs $this->prepareBody($req);
# spent 2µs making 1 call to Foswiki::Engine::prepareBody
10814µs12µs $this->prepareBodyParameters($req);
# spent 2µs making 1 call to Foswiki::Engine::prepareBodyParameters
10916µs11µs $this->prepareUploads($req);
# spent 1µs making 1 call to Foswiki::Engine::prepareUploads
110 }
111 catch Foswiki::EngineException with {
112 my $e = shift;
113 my $res = $e->{response};
114 unless ( defined $res ) {
115 $res = new Foswiki::Response();
116 $res->header( -type => 'text/html', -status => $e->{status} );
117 my $html = CGI::start_html( $e->{status} . ' Bad Request' );
118 $html .= CGI::h1( {}, 'Bad Request' );
119 $html .= CGI::p( {}, $e->{reason} );
120 $html .= CGI::end_html();
121 $res->print($html);
122 }
123 $this->finalizeError( $res, $req );
124 return $e->{status};
125 }
126 otherwise {
127 my $e = shift;
128 my $res = Foswiki::Response->new();
129 my $mess =
130 $e->can('stringify')
131 ? $e->stringify()
132 : 'Unknown ' . ref($e) . ' exception: ' . $@;
133 $res->header( -type => 'text/plain', -status => '500' );
134 if (DEBUG) {
135
136 # output the full message and stacktrace to the browser
137 $res->print($mess);
138 }
139 else {
140 print STDERR $mess;
141
142 # tell the browser where to look for more help
143 my $text =
144'Foswiki detected an internal error - please check your Foswiki logs and webserver logs for more information.'
145 . "\n\n";
146 $mess =~ s/ at .*$//s;
147
148 # cut out pathnames from public announcement
149 $mess =~ s#/[\w./]+#path#g;
150 $text .= $mess;
151 $res->print($text);
152 }
153 $this->finalizeError( $res, $req );
154 return 500; # Internal server error
155142µs4263µs };
# spent 252µs making 1 call to Error::subs::try # spent 5µs making 1 call to Error::subs::otherwise # spent 4µs making 1 call to Error::catch # spent 2µs making 1 call to Error::subs::with
15613µs return $req;
157}
158
159=begin TML
160
161---++ ObjectMethod prepareConnection( $req )
162
163Abstract method, must be defined by inherited classes.
164 * =$req= - Foswiki::Request object to populate
165
166Should fill remoteAddr, method and secure fields of =$req= object.
167
168=cut
169
170sub prepareConnection { }
171
172=begin TML
173
174---++ ObjectMethod prepareQueryParameters( $req, $queryString )
175
176Populates $req with parameters extracted by parsing a
177byte string (which may include url-encoded characters, which may
178in turn be parts of utf8-encoded characters).
179
180Note that parameter names and values are decoded to unicode.
181
182=cut
183
184sub prepareQueryParameters {
185 my ( $this, $req, $queryString ) = @_;
186 my @pairs = split /[&;]/, $queryString;
187 my ( $param, $value, %params, @plist );
188 foreach my $pair (@pairs) {
189 ( $param, $value ) = split( '=', $pair, 2 );
190
191 # url decode
192 if ( defined $value ) {
193 $value =~ tr/+/ /;
194 $value =~ s/%([0-9A-F]{2})/chr(hex($1))/gei;
195 $value = Foswiki::decode_utf8($value);
196 }
197 if ( defined $param ) {
198 $param =~ tr/+/ /;
199 $param =~ s/%([0-9A-F]{2})/chr(hex($1))/gei;
200 $param = Foswiki::decode_utf8($param);
201 push( @{ $params{$param} }, $value );
202 push( @plist, $param );
203 }
204 }
205 foreach my $param (@plist) {
206 (undef) = $req->queryParam( $param, $params{$param} );
207 }
208}
209
210=begin TML
211
212---++ ObjectMethod prepareHeaders( $req )
213
214Abstract method, must be defined by inherited classes.
215 * =$req= - Foswiki::Request object to populate
216
217Should fill $req's headers and remoteUser fields.
218
219=cut
220
221sub prepareHeaders { }
222
223=begin TML
224
225---++ ObjectMethod preparePath( $req )
226
227Abstract method, must be defined by inherited classes.
228 * =$req= - Foswiki::Request object to populate
229
230Should fill $req's uri and pathInfo fields.
231
232=cut
233
234sub preparePath { }
235
236=begin TML
237
238---++ ObjectMethod prepareCookies( $req )
239
240 * =$req= - Foswiki::Request object to populate
241
242Should fill $req's cookie field. This method take cookie data from
243previously populated headers field and initializes from it. Maybe
244doesn't need to overload in children classes.
245
246=cut
247
248sub prepareCookies {
249 my ( $this, $req ) = @_;
250 eval { require CGI::Cookie };
251 throw Error::Simple($@) if $@;
252 $req->cookies( scalar( CGI::Cookie->parse( $req->header('Cookie') ) ) )
253 if $req->header('Cookie');
254}
255
256=begin TML
257
258---++ ObjectMethod prepareBody( $req )
259
260Abstract method, must be defined by inherited classes.
261 * =$req= - Foswiki::Request object to populate
262
263Should perform any initialization tasks related to body processing.
264
265=cut
266
26713µs
# spent 2µs within Foswiki::Engine::prepareBody which was called: # once (2µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Engine.pm:110] at line 107
sub prepareBody { }
268
269=begin TML
270
271---++ ObjectMethod prepareBodyParameters( $req )
272
273Abstract method, must be defined by inherited classes.
274 * =$req= - Foswiki::Request object to populate
275
276Should fill $req's body parameters (parameters that are set in the
277request body, as against the query string). Implementations must
278convert parameter values to unicode.
279
280=cut
281
28213µs
# spent 2µs within Foswiki::Engine::prepareBodyParameters which was called: # once (2µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Engine.pm:110] at line 108
sub prepareBodyParameters { }
283
284=begin TML
285
286---++ ObjectMethod prepareUploads( $req )
287
288Abstract method, must be defined by inherited classes.
289 * =$req= - Foswiki::Request object to populate
290
291Should fill $req's {uploads} field. This is a hashref whose keys are
292upload names and values Foswiki::Request::Upload objects.
293
294Implementations must convert upload names to unicode.
295
296=cut
297
29813µs
# spent 1µs within Foswiki::Engine::prepareUploads which was called: # once (1µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Engine.pm:110] at line 109
sub prepareUploads { }
299
300=begin TML
301
302---++ ObjectMethod finalize($res, $req)
303
304Finalizes the request by calling many methods to send response to client and
305take any appropriate finalize actions, such as delete temporary files.
306 * =$res= is the Foswiki::Response object
307 * =$req= it the Foswiki::Request object.
308
309=cut
310
311
# spent 1.22ms (39µs+1.19) within Foswiki::Engine::finalize which was called: # once (39µs+1.19ms) by Foswiki::Engine::CLI::run at line 61 of /var/www/foswikidev/core/lib/Foswiki/Engine/CLI.pm
sub finalize {
31212µs my ( $this, $res, $req ) = @_;
31318µs14µs if ( $res->outputHasStarted() ) {
# spent 4µs making 1 call to Foswiki::Response::outputHasStarted
314 $this->flush( $res, $req );
315 }
316 else {
31718µs11µs $this->finalizeUploads( $res, $req );
# spent 1µs making 1 call to Foswiki::Engine::finalizeUploads
31813µs12µs $this->finalizeHeaders( $res, $req );
# spent 2µs making 1 call to Foswiki::Engine::CLI::finalizeHeaders
31917µs11.18ms $this->finalizeBody($res);
# spent 1.18ms making 1 call to Foswiki::Engine::finalizeBody
320 }
321}
322
323=begin TML
324
325---++ ObjectMethod finalizeUploads( $res, $req )
326
327Abstract method, must be defined by inherited classes.
328 * =$res= - Foswiki::Response object to get data from
329 * =$req= - Foswiki::Request object to get data from
330
331Should delete any temp files created in preparation phase.
332
333=cut
334
33515µs
# spent 1µs within Foswiki::Engine::finalizeUploads which was called: # once (1µs+0s) by Foswiki::Engine::finalize at line 317
sub finalizeUploads { }
336
337=begin TML
338
339---++ ObjectMethod finalizeError( $res, $req )
340
341Called if some engine especific error happens.
342
343 * =$res= - Foswiki::Response object to get data from
344 * =$req= - Foswiki::Request object to get data from
345
346=cut
347
348sub finalizeError {
349 my ( $this, $res, $req ) = @_;
350 $this->finalizeHeaders( $res, $req );
351 $this->finalizeBody( $res, $req );
352
353 # Item12590: prevent duplicated output by later call to finalize()
354 $res->body('');
355 $res->outputHasStarted(1);
356}
357
358=begin TML
359
360---++ ObjectMethod finalizeHeaders( $res, $req )
361
362Base method, must be redefined by inherited classes. For convenience
363this method deals with HEAD requests related stuff. Children classes
364should call SUPER.
365 * =$res= - Foswiki::Response object to get data from
366 * =$req= - Foswiki::Request object to get data from
367
368Should call finalizeCookies and then send $res' headers to client.
369
370=cut
371
372sub finalizeHeaders {
373 my ( $this, $res, $req ) = @_;
374 $this->finalizeCookies($res);
375 if ( $req && $req->method() && uc( $req->method() ) eq 'HEAD' ) {
376 $res->body('');
377 $res->deleteHeader('Content-Length');
378 }
379}
380
381=begin TML
382
383---++ ObjectMethod finalizeCookies( $res )
384
385 * =$res= - Foswiki::Response object to both get data from and populate
386
387Should populate $res' headers field with cookies, if any.
388
389=cut
390
391sub finalizeCookies {
392 my ( $this, $res ) = @_;
393
394 # SMELL: Review comment below, from CGI:
395 # if the user indicates an expiration time, then we need
396 # both an Expires and a Date header (so that the browser is
397 # uses OUR clock)
398 $res->pushHeader( 'Set-Cookie',
399 Scalar::Util::blessed $_
400 && $_->isa('CGI::Cookie') ? $_->as_string : $_ )
401 foreach $res->cookies;
402}
403
404=begin TML
405
406---++ ObjectMethod finalizeBody( $res, $req )
407
408 * =$res= - Foswiki::Response object to get data from
409 * =$req= - Foswiki::Request object to get data from
410
411Should send $res' body to client. This method calls =write()=
412as needed, so engines should redefine that method insted of this one.
413
414=cut
415
416
# spent 1.18ms (39µs+1.14) within Foswiki::Engine::finalizeBody which was called: # once (39µs+1.14ms) by Foswiki::Engine::finalize at line 319
sub finalizeBody {
41711µs my ( $this, $res, $req ) = @_;
41814µs11.05ms my $body = $res->body;
# spent 1.05ms making 1 call to Foswiki::Response::body
4191400ns return unless defined $body;
420110µs14µs $this->prepareWrite($res);
# spent 4µs making 1 call to Foswiki::Engine::prepareWrite
421119µs16µs if ( Scalar::Util::blessed($body) && $body->can('read')
# spent 6µs making 1 call to Scalar::Util::blessed
422 or ref $body eq 'GLOB' )
423 {
424 while ( !eof $body ) {
425 read $body, my $buffer, 4096;
426 last unless $this->write($buffer);
427 }
428 close $body;
429 }
430 else {
43113µs177µs $this->write($body);
# spent 77µs making 1 call to Foswiki::Engine::CLI::write
432 }
433}
434
435=begin TML
436
437---++ flush($res, $req)
438
439Forces the response headers to be emitted if they haven't already been sent
440(note that this may in some circumstances result in cookies being missed)
441before flushing what is in the body so far.
442
443Before headers are sent, any Content-length is removed, as a call to
444flush is a statement that there's more to follow, but we don't know
445how much at this point.
446
447This function should be used with great care! It requires that the output
448headers are fully complete before it is first called. Once it *has* been
449called, the response object will refuse any modifications that would alter
450the header.
451
452=cut
453
454sub flush {
455 my ( $this, $res, $req ) = @_;
456
457 unless ( $res->outputHasStarted() ) {
458 $res->deleteHeader('Content-Length');
459 $this->finalizeUploads( $res, $req );
460 $this->finalizeHeaders( $res, $req );
461 $this->prepareWrite($res);
462 $res->outputHasStarted(1);
463 }
464
465 my $body = $res->body();
466
467 if ( Scalar::Util::blessed($body) || ref($body) eq 'GLOB' ) {
468 throw Foswiki::EngineException('Cannot flush non-text response body');
469 }
470
471 $this->write($body);
472 $res->body('');
473}
474
475=begin TML
476
477---++ ObjectMethod prepareWrite( $res )
478
479Abstract method, may be defined by inherited classes.
480 * =$res= - Foswiki::Response object to get data from
481
482Should perform any task needed before writing.
483That's ok if none needed ;-)
484
485=cut
486
48714µs
# spent 4µs within Foswiki::Engine::prepareWrite which was called: # once (4µs+0s) by Foswiki::Engine::finalizeBody at line 420
sub prepareWrite { }
488
489=begin TML
490
491---++ ObjectMethod write( $buffer )
492
493Abstract method, must be defined by inherited classes.
494 * =$buffer= - chunk of data to be sent
495
496Should send $buffer to client.
497
498=cut
499
500sub write {
501 ASSERT('Pure virtual method - should never be called');
502}
503
50412µs1;
505__END__