From 915cd090798069a44dbb4b4c243bff9af2ae1b76 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 19 Jan 2019 05:25:30 +0000 Subject: [PATCH] solver: switch patch application to use a callback 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 71494e07..70d8a934 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; -- 2.44.0