# BEGIN BPS TAGGED BLOCK {{{
-#
+#
# COPYRIGHT:
-#
-# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
-# <jesse@bestpractical.com>
-#
+#
+# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
+# <sales@bestpractical.com>
+#
# (Except where explicitly superseded by other copyright notices)
-#
-#
+#
+#
# LICENSE:
-#
+#
# This work is made available to you under the terms of Version 2 of
# the GNU General Public License. A copy of that license should have
# been provided with this software, but in any event can be snarfed
# from www.gnu.org.
-#
+#
# This work is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 or visit their web page on the internet at
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
-#
-#
+#
+#
# CONTRIBUTION SUBMISSION POLICY:
-#
+#
# (The following paragraph is not intended to limit the rights granted
# to you to modify and distribute this software under the terms of
# the GNU General Public License and is only of importance to you if
# you choose to contribute your changes and enhancements to the
# community by submitting them to Best Practical Solutions, LLC.)
-#
+#
# By intentionally submitting any modifications, corrections or
# derivatives to this work, or any other work intended for use with
# Request Tracker, to Best Practical Solutions, LLC, you confirm that
# royalty-free, perpetual, license to use, copy, create derivative
# works based on those contributions, and sublicense and distribute
# those contributions and any derivatives thereof.
-#
+#
# END BPS TAGGED BLOCK }}}
package RT::Shredder;
use warnings;
+
=head1 NAME
RT::Shredder - Permanently wipeout data from RT
=head2 CLI
- rt-shredder --force --plugin 'Tickets=queue,general;status,deleted'
-
+ rt-shredder --force --plugin 'Tickets=query,Queue="General" and Status="deleted"'
=head1 DESCRIPTION
=head1 CONFIGURATION
-=head2 $RT::DependenciesLimit
+=head2 $DependenciesLimit
Shredder stops with an error if the object has more than
-C<$RT::DependenciesLimit> dependencies. For example: a ticket has 1000
+C<$DependenciesLimit> dependencies. For example: a ticket has 1000
transactions or a transaction has 1000 attachments. This is protection
from bugs in shredder from wiping out your whole database, but
sometimes when you have big mail loops you may hit it.
-Defaults to 1000.
+Defaults to 1000. To change this (for example, to 10000) add the
+following to your F<RT_SiteConfig.pm>:
-You can change the default value, in F<RT_SiteConfig.pm> add C<Set(
-$DependenciesLimit, new_limit );>
+ Set( $DependenciesLimit, 10_000 );>
=head2 $ShredderStoragePath
-Directory containing Shredder backup dumps.
+Directory containing Shredder backup dumps; defaults to
+F</opt/rt4/var/data/RT-Shredder> (assuming an /opt/rt4 installation).
+
+To change this (for example, to /some/backup/path) add the following to
+your F<RT_SiteConfig.pm>:
+
+ Set( $ShredderStoragePath, "/some/backup/path" );>
+
+Be sure to specify an absolute path.
+
+=head1 Database Indexes
+
+We have found that the following indexes significantly speed up
+shredding on most databases.
+
+ CREATE INDEX SHREDDER_CGM1 ON CachedGroupMembers(MemberId, GroupId, Disabled);
+ CREATE INDEX SHREDDER_CGM2 ON CachedGroupMembers(ImmediateParentId,MemberId);
+ CREATE INDEX SHREDDER_CGM3 on CachedGroupMembers (Via, Id);
-Defaults to F</path-to-RT-var-dir/data/RT-Shredder>.
+ CREATE UNIQUE INDEX SHREDDER_GM1 ON GroupMembers(MemberId, GroupId);
-You can change the default value, in F<RT_SiteConfig.pm> add C<Set(
-$ShredderStoragePath, new_path );> Be sure to use an absolute path.
+ CREATE INDEX SHREDDER_TXN1 ON Transactions(ReferenceType, OldReference);
+ CREATE INDEX SHREDDER_TXN2 ON Transactions(ReferenceType, NewReference);
+ CREATE INDEX SHREDDER_TXN3 ON Transactions(Type, OldValue);
+ CREATE INDEX SHREDDER_TXN4 ON Transactions(Type, NewValue);
+ CREATE INDEX SHREDDER_ATTACHMENTS1 ON Attachments(Creator);
=head1 INFORMATION FOR DEVELOPERS
use RT::Shredder;
RT::Shredder::Init( force => 1 );
- my $deleted = RT::Tickets->new( $RT::SystemUser );
+ my $deleted = RT::Tickets->new( RT->SystemUser );
$deleted->{'allow_deleted_search'} = 1;
$deleted->LimitQueue( VALUE => 'general' );
$deleted->LimitStatus( VALUE => 'deleted' );
# RT lib path
### after: push @INC, qw(@RT_LIB_PATH@);
- push @INC, qw(/opt/rt3/local/lib /opt/rt3/lib);
use RT::Shredder::Constants;
use RT::Shredder::Exceptions;
} elsif ( UNIVERSAL::isa( $targets, 'SCALAR' ) || !ref $targets ) {
$targets = $$targets if ref $targets;
my ($class, $id) = split /-/, $targets;
+ RT::Shredder::Exception->throw( "Unsupported class $class" )
+ unless $class =~ /^\w+(::\w+)*$/;
$class = 'RT::'. $class unless $class =~ /^RTx?::/i;
eval "require $class";
die "Couldn't load '$class' module" if $@;
- my $obj = $class->new( $RT::SystemUser );
+ my $obj = $class->new( RT->SystemUser );
die "Couldn't construct new '$class' object" unless $obj;
$obj->Load( $id );
unless ( $obj->id ) {
{
my $self = $_[0];
- while ( my ($k, $v) = each %{ $self->{'cache'} } ) {
- next if $v->{'State'} & (WIPED | IN_WIPING);
- $self->Wipeout( Object => $v->{'Object'} );
+ foreach my $cache_val ( values %{ $self->{'cache'} } ) {
+ next if $cache_val->{'State'} & (WIPED | IN_WIPING);
+ $self->Wipeout( Object => $cache_val->{'Object'} );
}
}
die "Couldn't commit transaction" unless $RT::Handle->Commit;
};
if( $@ ) {
+ my $error = $@;
$RT::Handle->Rollback('force');
$self->RollbackDumpTo( Mark => $mark ) if $mark;
- die $@ if RT::Shredder::Exception::Info->caught;
- die "Couldn't wipeout object: $@";
+ die $error if RT::Shredder::Exception::Info->caught;
+ die "Couldn't wipeout object: $error";
}
}
=head4 StoragePath
Returns an absolute path to the storage dir. See
-L<CONFIGURATION/$ShredderStoragePath>.
+L</$ShredderStoragePath>.
See also description of the L</GetFileName> method.