From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 4999521429 for ; Mon, 21 Jan 2019 20:52:57 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 16/37] solver: switch patch application to use a callback Date: Mon, 21 Jan 2019 20:52:32 +0000 Message-Id: <20190121205253.10455-17-e@80x24.org> In-Reply-To: <20190121205253.10455-1-e@80x24.org> References: <20190121205253.10455-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: A bit messy at the moment, but we need to break this up into smaller steps for fairness with other clients, as applying dozens of patches can take several hundred milliseconds. --- lib/PublicInbox/SolverGit.pm | 70 ++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/lib/PublicInbox/SolverGit.pm b/lib/PublicInbox/SolverGit.pm index 71494e0..70d8a93 100644 --- a/lib/PublicInbox/SolverGit.pm +++ b/lib/PublicInbox/SolverGit.pm @@ -290,16 +290,35 @@ sub di_url ($) { defined($url) ? "$url$mid/" : "<$mid>"; } -sub apply_patches ($$$$$) { - my ($self, $out, $wt, $found, $patches) = @_; +sub apply_patches_cb ($$$$$) { + my ($self, $out, $found, $patches, $oid_b) = @_; + my $wt = do_git_init_wt($self); my $wt_dir = $wt->dirname; my $wt_git = PublicInbox::Git->new("$wt_dir/.git"); $wt_git->{-wt} = $wt; my $cur = 0; my $tot = scalar @$patches; + my ($apply_pid, $rd, $di); + + # returns an empty string if in progress, undef if not found, + # or the final [ ::Git, oid_full, type, size, $di ] arrayref + # if found + sub { + if ($rd) { + $found->{$di->{oid_b}} = + do_apply_end($out, $wt_git, $rd, $di); + $rd = undef; + # continue to shift @$patches + } elsif ($apply_pid) { + $rd = do_apply_continue($wt_dir, $apply_pid); + $apply_pid = undef; + return ''; # $rd => do_apply_ned + } + + # may return undef here + $di = shift @$patches or return $found->{$oid_b}; - foreach my $di (@$patches) { my $i = ++$cur; my $oid_a = $di->{oid_a}; my $existing = $found->{$oid_a}; @@ -321,29 +340,10 @@ sub apply_patches ($$$$$) { join('', @{$di->{hdr_lines}}), "\n" or die "print \$out failed: $!"; - # apply the patch! - my $apply_pid = do_apply_begin($out, $wt_dir, $di); - my $rd = do_apply_continue($wt_dir, $apply_pid); - $found->{$di->{oid_b}} = do_apply_end($out, $wt_git, $rd, $di); - } -} - -sub dump_found ($$) { - my ($out, $found) = @_; - foreach my $oid (sort keys %$found) { - my ($git, $oid, undef, undef, $di) = @{$found->{$oid}}; - my $loc = $di ? di_url($di) : $git->src_blob_url($oid); - print $out "$oid from $loc\n"; - } -} - -sub dump_patches ($$) { - my ($out, $patches) = @_; - my $tot = scalar(@$patches); - my $i = 0; - foreach my $di (@$patches) { - ++$i; - print $out "[$i/$tot] ", di_url($di), "\n"; + # begin the patch application patch! + $apply_pid = do_apply_begin($out, $wt_dir, $di); + # next call to this callback will call do_apply_continue + ''; } } @@ -415,24 +415,16 @@ sub solve ($$$$) { unless (scalar(@$patches)) { print $out "no patch(es) for $oid_b\n"; - dump_found($out, $found); return; } # reconstruct the oid_b blob using patches we found: - eval { - my $wt = do_git_init_wt($self); - apply_patches($self, $out, $wt, $found, $patches); - }; - if ($@) { - print $out "E: $@\nfound: "; - dump_found($out, $found); - print $out "patches: "; - dump_patches($out, $patches); - return; + my $cb = apply_patches_cb($self, $out, $found, $patches, $oid_b); + my $ret; + while (1) { + $ret = $cb->(); + return $ret if (ref($ret) || !defined($ret)); } - - $found->{$oid_b}; } 1; -- EW