]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/SearchIdx.pm
searchidx: use Perl truthiness to detect XAPIAN_FLUSH_THRESHOLD
[public-inbox.git] / lib / PublicInbox / SearchIdx.pm
index fe089c8e8fb867fa4938db03fea8d8ae1a71c675..01b9f52dff965a0c7f334867c2d9ad9e2fd6e4d6 100644 (file)
@@ -12,7 +12,7 @@ use v5.10.1;
 use parent qw(PublicInbox::Search PublicInbox::Lock Exporter);
 use PublicInbox::Eml;
 use PublicInbox::InboxWritable;
-use PublicInbox::MID qw(mid_mime mids_for_index mids);
+use PublicInbox::MID qw(mids_for_index mids);
 use PublicInbox::MsgIter;
 use PublicInbox::IdxStack;
 use Carp qw(croak);
@@ -21,12 +21,11 @@ use PublicInbox::OverIdx;
 use PublicInbox::Spawn qw(spawn);
 use PublicInbox::Git qw(git_unquote);
 use PublicInbox::MsgTime qw(msg_timestamp msg_datestamp);
-our @EXPORT_OK = qw(too_big crlf_adjust log2stack is_ancestor);
+our @EXPORT_OK = qw(crlf_adjust log2stack is_ancestor check_size nodatacow_dir);
 my $X = \%PublicInbox::Search::X;
 my ($DB_CREATE_OR_OPEN, $DB_OPEN);
 our $DB_NO_SYNC = 0;
-our $BATCH_BYTES = defined($ENV{XAPIAN_FLUSH_THRESHOLD}) ?
-                       0x7fffffff : 1_000_000;
+our $BATCH_BYTES = $ENV{XAPIAN_FLUSH_THRESHOLD} ? 0x7fffffff : 1_000_000;
 use constant DEBUG => !!$ENV{DEBUG};
 
 my $xapianlevels = qr/\A(?:full|medium)\z/;
