+ return unless scalar(keys(%$xoids));
+
+ # see if it was indexed, but with different OID(s)
+ if (my @docids = _docids_for($self, $eml)) {
+ for my $docid (@docids) {
+ next if $seen{$docid};
+ for my $oid (keys %$xoids) {
+ $oidx->add_xref3($docid, -1, $oid, '.');
+ }
+ my $idx = $eidx->idx_shard($docid);
+ $idx->ipc_do('update_vmd', $docid, $vmd_mod);
+ }
+ return;
+ }
+ # totally unseen
+ my ($smsg, $idx) = _external_only($self, $xoids, $eml);
+ $idx->ipc_do('update_vmd', $smsg->{num}, $vmd_mod);
+}
+
+# set or update keywords for external message, called via ipc_do
+sub set_xvmd {
+ my ($self, $xoids, $eml, $vmd) = @_;
+
+ my ($eidx, $tl) = eidx_init($self);
+ my $oidx = $eidx->{oidx};
+ my %seen;
+
+ # see if we can just update existing docs
+ for my $oid (keys %$xoids) {
+ my @docids = $oidx->blob_exists($oid) or next;
+ scalar(@docids) > 1 and
+ warn "W: $oid indexed as multiple docids: @docids\n";
+ for my $docid (@docids) {
+ next if $seen{$docid}++;
+ my $idx = $eidx->idx_shard($docid);
+ $idx->ipc_do('set_vmd', $docid, $vmd);
+ }
+ delete $xoids->{$oid}; # all done with this oid
+ }
+ return unless scalar(keys(%$xoids));
+
+ # n.b. we don't do _docids_for here, we expect the caller
+ # already checked $lse->kw_changed before calling this sub
+
+ return unless (@{$vmd->{kw} // []}) || (@{$vmd->{L} // []});
+ # totally unseen:
+ my ($smsg, $idx) = _external_only($self, $xoids, $eml);
+ $idx->ipc_do('add_vmd', $smsg->{num}, $vmd);
+}
+
+sub checkpoint {
+ my ($self, $wait) = @_;
+ if (my $im = $self->{im}) {
+ $wait ? $im->barrier : $im->checkpoint;
+ }
+ $self->{priv_eidx}->checkpoint($wait);
+}
+
+sub xchg_stderr {
+ my ($self) = @_;
+ _tail_err($self) if $self->{-err_wr};
+ my $dir = $self->{priv_eidx}->{topdir};
+ return unless -e $dir;
+ my $old = delete $self->{-tmp_err};
+ my $pfx = POSIX::strftime('%Y%m%d%H%M%S', gmtime(time));
+ my $err = File::Temp->new(TEMPLATE => "$pfx.$$.lei_storeXXXX",
+ SUFFIX => '.err', DIR => $dir);
+ open STDERR, '>>', $err->filename or die "dup2: $!";
+ STDERR->autoflush(1); # shared with shard subprocesses
+ $self->{-tmp_err} = $err; # separate file description for RO access
+ undef;