Filename | /usr/local/perls/perl-5.26.1/lib/5.26.1/CPAN/Queue.pm |
Statements | Executed 30 statements in 110µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 30µs | 30µs | delete_first | CPAN::Queue::
3 | 1 | 1 | 22µs | 22µs | nullify_queue | CPAN::Queue::
1 | 1 | 1 | 22µs | 37µs | queue_item | CPAN::Queue::
1 | 1 | 1 | 10µs | 10µs | new | CPAN::Queue::Item::
2 | 1 | 1 | 8µs | 8µs | first | CPAN::Queue::
1 | 1 | 1 | 5µs | 5µs | as_string | CPAN::Queue::Item::
1 | 1 | 1 | 5µs | 5µs | qpush | CPAN::Queue::
1 | 1 | 1 | 3µs | 3µs | reqtype | CPAN::Queue::Item::
1 | 1 | 1 | 2µs | 2µs | optional | CPAN::Queue::Item::
0 | 0 | 0 | 0s | 0s | BEGIN | CPAN::Queue::
0 | 0 | 0 | 0s | 0s | delete | CPAN::Queue::
0 | 0 | 0 | 0s | 0s | exists | CPAN::Queue::
0 | 0 | 0 | 0s | 0s | jumpqueue | CPAN::Queue::
0 | 0 | 0 | 0s | 0s | reqtype_of | CPAN::Queue::
0 | 0 | 0 | 0s | 0s | size | CPAN::Queue::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # -*- Mode: cperl; coding: utf-8; cperl-indent-level: 4 -*- | ||||
2 | use strict; | ||||
3 | package CPAN::Queue::Item; | ||||
4 | |||||
5 | # CPAN::Queue::Item::new ; | ||||
6 | # spent 10µs within CPAN::Queue::Item::new which was called:
# once (10µs+0s) by CPAN::Queue::queue_item at line 80 | ||||
7 | 1 | 2µs | my($class,@attr) = @_; | ||
8 | 1 | 4µs | my $self = bless { @attr }, $class; | ||
9 | 1 | 6µs | return $self; | ||
10 | } | ||||
11 | |||||
12 | # spent 5µs within CPAN::Queue::Item::as_string which was called:
# once (5µs+0s) by CPAN::Shell::rematein at line 1800 of CPAN/Shell.pm | ||||
13 | 1 | 1µs | my($self) = @_; | ||
14 | 1 | 5µs | $self->{qmod}; | ||
15 | } | ||||
16 | |||||
17 | # r => requires, b => build_requires, c => commandline | ||||
18 | # spent 3µs within CPAN::Queue::Item::reqtype which was called:
# once (3µs+0s) by CPAN::Shell::rematein at line 1801 of CPAN/Shell.pm | ||||
19 | 1 | 1µs | my($self) = @_; | ||
20 | 1 | 4µs | $self->{reqtype}; | ||
21 | } | ||||
22 | |||||
23 | # spent 2µs within CPAN::Queue::Item::optional which was called:
# once (2µs+0s) by CPAN::Shell::rematein at line 1802 of CPAN/Shell.pm | ||||
24 | 1 | 1µs | my($self) = @_; | ||
25 | 1 | 3µs | $self->{optional}; | ||
26 | } | ||||
27 | |||||
28 | package CPAN::Queue; | ||||
29 | |||||
30 | # One use of the queue is to determine if we should or shouldn't | ||||
31 | # announce the availability of a new CPAN module | ||||
32 | |||||
33 | # Now we try to use it for dependency tracking. For that to happen | ||||
34 | # we need to draw a dependency tree and do the leaves first. This can | ||||
35 | # easily be reached by running CPAN.pm recursively, but we don't want | ||||
36 | # to waste memory and run into deep recursion. So what we can do is | ||||
37 | # this: | ||||
38 | |||||
39 | # CPAN::Queue is the package where the queue is maintained. Dependencies | ||||
40 | # often have high priority and must be brought to the head of the queue, | ||||
41 | # possibly by jumping the queue if they are already there. My first code | ||||
42 | # attempt tried to be extremely correct. Whenever a module needed | ||||
43 | # immediate treatment, I either unshifted it to the front of the queue, | ||||
44 | # or, if it was already in the queue, I spliced and let it bypass the | ||||
45 | # others. This became a too correct model that made it impossible to put | ||||
46 | # an item more than once into the queue. Why would you need that? Well, | ||||
47 | # you need temporary duplicates as the manager of the queue is a loop | ||||
48 | # that | ||||
49 | # | ||||
50 | # (1) looks at the first item in the queue without shifting it off | ||||
51 | # | ||||
52 | # (2) cares for the item | ||||
53 | # | ||||
54 | # (3) removes the item from the queue, *even if its agenda failed and | ||||
55 | # even if the item isn't the first in the queue anymore* (that way | ||||
56 | # protecting against never ending queues) | ||||
57 | # | ||||
58 | # So if an item has prerequisites, the installation fails now, but we | ||||
59 | # want to retry later. That's easy if we have it twice in the queue. | ||||
60 | # | ||||
61 | # I also expect insane dependency situations where an item gets more | ||||
62 | # than two lives in the queue. Simplest example is triggered by 'install | ||||
63 | # Foo Foo Foo'. People make this kind of mistakes and I don't want to | ||||
64 | # get in the way. I wanted the queue manager to be a dumb servant, not | ||||
65 | # one that knows everything. | ||||
66 | # | ||||
67 | # Who would I tell in this model that the user wants to be asked before | ||||
68 | # processing? I can't attach that information to the module object, | ||||
69 | # because not modules are installed but distributions. So I'd have to | ||||
70 | # tell the distribution object that it should ask the user before | ||||
71 | # processing. Where would the question be triggered then? Most probably | ||||
72 | # in CPAN::Distribution::rematein. | ||||
73 | |||||
74 | use vars qw{ @All $VERSION }; | ||||
75 | $VERSION = "5.5002"; | ||||
76 | |||||
77 | # CPAN::Queue::queue_item ; | ||||
78 | # spent 37µs (22+15) within CPAN::Queue::queue_item which was called:
# once (22µs+15µs) by CPAN::Shell::rematein at line 1764 of CPAN/Shell.pm | ||||
79 | 1 | 6µs | my($class,@attr) = @_; | ||
80 | 1 | 8µs | 1 | 10µs | my $item = "$class\::Item"->new(@attr); # spent 10µs making 1 call to CPAN::Queue::Item::new |
81 | 1 | 3µs | 1 | 5µs | $class->qpush($item); # spent 5µs making 1 call to CPAN::Queue::qpush |
82 | 1 | 4µs | return 1; | ||
83 | } | ||||
84 | |||||
85 | # CPAN::Queue::qpush ; | ||||
86 | # spent 5µs within CPAN::Queue::qpush which was called:
# once (5µs+0s) by CPAN::Queue::queue_item at line 81 | ||||
87 | 1 | 1µs | my($class,$obj) = @_; | ||
88 | 1 | 1µs | push @All, $obj; | ||
89 | CPAN->debug(sprintf("in new All[%s]", | ||||
90 | 1 | 4µs | join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All), | ||
91 | )) if $CPAN::DEBUG; | ||||
92 | } | ||||
93 | |||||
94 | # CPAN::Queue::first ; | ||||
95 | # spent 8µs within CPAN::Queue::first which was called 2 times, avg 4µs/call:
# 2 times (8µs+0s) by CPAN::Shell::rematein at line 1798 of CPAN/Shell.pm, avg 4µs/call | ||||
96 | 2 | 1µs | my $obj = $All[0]; | ||
97 | 2 | 8µs | $obj; | ||
98 | } | ||||
99 | |||||
100 | # CPAN::Queue::delete_first ; | ||||
101 | # spent 30µs within CPAN::Queue::delete_first which was called:
# once (30µs+0s) by CPAN::Shell::rematein at line 1927 of CPAN/Shell.pm | ||||
102 | 1 | 1µs | my($class,$what) = @_; | ||
103 | 1 | 8µs | my $i; | ||
104 | 1 | 4µs | for my $i (0..$#All) { | ||
105 | 1 | 1µs | if ( $All[$i]->{qmod} eq $what ) { | ||
106 | 1 | 1µs | splice @All, $i, 1; | ||
107 | 1 | 1µs | last; | ||
108 | } | ||||
109 | } | ||||
110 | CPAN->debug(sprintf("after delete_first mod[%s] All[%s]", | ||||
111 | $what, | ||||
112 | 1 | 9µs | join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All) | ||
113 | )) if $CPAN::DEBUG; | ||||
114 | } | ||||
115 | |||||
116 | # CPAN::Queue::jumpqueue ; | ||||
117 | sub jumpqueue { | ||||
118 | my $class = shift; | ||||
119 | my @what = @_; | ||||
120 | CPAN->debug(sprintf("before jumpqueue All[%s] what[%s]", | ||||
121 | join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All), | ||||
122 | join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @what), | ||||
123 | )) if $CPAN::DEBUG; | ||||
124 | unless (defined $what[0]{reqtype}) { | ||||
125 | # apparently it was not the Shell that sent us this enquiry, | ||||
126 | # treat it as commandline | ||||
127 | $what[0]{reqtype} = "c"; | ||||
128 | } | ||||
129 | my $inherit_reqtype = $what[0]{reqtype} =~ /^(c|r)$/ ? "r" : "b"; | ||||
130 | WHAT: for my $what_tuple (@what) { | ||||
131 | my($qmod,$reqtype,$optional) = @$what_tuple{qw(qmod reqtype optional)}; | ||||
132 | if ($reqtype eq "r" | ||||
133 | && | ||||
134 | $inherit_reqtype eq "b" | ||||
135 | ) { | ||||
136 | $reqtype = "b"; | ||||
137 | } | ||||
138 | my $jumped = 0; | ||||
139 | for (my $i=0; $i<$#All;$i++) { #prevent deep recursion | ||||
140 | if ($All[$i]{qmod} eq $qmod) { | ||||
141 | $jumped++; | ||||
142 | } | ||||
143 | } | ||||
144 | # high jumped values are normal for popular modules when | ||||
145 | # dealing with large bundles: XML::Simple, | ||||
146 | # namespace::autoclean, UNIVERSAL::require | ||||
147 | CPAN->debug("qmod[$qmod]jumped[$jumped]") if $CPAN::DEBUG; | ||||
148 | my $obj = "$class\::Item"->new( | ||||
149 | qmod => $qmod, | ||||
150 | reqtype => $reqtype, | ||||
151 | optional => !! $optional, | ||||
152 | ); | ||||
153 | unshift @All, $obj; | ||||
154 | } | ||||
155 | CPAN->debug(sprintf("after jumpqueue All[%s]", | ||||
156 | join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All) | ||||
157 | )) if $CPAN::DEBUG; | ||||
158 | } | ||||
159 | |||||
160 | # CPAN::Queue::exists ; | ||||
161 | sub exists { | ||||
162 | my($self,$what) = @_; | ||||
163 | my @all = map { $_->{qmod} } @All; | ||||
164 | my $exists = grep { $_->{qmod} eq $what } @All; | ||||
165 | # warn "in exists what[$what] all[@all] exists[$exists]"; | ||||
166 | $exists; | ||||
167 | } | ||||
168 | |||||
169 | # CPAN::Queue::delete ; | ||||
170 | sub delete { | ||||
171 | my($self,$mod) = @_; | ||||
172 | @All = grep { $_->{qmod} ne $mod } @All; | ||||
173 | CPAN->debug(sprintf("after delete mod[%s] All[%s]", | ||||
174 | $mod, | ||||
175 | join("",map {sprintf " %s\[%s][%s]\n",$_->{qmod},$_->{reqtype},$_->{optional}} @All) | ||||
176 | )) if $CPAN::DEBUG; | ||||
177 | } | ||||
178 | |||||
179 | # CPAN::Queue::nullify_queue ; | ||||
180 | # spent 22µs within CPAN::Queue::nullify_queue which was called 3 times, avg 7µs/call:
# 3 times (22µs+0s) by CPAN::shell at line 432 of CPAN.pm, avg 7µs/call | ||||
181 | 3 | 22µs | @All = (); | ||
182 | } | ||||
183 | |||||
184 | # CPAN::Queue::size ; | ||||
185 | sub size { | ||||
186 | return scalar @All; | ||||
187 | } | ||||
188 | |||||
189 | sub reqtype_of { | ||||
190 | my($self,$mod) = @_; | ||||
191 | my $best = ""; | ||||
192 | for my $item (grep { $_->{qmod} eq $mod } @All) { | ||||
193 | my $c = $item->{reqtype}; | ||||
194 | if ($c eq "c") { | ||||
195 | $best = $c; | ||||
196 | last; | ||||
197 | } elsif ($c eq "r") { | ||||
198 | $best = $c; | ||||
199 | } elsif ($c eq "b") { | ||||
200 | if ($best eq "") { | ||||
201 | $best = $c; | ||||
202 | } | ||||
203 | } else { | ||||
204 | die "Panic: in reqtype_of: reqtype[$c] seen, should never happen"; | ||||
205 | } | ||||
206 | } | ||||
207 | return $best; | ||||
208 | } | ||||
209 | |||||
210 | 1; | ||||
211 | |||||
212 | __END__ |