Merge branch 'master' of https://github.com/jgoodman/Freeside
[freeside.git] / rt / lib / RT / Shredder.pm
index 5e1e86e..125ed0d 100644 (file)
@@ -1,40 +1,40 @@
 # 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-2014 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
@@ -43,7 +43,7 @@
 # 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;
@@ -52,6 +52,7 @@ use strict;
 use warnings;
 
 
+
 =head1 NAME
 
 RT::Shredder - Permanently wipeout data from RT
@@ -61,8 +62,7 @@ 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
 
@@ -138,29 +138,47 @@ shredding session when the file had been created.
 
 =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.
 
-Defaults to F</path-to-RT-var-dir/data/RT-Shredder>.
+    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);
 
-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 UNIQUE INDEX SHREDDER_GM1 ON GroupMembers(MemberId, GroupId);
 
+    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)
 
 =head1 INFORMATION FOR DEVELOPERS
 
@@ -176,7 +194,7 @@ example from L</SYNOPSIS>:
 
   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' );
@@ -202,7 +220,6 @@ BEGIN {
 # 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;
 
@@ -349,10 +366,12 @@ sub CastObjectsToRecords
     } 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 ) {
@@ -535,9 +554,9 @@ sub WipeoutAll
 {
     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'} );
     }
 }
 
@@ -553,10 +572,11 @@ sub Wipeout
         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";
     }
 }
 
@@ -715,7 +735,7 @@ sub GetFileName
 =head4 StoragePath
 
 Returns an absolute path to the storage dir.  See
-L<CONFIGURATION/$ShredderStoragePath>.
+L</$ShredderStoragePath>.
 
 See also description of the L</GetFileName> method.