← 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:43 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Store.pm
StatementsExecuted 755 statements in 5.31ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
122541.82ms2.46msFoswiki::Store::::cleanUpRevIDFoswiki::Store::cleanUpRevID
70111.18ms1.18msFoswiki::Store::::askListenersFoswiki::Store::askListeners
12111640µs640µsFoswiki::Store::::CORE:matchFoswiki::Store::CORE:match (opcode)
21134µs34µsFoswiki::Store::::askListenersRevisionHistoryFoswiki::Store::askListenersRevisionHistory
11133µs73µsFoswiki::Store::::newFoswiki::Store::new
11130µs40µsFoswiki::Store::::_LoadAndRegisterListenersFoswiki::Store::_LoadAndRegisterListeners
11125µs45µsFoswiki::Store::::BEGIN@53Foswiki::Store::BEGIN@53
11124µs31µsFoswiki::Store::::BEGIN@52Foswiki::Store::BEGIN@52
11118µs56µsFoswiki::Store::::BEGIN@56Foswiki::Store::BEGIN@56
11116µs382µsFoswiki::Store::::BEGIN@55Foswiki::Store::BEGIN@55
11110µs10µsFoswiki::Store::::CORE:sortFoswiki::Store::CORE:sort (opcode)
1119µs9µsFoswiki::Store::::BEGIN@60Foswiki::Store::BEGIN@60
1119µs9µsFoswiki::Store::::BEGIN@58Foswiki::Store::BEGIN@58
1118µs8µsFoswiki::Store::::BEGIN@59Foswiki::Store::BEGIN@59
1118µs8µsFoswiki::Store::::BEGIN@61Foswiki::Store::BEGIN@61
1117µs7µsFoswiki::Store::::finishFoswiki::Store::finish
0000s0sFoswiki::Store::::askListenersVersionInfoFoswiki::Store::askListenersVersionInfo
0000s0sFoswiki::Store::::getWorkAreaFoswiki::Store::getWorkArea
0000s0sFoswiki::Store::::setListenerPriorityFoswiki::Store::setListenerPriority
0000s0sFoswiki::Store::::tellListenersFoswiki::Store::tellListeners
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::Store
6
7This class is a pure virtual base class that specifies the interface
8between the actual store implementation and the rest of the Foswiki
9system.
10
11Subclasses of this class (known as "store implementations") are
12responsible for checking for topic existance, access permissions, and
13all the other general admin tasks required of a store.
14
15This class knows *nothing* about how the data is actually _stored_ -
16that knowledge is entirely encapsulated in the implementation.
17
18The general contract for methods in the class requires that errors
19are signalled using exceptions. Foswiki::AccessControlException is
20used for access control exceptions, and Error::Simple for all other
21types of error.
22
23Reference implementations of this base class are =Foswiki::Store::RcsWrap=
24and =Foswiki::Store::RcsLite= (these are both implemented in terms of
25VC::Store, which is an abstract implementation of a store based on a
26version control system).
27
28Methods of this class and all subclasses should *only* be called from
29=Foswiki= and =Foswiki::Meta=. All other system components must delegate
30store interactions via =Foswiki::Meta=.
31
32For readers who are familiar with Foswiki version 1.0.0, this class
33_describes_ the interface to the old =Foswiki::Store= without actually
34_implementing_ it.
35
36Note that most methods are passed a Foswiki::Meta object. This pattern is
37employed to reinforce the encapsulation of a "path" in a meta object, and
38also to allow the store to modify META fields in the object, something it
39would be unable to do if passed $web, $topic.
40
41Version numbers are required to be positive, non-zero integers. When
42passing in version numbers to the methods of a store implementation, 0,
43undef and '' are treated as referring to the *latest* (most recent)
44revision of the object. Version numbers are required to increase (later
45version numbers are greater than earlier) but are *not* required to be
46sequential.
47
48=cut
49
50package Foswiki::Store;
51
52245µs238µs
# spent 31µs (24+7) within Foswiki::Store::BEGIN@52 which was called: # once (24µs+7µs) by Foswiki::BEGIN@612 at line 52
use strict;
# spent 31µs making 1 call to Foswiki::Store::BEGIN@52 # spent 7µs making 1 call to strict::import
53249µs264µs
# spent 45µs (25+20) within Foswiki::Store::BEGIN@53 which was called: # once (25µs+20µs) by Foswiki::BEGIN@612 at line 53
use warnings;
# spent 45µs making 1 call to Foswiki::Store::BEGIN@53 # spent 20µs making 1 call to warnings::import
54
55247µs2749µs
# spent 382µs (16+367) within Foswiki::Store::BEGIN@55 which was called: # once (16µs+367µs) by Foswiki::BEGIN@612 at line 55
use Error qw( :try );
# spent 382µs making 1 call to Foswiki::Store::BEGIN@55 # spent 367µs making 1 call to Error::import
56244µs294µs
# spent 56µs (18+38) within Foswiki::Store::BEGIN@56 which was called: # once (18µs+38µs) by Foswiki::BEGIN@612 at line 56
use Assert;
# spent 56µs making 1 call to Foswiki::Store::BEGIN@56 # spent 38µs making 1 call to Assert::import
57
58236µs19µs
# spent 9µs within Foswiki::Store::BEGIN@58 which was called: # once (9µs+0s) by Foswiki::BEGIN@612 at line 58
use Foswiki ();
# spent 9µs making 1 call to Foswiki::Store::BEGIN@58
59236µs18µs
# spent 8µs within Foswiki::Store::BEGIN@59 which was called: # once (8µs+0s) by Foswiki::BEGIN@612 at line 59
use Foswiki::Meta ();
# spent 8µs making 1 call to Foswiki::Store::BEGIN@59
60236µs19µs
# spent 9µs within Foswiki::Store::BEGIN@60 which was called: # once (9µs+0s) by Foswiki::BEGIN@612 at line 60
use Foswiki::Sandbox ();
# spent 9µs making 1 call to Foswiki::Store::BEGIN@60
6121.17ms18µs
# spent 8µs within Foswiki::Store::BEGIN@61 which was called: # once (8µs+0s) by Foswiki::BEGIN@612 at line 61
use Foswiki::AccessControlException ();
# spent 8µs making 1 call to Foswiki::Store::BEGIN@61
62
6312µsour $STORE_FORMAT_VERSION = '1.1';
64
65=begin TML
66
67---++ ClassMethod new()
68
69Construct a Store module.
70
71=cut
72
73
# spent 73µs (33+40) within Foswiki::Store::new which was called: # once (33µs+40µs) by Foswiki::new at line 1697 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub new {
74435µs my $class = shift;
75
76 my $this = bless( {}, $class );
77140µs $this->_LoadAndRegisterListeners();
# spent 40µs making 1 call to Foswiki::Store::_LoadAndRegisterListeners
78
79 return $this;
80}
81
82#extracted so we can re-jig the list while running (for eg, non-optionally load a listener from code.
83
# spent 40µs (30+10) within Foswiki::Store::_LoadAndRegisterListeners which was called: # once (30µs+10µs) by Foswiki::Store::new at line 77
sub _LoadAndRegisterListeners {
84439µs my $this = shift;
85
86 # Create and register store listeners. Store listeners are subclasses
87 # of Foswiki::Store::Interfaces::Listener
88
89 my @evl;
9013µs110µs foreach my $key (
# spent 10µs making 1 call to Foswiki::Store::CORE:sort
91 sort {
92 $Foswiki::cfg{Store}{Listeners}{$a} <=> $Foswiki::cfg{Store}
93 {Listeners}{$b}
94 } keys( %{ $Foswiki::cfg{Store}{Listeners} } )
95 )
96 {
97 if ( $Foswiki::cfg{Store}{Listeners}{$key} ) {
98
99 #print STDERR "loading $key\n";
100 eval "require $key";
101 die "Failed to load $key: $@" if $@;
102 push( @evl, $key->new() );
103 }
104 else {
105
106 #don't try (and thus potentially crash on disabled listener
107 delete $Foswiki::cfg{Store}{Listeners}{$key};
108 }
109 }
110
111 $this->{event_listeners} = \@evl;
112}
113
114=begin TML
115
116---++ ObjectMethod setListenerPriority()
117allows you to enable/disable (set priority to 0) a new Listener, or to change its priority
118
119=cut
120
121sub setListenerPriority {
122 my $this = shift;
123 my $classname = shift;
124 my $priority = shift;
125
126 $Foswiki::cfg{Store}{Listeners}{$classname} = $priority;
127 $this->_LoadAndRegisterListeners();
128}
129
130=begin TML
131
132---++ ObjectMethod finish()
133Break circular references.
134
135=cut
136
137# Note to developers; please undef *all* fields in the object explicitly,
138# whether they are references or not. That way this method is "golden
139# documentation" of the live fields in the object.
140
# spent 7µs within Foswiki::Store::finish which was called: # once (7µs+0s) by Foswiki::Store::VC::Store::finish at line 60 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/VC/Store.pm
sub finish {
141213µs my $this = shift;
142 undef $this->{event_listeners};
143}
144
145=begin TML
146
147---++ ObjectMethod tellListeners( $event, ... )
148Invoke listeners that have registered an interest in events on this store.
149The $event method on the listener is invoked, passing the ... parameters
150to the listener.
151
152=cut
153
154sub tellListeners {
155 my $this = shift;
156 my %arg = @_;
157 my $event = $arg{verb};
158
159 foreach my $el ( @{ $this->{event_listeners} } ) {
160 next unless $el->can($event);
161 $el->$event(%arg);
162 }
163}
164
165=begin TML
166
167---++ ObjectMethod askListeners( $topicObject, $version )
168Ask listeners if they would like to provide the object specified in the
169$topicObject, at the given version. The first listener to respond with a
170non-zero revision will be assumed to have loaded the topic object.
171
172Listeners are expected to implement =loadTopic=. If they do not, they
173will not be asked.
174
175=cut
176
177
# spent 1.18ms within Foswiki::Store::askListeners which was called 70 times, avg 17µs/call: # 70 times (1.18ms+0s) by Foswiki::Store::VC::Store::readTopic at line 82 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/VC/Store.pm, avg 17µs/call
sub askListeners {
1782801.05ms my ( $this, $meta, $version ) = @_;
179 my ( $gotRev, $isLatest );
180
18170182µs foreach my $el ( @{ $this->{event_listeners} } ) {
182 next unless $el->can('loadTopic');
183 ( $gotRev, $isLatest ) = $el->loadTopic( $meta, $version );
184 return ( $gotRev, $isLatest ) if $gotRev;
185 }
186 return ( undef, undef );
187}
188
189=begin TML
190
191---++ ObjectMethod askListenersRevisionHistory( $topicObject, $attachment )
192Ask listeners if they would like to provide the object specified in the
193$topicObject, at the given version. The first listener to respond with a
194non-zero revision will be assumed to have loaded the topic object.
195
196Listeners are expected to implement =loadTopic=. If they do not, they
197will not be asked.
198
199=cut
200
201
# spent 34µs within Foswiki::Store::askListenersRevisionHistory which was called 2 times, avg 17µs/call: # 2 times (34µs+0s) by Foswiki::Store::VC::Store::getRevisionHistory at line 282 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/VC/Store.pm, avg 17µs/call
sub askListenersRevisionHistory {
202840µs my ( $this, $meta, $attachment ) = @_;
203 my ($itr);
204
20524µs foreach my $el ( @{ $this->{event_listeners} } ) {
206 next unless $el->can('getRevisionHistory');
207 return $itr = $el->getRevisionHistory( $meta, $attachment );
208 }
209 return undef;
210}
211
212# my $itr = $this->askListenersRevisionHistory($topicObject, $attachment);
213
214=begin TML
215
216---++ ObjectMethod askListenersVersionInfo( $topicObject, $version )
217Ask listeners if they would like to answer Foswiki::Store->getVersionInfo()
218- a hashref containing date, user, version, comment keys
219
220=cut
221
222sub askListenersVersionInfo {
223 my ( $this, $meta, $version, $attachment ) = @_;
224
225 foreach my $el ( @{ $this->{event_listeners} } ) {
226 next unless $el->can('getVersionInfo');
227 return $el->getVersionInfo( $meta, $version, $attachment );
228 }
229 return undef;
230}
231
232=begin TML
233
234---++ StaticMethod cleanUpRevID( $rev ) -> $integer
235
236Cleans up (maps) a user-supplied revision ID and converts it to an integer
237number that can be incremented to create a new revision number.
238
239This method should be used to sanitise user-provided revision IDs.
240
241Returns 0 if it was unable to determine a valid rev number from the
242string passed.
243
244=cut
245
246
# spent 2.46ms (1.82+640µs) within Foswiki::Store::cleanUpRevID which was called 122 times, avg 20µs/call: # 67 times (956µs+385µs) by Foswiki::Meta::setEmbeddedStoreForm at line 3537 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm, avg 20µs/call # 35 times (412µs+127µs) by Foswiki::Meta::setEmbeddedStoreForm at line 3539 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm, avg 15µs/call # 13 times (352µs+116µs) by Foswiki::Store::VC::Handler::_getTOPICINFO at line 274 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/VC/Handler.pm, avg 36µs/call # 6 times (85µs+11µs) by Foswiki::REVINFO at line 18 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/REVINFO.pm, avg 16µs/call # once (13µs+0s) by Foswiki::UI::View::view at line 101 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/UI/View.pm
sub cleanUpRevID {
2472511.62ms my $rev = shift;
248
249 # RCS format: 1.2, or plain integer: 2
250115847µs121640µs if ( defined $rev && $rev =~ /^(?:\d+\.)?(\d+)$/ ) {
# spent 640µs making 121 calls to Foswiki::Store::CORE:match, avg 5µs/call
251 return $1;
252 }
253
254 return 0;
255}
256
257=begin TML
258
259---+++ ObjectMethod getWorkArea( $key ) -> $directorypath
260
261Gets a private directory uniquely identified by $key. The directory is
262intended as a work area for plugins.
263
264The standard is a directory named the same as "key" under
265$Foswiki::cfg{WorkingDir}/work_areas
266
267=cut
268
269sub getWorkArea {
270 my ( $this, $key ) = @_;
271
272 # untaint and detect nasties. The rules are the same as for
273 # attachment names.
274 $key = Foswiki::Sandbox::untaint( $key,
275 \&Foswiki::Sandbox::validateAttachmentName );
276 throw Error::Simple("Bad work area name $key") unless ($key);
277
278 my $dir = "$Foswiki::cfg{WorkingDir}/work_areas/$key";
279
280 unless ( -d $dir ) {
281 mkdir($dir) || throw Error::Simple(<<ERROR);
282Failed to create $key work area. Check your setting of {WorkingDir}
283in =configure=.
284ERROR
285 }
286 return $dir;
287}
288
28915µs1;
290__END__
 
# spent 640µs within Foswiki::Store::CORE:match which was called 121 times, avg 5µs/call: # 121 times (640µs+0s) by Foswiki::Store::cleanUpRevID at line 250, avg 5µs/call
sub Foswiki::Store::CORE:match; # opcode
# spent 10µs within Foswiki::Store::CORE:sort which was called: # once (10µs+0s) by Foswiki::Store::_LoadAndRegisterListeners at line 90
sub Foswiki::Store::CORE:sort; # opcode