← 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/Configure/Load.pm
StatementsExecuted 2349 statements in 13.7ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1118.88ms13.2msFoswiki::Configure::Load::::readConfigFoswiki::Configure::Load::readConfig
741423.72ms4.32msFoswiki::Configure::Load::::expandValueFoswiki::Configure::Load::expandValue (recurses: max depth 4, inclusive time 8.33ms)
2311606µs606µsFoswiki::Configure::Load::::_handleExpandFoswiki::Configure::Load::_handleExpand
11120µs43µsFoswiki::Configure::Load::::BEGIN@14Foswiki::Configure::Load::BEGIN@14
11114µs24µsFoswiki::Configure::Load::::BEGIN@15Foswiki::Configure::Load::BEGIN@15
0000s0sFoswiki::Configure::Load::::_loadDefaultsFromFoswiki::Configure::Load::_loadDefaultsFrom
0000s0sFoswiki::Configure::Load::::mergeHashFoswiki::Configure::Load::mergeHash
0000s0sFoswiki::Configure::Load::::readDefaultsFoswiki::Configure::Load::readDefaults
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::Configure::Load
6
7Handling for loading configuration information (Foswiki.spec, Config.spec and
8LocalSite.cfg) as efficiently and flexibly as possible.
9
10=cut
11
12package Foswiki::Configure::Load;
13
14240µs267µs
# spent 43µs (20+24) within Foswiki::Configure::Load::BEGIN@14 which was called: # once (20µs+24µs) by Foswiki::BEGIN@51 at line 14
use strict;
# spent 43µs making 1 call to Foswiki::Configure::Load::BEGIN@14 # spent 24µs making 1 call to strict::import
1521.52ms234µs
# spent 24µs (14+10) within Foswiki::Configure::Load::BEGIN@15 which was called: # once (14µs+10µs) by Foswiki::BEGIN@51 at line 15
use warnings;
# spent 24µs making 1 call to Foswiki::Configure::Load::BEGIN@15 # spent 10µs making 1 call to warnings::import
16
171500nsour $TRUE = 1;
181100nsour $FALSE = 0;
19
20# Configuration items that have been deprecated and must be mapped to
21# new configuration items. The value is mapped unchanged.
2215µsour %remap = (
23 '{StoreImpl}' => '{Store}{Implementation}',
24 '{AutoAttachPubFiles}' => '{RCS}{AutoAttachPubFiles}',
25 '{QueryAlgorithm}' => '{Store}{QueryAlgorithm}',
26 '{SearchAlgorithm}' => '{Store}{SearchAlgorithm}',
27 '{RCS}{FgrepCmd}' => '{Store}{FgrepCmd}',
28 '{RCS}{EgrepCmd}' => '{Store}{EgrepCmd}',
29);
30
31=begin TML
32
33---++ StaticMethod readConfig([$noexpand])
34
35In normal Foswiki operations as a web server this method is called by the
36=BEGIN= block of =Foswiki.pm=. However, when benchmarking/debugging it can be
37replaced by custom code which sets the configuration hash. To prevent us from
38overriding the custom code again, we use an "unconfigurable" key
39=$cfg{ConfigurationFinished}= as an indicator.
40
41Note that this method is called by Foswiki and configure, and *only* reads
42Foswiki.spec= to get defaults. Other spec files (those for extensions) are
43*not* read.
44
45The assumption is that =configure= will be run when an extension is installed,
46and that will add the config values to LocalSite.cfg, so no defaults are
47needed. Foswiki.spec is still read because so much of the core code doesn't
48provide defaults, and it would be silly to have them in two places anyway.
49
50$noexpand can be set to suppress expansion of $Foswiki vars embedded in
51values.
52
53=cut
54
55
# spent 13.2ms (8.88+4.29) within Foswiki::Configure::Load::readConfig which was called: # once (8.88ms+4.29ms) by Foswiki::BEGIN@137 at line 334 of /var/www/foswiki11/lib/Foswiki.pm
sub readConfig {
561800ns my $noexpand = shift;
57
581500ns return if $Foswiki::cfg{ConfigurationFinished};
591300ns my $validLSC =
60 1; # Assume it's valid - will be set false if errors detected.
61
62 # Read Foswiki.spec and LocalSite.cfg
6311µs for my $file (qw( Foswiki.spec LocalSite.cfg)) {
6427.54ms unless ( my $return = do $file ) {
65 my $errorMessage;
66 if ($@) {
67 $errorMessage = "Could not parse $file: $@";
68 print STDERR "$errorMessage \n";
69 }
70 elsif ( not defined $return ) {
71 print STDERR
72"Could not 'do' $file: $! \n - This might be okay if file LocalSite.cfg does not exist in a new installation.\n";
73 unless ( $! == 2 && $file eq 'LocalSite.cfg' ) {
74
75 # LocalSite.cfg doesn't exist, which is OK
76 $errorMessage = "Could not do $file: $!";
77 }
78 $validLSC = 0;
79 }
80 elsif ( not $return eq '1' ) {
81 print STDERR
82 "Running file $file returned unexpected results: $return \n";
83 $errorMessage = "Could not run $file" unless $return;
84 }
85 if ($errorMessage) {
86 die <<GOLLYGOSH;
87Content-type: text/plain
88
89$errorMessage
90Please inform the site admin.
91GOLLYGOSH
92 exit 1;
93 }
94 }
95 }
96
97 # If we got this far without definitions for key variables, then
98 # we need to default them. otherwise we get peppered with
99 # 'uninitialised variable' alerts later.
100
10111µs foreach my $var (
102 qw( DataDir DefaultUrlHost PubUrlPath ToolsDir WorkingDir
103 PubDir TemplateDir ScriptDir ScriptUrlPath LocalesDir )
104 )
105 {
106
107 # We can't do this, because it prevents Foswiki being run without
108 # a LocalSite.cfg, which we don't want
109 # die "$var must be defined in LocalSite.cfg"
110 # unless( defined $Foswiki::cfg{$var} );
111105µs unless ( defined $Foswiki::cfg{$var} ) {
112 $Foswiki::cfg{$var} = 'NOT SET';
113 $validLSC = 0;
114 }
115 }
116
117 # Patch deprecated config settings
1181500ns if ( exists $Foswiki::cfg{StoreImpl} ) {
119 $Foswiki::cfg{Store}{Implementation} =
120 'Foswiki::Store::' . $Foswiki::cfg{StoreImpl};
121 delete $Foswiki::cfg{StoreImpl};
122 }
12313µs foreach my $el ( keys %remap ) {
1246278µs if ( eval 'exists $Foswiki::cfg' . $el ) {
# spent 9µs executing statements in string eval # spent 4µs executing statements in string eval # spent 3µs executing statements in string eval # spent 2µs executing statements in string eval # spent 2µs executing statements in string eval # spent 2µs executing statements in string eval
125 eval <<CODE;
126\$Foswiki::cfg$remap{$el}=\$Foswiki::cfg$el;
127delete \$Foswiki::cfg$el;
128CODE
129 }
130 }
131
132 # Expand references to $Foswiki::cfg vars embedded in the values of
133 # other $Foswiki::cfg vars.
13413µs14.29ms expandValue( \%Foswiki::cfg ) unless $noexpand;
# spent 4.29ms making 1 call to Foswiki::Configure::Load::expandValue
135
13611µs $Foswiki::cfg{ConfigurationFinished} = 1;
137
138#on Windows, File::Spec returns a really useless empty string for tempdir under apache
139#(in its unix code, it assumes /tmp - but at least thats standard..)
140#so defaulting $ENV{TMP} can get us limping along (and can over-ride using TMPDIR or TEMP env
14111µs if ( $^O eq 'MSWin32' ) {
142
143 #force paths to use '/'
144 $Foswiki::cfg{PubDir} =~ s|\\|/|g;
145 $Foswiki::cfg{DataDir} =~ s|\\|/|g;
146 $Foswiki::cfg{ToolsDir} =~ s|\\|/|g;
147 $Foswiki::cfg{ScriptDir} =~ s|\\|/|g;
148 $Foswiki::cfg{TemplateDir} =~ s|\\|/|g;
149 $Foswiki::cfg{LocalesDir} =~ s|\\|/|g;
150 $Foswiki::cfg{WorkingDir} =~ s|\\|/|g;
151
152 #$ENV{TMPDIR}
153 #$ENV{TEMP}
154 #$ENV{TMP}
155 $ENV{TMP} = $Foswiki::cfg{WorkingDir};
156 }
157
158 # Alias TWiki cfg to Foswiki cfg for plugins and contribs
15912µs *TWiki::cfg = \%Foswiki::cfg;
160
161 # Explicit return true if we've completed the load
16215µs return $validLSC;
163}
164
165=begin TML
166
167---++ StaticMethod expandValue($datum)
168
169Expands references to Foswiki configuration items which occur in the
170values configuration items contained within the datum, which may be a
171hash reference or a scalar value. The replacement is done in-place.
172
173=cut
174
175
# spent 4.32ms (3.72+606µs) within Foswiki::Configure::Load::expandValue which was called 741 times, avg 6µs/call: # 652 times (3.18ms+-3.18ms) by Foswiki::Configure::Load::expandValue at line 177, avg 0s/call # 85 times (155µs+-155µs) by Foswiki::Configure::Load::expandValue at line 180, avg 0s/call # 3 times (32µs+0s) by Foswiki::Logger::PlainFile::_getLogForLevel at line 249 of /var/www/foswiki11/lib/Foswiki/Logger/PlainFile.pm, avg 11µs/call # once (348µs+3.94ms) by Foswiki::Configure::Load::readConfig at line 134
sub expandValue {
1767411.78ms if ( ref( $_[0] ) eq 'HASH' ) {
1778201.11ms6520s map { expandValue($_) } values %{ $_[0] };
# spent 8.18ms making 652 calls to Foswiki::Configure::Load::expandValue, avg 13µs/call, recursion: max depth 4, sum of overlapping time 8.18ms
178 }
179 elsif ( ref( $_[0] ) eq 'ARRAY' ) {
18088113µs850s map { expandValue($_) } @{ $_[0] };
# spent 155µs making 85 calls to Foswiki::Configure::Load::expandValue, avg 2µs/call, recursion: max depth 3, sum of overlapping time 155µs
181
182 # Can't do this, because Windows uses an object (Regexp) for regular
183 # expressions.
184 # } elsif (ref($_[0])) {
185 # Carp::confess("Can't handle a ".ref($_[0]));
186 }
187 elsif ( defined( $_[0] ) ) {
188570621µs while (
1892334µs23606µs $_[0] =~ s/(\$Foswiki::cfg{[[A-Za-z0-9{}]+})/_handleExpand($1)/ge )
# spent 606µs making 23 calls to Foswiki::Configure::Load::_handleExpand, avg 26µs/call
190 {
191 }
192 }
193}
194
195# Used to expand the $Foswiki::cfg variable in the expand* routines.
196# Resolves issue with defined but null variables expanding as "undef"
197# Tasks:Item5608
198
# spent 606µs within Foswiki::Configure::Load::_handleExpand which was called 23 times, avg 26µs/call: # 23 times (606µs+0s) by Foswiki::Configure::Load::expandValue at line 189, avg 26µs/call
sub _handleExpand {
19923504µs my $val = eval $_[0];
# spent 14µs executing statements in 5 string evals (merged) # spent 12µs executing statements in 4 string evals (merged) # spent 11µs executing statements in 4 string evals (merged) # spent 10µs executing statements in 4 string evals (merged) # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval
200236µs $val = ( defined $val ) ? $val : 'undef';
2012386µs return $val;
202}
203
204=begin TML
205
206---++ StaticMethod readDefaults() -> \@errors
207
208This is only called by =configure= to initialise the Foswiki config hash with
209default values from the .spec files.
210
211Normally all configuration values come from LocalSite.cfg. However when
212=configure= runs it has to get default values for config vars that have not
213yet been saved to =LocalSite.cfg=.
214
215Returns a reference to a list of the errors it saw.
216
217SEE ALSO: Foswiki::Configure::FoswikiCfg::load
218
219=cut
220
221sub readDefaults {
222 my %read = ();
223 my @errors;
224
225 eval {
226 do 'Foswiki.spec';
227 $read{'Foswiki.spec'} = $INC{'Foswiki.spec'};
228 };
229 push( @errors, $@ ) if ($@);
230 foreach my $dir (@INC) {
231 my $root; # SMELL: Not used
232 _loadDefaultsFrom( "$dir/Foswiki/Plugins", $root, \%read, \@errors );
233 _loadDefaultsFrom( "$dir/Foswiki/Contrib", $root, \%read, \@errors );
234 _loadDefaultsFrom( "$dir/TWiki/Plugins", $root, \%read, \@errors );
235 _loadDefaultsFrom( "$dir/TWiki/Contrib", $root, \%read, \@errors );
236 }
237
238 # SMELL: This will create the %TWiki::cfg
239 # But as it ought to be aliased to %Foswiki::cfg, it's not a big deal
240 # XXX: Do we still need this code?
241 if ( %TWiki::cfg && \%TWiki::cfg != \%Foswiki::cfg ) {
242
243 # We had some TWiki plugins, need to map their config to Foswiki
244 sub mergeHash {
245
246 # Merges the keys in the right hashref to the ones in the
247 # left hashref
248 my ( $left, $right, $errors ) = @_;
249 while ( my ( $key, $value ) = each %$right ) {
250 if ( exists $left->{$key} ) {
251 if ( ref($value) ne ref( $left->{$key} ) ) {
252 push @$errors,
253 'Trying to overwrite $Foswiki::cfg{'
254 . $key
255 . '} with its $TWiki::cfg version ('
256 . $value . ')';
257 }
258 elsif ( ref($value) eq 'SCALAR' ) {
259 $left->{$key} = $value;
260 }
261 elsif ( ref($value) eq 'HASH' ) {
262 $left->{$key} =
263 mergeHash( $left->{$key}, $value, $errors );
264 }
265 elsif ( ref($value) eq 'ARRAY' ) {
266
267 # It's an array. try to be smart
268 # SMELL: Ideally, it should keep order too
269 foreach my $item (@$value) {
270 unless ( grep /^$item$/, @{ $left->{$key} } ) {
271
272 # The item isn't in the current list,
273 # add it at the end
274 unshift @{ $left->{$key} }, $item;
275 }
276 }
277 }
278 else {
279
280 # It's something else (GLOB, coderef, ...)
281 push @$errors,
282 '$TWiki::cfg{'
283 . $key
284 . '} is a reference to a'
285 . ref($value)
286 . '. No idea how to merge that, sorry.';
287 }
288 }
289 else {
290
291 # We don't already have such a key in the Foswiki scope
292 $left->{$key} = $value;
293 }
294 }
295 return $left;
296 }
297 mergeHash \%Foswiki::cfg, \%TWiki::cfg, \@errors;
298 }
299
300 return \@errors;
301}
302
303sub _loadDefaultsFrom {
304 my ( $dir, $root, $read, $errors ) = @_;
305
306 return unless opendir( D, $dir );
307 foreach my $extension ( grep { !/^\./ } readdir D ) {
308 $extension =~ /(.*)/;
309 $extension = $1; # untaint
310 next if $read->{$extension};
311 my $file = "$dir/$extension/Config.spec";
312 next unless -e $file;
313 eval { do $file; };
314 push( @$errors, $@ ) if ($@);
315 $read->{$extension} = $file;
316 }
317 closedir(D);
318}
319
32016µs1;
321__END__