@@ -67,7 +66,7 @@ sub new {
                $self->{lock_path} = "$inboxdir/ssoma.lock";
                my $dir = $self->xdir;
                $self->{over} = PublicInbox::OverIdx->new("$dir/over.sqlite3");
-               $self->{over}->{-no_sync} = 1 if $ibx->{-no_sync};
+               $self->{over}->{-no_fsync} = 1 if $ibx->{-no_fsync};
                $self->{index_max_size} = $ibx->{index_max_size};
        } elsif ($version == 2) {
                defined $shard or die "shard is required for v2\n";
@@ -110,6 +109,12 @@ sub load_xapian_writable () {
        1;
 }
 
+sub nodatacow_dir ($) {
+       my ($dir) = @_;
+       opendir my $dh, $dir or die "opendir($dir): $!\n";
+       PublicInbox::Spawn::set_nodatacow(fileno($dh));
+}
+
 sub idx_acquire {
        my ($self) = @_;
        my $flag;
@@ -125,12 +130,14 @@ sub idx_acquire {
 
                # don't create empty Xapian directories if we don't need Xapian
                my $is_shard = defined($self->{shard});
-               if (!$is_shard || ($is_shard && need_xapian($self))) {
+               if (!-d $dir && (!$is_shard ||
+                               ($is_shard && need_xapian($self)))) {
                        File::Path::mkpath($dir);
+                       nodatacow_dir($dir);
                }
        }
        return unless defined $flag;
-       $flag |= $DB_NO_SYNC if $self->{ibx}->{-no_sync};
+       $flag |= $DB_NO_SYNC if $self->{ibx}->{-no_fsync};
        my $xdb = eval { ($X->{WritableDatabase})->new($dir, $flag) };
        if ($@) {
                die "Failed opening $dir: ", $@;
@@ -342,8 +349,7 @@ sub index_ids ($$$$) {
 }
 
 sub add_xapian ($$$$) {
-       my ($self, $mime, $smsg, $mids) = @_;
-       my $hdr = $mime->header_obj;
+       my ($self, $eml, $smsg, $mids) = @_;
        my $doc = $X->{Document}->new;
        add_val($doc, PublicInbox::Search::TS(), $smsg->{ts});
        my @ds = gmtime($smsg->{ds});
@@ -358,10 +364,10 @@ sub add_xapian ($$$$) {
        $tg->set_document($doc);
        index_headers($self, $smsg);
 
-       msg_iter($mime, \&index_xapian, [ $self, $doc ]);
-       index_ids($self, $doc, $hdr, $mids);
+       msg_iter($eml, \&index_xapian, [ $self, $doc ]);
+       index_ids($self, $doc, $eml, $mids);
        $smsg->{to} = $smsg->{cc} = ''; # WWW doesn't need these, only NNTP
-       PublicInbox::OverIdx::parse_references($smsg, $hdr, $mids);
+       PublicInbox::OverIdx::parse_references($smsg, $eml, $mids);
        my $data = $smsg->to_doc_data;
        $doc->set_data($data);
        if (my $altid = $self->{-altid}) {
@@ -382,7 +388,7 @@ sub _msgmap_init ($) {
        die "BUG: _msgmap_init is only for v1\n" if $self->{ibx_ver} != 1;
        $self->{mm} //= eval {
                require PublicInbox::Msgmap;
-               my $rw = $self->{ibx}->{-no_sync} ? 2 : 1;
+               my $rw = $self->{ibx}->{-no_fsync} ? 2 : 1;
                PublicInbox::Msgmap->new($self->{ibx}->{inboxdir}, $rw);
        };
 }
@@ -390,8 +396,7 @@ sub _msgmap_init ($) {
 sub add_message {
        # mime = PublicInbox::Eml or Email::MIME object
        my ($self, $mime, $smsg, $sync) = @_;
-       my $hdr = $mime->header_obj;
-       my $mids = mids_for_index($hdr);
+       my $mids = mids_for_index($mime);
        $smsg //= bless { blob => '' }, 'PublicInbox::Smsg'; # test-only compat
        $smsg->{mid} //= $mids->[0]; # v1 compatibility
        $smsg->{num} //= do { # v1
@@ -400,7 +405,7 @@ sub add_message {
        };
 
        # v1 and tests only:
-       $smsg->populate($hdr, $sync);
+       $smsg->populate($mime, $sync);
        $smsg->{bytes} //= length($mime->as_string);
 
        eval {
@@ -484,6 +489,11 @@ sub unindex_eml {
        while (my ($num, $nr) = each %tmp) {
                warn "BUG: $num appears >1 times ($nr) for $oid\n" if $nr != 1;
        }
+       if ($nr) {
+               $self->{mm}->num_delete($_) for (keys %tmp);
+       } else { # just in case msgmap and over.sqlite3 become desynched:
+               $self->{mm}->mid_delete($mids->[0]);
+       }
        xdb_remove($self, $oid, keys %tmp) if need_xapian($self);
 }
 
@@ -504,11 +514,6 @@ sub index_mm {
        }
 }
 
-sub unindex_mm {
-       my ($self, $mime) = @_;
-       $self->{mm}->mid_delete(mid_mime($mime));
-}
-
 # returns the number of bytes to add if given a non-CRLF arg
 sub crlf_adjust ($) {
        if (index($_[0], "\r\n") < 0) {
@@ -536,9 +541,7 @@ sub index_both { # git->cat_async callback
 
 sub unindex_both { # git->cat_async callback
        my ($bref, $oid, $type, $size, $self) = @_;
-       my $eml = PublicInbox::Eml->new($bref);
-       unindex_eml($self, $oid, $eml);
-       unindex_mm($self, $eml);
+       unindex_eml($self, $oid, PublicInbox::Eml->new($bref));
 }
 
 # called by public-inbox-index
@@ -553,21 +556,11 @@ sub index_sync {
        }
 }
 
-sub too_big ($$) {
-       my ($self, $oid) = @_;
-       my $max_size = $self->{index_max_size} or return;
-       my (undef, undef, $size) = $self->{ibx}->git->check($oid);
-       die "E: bad $oid in $self->{ibx}->{inboxdir}\n" if !defined($size);
-       return if $size <= $max_size;
-       warn "W: skipping $oid ($size > $max_size)\n";
-       1;
-}
-
-sub ck_size { # check_async cb for -index --max-size=...
+sub check_size { # check_async cb for -index --max-size=...
        my ($oid, $type, $size, $arg, $git) = @_;
        (($type // '') eq 'blob') or die "E: bad $oid in $git->{git_dir}";
        if ($size <= $arg->{index_max_size}) {
-               $git->cat_async($oid, \&index_both, $arg);
+               $git->cat_async($oid, $arg->{index_oid}, $arg);
        } else {
                warn "W: skipping $oid ($size > $arg->{index_max_size})\n";
        }
@@ -630,12 +623,14 @@ sub process_stack {
                        $git->cat_async($oid, \&unindex_both, $self);
                }
        }
-       $sync->{index_max_size} = $self->{ibx}->{index_max_size};
+       if ($sync->{index_max_size} = $self->{ibx}->{index_max_size}) {
+               $sync->{index_oid} = \&index_both;
+       }
        while (my ($f, $at, $ct, $oid) = $stk->pop_rec) {
                if ($f eq 'm') {
                        my $arg = { %$sync, autime => $at, cotime => $ct };
                        if ($sync->{index_max_size}) {
-                               $git->check_async($oid, \&ck_size, $arg);
+                               $git->check_async($oid, \&check_size, $arg);
                        } else {
                                $git->cat_async($oid, \&index_both, $arg);
                        }