1 package NonameTV
::FileStore
;
5 use NonameTV
::Log qw
/d p w f/;
7 use File
::Slurp qw
/read_file/;
8 use LWP
::Simple qw
/get/;
9 use Digest
::MD5 qw
/md5_hex/;
10 use File
::Path qw
/mkpath/;
13 use Carp qw
/croak carp/;
19 Class: NonameTV::FileStore
31 my $class = ref( $_[0] ) || $_[0];
36 # Copy the parameters supplied in the constructor.
37 foreach my $key ( keys( %{ $_[1] } ) ) {
38 $self->{$key} = ( $_[1] )->{$key};
41 croak
"Failed to specify Path"
42 if not defined $self->{Path
};
53 Add a new file to the filestore for a specific channel. If an
54 identical file already exists (same filename and md5sum), no action is
55 performed. If a file with the same name but different content exists,
56 the old file is replaced with the new file.
62 sub AddFile
#( $xmltvid, $filename, $cref )
65 my( $xmltvid, $filename, $cref ) = @_;
67 $self->LoadFileList( $xmltvid );
69 carp
"Cannot add a file to a remote filestore"
70 if not $self->PathIsLocal();
72 my $dir = $self->{Path
} . "/$xmltvid";
76 my( $oldmd5, $ts ) = $self->GetFileMeta( $xmltvid, $filename );
78 my $newmd5 = md5_hex
( $$cref );
79 if( not defined( $oldmd5 ) ) {
80 my $fullname = "$dir/$filename";
81 open( OUT
, "> $fullname" ) or die "Failed to write to $fullname";
85 $self->AddFileMeta( $xmltvid, $filename, $newmd5 );
87 elsif( $oldmd5 ne $newmd5 ) {
88 # Same filename but different content. Make up a new filename.
89 my( $base, $ext ) = ($filename =~ /^(.*)(\..*?)$/);
90 if( not defined $ext ) {
98 for( my $c=1; $c<100; $c++ ) {
99 $nextfilename = "$base-$c$ext";
100 ( $nextmd5 ) = $self->GetFileMeta( $xmltvid, $nextfilename );
101 if( (not defined( $nextmd5 )) or ($nextmd5 eq $newmd5) ) {
106 if( not defined( $nextmd5 ) ) {
107 my $fullname = "$dir/$nextfilename";
108 open( OUT
, "> $fullname" ) or die "Failed to write to $fullname";
112 $self->AddFileMeta( $xmltvid, $nextfilename, $newmd5 );
116 # print "Duplicate file skipped.\n";
122 my( $xmltvid, $filename, $md5 ) = @_;
124 # Delete any entry with the same filename
125 $self->{_fl
}->{$xmltvid} =
126 [ grep { $_->[0] ne $filename } @
{$self->{_fl
}->{$xmltvid}} ];
128 push @
{$self->{_fl
}->{$xmltvid}}, [ $filename, $md5, time()];
129 $self->{_flmodified
}->{$xmltvid} = 1;
136 Returns an array with arrayrefs, where each arrayref contains a
137 filename, an md5sum, and a timestamp for when the file was first added.
141 sub ListFiles
#( $xmltvid )
146 $self->LoadFileList( $xmltvid );
148 return @
{$self->{_fl
}->{$xmltvid}};
155 Returns a reference to the contents of the specified file or undef
156 if the file does not exist.
162 my( $xmltvid, $filename ) = @_;
164 my $fullname = $self->{Path
} . "/$xmltvid/$filename";
168 if( $self->PathIsLocal() ) {
169 $result = read_file
( $fullname, err_mode
=> 'quiet' );
172 $result = get
( $fullname );
175 return defined( $result ) ? \
$result : undef;
180 my( $xmltvid, $filename ) = @_;
182 foreach my $e (@
{$self->{_fl
}->{$xmltvid}}) {
183 return ($e->[1], $e->[2]) if $e->[0] eq $filename;
191 Method: RemoveOldFiles
193 Remove all files for a specific channel that were added more than
198 sub RemoveOldFiles
#( $xmltvid, $days )
205 return not $self->{Path
} =~ /^http:/;
212 return if defined $self->{_fl
}->{$xmltvid};
216 my $fl = $self->GetFile( $xmltvid, "00files" );
218 if( not defined $fl ) {
219 $self->RecreateIndex( $xmltvid );
223 foreach my $line (split( "\n", $$fl)) {
224 my( $filename, $md5sum, $ts ) = split( "\t", $line );
225 push @d, [ $filename, $md5sum, $ts ];
228 $self->{_fl
}->{$xmltvid} = \
@d;
229 $self->{_flmodified
}->{$xmltvid} = 0;
234 Method: RecreateIndex
236 Recreate the index file from the files stored in the correct location.
240 sub RecreateIndex
#( $xmltvid )
247 unlink( $self->{Path
} . "/$xmltvid/00files" );
249 foreach my $file (glob( $self->{Path
} . "/$xmltvid/*" )) {
250 my( $name ) = ($file =~ /.*\/(.*)/ );
251 open(FILE
, $file) or die "Can’t open ’$file’: $!";
254 my $md5 = Digest
::MD5
->new->addfile(*FILE
)->hexdigest;
255 my $st = stat($file) or die "Couldn't stat $file: $!";
256 my $mtime = $st->mtime;
258 push( @data, [$name, $md5, $mtime] );
261 $self->{_fl
}->{$xmltvid} = [ sort { $a->[2] <=> $b->[2] } @data ];
262 $self->{_flmodified
}->{$xmltvid} = 1;
269 my $fullname = $self->{Path
} . "/$xmltvid/00files";
270 open( OUT
, "> $fullname" ) or die "Failed to write to $fullname";
271 foreach my $e (@
{$self->{_fl
}->{$xmltvid}}) {
272 print OUT
join( "\t", @
{$e} ) . "\n";
280 foreach my $xmltvid (keys %{$self->{_flmodified
}} ) {
281 $self->WriteFileMeta( $xmltvid )
282 if $self->{_flmodified
}->{$xmltvid};
288 Copyright (C) 2008 Mattias Holmlund.
294 ### Setup coding system