]> git.donarmstrong.com Git - debbugs.git/blob - Debbugs/Estraier.pm
174ad4c6493306dd2e5f2b5acb11157ec27cf9f8
[debbugs.git] / Debbugs / Estraier.pm
1 # This module is part of debbugs, and is released
2 # under the terms of the GPL version 2, or any later
3 # version at your option.
4 # See the file README and COPYING for more information.
5 #
6 # Copyright 2007 by Don Armstrong <don@donarmstrong.com>.
7
8 package Debbugs::Estraier;
9
10 =head1 NAME
11
12 Debbugs::Estraier -- Routines for interfacing bugs to HyperEstraier
13
14 =head1 SYNOPSIS
15
16 use Debbugs::Estraier;
17
18
19 =head1 DESCRIPTION
20
21
22 =head1 BUGS
23
24 None known.
25
26 =cut
27
28 use warnings;
29 use strict;
30 use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
31 use Exporter qw(import);
32 use Debbugs::Log;
33 use Search::Estraier;
34 use Debbugs::Common qw(getbuglocation getbugcomponent make_list);
35 use Debbugs::Status qw(readbug);
36 use Debbugs::MIME qw(parse);
37 use Encode qw(encode_utf8);
38
39 BEGIN{
40      ($VERSION) = q$Revision: 1.3 $ =~ /^Revision:\s+([^\s+])/;
41      $DEBUG = 0 unless defined $DEBUG;
42
43      @EXPORT = ();
44      %EXPORT_TAGS = (add    => [qw(add_bug_log add_bug_message)],
45                     );
46      @EXPORT_OK = ();
47      Exporter::export_ok_tags(qw(add));
48      $EXPORT_TAGS{all} = [@EXPORT_OK];
49 }
50
51
52 sub add_bug_log{
53      my ($est,$bug_num) = @_;
54
55      # We want to read the entire bug log, pulling out individual
56      # messages, and shooting them through hyper estraier
57
58      my $location = getbuglocation($bug_num,'log');
59      my $bug_log = getbugcomponent($bug_num,'log',$location);
60      my $log_fh = new IO::File $bug_log, 'r' or
61           die "Unable to open bug log $bug_log for reading: $!";
62
63      my $log = Debbugs::Log->new($log_fh) or
64           die "Debbugs::Log was unable to be initialized";
65
66      my %seen_msg_ids;
67      my $msg_num=0;
68      my $status = {};
69      if (my $location = getbuglocation($bug_num,'summary')) {
70           $status = readbug($bug_num,$location);
71      }
72      while (my $record = $log->read_record()) {
73           $msg_num++;
74           next unless $record->{type} eq 'incoming-recv';
75           my ($msg_id) = $record->{text} =~ /^Message-Id:\s+<(.+)>/im;
76           next if defined $msg_id and exists $seen_msg_ids{$msg_id};
77           $seen_msg_ids{$msg_id} = 1 if defined $msg_id;
78           next if defined $msg_id and $msg_id =~ /handler\..+\.ack(?:info)?\@/;
79           add_bug_message($est,$record->{text},$bug_num,$msg_num,$status)
80      }
81      return $msg_num;
82 }
83
84 =head2 remove_old_message
85
86      remove_old_message($est,300000,50);
87
88 Removes all messages which are no longer in the log
89
90 =cut
91
92 sub remove_old_messages{
93      my ($est,$bug_num,$max_message) = @_;
94      # remove records which are no longer present in the log (uri > $msg_num)
95      my $cond = new Search::Estraier::Condition;
96      $cond->add_attr('@uri STRBW '.$bug_num.'/');
97      $cond->set_max(50);
98      my $nres;
99      while ($nres = $est->search($cond,0) and $nres->doc_num > 0){
100           for my $rdoc (map {$nres->get_doc($_)} 0..($nres->doc_num-1)) {
101                my $uri = $rdoc->uri;
102                my ($this_message) = $uri =~ m{/(\d+)$};
103                next unless $this_message > $max_message;
104                $est->out_doc_by_uri($uri);
105           }
106           last unless $nres->doc_num >= $cond->max;
107           $cond->set_skip($cond->skip+$cond->max);
108      }
109
110 }
111
112 sub add_bug_message{
113      my ($est,$bug_message,$bug_num,
114          $msg_num,$status) = @_;
115
116      my $doc;
117      my $uri = "$bug_num/$msg_num";
118      $doc = $est->get_doc_by_uri($uri);
119      $doc = new Search::Estraier::Document if not defined $doc;
120
121      my $message = parse($bug_message);
122      $doc->add_text(encode_utf8(join("\n",make_list(values %{$message}))));
123
124      # * @id : the ID number determined automatically when the document is registered.
125      # * @uri : the location of a document which any document should have.
126      # * @digest : the message digest calculated automatically when the document is registered.
127      # * @cdate : the creation date.
128      # * @mdate : the last modification date.
129      # * @adate : the last access date.
130      # * @title : the title used as a headline in the search result.
131      # * @author : the author.
132      # * @type : the media type.
133      # * @lang : the language.
134      # * @genre : the genre.
135      # * @size : the size.
136      # * @weight : the scoring weight.
137      # * @misc : miscellaneous information.
138      my @attr = qw(status subject date submitter package tags severity);
139      # parse the date
140      my ($date) = $bug_message =~ /^Date:\s+(.+?)\s*$/mi;
141      $doc->add_attr('@cdate' => encode_utf8($date)) if defined $date;
142      # parse the title
143      my ($subject) = $bug_message =~ /^Subject:\s+(.+?)\s*$/mi;
144      $doc->add_attr('@title' => encode_utf8($subject)) if defined $subject;
145      # parse the author
146      my ($author) = $bug_message =~ /^From:\s+(.+?)\s*$/mi;
147      $doc->add_attr('@author' => encode_utf8($author)) if defined $author;
148      # create the uri
149      $doc->add_attr('@uri' => encode_utf8($uri));
150      foreach my $attr (@attr) {
151           $doc->add_attr($attr => encode_utf8($status->{$attr})) if defined $status->{$attr};
152      }
153      print STDERR "adding $uri\n" if $DEBUG;
154      # Try a bit harder if estraier is returning timeouts
155      my $attempt = 5;
156      while ($attempt > 0) {
157           $est->put_doc($doc) and last;
158           my $status = $est->status;
159           $attempt--;
160           print STDERR "Failed to add $uri\n".$status."\n";
161           last unless $status =~ /^5/;
162           sleep 20;
163      }
164
165 }
166
167
168 1;
169
170
171 __END__
172
173
174
175
176
177