+sub _lms_rw ($) { # it is important to have eidx processes open before lms
+ my ($self) = @_;
+ my ($eidx, $tl) = eidx_init($self);
+ $self->{lms} //= do {
+ require PublicInbox::LeiMailSync;
+ my $f = "$self->{priv_eidx}->{topdir}/mail_sync.sqlite3";
+ my $lms = PublicInbox::LeiMailSync->new($f);
+ $lms->lms_write_prepare;
+ $lms;
+ };
+}
+
+sub set_sync_info {
+ my ($self, $oidhex, $folder, $id) = @_;
+ _lms_rw($self)->set_src(pack('H*', $oidhex), $folder, $id);
+}
+
+sub _remove_if_local { # git->cat_async arg
+ my ($bref, $oidhex, $type, $size, $self) = @_;
+ $self->{im}->remove($bref) if $bref;
+}
+
+sub remove_docids ($;@) {
+ my ($self, @docids) = @_;
+ my $eidx = eidx_init($self);
+ for my $docid (@docids) {
+ $eidx->remove_doc($docid);
+ $eidx->{oidx}->{dbh}->do(<<EOF, undef, $docid);
+DELETE FROM xref3 WHERE docid = ?
+EOF
+ }
+}
+
+# remove the entire message from the index, does not touch mail_sync.sqlite3
+sub remove_eml {
+ my ($self, $eml) = @_;
+ my $im = $self->importer; # may create new epoch
+ my ($eidx, $tl) = eidx_init($self);
+ my $oidx = $eidx->{oidx};
+ my @docids = _docids_for($self, $eml);
+ my $git = $eidx->git;
+ for my $docid (@docids) {
+ my $xr3 = $oidx->get_xref3($docid, 1);
+ for my $row (@$xr3) {
+ my (undef, undef, $oidbin) = @$row;
+ my $oidhex = unpack('H*', $oidbin);
+ $git->cat_async($oidhex, \&_remove_if_local, $self);
+ }
+ }
+ $git->async_wait_all;
+ remove_docids($self, @docids);
+ \@docids;
+}
+
+sub oid2docid ($$) {
+ my ($self, $oid) = @_;
+ my $eidx = eidx_init($self);
+ my ($docid, @cull) = $eidx->{oidx}->blob_exists($oid);
+ if (@cull) { # fixup old bugs...
+ warn <<EOF;
+W: $oid indexed as multiple docids: $docid @cull, culling to fixup old bugs
+EOF
+ remove_docids($self, @cull);
+ }
+ $docid;
+}
+
+sub _add_vmd ($$$$) {
+ my ($self, $idx, $docid, $vmd) = @_;
+ $idx->ipc_do('add_vmd', $docid, $vmd);
+ sto_export_kw($self, $docid, $vmd);
+}
+
+sub _docids_and_maybe_kw ($$) {
+ my ($self, $docids) = @_;
+ return $docids unless wantarray;
+ my $kw = {};
+ for my $num (@$docids) { # likely only 1, unless ContentHash changes
+ # can't use ->search->msg_keywords on uncommitted docs
+ my $idx = $self->{priv_eidx}->idx_shard($num);
+ my $tmp = eval { $idx->ipc_do('get_terms', 'K', $num) };
+ if ($@) { warn "#$num get_terms: $@" }
+ else { @$kw{keys %$tmp} = values(%$tmp) };
+ }
+ ($docids, [ sort keys %$kw ]);
+}
+