← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/local/src/github.com/foswiki/core/bin/view
  Run on Sun Dec 4 17:17:59 2011
Reported on Sun Dec 4 17:26:39 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine.pm
StatementsExecuted 51 statements in 3.02ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1112.70ms4.70msFoswiki::Engine::::prepareCookiesFoswiki::Engine::prepareCookies
11198µs6.10msFoswiki::Engine::::__ANON__[:102]Foswiki::Engine::__ANON__[:102]
11198µs6.28msFoswiki::Engine::::prepareFoswiki::Engine::prepare
11173µs2.00msFoswiki::Engine::::finalizeFoswiki::Engine::finalize
11173µs755µsFoswiki::Engine::::finalizeCookiesFoswiki::Engine::finalizeCookies
11160µs180µsFoswiki::Engine::::finalizeBodyFoswiki::Engine::finalizeBody
11151µs820µsFoswiki::Engine::::finalizeHeadersFoswiki::Engine::finalizeHeaders
11124µs31µsFoswiki::Engine::::BEGIN@17Foswiki::Engine::BEGIN@17
11121µs69µsFoswiki::Engine::::BEGIN@20Foswiki::Engine::BEGIN@20
11120µs20µsFoswiki::Engine::::newFoswiki::Engine::new
11119µs415µsFoswiki::Engine::::BEGIN@19Foswiki::Engine::BEGIN@19
11117µs34µsFoswiki::Engine::::BEGIN@18Foswiki::Engine::BEGIN@18
1119µs9µsFoswiki::Engine::::BEGIN@21Foswiki::Engine::BEGIN@21
1114µs4µsFoswiki::Engine::::prepareWriteFoswiki::Engine::prepareWrite
0000s0sFoswiki::Engine::::__ANON__[:117]Foswiki::Engine::__ANON__[:117]
0000s0sFoswiki::Engine::::__ANON__[:144]Foswiki::Engine::__ANON__[:144]
0000s0sFoswiki::Engine::::finalizeErrorFoswiki::Engine::finalizeError
0000s0sFoswiki::Engine::::finalizeUploadsFoswiki::Engine::finalizeUploads
0000s0sFoswiki::Engine::::flushFoswiki::Engine::flush
0000s0sFoswiki::Engine::::prepareBodyFoswiki::Engine::prepareBody
0000s0sFoswiki::Engine::::prepareBodyParametersFoswiki::Engine::prepareBodyParameters
0000s0sFoswiki::Engine::::prepareConnectionFoswiki::Engine::prepareConnection
0000s0sFoswiki::Engine::::prepareHeadersFoswiki::Engine::prepareHeaders
0000s0sFoswiki::Engine::::preparePathFoswiki::Engine::preparePath
0000s0sFoswiki::Engine::::prepareQueryParametersFoswiki::Engine::prepareQueryParameters
0000s0sFoswiki::Engine::::prepareUploadsFoswiki::Engine::prepareUploads
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
17245µs238µs
# spent 31µs (24+7) within Foswiki::Engine::BEGIN@17 which was called: # once (24µs+7µs) by Foswiki::Engine::CGI::BEGIN@18 at line 17
use strict;
# spent 31µs making 1 call to Foswiki::Engine::BEGIN@17 # spent 7µs making 1 call to strict::import
18247µs251µs
# spent 34µs (17+17) within Foswiki::Engine::BEGIN@18 which was called: # once (17µs+17µs) by Foswiki::Engine::CGI::BEGIN@18 at line 18
use warnings;
# spent 34µs making 1 call to Foswiki::Engine::BEGIN@18 # spent 17µs making 1 call to warnings::import
19250µs2811µs
# spent 415µs (19+396) within Foswiki::Engine::BEGIN@19 which was called: # once (19µs+396µs) by Foswiki::Engine::CGI::BEGIN@18 at line 19
use Error qw( :try );
# spent 415µs making 1 call to Foswiki::Engine::BEGIN@19 # spent 396µs making 1 call to Error::import
20248µs2117µs
# spent 69µs (21+48) within Foswiki::Engine::BEGIN@20 which was called: # once (21µs+48µs) by Foswiki::Engine::CGI::BEGIN@18 at line 20
use Assert;
# spent 69µs making 1 call to Foswiki::Engine::BEGIN@20 # spent 48µs making 1 call to Assert::import
2122.20ms19µs
# spent 9µs within Foswiki::Engine::BEGIN@21 which was called: # once (9µs+0s) by Foswiki::Engine::CGI::BEGIN@18 at line 21
use Scalar::Util ();
# spent 9µ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 20µs within Foswiki::Engine::new which was called: # once (20µs+0s) by Foswiki::BEGIN@134 at line 1 of (eval 33)[/usr/local/src/github.com/foswiki/core/lib/Foswiki.pm:597]
sub new {
32423µs my $proto = shift;
33 my $class = ref($proto) || $proto;
34 my $this = {};
35 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.28ms (98µs+6.19) within Foswiki::Engine::prepare which was called: # once (98µs+6.19ms) by Foswiki::Engine::CGI::run at line 39 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine/CGI.pm
sub prepare {
65588µs my $this = shift;
66 my $req;
67
68 if ( $Foswiki::cfg{RCS}{overrideUmask} && $Foswiki::cfg{OS} ne 'WINDOWS' ) {
69
70# Note: The addition of zero is required to force dirPermission and filePermission
71# to be numeric. Without the additition, certain values of the permissions cause
72# runtime errors about illegal characters in subtraction. "and" with 777 to prevent
73# sticky-bits from breaking the umask.
74 my $oldUmask = umask(
75 (
76 oct(777) - (
77 (
78 $Foswiki::cfg{RCS}{dirPermission} + 0 |
79 $Foswiki::cfg{RCS}{filePermission} + 0
80 )
81 ) & oct(777)
82 )
83 );
84
85#my $umask = sprintf('%04o', umask() );
86#$oldUmask = sprintf('%04o', $oldUmask );
87#my $dirPerm = sprintf('%04o', $Foswiki::cfg{RCS}{dirPermission}+0 );
88#my $filePerm = sprintf('%04o', $Foswiki::cfg{RCS}{filePermission}+0 );
89#print STDERR " ENGINE changes $oldUmask to $umask from $dirPerm and $filePerm \n";
90 }
91
92
# spent 6.10ms (98µs+6.01) within Foswiki::Engine::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine.pm:102] which was called: # once (98µs+6.01ms) by Error::subs::try at line 416 of Error.pm
try {
93969µs142µs $req = Foswiki::Request->new();
# spent 42µs making 1 call to Foswiki::Request::new
941122µs $this->prepareConnection($req);
# spent 122µs making 1 call to Foswiki::Engine::CGI::prepareConnection
9518µs $this->prepareQueryParameters($req);
# spent 8µs making 1 call to Foswiki::Engine::CGI::prepareQueryParameters
961919µs $this->prepareHeaders($req);
# spent 919µs making 1 call to Foswiki::Engine::CGI::prepareHeaders
9714.70ms $this->prepareCookies($req);
# spent 4.70ms making 1 call to Foswiki::Engine::prepareCookies
981195µs $this->preparePath($req);
# spent 195µs making 1 call to Foswiki::Engine::CGI::preparePath
9918µs $this->prepareBody($req);
# spent 8µs making 1 call to Foswiki::Engine::CGI::prepareBody
10017µs $this->prepareBodyParameters($req);
# spent 7µs making 1 call to Foswiki::Engine::CGI::prepareBodyParameters
10117µs $this->prepareUploads($req);
# spent 7µs making 1 call to Foswiki::Engine::CGI::prepareUploads
102 }
103 catch Foswiki::EngineException with {
104 my $e = shift;
105 my $res = $e->{response};
106 unless ( defined $res ) {
107 $res = new Foswiki::Response();
108 $res->header( -type => 'text/html', -status => $e->{status} );
109 my $html = CGI::start_html( $e->{status} . ' Bad Request' );
110 $html .= CGI::h1( {}, 'Bad Request' );
111 $html .= CGI::p( {}, $e->{reason} );
112 $html .= CGI::end_html();
113 $res->print($html);
114 }
115 $this->finalizeError( $res, $req );
116 return $e->{status};
117 }
118 otherwise {
119 my $e = shift;
120 my $res = Foswiki::Response->new();
121 $res->header( -type => 'text/plain' );
122 if (DEBUG) {
123
124 # output the full message and stacktrace to the browser
125 $res->print( $e->stringify() );
126 }
127 else {
128 my $mess = $e->stringify();
129 print STDERR $mess;
130
131 # tell the browser where to look for more help
132 my $text =
133'Foswiki detected an internal error - please check your Foswiki logs and webserver logs for more information.'
134 . "\n\n";
135 $mess =~ s/ at .*$//s;
136
137 # cut out pathnames from public announcement
138 $mess =~ s#/[\w./]+#path#g;
139 $text .= $mess;
140 $res->print($text);
141 }
142 $this->finalizeError( $res, $req );
143 return 500; # Internal server error
14446.19ms };
# spent 6.15ms making 1 call to Error::subs::try # spent 14µs making 1 call to Error::catch # spent 14µs making 1 call to Error::subs::otherwise # spent 5µs making 1 call to Error::subs::with
145 return $req;
146}
147
148=begin TML
149
150---++ ObjectMethod prepareConnection( $req )
151
152Abstract method, must be defined by inherited classes.
153 * =$req= - Foswiki::Request object to populate
154
155Should fill remoteAddr, method and secure fields of =$req= object.
156
157=cut
158
159sub prepareConnection { }
160
161=begin TML
162
163---++ ObjectMethod prepareQueryParameters( $req, $queryString )
164
165Should fill $req's query parameters field.
166
167This method populates $req as it should if given $queryString parameter.
168Subclasses may redefine this method and call SUPER with query string obtained.
169
170=cut
171
172sub prepareQueryParameters {
173 my ( $this, $req, $queryString ) = @_;
174 my @pairs = split /[&;]/, $queryString;
175 my ( $param, $value, %params, @plist );
176 foreach my $pair (@pairs) {
177 ( $param, $value ) = split( '=', $pair, 2 );
178
179 # url decode
180 if ( defined $value ) {
181 $value =~ tr/+/ /;
182 $value =~ s/%([0-9A-F]{2})/chr(hex($1))/gei;
183 }
184 if ( defined $param ) {
185 $param =~ tr/+/ /;
186 $param =~ s/%([0-9A-F]{2})/chr(hex($1))/gei;
187 push @{ $params{$param} }, $value;
188 push @plist, $param;
189 }
190 }
191 foreach my $param (@plist) {
192 $req->queryParam( $param, $params{$param} );
193 }
194}
195
196=begin TML
197
198---++ ObjectMethod prepareHeaders( $req )
199
200Abstract method, must be defined by inherited classes.
201 * =$req= - Foswiki::Request object to populate
202
203Should fill $req's headers and remoteUser fields.
204
205=cut
206
207sub prepareHeaders { }
208
209=begin TML
210
211---++ ObjectMethod preparePath( $req )
212
213Abstract method, must be defined by inherited classes.
214 * =$req= - Foswiki::Request object to populate
215
216Should fill $req's uri and pathInfo fields.
217
218=cut
219
220sub preparePath { }
221
222=begin TML
223
224---++ ObjectMethod prepareCookies( $req )
225
226 * =$req= - Foswiki::Request object to populate
227
228Should fill $req's cookie field. This method take cookie data from
229previously populated headers field and initializes from it. Maybe
230doesn't need to overload in children classes.
231
232=cut
233
234
# spent 4.70ms (2.70+2.00) within Foswiki::Engine::prepareCookies which was called: # once (2.70ms+2.00ms) by Foswiki::Engine::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine.pm:102] at line 97
sub prepareCookies {
235437µs my ( $this, $req ) = @_;
2361152µs eval { require CGI::Cookie };
237 throw Error::Simple($@) if $@;
23841.61ms $req->cookies( scalar CGI::Cookie->parse( $req->header('Cookie') ) )
# spent 1.49ms making 1 call to CGI::Cookie::parse # spent 116µs making 2 calls to Foswiki::Request::header, avg 58µs/call # spent 7µs making 1 call to Foswiki::Request::cookies
239 if $req->header('Cookie');
240}
241
242=begin TML
243
244---++ ObjectMethod prepareBody( $req )
245
246Abstract method, must be defined by inherited classes.
247 * =$req= - Foswiki::Request object to populate
248
249Should perform any initialization tasks related to body processing.
250
251=cut
252
253sub prepareBody { }
254
255=begin TML
256
257---++ ObjectMethod prepareBodyParameters( $req )
258
259Abstract method, must be defined by inherited classes.
260 * =$req= - Foswiki::Request object to populate
261
262Should fill $req's body parameters.
263
264=cut
265
266sub prepareBodyParameters { }
267
268=begin TML
269
270---++ ObjectMethod prepareUploads( $req )
271
272Abstract method, must be defined by inherited classes.
273 * =$req= - Foswiki::Request object to populate
274
275Should fill $req's uploads field. Its a hashref whose keys are
276parameter names and values Foswiki::Request::Upload objects.
277
278=cut
279
280sub prepareUploads { }
281
282=begin TML
283
284---++ ObjectMethod finalize($res, $req)
285
286Finalizes the request by calling many methods to send response to client and
287take any appropriate finalize actions, such as delete temporary files.
288 * =$res= is the Foswiki::Response object
289 * =$req= it the Foswiki::Request object.
290
291=cut
292
293
# spent 2.00ms (73µs+1.93) within Foswiki::Engine::finalize which was called: # once (73µs+1.93ms) by Foswiki::Engine::CGI::run at line 42 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine/CGI.pm
sub finalize {
294223µs my ( $this, $res, $req ) = @_;
295332µs110µs if ( $res->outputHasStarted() ) {
# spent 10µs making 1 call to Foswiki::Response::outputHasStarted
296 $this->flush( $res, $req );
297 }
298 else {
299142µs $this->finalizeUploads( $res, $req );
# spent 42µs making 1 call to Foswiki::Engine::CGI::finalizeUploads
30011.70ms $this->finalizeHeaders( $res, $req );
# spent 1.70ms making 1 call to Foswiki::Engine::CGI::finalizeHeaders
3011180µs $this->finalizeBody($res);
# spent 180µs making 1 call to Foswiki::Engine::finalizeBody
302 }
303}
304
305=begin TML
306
307---++ ObjectMethod finalizeUploads( $res, $req )
308
309Abstract method, must be defined by inherited classes.
310 * =$res= - Foswiki::Response object to get data from
311 * =$req= - Foswiki::Request object to get data from
312
313Should delete any temp files created in preparation phase.
314
315=cut
316
317sub finalizeUploads { }
318
319=begin TML
320
321---++ ObjectMethod finalizeError( $res, $req )
322
323Called if some engine especific error happens.
324
325 * =$res= - Foswiki::Response object to get data from
326 * =$req= - Foswiki::Request object to get data from
327
328=cut
329
330sub finalizeError {
331 my ( $this, $res, $req ) = @_;
332 $this->finalizeHeaders( $res, $req );
333 $this->finalizeBody( $res, $req );
334}
335
336=begin TML
337
338---++ ObjectMethod finalizeHeaders( $res, $req )
339
340Base method, must be redefined by inherited classes. For convenience
341this method deals with HEAD requests related stuff. Children classes
342should call SUPER.
343 * =$res= - Foswiki::Response object to get data from
344 * =$req= - Foswiki::Request object to get data from
345
346Should call finalizeCookies and then send $res' headers to client.
347
348=cut
349
350
# spent 820µs (51+769) within Foswiki::Engine::finalizeHeaders which was called: # once (51µs+769µs) by Foswiki::Engine::CGI::finalizeHeaders at line 193 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine/CGI.pm
sub finalizeHeaders {
351340µs my ( $this, $res, $req ) = @_;
3521755µs $this->finalizeCookies($res);
# spent 755µs making 1 call to Foswiki::Engine::finalizeCookies
353214µs if ( $req && $req->method() && uc( $req->method() ) eq 'HEAD' ) {
# spent 14µs making 2 calls to Foswiki::Request::method, avg 7µs/call
354 $res->body('');
355 $res->deleteHeader('Content-Length');
356 }
357}
358
359=begin TML
360
361---++ ObjectMethod finalizeCookies( $res )
362
363 * =$res= - Foswiki::Response object to both get data from and populate
364
365Should populate $res' headers field with cookies, if any.
366
367=cut
368
369
# spent 755µs (73+682) within Foswiki::Engine::finalizeCookies which was called: # once (73µs+682µs) by Foswiki::Engine::finalizeHeaders at line 352
sub finalizeCookies {
370285µs my ( $this, $res ) = @_;
371
372 # SMELL: Review comment below, from CGI:
373 # if the user indicates an expiration time, then we need
374 # both an Expires and a Date header (so that the browser is
375 # uses OUR clock)
376 $res->pushHeader( 'Set-Cookie',
377 Scalar::Util::blessed $_
378 && $_->isa('CGI::Cookie') ? $_->as_string : $_ )
3799682µs foreach $res->cookies;
# spent 525µs making 2 calls to CGI::Cookie::as_string, avg 262µs/call # spent 135µs making 2 calls to Foswiki::Response::pushHeader, avg 68µs/call # spent 9µs making 1 call to Foswiki::Response::cookies # spent 7µs making 2 calls to Scalar::Util::blessed, avg 4µs/call # spent 6µs making 2 calls to UNIVERSAL::isa, avg 3µs/call
380}
381
382=begin TML
383
384---++ ObjectMethod finalizeBody( $res, $req )
385
386 * =$res= - Foswiki::Response object to get data from
387 * =$req= - Foswiki::Request object to get data from
388
389Should send $res' body to client. This method calls =write()=
390as needed, sou engines should redefine that method insted of this one.
391
392=cut
393
394
# spent 180µs (60+120) within Foswiki::Engine::finalizeBody which was called: # once (60µs+120µs) by Foswiki::Engine::finalize at line 301
sub finalizeBody {
395557µs my ( $this, $res, $req ) = @_;
396135µs my $body = $res->body;
# spent 35µs making 1 call to Foswiki::Response::body
397 return unless defined $body;
39814µs $this->prepareWrite($res);
# spent 4µs making 1 call to Foswiki::Engine::prepareWrite
39917µs110µs if ( Scalar::Util::blessed($body) && $body->can('read')
# spent 10µs making 1 call to Scalar::Util::blessed
400 or ref $body eq 'GLOB' )
401 {
402 while ( !eof $body ) {
403 read $body, my $buffer, 4096;
404 last unless $this->write($buffer);
405 }
406 close $body;
407 }
408 else {
409172µs $this->write($body);
# spent 72µs making 1 call to Foswiki::Engine::CGI::write
410 }
411}
412
413=begin TML
414
415---++ flush($res, $req)
416
417Forces the response headers to be emitted if they haven't already been sent
418(note that this may in some circumstances result in cookies being missed)
419before flushing what is in the body so far.
420
421Before headers are sent, any Content-length is removed, as a call to
422flush is a statement that there's more to follow, but we don't know
423how much at this point.
424
425This function should be used with great care! It requires that the output
426headers are fully complete before it is first called. Once it *has* been
427called, the response object will refuse any modifications that would alter
428the header.
429
430=cut
431
432sub flush {
433 my ( $this, $res, $req ) = @_;
434
435 unless ( $res->outputHasStarted() ) {
436 $res->deleteHeader('Content-Length');
437 $this->finalizeUploads( $res, $req );
438 $this->finalizeHeaders( $res, $req );
439 $this->prepareWrite($res);
440 $res->outputHasStarted(1);
441 }
442
443 my $body = $res->body();
444
445 if ( Scalar::Util::blessed($body) || ref($body) eq 'GLOB' ) {
446 throw Foswiki::EngineException('Cannot flush non-text response body');
447 }
448
449 $this->write($body);
450 $res->body('');
451}
452
453=begin TML
454
455---++ ObjectMethod prepareWrite( $res )
456
457Abstract method, may be defined by inherited classes.
458 * =$res= - Foswiki::Response object to get data from
459
460Should perform any task needed before writing.
461That's ok if none needed ;-)
462
463=cut
464
46519µs
# spent 4µs within Foswiki::Engine::prepareWrite which was called: # once (4µs+0s) by Foswiki::Engine::finalizeBody at line 398
sub prepareWrite { }
466
467=begin TML
468
469---++ ObjectMethod write( $buffer )
470
471Abstract method, must be defined by inherited classes.
472 * =$buffer= - chunk of data to be sent
473
474Should send $buffer to client.
475
476=cut
477
478sub write {
479 ASSERT('Pure virtual method - should never be called');
480}
481
48214µs1;
483__END__