From: Ian Beckwith Date: Fri, 1 Oct 2010 19:55:37 +0000 (+0100) Subject: id3fs-index: removed unused entries when reindexing X-Git-Tag: debian/1.0-1~152 X-Git-Url: http://erislabs.net/gitweb/?p=id3fs.git;a=commitdiff_plain;h=40f0c2722d03f8c86d867cddf4f323f992a4065b id3fs-index: removed unused entries when reindexing --- diff --git a/bin/id3fs-index b/bin/id3fs-index index 89f6f12..9493f7c 100755 --- a/bin/id3fs-index +++ b/bin/id3fs-index @@ -16,6 +16,7 @@ my $basedir=undef; my $dbpath=undef; my $list=0; my @extensions=qw(mp3 flac ogg); +my $files_pruned; Configure(qw(bundling no_ignore_case)); my $optret=GetOptions( @@ -44,10 +45,16 @@ else { $db->last_update(time()); + my $directories_pruned=$db->prune_directories(); while(my $path=shift) { File::Find::find( {wanted => \&wanted, follow => 1, no_chdir => 1}, $path); } + if($files_pruned || $directories_pruned) + { + print "Removing data from pruned files\n" if $verbose; + $db->remove_unused(); + } } sub wanted @@ -57,6 +64,7 @@ sub wanted if(-d) { print("$_\n") if $verbose; + prune($_); } elsif(-f && scalar(grep({ $ext eq lc($_);} @extensions))) { @@ -65,6 +73,33 @@ sub wanted } } + +sub prune +{ + my $dir=shift; + return unless(opendir(DIR, $dir)); + print "Pruning $dir\n"; + my @oldfiles=$db->files_in($dir); + my @newfiles=grep { !/^\.\.?$/; } readdir(DIR); + closedir(DIR); + @oldfiles=sort @oldfiles; + @newfiles=sort @newfiles; + my %hash; + @hash{@newfiles}=(); + for my $file (@oldfiles) + { + unless(exists($hash{$file})) + { + # FIXME: add path, rebasify + $files_pruned=1; + $db->unindex($file); + } + } +} + + + + sub list_tags { my($db)=@_; diff --git a/lib/ID3FS/DB.pm b/lib/ID3FS/DB.pm index b4c95aa..5f08a04 100644 --- a/lib/ID3FS/DB.pm +++ b/lib/ID3FS/DB.pm @@ -520,6 +520,91 @@ sub tag_has_values return $rows; } +sub files_in +{ + my ($self, $dir)=@_; + $dir=~s/^$self->{base}\/?//; + print "Munged dir: $dir\n"; + my $sql=("SELECT files.name FROM files\n" . + "INNER JOIN paths ON files.paths_id=paths.id\n" . + "WHERE paths.name=?\n"); + my $files=$self->cmd_rows($sql, $dir); + return(map { $_->[0]; } @$files); +} + +sub prune_directories +{ + my($self)=@_; + my $sql=("SELECT name, id FROM paths ORDER BY name\n"); + my $pathsref=$self->cmd_rows($sql); + my @ids=(); + for my $pathpair (@$pathsref) + { + my($path, $id)=@$pathpair; + my $fullpath="$self->{absbase}/$path"; + print "PRUNING PATH $fullpath: "; + unless(-d $fullpath) + { + push(@ids, $id) + } + } + $self->prune_paths(@ids); + return scalar(@ids); +} + +sub prune_paths +{ + my($self, @ids)=@_; + my $sql=("DELETE FROM files WHERE paths_id IN (\n\t" . + join(', ', map { "\"$_\""; } @ids). "\n\t)"); + print "SQL: \n", $sql, "\n"; + $self->cmd($sql); +} + +sub remove_unused +{ + my($self)=@_; + my $sql=<<'EOT'; + DELETE FROM artists WHERE id IN ( + SELECT artists.id FROM artists + LEFT JOIN files ON files.artists_id=artists.id + WHERE files.id IS NULL); + + DELETE FROM albums WHERE id IN ( + SELECT albums.id FROM albums + LEFT JOIN files ON files.albums_id=albums.id + WHERE files.id IS NULL); + + DELETE FROM paths WHERE id IN ( + SELECT paths.id FROM paths + LEFT JOIN files ON files.paths_id=paths.id + WHERE files.id IS NULL); + + DELETE FROM files_x_tags WHERE files_id IN ( + SELECT files_x_tags.files_id FROM files_x_tags + LEFT JOIN files ON files.id=files_x_tags.files_id + WHERE files.id IS NULL); + + DELETE FROM tags WHERE id IN ( + SELECT tags.id FROM tags + LEFT JOIN files_x_tags ON files_x_tags.tags_id=tags.id + WHERE files_x_tags.files_id IS NULL); + + DELETE FROM tags_x_tagvals WHERE tags_id IN ( + SELECT tags_x_tagvals.tags_id FROM tags_x_tagvals + LEFT JOIN tags ON tags.id=tags_x_tagvals.tags_id + WHERE tags.id IS NULL); + + DELETE FROM tagvals WHERE id IN ( + SELECT tagvals.id FROM tagvals + LEFT JOIN tags_x_tagvals ON tags_x_tagvals.tagvals_id=tagvals.id + WHERE tags_x_tagvals.tagvals_id IS NULL); +EOT + print "SQL: $sql\n"; + my @sql=split(/\n\n/, $sql); + $self->cmd($_) for (@sql); +} + sub relation_exists { my ($self, $relname, $fields)=@_; @@ -640,3 +725,4 @@ CREATE TABLE tags_x_tagvals ( FOREIGN KEY(tags_id) REFERENCES tags(id) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY(tagvals_id) REFERENCES tagvals(id) ON DELETE CASCADE ON UPDATE CASCADE ); +