rt 4.0.23
[freeside.git] / rt / sbin / rt-fulltext-indexer.in
index 7e31cac..a55eb47 100644 (file)
@@ -3,7 +3,7 @@
 #
 # COPYRIGHT:
 #
-# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
 #                                          <sales@bestpractical.com>
 #
 # (Except where explicitly superseded by other copyright notices)
@@ -84,8 +84,9 @@ use RT::Interface::CLI ();
 my %OPT = (
     help        => 0,
     debug       => 0,
+    quiet       => 0,
 );
-my @OPT_LIST = qw(help|h! debug!);
+my @OPT_LIST = qw(help|h! debug! quiet);
 
 my $db_type = RT->Config->Get('DatabaseType');
 if ( $db_type eq 'Pg' ) {
@@ -122,6 +123,18 @@ if ( $OPT{'help'} ) {
     );
 }
 
+use Fcntl ':flock';
+if ( !flock main::DATA, LOCK_EX | LOCK_NB ) {
+    if ( $OPT{quiet} ) {
+        RT::Logger->info("$0 is already running; aborting silently, as requested");
+        exit;
+    }
+    else {
+        print STDERR "$0 is already running\n";
+        exit 1;
+    }
+}
+
 my $fts_config = RT->Config->Get('FullTextSearch') || {};
 unless ( $fts_config->{'Enable'} ) {
     print STDERR <<EOT;
@@ -217,6 +230,11 @@ sub attachments {
         VALUE => 'deleted'
     );
 
+    # On newer DBIx::SearchBuilder's, indicate that making the query DISTINCT
+    # is unnecessary because the joins won't produce duplicates.  This
+    # drastically improves performance when fetching attachments.
+    $res->{joins_are_distinct} = 1;
+
     return goto_specific(
         suffix => $type,
         error => "Don't know how to find $type attachments",
@@ -369,11 +387,18 @@ sub process_pg {
 
     my $status = eval { $dbh->do( $query, undef, $$text, $attachment->id ) };
     unless ( $status ) {
-        if ($dbh->errstr =~ /string is too long for tsvector/) {
-            warn "Attachment @{[$attachment->id]} not indexed, as it contains too many unique words to be indexed";
+        if ( $dbh->err == 7  && $dbh->state eq '54000' ) {
+            warn "Attachment @{[$attachment->id]} cannot be indexed. Most probably it contains too many unique words. Error: ". $dbh->errstr;
+        } elsif ( $dbh->err == 7 && $dbh->state eq '22021' ) {
+            warn "Attachment @{[$attachment->id]} cannot be indexed. Most probably it contains invalid UTF8 bytes. Error: ". $dbh->errstr;
         } else {
             die "error: ". $dbh->errstr;
         }
+
+        # Insert an empty tsvector, so we count this row as "indexed"
+        # for purposes of knowing where to pick up
+        eval { $dbh->do( $query, undef, "", $attachment->id ) }
+            or die "Failed to insert empty tsvector: " . $dbh->errstr;
     }
 }
 
@@ -410,7 +435,10 @@ sub extract_html {
     my $attachment = shift;
     my $text = $attachment->Content;
     return undef unless defined $text && length($text);
-# TODO: html -> text
+# the rich text editor generates html entities for characters
+# but Pg doesn't index them, so decode to something it can index.
+    require HTML::Entities;
+    HTML::Entities::decode_entities($text);
     return \$text;
 }
 
@@ -451,3 +479,4 @@ Alex Vandiver E<lt>alexmv@bestpractical.comE<gt>
 
 =cut
 
+__DATA__