Skip to content

Commit

Permalink
Item4795: update unit tests to eliminate calls to core functions, and…
Browse files Browse the repository at this point in the history
… perltidy

git-svn-id: http://svn.foswiki.org/trunk/DBCacheContrib@2988 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
CrawfordCurrie authored and CrawfordCurrie committed Mar 11, 2009
1 parent 47ec23b commit 274b8a8
Show file tree
Hide file tree
Showing 19 changed files with 1,356 additions and 1,133 deletions.
211 changes: 120 additions & 91 deletions lib/Foswiki/Contrib/DBCacheContrib.pm
Expand Up @@ -3,6 +3,7 @@
# Copyright (C) Crawford Currie 2004 - All rights reserved
#
package Foswiki::Contrib::DBCacheContrib;

#use base 'Foswiki::Contrib::DBCacheContrib::Map';

use strict;
Expand Down Expand Up @@ -42,7 +43,7 @@ As topics are loaded, the readTopicLine method gives subclasses an opportunity t

use vars qw( $initialised $storable $VERSION $RELEASE );

$initialised = 0; # Not initialised until the first new
$initialised = 0; # Not initialised until the first new

$VERSION = '$Rev$';
$RELEASE = 'Foswiki-1';
Expand All @@ -62,25 +63,28 @@ sub new {
$cacheName ||= '_DBCache';

# Backward compatibility
unless( $Foswiki::cfg{DBCacheContrib}{Archivist} ) {
unless ( $Foswiki::cfg{DBCacheContrib}{Archivist} ) {
$Foswiki::cfg{DBCacheContrib}{Archivist} =
'Foswiki::Contrib::DBCacheContrib::Archivist::Storable';
}
eval "use $Foswiki::cfg{DBCacheContrib}{Archivist}";
die $@ if ( $@ );
die $@ if ($@);

my $this = bless( {
_cache => undef, # pointer to the DB, load on demand
_web => $web,
_cachename => $cacheName,
}, $class);
my $this = bless(
{
_cache => undef, # pointer to the DB, load on demand
_web => $web,
_cachename => $cacheName,
},
$class
);

# Create the archivist. This will connect to an existing DB or create
# a new DB if required.
my $workDir = Foswiki::Func::getWorkArea('DBCacheContrib');
my $workDir = Foswiki::Func::getWorkArea('DBCacheContrib');
my $cacheFile = "$workDir/$web.$cacheName";
$this->{archivist} = $Foswiki::cfg{DBCacheContrib}{Archivist}->new(
$cacheFile);
$this->{archivist} =
$Foswiki::cfg{DBCacheContrib}{Archivist}->new($cacheFile);
return $this;
}

Expand All @@ -97,17 +101,18 @@ sub _loadTopic {
my ( $this, $dataDir, $topic ) = @_;
my $filename = "$dataDir/$topic.txt";
my $fh;

#print STDERR "DBCacheContrib::_loadTopic($filename)\n";

unless (open( $fh, "<$filename" )) {
unless ( open( $fh, "<$filename" ) ) {
print STDERR "WARNING: Failed to open $filename\n";
return 0;
}

my $meta = $this->{archivist}->newMap();
$meta->set( 'name', $topic );
$meta->set( 'name', $topic );
$meta->set( 'topic', $topic );
my @s = stat($filename);
my @s = stat($filename);
my $time = $s[9];
$meta->set( '.cache_file', $filename );
$meta->set( '.cache_time', $time );
Expand All @@ -118,72 +123,81 @@ sub _loadTopic {
my $tailMeta = 0;
local $/;
my $all = <$fh>;
close( $fh );
my @lines = split(/\r?\n/, $all);
while (scalar(@lines)) {
close($fh);
my @lines = split( /\r?\n/, $all );
while ( scalar(@lines) ) {
my $line = shift(@lines);
if ( $line =~ m/^%META:FORM{name=\"([^\"]*)\"}%/o ) {
$form = $this->{archivist}->newMap() unless $form;
my( $web, $topic ) = Foswiki::Func::normalizeWebTopicName('', $1);
$form->set('name', $web.'.'.$topic);
$form->set('_up', $meta);
$form->set('_web', $this->{_cache});
$meta->set('form', $topic);
$meta->set($topic, $form);
my ( $web, $topic ) =
Foswiki::Func::normalizeWebTopicName( '', $1 );
$form->set( 'name', $web . '.' . $topic );
$form->set( '_up', $meta );
$form->set( '_web', $this->{_cache} );
$meta->set( 'form', $topic );
$meta->set( $topic, $form );
$tailMeta = 1;
} elsif ( $line =~ m/^%META:TOPICPARENT{name=\"([^\"]*)\"}%/o ) {
$meta->set('parent', $1);
}
elsif ( $line =~ m/^%META:TOPICPARENT{name=\"([^\"]*)\"}%/o ) {
$meta->set( 'parent', $1 );
$tailMeta = 1;
} elsif ( $line =~ m/^%META:TOPICINFO{(.*)}%/o ) {
my $att = $this->{archivist}->newMap(initial => $1);
$att->set( '_up', $meta);
$att->set( '_web', $this->{_cache});
}
elsif ( $line =~ m/^%META:TOPICINFO{(.*)}%/o ) {
my $att = $this->{archivist}->newMap( initial => $1 );
$att->set( '_up', $meta );
$att->set( '_web', $this->{_cache} );
$meta->set( 'info', $att );
} elsif ( $line =~ m/^%META:TOPICMOVED{(.*)}%/o ) {
my $att = $this->{archivist}->newMap(initial => $1);
$att->set( '_up', $meta);
$att->set( '_web', $this->{_cache});
}
elsif ( $line =~ m/^%META:TOPICMOVED{(.*)}%/o ) {
my $att = $this->{archivist}->newMap( initial => $1 );
$att->set( '_up', $meta );
$att->set( '_web', $this->{_cache} );
$meta->set( 'moved', $att );
$tailMeta = 1;
} elsif ( $line =~ m/^%META:FIELD{(.*)}%/o ) {
}
elsif ( $line =~ m/^%META:FIELD{(.*)}%/o ) {
my $fs = new Foswiki::Attrs($1);
$form = $this->{archivist}->newMap() unless $form;
$form->set( '_web', $this->{_cache} );
$form->set( $fs->get('name'), $fs->get('value'));
$form->set( '_web', $this->{_cache} );
$form->set( $fs->get('name'), $fs->get('value') );
$tailMeta = 1;
} elsif ( $line =~ m/^%META:FILEATTACHMENT{(.*)}%/o ) {
my $att = $this->{archivist}->newMap(initial => $1);
$att->set( '_up', $meta);
$att->set( '_web', $this->{_cache});
my $atts = $meta->get( 'attachments' );
if ( !defined( $atts )) {
}
elsif ( $line =~ m/^%META:FILEATTACHMENT{(.*)}%/o ) {
my $att = $this->{archivist}->newMap( initial => $1 );
$att->set( '_up', $meta );
$att->set( '_web', $this->{_cache} );
my $atts = $meta->get('attachments');
if ( !defined($atts) ) {
$atts = $this->{archivist}->newArray();
$meta->set( 'attachments', $atts );
}
$atts->add( $att );
$atts->add($att);
$tailMeta = 1;
} elsif ( $line =~ m/^%META:PREFERENCE{(.*)}%/o ) {
my $pref = $this->{archivist}->newMap(initial => $1);
$pref->set( '_up', $meta);
$pref->set( '_web', $this->{_cache});
}
elsif ( $line =~ m/^%META:PREFERENCE{(.*)}%/o ) {
my $pref = $this->{archivist}->newMap( initial => $1 );
$pref->set( '_up', $meta );
$pref->set( '_web', $this->{_cache} );
my $prefs = $meta->get('preferences');
if (!defined($prefs)) {
if ( !defined($prefs) ) {
$prefs = $this->{archivist}->newArray();
$meta->set('preferences', $prefs);
$meta->set( 'preferences', $prefs );
}
$prefs->add($pref);
$tailMeta = 1;
} else {
if ($this->can('readTopicLine')) {
}
else {
if ( $this->can('readTopicLine') ) {
$text .= $this->readTopicLine( $topic, $meta, $line, \@lines );
} else {
}
else {
$text .= $line if $line && $line !~ /%META:[A-Z].*?}%/o;
}
}
}
$text =~ s/\n$//s if $tailMeta;
$meta->set( 'text', $text );
$meta->set( 'all', $all );
$meta->set( 'all', $all );
$this->{_cache}->set( $topic, $meta );

return $meta;
Expand Down Expand Up @@ -213,29 +227,33 @@ read from disc rather than from the cache. Passed a list of topic names that hav
=cut

sub onReload {

#my ( $this, @$topics) = @_;
}

sub _onReload {
my $this = shift;

foreach my $topic ( $this->{_cache}->getValues() ) {

# Fill in parent relations
unless ($topic->FETCH('parent')) {
$topic->set('parent', $Foswiki::cfg{HomeTopicName});
# last parent is WebHome
unless ( $topic->FETCH('parent') ) {
$topic->set( 'parent', $Foswiki::cfg{HomeTopicName} );

# last parent is WebHome
}
unless ( $topic->FETCH( '_up' )) {
my $parent = $topic->FETCH( 'parent' );
$parent = $this->{_cache}->FETCH( $parent ) if $parent;
unless ( $topic->FETCH('_up') ) {
my $parent = $topic->FETCH('parent');
$parent = $this->{_cache}->FETCH($parent) if $parent;

# prevent the _up to be undefined in case of
# a parent info to a non-existing topic;
# the parent chain ends at the web hash
if ($parent) {
$topic->set( '_up', $parent );
} else {
$topic->set( '_up', $this );
$topic->set( '_up', $parent );
}
else {
$topic->set( '_up', $this );
}
}

Expand All @@ -244,7 +262,6 @@ sub _onReload {
$topic->set( 'web', $this->{_web} );
}


$this->onReload(@_);
}

Expand All @@ -264,32 +281,33 @@ the afterSaveHandler and from the new REST updateCache handler
=cut

sub load {
my $this = shift;
my $this = shift;
my $updateCache = shift
|| $Foswiki::cfg{DBCacheContrib}{AlwaysUpdateCache};
$updateCache = 1 unless (defined($updateCache));
$updateCache = 1 unless ( defined($updateCache) );

#print STDERR "Called load($updateCache)\n";

return (0, 0, 0) if ( $this->{_cache} ); # already loaded?
return ( 0, 0, 0 ) if ( $this->{_cache} ); # already loaded?

my $web = $this->{_web};
$web =~ s/\//\./g;

$this->{_cache} = $this->{archivist}->getRoot();
ASSERT($this->{_cache}) if DEBUG;
ASSERT( $this->{_cache} ) if DEBUG;

# Check what's there already
my $readFromCache = $this->{_cache}->size();
my $readFromFile = 0;
my $removed = 0;
my $readFromFile = 0;
my $removed = 0;

if ( $updateCache || $this->{_cache}->size() == 0 ) {
eval {
( $readFromCache, $readFromFile, $removed ) =
$this->_updateCache( $web );
$this->_updateCache($web);
};

if ( $@ ) {
if ($@) {
print STDERR "Cache read failed $@...\n" if DEBUG;
Foswiki::Func::writeWarning("DBCache: Cache read failed: $@");
$this->{_cache} = undef;
Expand All @@ -300,7 +318,7 @@ sub load {
}
}

#print STDERR "DBCacheContrib: Loaded $readFromCache from cache, $readFromFile from file, $removed removed\n";
#print STDERR "DBCacheContrib: Loaded $readFromCache from cache, $readFromFile from file, $removed removed\n";

return ( $readFromCache, $readFromFile, $removed );
}
Expand All @@ -311,30 +329,37 @@ sub _updateCache {
my ( $this, $web ) = @_;

my $readFromCache = $this->{_cache}->size();
foreach my $cached ( $this->{_cache}->getValues()) {
foreach my $cached ( $this->{_cache}->getValues() ) {
$cached->set( '.fresh', 0 );
}

my $readFromFile = 0;
my @readTopic;

$web =~ s/\./\//g;
my $dataDir = Foswiki::Func::getDataDir()."/$web";
my $dataDir = Foswiki::Func::getDataDir() . "/$web";

#print STDERR "_updateCache from $dataDir\n";

# load topics that are missing from the cache
opendir(D, $dataDir) || return (0, 0, 0);
opendir( D, $dataDir ) || return ( 0, 0, 0 );
foreach my $topic ( readdir(D) ) {
next unless $topic =~ s/\.txt$//;
my $topcache = $this->{_cache}->FETCH( $topic );
if ($topcache && !uptodate( $topcache->FETCH( '.cache_file' ),
$topcache->FETCH( '.cache_time' ))) {
$this->{_cache}->remove( $topic );
my $topcache = $this->{_cache}->FETCH($topic);
if (
$topcache
&& !uptodate(
$topcache->FETCH('.cache_file'),
$topcache->FETCH('.cache_time')
)
)
{
$this->{_cache}->remove($topic);
$readFromCache--;
$topcache = undef;
}
if ( !$topcache ) {

# Not in cache
$topcache = $this->_loadTopic( $dataDir, $topic );
if ($topcache) {
Expand All @@ -345,25 +370,29 @@ sub _updateCache {
$topcache->set( '.fresh', 1 ) if $topcache;

#don't disadvantage users just because the cache is off
last if defined($Foswiki::cfg{DBCacheContrib}{LoadFileLimit}) &&
( $Foswiki::cfg{DBCacheContrib}{LoadFileLimit} > 0 ) &&
( $readFromFile > $Foswiki::cfg{DBCacheContrib}{LoadFileLimit} );
last
if defined( $Foswiki::cfg{DBCacheContrib}{LoadFileLimit} )
&& ( $Foswiki::cfg{DBCacheContrib}{LoadFileLimit} > 0 )
&& ( $readFromFile >
$Foswiki::cfg{DBCacheContrib}{LoadFileLimit} );
}
closedir(D);

# Find smelly topics in the cache
my $removed = 0;
foreach my $cached ( $this->{_cache}->getValues()) {
if( $cached->FETCH( '.fresh' )) {
$cached->remove( '.fresh' );
} else {
$this->{_cache}->remove( $cached->FETCH( 'name' ) );
foreach my $cached ( $this->{_cache}->getValues() ) {
if ( $cached->FETCH('.fresh') ) {
$cached->remove('.fresh');
}
else {
$this->{_cache}->remove( $cached->FETCH('name') );
$readFromCache--;
$removed++;
}
}

if ( $readFromFile || $removed ) {

# refresh relations
$this->_onReload( \@readTopic );
}
Expand All @@ -379,11 +408,11 @@ Check the file time against what is seen on disc. Return 1 if consistent, 0 if i
=cut

sub uptodate {
my ($file, $time) = @_;
if ( -f $file && defined( $time )) {
my @sinfo = stat( $file );
my ( $file, $time ) = @_;
if ( -f $file && defined($time) ) {
my @sinfo = stat($file);
my $fileTime = $sinfo[9];
if ( defined( $fileTime) && $fileTime == $time ) {
if ( defined($fileTime) && $fileTime == $time ) {
return 1;
}
}
Expand Down

0 comments on commit 274b8a8

Please sign in to comment.