← 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:27:09 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/VC/Store.pm
StatementsExecuted 3297 statements in 22.1ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
70118.26ms93.8sFoswiki::Store::VC::Store::::readTopicFoswiki::Store::VC::Store::readTopic
272337.21ms35.6msFoswiki::Store::VC::Store::::topicExistsFoswiki::Store::VC::Store::topicExists
1112.20ms1.66sFoswiki::Store::VC::Store::::queryFoswiki::Store::VC::Store::query
344311.09ms1.09msFoswiki::Store::VC::Store::::CORE:substFoswiki::Store::VC::Store::CORE:subst (opcode)
111753µs170msFoswiki::Store::VC::Store::::eachTopicFoswiki::Store::VC::Store::eachTopic
211109µs621msFoswiki::Store::VC::Store::::getRevisionHistoryFoswiki::Store::VC::Store::getRevisionHistory
21180µs348µsFoswiki::Store::VC::Store::::webExistsFoswiki::Store::VC::Store::webExists
11155µs62µsFoswiki::Store::VC::Store::::finishFoswiki::Store::VC::Store::finish
11124µs31µsFoswiki::Store::VC::Store::::BEGIN@33Foswiki::Store::VC::Store::BEGIN@33
11123µs62µsFoswiki::Store::VC::Store::::BEGIN@39Foswiki::Store::VC::Store::BEGIN@39
11120µs442µsFoswiki::Store::VC::Store::::BEGIN@40Foswiki::Store::VC::Store::BEGIN@40
11118µs54µsFoswiki::Store::VC::Store::::BEGIN@574Foswiki::Store::VC::Store::BEGIN@574
11116µs34µsFoswiki::Store::VC::Store::::BEGIN@34Foswiki::Store::VC::Store::BEGIN@34
11116µs45µsFoswiki::Store::VC::Store::::BEGIN@576Foswiki::Store::VC::Store::BEGIN@576
1119µs9µsFoswiki::Store::VC::Store::::BEGIN@42Foswiki::Store::VC::Store::BEGIN@42
1119µs9µsFoswiki::Store::VC::Store::::BEGIN@43Foswiki::Store::VC::Store::BEGIN@43
1119µs9µsFoswiki::Store::VC::Store::::BEGIN@36Foswiki::Store::VC::Store::BEGIN@36
1119µs9µsFoswiki::Store::VC::Store::::BEGIN@44Foswiki::Store::VC::Store::BEGIN@44
1119µs9µsFoswiki::Store::VC::Store::::BEGIN@46Foswiki::Store::VC::Store::BEGIN@46
1112µs2µsFoswiki::Store::VC::Store::::CORE:matchFoswiki::Store::VC::Store::CORE:match (opcode)
0000s0sFoswiki::Store::VC::Store::::atomicLockFoswiki::Store::VC::Store::atomicLock
0000s0sFoswiki::Store::VC::Store::::atomicLockInfoFoswiki::Store::VC::Store::atomicLockInfo
0000s0sFoswiki::Store::VC::Store::::atomicUnlockFoswiki::Store::VC::Store::atomicUnlock
0000s0sFoswiki::Store::VC::Store::::attachmentExistsFoswiki::Store::VC::Store::attachmentExists
0000s0sFoswiki::Store::VC::Store::::copyAttachmentFoswiki::Store::VC::Store::copyAttachment
0000s0sFoswiki::Store::VC::Store::::delRevFoswiki::Store::VC::Store::delRev
0000s0sFoswiki::Store::VC::Store::::eachAttachmentFoswiki::Store::VC::Store::eachAttachment
0000s0sFoswiki::Store::VC::Store::::eachChangeFoswiki::Store::VC::Store::eachChange
0000s0sFoswiki::Store::VC::Store::::eachWebFoswiki::Store::VC::Store::eachWeb
0000s0sFoswiki::Store::VC::Store::::getApproxRevTimeFoswiki::Store::VC::Store::getApproxRevTime
0000s0sFoswiki::Store::VC::Store::::getAttachmentVersionInfoFoswiki::Store::VC::Store::getAttachmentVersionInfo
0000s0sFoswiki::Store::VC::Store::::getHandlerFoswiki::Store::VC::Store::getHandler
0000s0sFoswiki::Store::VC::Store::::getLeaseFoswiki::Store::VC::Store::getLease
0000s0sFoswiki::Store::VC::Store::::getNextRevisionFoswiki::Store::VC::Store::getNextRevision
0000s0sFoswiki::Store::VC::Store::::getRevisionAtTimeFoswiki::Store::VC::Store::getRevisionAtTime
0000s0sFoswiki::Store::VC::Store::::getRevisionDiffFoswiki::Store::VC::Store::getRevisionDiff
0000s0sFoswiki::Store::VC::Store::::getVersionInfoFoswiki::Store::VC::Store::getVersionInfo
0000s0sFoswiki::Store::VC::Store::::moveAttachmentFoswiki::Store::VC::Store::moveAttachment
0000s0sFoswiki::Store::VC::Store::::moveTopicFoswiki::Store::VC::Store::moveTopic
0000s0sFoswiki::Store::VC::Store::::moveWebFoswiki::Store::VC::Store::moveWeb
0000s0sFoswiki::Store::VC::Store::::openAttachmentFoswiki::Store::VC::Store::openAttachment
0000s0sFoswiki::Store::VC::Store::::removeFoswiki::Store::VC::Store::remove
0000s0sFoswiki::Store::VC::Store::::removeSpuriousLeasesFoswiki::Store::VC::Store::removeSpuriousLeases
0000s0sFoswiki::Store::VC::Store::::repRevFoswiki::Store::VC::Store::repRev
0000s0sFoswiki::Store::VC::Store::::saveAttachmentFoswiki::Store::VC::Store::saveAttachment
0000s0sFoswiki::Store::VC::Store::::saveTopicFoswiki::Store::VC::Store::saveTopic
0000s0sFoswiki::Store::VC::Store::::setLeaseFoswiki::Store::VC::Store::setLease
0000s0sFoswiki::Store::VC::Store::::testAttachmentFoswiki::Store::VC::Store::testAttachment
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::VC::Store
6
7Almost-complete implementation of =Foswiki::Store=. The methods
8of this class implement the =Foswiki::Store= interface.
9
10The store uses a "handler" class to handle all interactions with the
11actual version control system (and via it with the actual file system).
12A "handler" is created for each individual file in the file system, and
13this handler then brokers all requests to open, read, write etc the file.
14The handler object must implement the interface specified by
15=Foswiki::Store::VC::Handler=.
16
17The main additional responsibilities of _this_ class are to support storing
18Foswiki meta-data in plain text files, and to ensure that the =Foswiki::Meta=
19for a page is maintained in synchronisation with the files on disk.
20
21All that is required to create a working store is to subclass this class
22and override the 'new' method to specify the actual handler to use. See
23Foswiki::Store::RcsWrap for an example subclass.
24
25For readers who are familiar with Foswiki version 1.0, the functionality
26in this class _previously_ resided in =Foswiki::Store=.
27
28These methods are documented in the Foswiki:Store abstract base class
29
30=cut
31
32package Foswiki::Store::VC::Store;
33244µs238µs
# spent 31µs (24+7) within Foswiki::Store::VC::Store::BEGIN@33 which was called: # once (24µs+7µs) by Foswiki::Store::RcsWrap::BEGIN@23 at line 33
use strict;
# spent 31µs making 1 call to Foswiki::Store::VC::Store::BEGIN@33 # spent 7µs making 1 call to strict::import
34248µs251µs
# spent 34µs (16+17) within Foswiki::Store::VC::Store::BEGIN@34 which was called: # once (16µs+17µs) by Foswiki::Store::RcsWrap::BEGIN@23 at line 34
use warnings;
# spent 34µs making 1 call to Foswiki::Store::VC::Store::BEGIN@34 # spent 17µs making 1 call to warnings::import
35
36269µs19µs
# spent 9µs within Foswiki::Store::VC::Store::BEGIN@36 which was called: # once (9µs+0s) by Foswiki::Store::RcsWrap::BEGIN@23 at line 36
use Foswiki::Store ();
# spent 9µs making 1 call to Foswiki::Store::VC::Store::BEGIN@36
37111µsour @ISA = ('Foswiki::Store');
38
39247µs2100µs
# spent 62µs (23+38) within Foswiki::Store::VC::Store::BEGIN@39 which was called: # once (23µs+38µs) by Foswiki::Store::RcsWrap::BEGIN@23 at line 39
use Assert;
# spent 62µs making 1 call to Foswiki::Store::VC::Store::BEGIN@39 # spent 38µs making 1 call to Assert::import
40251µs2864µs
# spent 442µs (20+422) within Foswiki::Store::VC::Store::BEGIN@40 which was called: # once (20µs+422µs) by Foswiki::Store::RcsWrap::BEGIN@23 at line 40
use Error qw( :try );
# spent 442µs making 1 call to Foswiki::Store::VC::Store::BEGIN@40 # spent 422µs making 1 call to Error::import
41
42244µs19µs
# spent 9µs within Foswiki::Store::VC::Store::BEGIN@42 which was called: # once (9µs+0s) by Foswiki::Store::RcsWrap::BEGIN@23 at line 42
use Foswiki ();
# spent 9µs making 1 call to Foswiki::Store::VC::Store::BEGIN@42
43238µs19µs
# spent 9µs within Foswiki::Store::VC::Store::BEGIN@43 which was called: # once (9µs+0s) by Foswiki::Store::RcsWrap::BEGIN@23 at line 43
use Foswiki::Meta ();
# spent 9µs making 1 call to Foswiki::Store::VC::Store::BEGIN@43
44282µs19µs
# spent 9µs within Foswiki::Store::VC::Store::BEGIN@44 which was called: # once (9µs+0s) by Foswiki::Store::RcsWrap::BEGIN@23 at line 44
use Foswiki::Sandbox ();
# spent 9µs making 1 call to Foswiki::Store::VC::Store::BEGIN@44
45
46
# spent 9µs within Foswiki::Store::VC::Store::BEGIN@46 which was called: # once (9µs+0s) by Foswiki::Store::RcsWrap::BEGIN@23 at line 53
BEGIN {
47
48 # Do a dynamic 'use locale' for this module
4919µs if ( $Foswiki::cfg{UseLocale} ) {
50 require locale;
51 import locale();
52 }
5314.09ms19µs}
# spent 9µs making 1 call to Foswiki::Store::VC::Store::BEGIN@46
54
55# Note to developers; please undef *all* fields in the object explicitly,
56# whether they are references or not. That way this method is "golden
57# documentation" of the live fields in the object.
58
# spent 62µs (55+7) within Foswiki::Store::VC::Store::finish which was called: # once (55µs+7µs) by Foswiki::finish at line 2100 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub finish {
5912µs my $this = shift;
60140µs17µs $this->SUPER::finish();
# spent 7µs making 1 call to Foswiki::Store::finish
6119µs undef $this->{searchFn};
62}
63
64# SMELL: this module does not respect $Foswiki::inUnitTestMode; tests
65# just sit on top of the store which is configured in the current $Foswiki::cfg.
66# Most of the time this is ok, as store listeners will be told that
67# the store is in test mode, so caches should be unaffected. However
68# it's very untidy, potentially risky, and causes grief when unit tests
69# don't clean up after themselves.
70
71# PACKAGE PRIVATE
72# Get a handler for the given object in the store.
73sub getHandler {
74
75 #my ( $this, $web, $topic, $attachment ) = @_;
76 ASSERT( 0, "Must be implemented by subclasses" ) if DEBUG;
77}
78
79
# spent 93.8s (8.26ms+93.8) within Foswiki::Store::VC::Store::readTopic which was called 70 times, avg 1.34s/call: # 70 times (8.26ms+93.8s) by Foswiki::Meta::loadVersion at line 1051 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm, avg 1.34s/call
sub readTopic {
8070150µs my ( $this, $topicObject, $version ) = @_;
81
8270499µs701.18ms my ( $gotRev, $isLatest ) = $this->askListeners( $topicObject, $version );
# spent 1.18ms making 70 calls to Foswiki::Store::askListeners, avg 17µs/call
83
8470101µs if ( defined($gotRev) and ( $gotRev > 0 or ($isLatest) ) ) {
85 return ( $gotRev, $isLatest );
86 }
8770357µs70257µs ASSERT( not $isLatest ) if DEBUG;
# spent 257µs making 70 calls to Assert::ASSERTS_OFF, avg 4µs/call
88
8970389µs706.01ms my $handler = $this->getHandler($topicObject);
# spent 6.01ms making 70 calls to Foswiki::Store::RcsWrap::getHandler, avg 86µs/call
907098µs $isLatest = 0;
91
92 # check that the requested revision actually exists
9370220µs12µs if ( defined $version && $version =~ /^\d+$/ ) {
# spent 2µs making 1 call to Foswiki::Store::VC::Store::CORE:match
94 if ( $version == 0 || !$handler->revisionExists($version) ) {
95 $version = $handler->getLatestRevisionID();
96 }
97 }
98 else {
9970112µs undef $version; # if it's a non-numeric string, we need to return undef
100 # "...$version is defined but refers to a version that does not exist, then $rev is undef"
101 }
102
103701.01ms7012.1ms ( my $text, $isLatest ) = $handler->getRevision($version);
# spent 12.1ms making 70 calls to Foswiki::Store::VC::RcsWrapHandler::getRevision, avg 173µs/call
10470117µs unless ( defined $text ) {
105 ASSERT( not $isLatest ) if DEBUG;
106 return ( undef, $isLatest );
107 }
108
10970940µs70536µs $text =~ s/\r//g; # Remove carriage returns
# spent 536µs making 70 calls to Foswiki::Store::VC::Store::CORE:subst, avg 8µs/call
11070598µs70131ms $topicObject->setEmbeddedStoreForm($text);
# spent 131ms making 70 calls to Foswiki::Meta::setEmbeddedStoreForm, avg 1.87ms/call
111
11270493µs703.90ms unless ( $handler->noCheckinPending() ) {
# spent 3.90ms making 70 calls to Foswiki::Store::VC::Handler::noCheckinPending, avg 56µs/call
113
114 # If a checkin is pending, fix the TOPICINFO
11521125µs21428µs my $ri = $topicObject->get('TOPICINFO');
# spent 428µs making 21 calls to Foswiki::Meta::get, avg 20µs/call
11621199µs2192.8s my $truth = $handler->getInfo($version);
# spent 92.8s making 21 calls to Foswiki::Store::VC::RcsWrapHandler::getInfo, avg 4.42s/call
11721205µs for my $i (qw(author version date)) {
11863310µs $ri->{$i} = $truth->{$i};
119 }
120 }
121
12270106µs $gotRev = $version;
12370201µs unless ( defined $gotRev ) {
124
125 # First try the just-loaded for the revision.
12670618µs701.87ms my $ri = $topicObject->get('TOPICINFO');
# spent 1.87ms making 70 calls to Foswiki::Meta::get, avg 27µs/call
12770195µs $gotRev = $ri->{version} if defined $ri;
128 }
12970101µs if ( !defined $gotRev ) {
130
131 # No revision from any other source; must be latest
132357µs3790ms $gotRev = $handler->getLatestRevisionID();
# spent 790ms making 3 calls to Foswiki::Store::VC::Handler::getLatestRevisionID, avg 263ms/call
133330µs326µs ASSERT( defined $gotRev ) if DEBUG;
# spent 26µs making 3 calls to Assert::ASSERTS_OFF, avg 9µs/call
134 }
135
136 # Add attachments that are new from reading the pub directory.
137 # Only check the currently requested topic.
13870208µs if ( $Foswiki::cfg{RCS}{AutoAttachPubFiles}
139 && $topicObject->isSessionTopic() )
140 {
141 my @knownAttachments = $topicObject->find('FILEATTACHMENT');
142 my @attachmentsFoundInPub =
143 $handler->synchroniseAttachmentsList( \@knownAttachments );
144 my @validAttachmentsFound;
145 foreach my $foundAttachment (@attachmentsFoundInPub) {
146
147 # test if the attachment filename is valid without having to
148 # be sanitized. If not, ignore it.
149 my $validated = Foswiki::Sandbox::validateAttachmentName(
150 $foundAttachment->{name} );
151 unless ( defined $validated
152 && $validated eq $foundAttachment->{name} )
153 {
154
155 print STDERR 'AutoAttachPubFiles ignoring '
156 . $foundAttachment->{name} . ' in '
157 . $topicObject->getPath()
158 . ' - not a valid Foswiki Attachment filename';
159 }
160 else {
161 push @validAttachmentsFound, $foundAttachment;
162 $this->tellListeners(
163 verb => 'autoattach',
164 newmeta => $topicObject,
165 newattachment => $foundAttachment
166 );
167 }
168 }
169
170 $topicObject->putAll( 'FILEATTACHMENT', @validAttachmentsFound )
171 if @validAttachmentsFound;
172 }
173
17470359µs70264µs ASSERT( defined($gotRev) ) if DEBUG;
# spent 264µs making 70 calls to Assert::ASSERTS_OFF, avg 4µs/call
17570661µs return ( $gotRev, $isLatest );
176}
177
178sub moveAttachment {
179 my ( $this, $oldTopicObject, $oldAttachment, $newTopicObject,
180 $newAttachment, $cUID )
181 = @_;
182
183 my $handler = $this->getHandler( $oldTopicObject, $oldAttachment );
184 if ( $handler->storedDataExists() ) {
185 $handler->moveAttachment( $this, $newTopicObject->web,
186 $newTopicObject->topic, $newAttachment );
187 $this->tellListeners(
188 verb => 'update',
189 oldmeta => $oldTopicObject,
190 oldattachment => $oldAttachment,
191 newmeta => $newTopicObject,
192 newattachment => $newAttachment
193 );
194 $handler->recordChange( $cUID, 0 );
195 }
196}
197
198sub copyAttachment {
199 my ( $this, $oldTopicObject, $oldAttachment, $newTopicObject,
200 $newAttachment, $cUID )
201 = @_;
202
203 my $handler = $this->getHandler( $oldTopicObject, $oldAttachment );
204 if ( $handler->storedDataExists() ) {
205 $handler->copyAttachment( $this, $newTopicObject->web,
206 $newTopicObject->topic, $newAttachment );
207 $this->tellListeners(
208 verb => 'insert',
209 newmeta => $newTopicObject,
210 newattachment => $newAttachment
211 );
212 $handler->recordChange( $cUID, 0 );
213 }
214}
215
216sub attachmentExists {
217 my ( $this, $topicObject, $att ) = @_;
218 my $handler = $this->getHandler( $topicObject, $att );
219 return $handler->storedDataExists();
220}
221
222sub moveTopic {
223 my ( $this, $oldTopicObject, $newTopicObject, $cUID ) = @_;
224 ASSERT($cUID) if DEBUG;
225
226 my $handler = $this->getHandler( $oldTopicObject, '' );
227 my $rev = $handler->getLatestRevisionID();
228
229 $handler->moveTopic( $this, $newTopicObject->web, $newTopicObject->topic );
230
231 $this->tellListeners(
232 verb => 'update',
233 oldmeta => $oldTopicObject,
234 newmeta => $newTopicObject
235 );
236
237 if ( $newTopicObject->web ne $oldTopicObject->web ) {
238
239 # Record that it was moved away
240 $handler->recordChange( $cUID, $rev );
241 }
242
243 $handler = $this->getHandler( $newTopicObject, '' );
244 $handler->recordChange( $cUID, $rev );
245}
246
247sub moveWeb {
248 my ( $this, $oldWebObject, $newWebObject, $cUID ) = @_;
249 ASSERT($cUID) if DEBUG;
250
251 my $handler = $this->getHandler($oldWebObject);
252 $handler->moveWeb( $newWebObject->web );
253
254 $this->tellListeners(
255 verb => 'update',
256 oldmeta => $oldWebObject,
257 newmeta => $newWebObject
258 );
259
260 # We have to log in the new web, otherwise we would re-create the dir with
261 # a useless .changes. See Item9278
262 $handler = $this->getHandler($newWebObject);
263 $handler->recordChange( $cUID, 0, 'Moved from ' . $oldWebObject->web );
264}
265
266sub testAttachment {
267 my ( $this, $topicObject, $attachment, $test ) = @_;
268 my $handler = $this->getHandler( $topicObject, $attachment );
269 return $handler->test($test);
270}
271
272sub openAttachment {
273 my ( $this, $topicObject, $att, $mode, @opts ) = @_;
274
275 my $handler = $this->getHandler( $topicObject, $att );
276 return $handler->openStream( $mode, @opts );
277}
278
279
# spent 621ms (109µs+621) within Foswiki::Store::VC::Store::getRevisionHistory which was called 2 times, avg 310ms/call: # 2 times (109µs+621ms) by Foswiki::Meta::getRevisionHistory at line 2337 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm, avg 310ms/call
sub getRevisionHistory {
28025µs my ( $this, $topicObject, $attachment ) = @_;
281
282220µs234µs my $itr = $this->askListenersRevisionHistory( $topicObject, $attachment );
# spent 34µs making 2 calls to Foswiki::Store::askListenersRevisionHistory, avg 17µs/call
283
28423µs if ( defined($itr) ) {
285 return $itr;
286 }
287
288213µs2198µs my $handler = $this->getHandler( $topicObject, $attachment );
# spent 198µs making 2 calls to Foswiki::Store::RcsWrap::getHandler, avg 99µs/call
289256µs2620ms return $handler->getRevisionHistory();
# spent 620ms making 2 calls to Foswiki::Store::VC::Handler::getRevisionHistory, avg 310ms/call
290}
291
292sub getNextRevision {
293 my ( $this, $topicObject ) = @_;
294 my $handler = $this->getHandler($topicObject);
295 return $handler->getNextRevisionID();
296}
297
298sub getRevisionDiff {
299 my ( $this, $topicObject, $rev2, $contextLines ) = @_;
300 ASSERT( defined($contextLines) ) if DEBUG;
301
302 my $rcs = $this->getHandler($topicObject);
303 return $rcs->revisionDiff( $topicObject->getLoadedRev(), $rev2,
304 $contextLines );
305}
306
307sub getAttachmentVersionInfo {
308 my ( $this, $topicObject, $rev, $attachment ) = @_;
309 my $handler = $this->getHandler( $topicObject, $attachment );
310 return $handler->getInfo( $rev || 0 );
311}
312
313sub getVersionInfo {
314 my ( $this, $topicObject ) = @_;
315 my $info = $this->askListenersVersionInfo($topicObject);
316
317 if ( not defined $info ) {
318 my $handler = $this->getHandler($topicObject);
319
320 $info = $handler->getInfo( $topicObject->getLoadedRev() );
321 }
322
323 return $info;
324}
325
326sub saveAttachment {
327 my ( $this, $topicObject, $name, $stream, $cUID, $comment ) = @_;
328 my $handler = $this->getHandler( $topicObject, $name );
329 my $currentRev = $handler->getLatestRevisionID();
330 my $nextRev = $currentRev + 1;
331 my $verb = ( $topicObject->hasAttachment($name) ) ? 'update' : 'insert';
332 $handler->addRevisionFromStream( $stream, $comment, $cUID );
333 $this->tellListeners(
334 verb => $verb,
335 newmeta => $topicObject,
336 newattachment => $name
337 );
338 $handler->recordChange( $cUID, $nextRev );
339 return $nextRev;
340}
341
342sub saveTopic {
343 my ( $this, $topicObject, $cUID, $options ) = @_;
344 ASSERT( $topicObject->isa('Foswiki::Meta') ) if DEBUG;
345 ASSERT($cUID) if DEBUG;
346
347 my $handler = $this->getHandler($topicObject);
348
349 my $verb = ( $topicObject->existsInStore() ) ? 'update' : 'insert';
350
351 # just in case they are not sequential
352 my $nextRev = $handler->getNextRevisionID();
353 my $ti = $topicObject->get('TOPICINFO');
354 $ti->{version} = $nextRev;
355 $ti->{author} = $cUID;
356
357 $handler->addRevisionFromText( $topicObject->getEmbeddedStoreForm(),
358 'save topic', $cUID, $options->{forcedate} );
359
360 my $extra = $options->{minor} ? 'minor' : '';
361 $handler->recordChange( $cUID, $nextRev, $extra );
362
363 $this->tellListeners( verb => $verb, newmeta => $topicObject );
364
365 return $nextRev;
366}
367
368sub repRev {
369 my ( $this, $topicObject, $cUID, %options ) = @_;
370 ASSERT( $topicObject->isa('Foswiki::Meta') ) if DEBUG;
371 ASSERT($cUID) if DEBUG;
372 my $info = $topicObject->getRevisionInfo();
373 my $handler = $this->getHandler($topicObject);
374 $handler->replaceRevision( $topicObject->getEmbeddedStoreForm(),
375 'reprev', $cUID, $info->{date} );
376 my $rev = $handler->getLatestRevisionID();
377 $handler->recordChange( $cUID, $rev, 'minor, reprev' );
378
379 $this->tellListeners( verb => 'update', newmeta => $topicObject );
380
381 return $rev;
382}
383
384sub delRev {
385 my ( $this, $topicObject, $cUID ) = @_;
386 ASSERT( $topicObject->isa('Foswiki::Meta') ) if DEBUG;
387 ASSERT($cUID) if DEBUG;
388
389 my $handler = $this->getHandler($topicObject);
390 my $rev = $handler->getLatestRevisionID();
391 if ( $rev <= 1 ) {
392 throw Error::Simple( 'Cannot delete initial revision of '
393 . $topicObject->web . '.'
394 . $topicObject->topic );
395 }
396 $handler->deleteRevision();
397
398 # restore last topic from repository
399 $handler->restoreLatestRevision($cUID);
400
401 # reload the topic object
402 $topicObject->unload();
403 $topicObject->loadVersion();
404
405 $this->tellListeners( verb => 'update', newmeta => $topicObject );
406
407 $handler->recordChange( $cUID, $rev );
408
409 return $rev;
410}
411
412sub atomicLockInfo {
413 my ( $this, $topicObject ) = @_;
414 my $handler = $this->getHandler($topicObject);
415 return $handler->isLocked();
416}
417
418# It would be nice to use flock to do this, but the API is unreliable
419# (doesn't work on all platforms)
420sub atomicLock {
421 my ( $this, $topicObject, $cUID ) = @_;
422 my $handler = $this->getHandler($topicObject);
423 $handler->setLock( 1, $cUID );
424}
425
426sub atomicUnlock {
427 my ( $this, $topicObject, $cUID ) = @_;
428
429 my $handler = $this->getHandler($topicObject);
430 $handler->setLock( 0, $cUID );
431}
432
433# A web _has_ to have a preferences topic to be a web.
434
# spent 348µs (80+268) within Foswiki::Store::VC::Store::webExists which was called 2 times, avg 174µs/call: # 2 times (80µs+268µs) by Foswiki::webExists at line 3657 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 174µs/call
sub webExists {
43525µs my ( $this, $web ) = @_;
436
43723µs return 0 unless defined $web;
438224µs29µs $web =~ s#\.#/#go;
# spent 9µs making 2 calls to Foswiki::Store::VC::Store::CORE:subst, avg 4µs/call
439
440 # Foswiki ships with TWikiCompatibilityPlugin but if it is disabled we
441 # do not want the TWiki web to appear as a valid web to anyone.
44224µs if ( $web eq 'TWiki' ) {
443 unless ( exists $Foswiki::cfg{Plugins}{TWikiCompatibilityPlugin}
444 && defined $Foswiki::cfg{Plugins}{TWikiCompatibilityPlugin}{Enabled}
445 && $Foswiki::cfg{Plugins}{TWikiCompatibilityPlugin}{Enabled} == 1 )
446 {
447 return 0;
448 }
449 }
450
451222µs2199µs my $handler = $this->getHandler( $web, $Foswiki::cfg{WebPrefsTopicName} );
# spent 199µs making 2 calls to Foswiki::Store::RcsWrap::getHandler, avg 99µs/call
452228µs261µs return $handler->storedDataExists();
# spent 61µs making 2 calls to Foswiki::Store::VC::Handler::storedDataExists, avg 30µs/call
453}
454
455
# spent 35.6ms (7.21+28.4) within Foswiki::Store::VC::Store::topicExists which was called 272 times, avg 131µs/call: # 155 times (3.89ms+16.4ms) by Foswiki::topicExists at line 3674 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 131µs/call # 97 times (2.76ms+9.87ms) by Foswiki::Meta::existsInStore at line 703 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm, avg 130µs/call # 20 times (561µs+2.13ms) by Foswiki::INCLUDE at line 182 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Macros/INCLUDE.pm, avg 135µs/call
sub topicExists {
456272589µs my ( $this, $web, $topic ) = @_;
457
458272451µs return 0 unless defined $web && $web ne '';
4592721.95ms272540µs $web =~ s#\.#/#go;
# spent 540µs making 272 calls to Foswiki::Store::VC::Store::CORE:subst, avg 2µs/call
460272369µs return 0 unless defined $topic && $topic ne '';
461
4622721.60ms27222.7ms my $handler = $this->getHandler( $web, $topic );
# spent 22.7ms making 272 calls to Foswiki::Store::RcsWrap::getHandler, avg 83µs/call
4632722.62ms2725.13ms return $handler->storedDataExists();
# spent 5.13ms making 272 calls to Foswiki::Store::VC::Handler::storedDataExists, avg 19µs/call
464}
465
466sub getApproxRevTime {
467 my ( $this, $web, $topic ) = @_;
468
469 my $handler = $this->getHandler( $web, $topic );
470 return $handler->getLatestRevisionTime();
471}
472
473sub eachChange {
474 my ( $this, $webObject, $time ) = @_;
475
476 my $handler = $this->getHandler($webObject);
477 return $handler->eachChange($time);
478}
479
480sub eachAttachment {
481 my ( $this, $topicObject ) = @_;
482
483 my $handler = $this->getHandler($topicObject);
484 my @list = $handler->getAttachmentList();
485 require Foswiki::ListIterator;
486 return new Foswiki::ListIterator( \@list );
487}
488
489
# spent 170ms (753µs+169) within Foswiki::Store::VC::Store::eachTopic which was called: # once (753µs+169ms) by Foswiki::Meta::eachTopic at line 950 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm
sub eachTopic {
49012µs my ( $this, $webObject ) = @_;
491
492110µs1178µs my $handler = $this->getHandler($webObject);
# spent 178µs making 1 call to Foswiki::Store::RcsWrap::getHandler
4931691µs1169ms my @list = $handler->getTopicNames();
# spent 169ms making 1 call to Foswiki::Store::VC::Handler::getTopicNames
494
49514µs require Foswiki::ListIterator;
496138µs152µs return new Foswiki::ListIterator( \@list );
# spent 52µs making 1 call to Foswiki::ListIterator::new
497}
498
499sub eachWeb {
500 my ( $this, $webObject, $all ) = @_;
501
502 # Undocumented; this fn actually accepts a web name as well. This is
503 # to make the recursion more efficient.
504 my $web = ref($webObject) ? $webObject->web : $webObject;
505
506 my $handler = $this->getHandler($web);
507 my @list = $handler->getWebNames();
508 if ($all) {
509 my $root = $web ? "$web/" : '';
510 my @expandedList;
511 while ( my $wp = shift(@list) ) {
512 push( @expandedList, $wp );
513 my $it = $this->eachWeb( $root . $wp, $all );
514 push( @expandedList, map { "$wp/$_" } $it->all() );
515 }
516 @list = @expandedList;
517 }
518 @list = sort(@list);
519 require Foswiki::ListIterator;
520 return new Foswiki::ListIterator( \@list );
521}
522
523sub remove {
524 my ( $this, $cUID, $topicObject, $attachment ) = @_;
525 ASSERT( $topicObject->web ) if DEBUG;
526
527 my $handler = $this->getHandler( $topicObject, $attachment );
528 $handler->remove();
529
530 $this->tellListeners(
531 verb => 'remove',
532 oldmeta => $topicObject,
533 oldattachment => $attachment
534 );
535
536 # Only log when deleting topics or attachment, otherwise we would re-create
537 # an empty directory with just a .changes. See Item9278
538 if ( my $topic = $topicObject->topic ) {
539 $handler->recordChange( $cUID, 0, 'Deleted ' . $topic );
540 }
541 elsif ($attachment) {
542 $handler->recordChange( $cUID, 0, 'Deleted attachment ' . $attachment );
543 }
544}
545
546
# spent 1.66s (2.20ms+1.66) within Foswiki::Store::VC::Store::query which was called: # once (2.20ms+1.66s) by Foswiki::Meta::query at line 907 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Meta.pm
sub query {
54713µs my ( $this, $query, $inputTopicSet, $session, $options ) = @_;
548
54911µs my $engine;
550122µs13µs if ( $query->isa('Foswiki::Query::Node') ) {
# spent 3µs making 1 call to UNIVERSAL::isa
55114µs unless ( $this->{queryObj} ) {
55214µs my $module = $Foswiki::cfg{Store}{QueryAlgorithm};
553169µs eval "require $module";
# spent 292µs executing statements in string eval
55412µs die
555"Bad {Store}{QueryAlgorithm}; suggest you run configure and select a different algorithm\n$@"
556 if $@;
557115µs155µs $this->{queryObj} = $module->new();
# spent 55µs making 1 call to Foswiki::Store::QueryAlgorithms::BruteForce::new
558 }
55912µs $engine = $this->{queryObj};
560 }
561 else {
562 ASSERT( $query->isa('Foswiki::Search::Node') ) if DEBUG;
563 unless ( $this->{searchQueryObj} ) {
564 my $module = $Foswiki::cfg{Store}{SearchAlgorithm};
565 eval "require $module";
566 die
567"Bad {Store}{SearchAlgorithm}; suggest you run configure and select a different algorithm\n$@"
568 if $@;
569 $this->{searchQueryObj} = $module->new();
570 }
571 $engine = $this->{searchQueryObj};
572 }
573
574268µs291µs
# spent 54µs (18+37) within Foswiki::Store::VC::Store::BEGIN@574 which was called: # once (18µs+37µs) by Foswiki::Store::RcsWrap::BEGIN@23 at line 574
no strict 'refs';
# spent 54µs making 1 call to Foswiki::Store::VC::Store::BEGIN@574 # spent 37µs making 1 call to strict::unimport
575123µs11.65s return $engine->query( $query, $inputTopicSet, $session, $options );
5762306µs275µs
# spent 45µs (16+30) within Foswiki::Store::VC::Store::BEGIN@576 which was called: # once (16µs+30µs) by Foswiki::Store::RcsWrap::BEGIN@23 at line 576
use strict 'refs';
# spent 45µs making 1 call to Foswiki::Store::VC::Store::BEGIN@576 # spent 30µs making 1 call to strict::import
577}
578
579sub getRevisionAtTime {
580 my ( $this, $topicObject, $time ) = @_;
581
582 my $handler = $this->getHandler($topicObject);
583 return $handler->getRevisionAtTime($time);
584}
585
586sub getLease {
587 my ( $this, $topicObject ) = @_;
588
589 my $handler = $this->getHandler($topicObject);
590 my $lease = $handler->getLease();
591 return $lease;
592}
593
594sub setLease {
595 my ( $this, $topicObject, $lease ) = @_;
596
597 my $handler = $this->getHandler($topicObject);
598 $handler->setLease($lease);
599}
600
601sub removeSpuriousLeases {
602 my ( $this, $web ) = @_;
603 my $handler = $this->getHandler($web);
604 $handler->removeSpuriousLeases();
605}
606
60716µs1;
608__END__
 
# spent 2µs within Foswiki::Store::VC::Store::CORE:match which was called: # once (2µs+0s) by Foswiki::Store::VC::Store::readTopic at line 93
sub Foswiki::Store::VC::Store::CORE:match; # opcode
# spent 1.09ms within Foswiki::Store::VC::Store::CORE:subst which was called 344 times, avg 3µs/call: # 272 times (540µs+0s) by Foswiki::Store::VC::Store::topicExists at line 459, avg 2µs/call # 70 times (536µs+0s) by Foswiki::Store::VC::Store::readTopic at line 109, avg 8µs/call # 2 times (9µs+0s) by Foswiki::Store::VC::Store::webExists at line 438, avg 4µs/call
sub Foswiki::Store::VC::Store::CORE:subst; # opcode