From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 03/30] qspawn: remove some anonymous subs for psgi_qx
Date: Wed, 25 Dec 2019 07:50:37 +0000 [thread overview]
Message-ID: <20191225075104.22184-4-e@80x24.org> (raw)
In-Reply-To: <20191225075104.22184-1-e@80x24.org>
By passing a user-supplied arg to $qx_cb, we can eliminate the
callers' need to capture on-stack variables with a closure.
This saves several kilobytes of memory allocation at the expense
of some extra hash table lookups in user-supplied callbacks. It
also reduces the risk of memory leaks by eliminating a common
source of circular references.
---
lib/PublicInbox/Qspawn.pm | 4 +-
lib/PublicInbox/SolverGit.pm | 88 ++++++++++++++++++++----------------
lib/PublicInbox/ViewVCS.pm | 33 ++++++++------
3 files changed, 71 insertions(+), 54 deletions(-)
diff --git a/lib/PublicInbox/Qspawn.pm b/lib/PublicInbox/Qspawn.pm
index c2856609..22603ca7 100644
--- a/lib/PublicInbox/Qspawn.pm
+++ b/lib/PublicInbox/Qspawn.pm
@@ -155,13 +155,13 @@ sub start {
# $env is the PSGI env. As with ``/qx; only use this when output is small
# and safe to slurp.
sub psgi_qx {
- my ($self, $env, $limiter, $qx_cb) = @_;
+ my ($self, $env, $limiter, $qx_cb, $cb_arg) = @_;
my $scalar = '';
open(my $qx, '+>', \$scalar) or die; # PerlIO::scalar
my $end = sub {
my $err = $_[0]; # $!
log_err($env, "psgi_qx: $err") if defined($err);
- finish($self, $env, sub { $qx_cb->(\$scalar) });
+ finish($self, $env, sub { $qx_cb->(\$scalar, $cb_arg) });
$qx = undef;
};
my $rpipe; # comes from popen_rd
diff --git a/lib/PublicInbox/SolverGit.pm b/lib/PublicInbox/SolverGit.pm
index d59320bc..f81f69ca 100644
--- a/lib/PublicInbox/SolverGit.pm
+++ b/lib/PublicInbox/SolverGit.pm
@@ -221,6 +221,16 @@ sub find_extract_diffs ($$$) {
@di ? \@di : undef;
}
+sub update_index_result ($$) {
+ my ($bref, $self) = @_;
+ my ($qsp, $msg) = delete @$self{qw(-qsp -msg)};
+ if (my $err = $qsp->{err}) {
+ ERR($self, "git update-index error: $err");
+ }
+ dbg($self, $msg);
+ next_step($self); # onto do_git_apply
+}
+
sub prepare_index ($) {
my ($self) = @_;
my $patches = $self->{patches};
@@ -248,15 +258,10 @@ sub prepare_index ($) {
my $rdr = { 0 => fileno($in), -hold => $in };
my $cmd = [ qw(git update-index -z --index-info) ];
my $qsp = PublicInbox::Qspawn->new($cmd, $self->{git_env}, $rdr);
- $qsp->psgi_qx($self->{psgi_env}, undef, sub {
- my ($bref) = @_;
- if (my $err = $qsp->{err}) {
- ERR($self, "git update-index error: $err");
- }
- dbg($self, "index prepared:\n" .
- "$mode_a $oid_full\t" . git_quote($path_a));
- next_step($self); # onto do_git_apply
- });
+ $path_a = git_quote($path_a);
+ $self->{-qsp} = $qsp;
+ $self->{-msg} = "index prepared:\n$mode_a $oid_full\t$path_a";
+ $qsp->psgi_qx($self->{psgi_env}, undef, \&update_index_result, $self);
}
# pure Perl "git init"
@@ -383,8 +388,9 @@ sub mark_found ($$$) {
}
}
-sub parse_ls_files ($$$$) {
- my ($self, $qsp, $bref, $di) = @_;
+sub parse_ls_files ($$) {
+ my ($self, $bref) = @_;
+ my ($qsp, $di) = delete @$self{qw(-qsp -cur_di)};
if (my $err = $qsp->{err}) {
die "git ls-files error: $err";
}
@@ -410,15 +416,10 @@ sub parse_ls_files ($$$$) {
next_step($self); # onto the next patch
}
-sub start_ls_files ($$) {
- my ($self, $di) = @_;
- my $cmd = [qw(git ls-files -s -z)];
- my $qsp = PublicInbox::Qspawn->new($cmd, $self->{git_env});
- $qsp->psgi_qx($self->{psgi_env}, undef, sub {
- my ($bref) = @_;
- eval { parse_ls_files($self, $qsp, $bref, $di) };
- ERR($self, $@) if $@;
- });
+sub ls_files_result {
+ my ($bref, $self) = @_;
+ eval { parse_ls_files($self, $bref) };
+ ERR($self, $@) if $@;
}
sub oids_same_ish ($$) {
@@ -438,6 +439,31 @@ sub skip_identical ($$$) {
}
}
+sub apply_result ($$) {
+ my ($bref, $self) = @_;
+ my ($qsp, $di) = delete @$self{qw(-qsp -cur_di)};
+ dbg($self, $$bref);
+ my $patches = $self->{patches};
+ if (my $err = $qsp->{err}) {
+ my $msg = "git apply error: $err";
+ my $nxt = $patches->[0];
+ if ($nxt && oids_same_ish($nxt->{oid_b}, $di->{oid_b})) {
+ dbg($self, $msg);
+ dbg($self, 'trying '.di_url($self, $nxt));
+ } else {
+ ERR($self, $msg);
+ }
+ } else {
+ skip_identical($self, $patches, $di->{oid_b});
+ }
+
+ my @cmd = qw(git ls-files -s -z);
+ $qsp = PublicInbox::Qspawn->new(\@cmd, $self->{git_env});
+ $self->{-cur_di} = $di;
+ $self->{-qsp} = $qsp;
+ $qsp->psgi_qx($self->{psgi_env}, undef, \&ls_files_result, $self);
+}
+
sub do_git_apply ($) {
my ($self) = @_;
my $dn = $self->{tmp}->dirname;
@@ -465,24 +491,9 @@ sub do_git_apply ($) {
my $rdr = { 2 => 1 };
my $qsp = PublicInbox::Qspawn->new(\@cmd, $self->{git_env}, $rdr);
- $qsp->psgi_qx($self->{psgi_env}, undef, sub {
- my ($bref) = @_;
- dbg($self, $$bref);
- if (my $err = $qsp->{err}) {
- my $msg = "git apply error: $err";
- my $nxt = $patches->[0];
- if ($nxt && oids_same_ish($nxt->{oid_b}, $prv_oid_b)) {
- dbg($self, $msg);
- dbg($self, 'trying '.di_url($self, $nxt));
- } else {
- ERR($self, $msg);
- }
- } else {
- skip_identical($self, $patches, $di->{oid_b});
- }
- eval { start_ls_files($self, $di) };
- ERR($self, $@) if $@;
- });
+ $self->{-cur_di} = $di;
+ $self->{-qsp} = $qsp;
+ $qsp->psgi_qx($self->{psgi_env}, undef, \&apply_result, $self);
}
sub di_url ($$) {
@@ -564,6 +575,7 @@ sub new {
bless {
gits => $ibx->{-repo_objs},
user_cb => $user_cb,
+ # -cur_di, -qsp, -msg => temporary fields for Qspawn callbacks
# TODO: config option for searching related inboxes
inboxes => [ $ibx ],
diff --git a/lib/PublicInbox/ViewVCS.pm b/lib/PublicInbox/ViewVCS.pm
index 842c873c..886e10cb 100644
--- a/lib/PublicInbox/ViewVCS.pm
+++ b/lib/PublicInbox/ViewVCS.pm
@@ -73,6 +73,22 @@ sub stream_large_blob ($$$$) {
});
}
+sub show_other_result ($$) {
+ my ($bref, $ctx) = @_;
+ my ($qsp, $logref) = delete @$ctx{qw(-qsp -logref)};
+ if (my $err = $qsp->{err}) {
+ utf8::decode($$err);
+ $$logref .= "git show error: $err";
+ return html_page($ctx, 500, $logref);
+ }
+ my $l = PublicInbox::Linkify->new;
+ utf8::decode($$bref);
+ $l->linkify_1($$bref);
+ $$bref = '<pre>'. $l->linkify_2(ascii_html($$bref));
+ $$bref .= '</pre><hr>' . $$logref;
+ html_page($ctx, 200, $bref);
+}
+
sub show_other ($$$$) {
my ($ctx, $res, $logref, $fn) = @_;
my ($git, $oid, $type, $size) = @$res;
@@ -84,20 +100,9 @@ sub show_other ($$$$) {
qw(show --encoding=UTF-8 --no-color --no-abbrev), $oid ];
my $qsp = PublicInbox::Qspawn->new($cmd);
my $env = $ctx->{env};
- $qsp->psgi_qx($env, undef, sub {
- my ($bref) = @_;
- if (my $err = $qsp->{err}) {
- utf8::decode($$err);
- $$logref .= "git show error: $err";
- return html_page($ctx, 500, $logref);
- }
- my $l = PublicInbox::Linkify->new;
- utf8::decode($$bref);
- $l->linkify_1($$bref);
- $$bref = '<pre>'. $l->linkify_2(ascii_html($$bref));
- $$bref .= '</pre><hr>' . $$logref;
- html_page($ctx, 200, $bref);
- });
+ $ctx->{-qsp} = $qsp;
+ $ctx->{-logref} = $logref;
+ $qsp->psgi_qx($env, undef, \&show_other_result, $ctx);
}
sub solve_result {
next prev parent reply other threads:[~2019-12-25 7:51 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-25 7:50 [PATCH 00/30] www: eliminate most per-request closures Eric Wong
2019-12-25 7:50 ` [PATCH 01/30] git: allow async_cat to pass arg to callback Eric Wong
2019-12-25 7:50 ` [PATCH 02/30] httpd/async: support passing arg to callbacks Eric Wong
2019-12-26 7:53 ` Eric Wong
2019-12-25 7:50 ` Eric Wong [this message]
2019-12-25 7:50 ` [PATCH 04/30] qspawn: disambiguate command vs PSGI env Eric Wong
2019-12-25 7:50 ` [PATCH 05/30] qspawn: replace anonymous $end callbacks w/ event_step Eric Wong
2019-12-25 7:50 ` [PATCH 06/30] msg_iter: provide means to stop using anonymous subs Eric Wong
2019-12-25 7:50 ` [PATCH 07/30] qspawn: reduce local vars, de-anonymize rd_hdr Eric Wong
2019-12-25 7:50 ` [PATCH 08/30] httpd/async: get rid of ephemeral main_cb Eric Wong
2019-12-25 7:50 ` [PATCH 09/30] qspawn: psgi_return: initial cb can be named Eric Wong
2019-12-25 7:50 ` [PATCH 10/30] qspawn: psgi_return_start: hoist out from psgi_return Eric Wong
2019-12-25 7:50 ` [PATCH 11/30] qspawn: psgi_qx: eliminate anonymous subs Eric Wong
2019-12-25 7:50 ` [PATCH 12/30] qspawn: drop "qspawn.filter" support, for now Eric Wong
2019-12-25 7:50 ` [PATCH 13/30] qspawn: psgi_return: allow non-anon parse_hdr callback Eric Wong
2019-12-25 7:50 ` [PATCH 14/30] githttpbackend: split out wwwstatic Eric Wong
2019-12-26 12:50 ` Eric Wong
2019-12-27 10:36 ` Eric Wong
2019-12-25 7:50 ` [PATCH 15/30] www: lazy load Plack::Util Eric Wong
2019-12-25 7:50 ` [PATCH 16/30] mboxgz: pass $ctx to callback to avoid anon subs Eric Wong
2019-12-25 7:50 ` [PATCH 17/30] feed: avoid anonymous subs Eric Wong
2019-12-25 7:50 ` [PATCH 18/30] config: each_inbox: pass user arg to callback Eric Wong
2019-12-26 6:48 ` Eric Wong
2019-12-25 7:50 ` [PATCH 19/30] view: avoid anon sub in stream_thread Eric Wong
2019-12-25 7:50 ` [PATCH 20/30] view: msg_html: stop using an anonymous sub Eric Wong
2019-12-25 7:50 ` [PATCH 21/30] contentid: no " Eric Wong
2019-12-25 7:50 ` [PATCH 22/30] wwwtext: avoid anonymous sub in response Eric Wong
2019-12-25 7:50 ` [PATCH 23/30] searchview: pass named subs to Www*Stream Eric Wong
2019-12-25 7:50 ` [PATCH 24/30] view: thread_html: pass named sub to WwwStream Eric Wong
2019-12-25 7:50 ` [PATCH 25/30] searchview: remove anonymous sub when sorting threads by relevance Eric Wong
2019-12-25 7:51 ` [PATCH 26/30] view: msg_iter calls add_body_text directly Eric Wong
2019-12-25 7:51 ` [PATCH 27/30] wwwattach: avoid anonymous sub for msg_iter Eric Wong
2019-12-25 7:51 ` [PATCH 28/30] viewvcs: avoid anonymous sub for HTML response Eric Wong
2019-12-25 7:51 ` [PATCH 29/30] solvergit: allow passing arg to user-supplied callback Eric Wong
2019-12-28 9:17 ` Eric Wong
2019-12-25 7:51 ` [PATCH 30/30] search: retry_reopen passes user arg to callback Eric Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://public-inbox.org/README
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191225075104.22184-4-e@80x24.org \
--to=e@80x24.org \
--cc=meta@public-inbox.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/public-inbox.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).