line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
##################################################################### |
2
|
|
|
|
|
|
|
## AUTHOR: Mary Ehlers, regina.verbae@gmail.com |
3
|
|
|
|
|
|
|
## ABSTRACT: A data-processing unit for the Piper pipeline system |
4
|
|
|
|
|
|
|
##################################################################### |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Piper::Process; |
7
|
|
|
|
|
|
|
|
8
|
4
|
|
|
4
|
|
179618
|
use v5.10; |
|
4
|
|
|
|
|
10
|
|
9
|
4
|
|
|
4
|
|
16
|
use strict; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
66
|
|
10
|
4
|
|
|
4
|
|
12
|
use warnings; |
|
4
|
|
|
|
|
4
|
|
|
4
|
|
|
|
|
81
|
|
11
|
|
|
|
|
|
|
|
12
|
4
|
|
|
4
|
|
15
|
use Carp; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
168
|
|
13
|
4
|
|
|
4
|
|
774
|
use Piper::Instance; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
91
|
|
14
|
4
|
|
|
4
|
|
18
|
use Types::Standard qw(CodeRef); |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
22
|
|
15
|
|
|
|
|
|
|
|
16
|
4
|
|
|
4
|
|
1991
|
use Moo; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
21
|
|
17
|
4
|
|
|
4
|
|
868
|
use namespace::clean; |
|
4
|
|
|
|
|
6
|
|
|
4
|
|
|
|
|
29
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
with qw(Piper::Role::Segment); |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
use overload ( |
22
|
6
|
|
|
6
|
|
3390
|
q{""} => sub { $_[0]->label }, |
23
|
4
|
|
|
|
|
34
|
fallback => 1, |
24
|
4
|
|
|
4
|
|
845
|
); |
|
4
|
|
|
|
|
5
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
our $VERSION = '0.03'; # from Piper-0.03.tar.gz |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $CONFIG; |
29
|
|
|
|
|
|
|
sub import { |
30
|
5
|
|
|
5
|
|
22
|
my $class = shift; |
31
|
5
|
50
|
|
|
|
20
|
if (@_) { |
32
|
0
|
|
|
|
|
0
|
require Piper::Config; |
33
|
0
|
|
|
|
|
0
|
$CONFIG = Piper::Config->new(@_); |
34
|
|
|
|
|
|
|
} |
35
|
5
|
|
|
|
|
9230
|
return 1; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
#pod =head1 CONSTRUCTOR |
39
|
|
|
|
|
|
|
#pod |
40
|
|
|
|
|
|
|
#pod =head2 new(@args) |
41
|
|
|
|
|
|
|
#pod |
42
|
|
|
|
|
|
|
#pod The constructor accepts the following patterns for C<@args>: |
43
|
|
|
|
|
|
|
#pod |
44
|
|
|
|
|
|
|
#pod Piper::Process->new({ |
45
|
|
|
|
|
|
|
#pod label => $label, # recommended |
46
|
|
|
|
|
|
|
#pod handler => $handler, # required |
47
|
|
|
|
|
|
|
#pod batch_size => $num, # optional |
48
|
|
|
|
|
|
|
#pod allow => $allow, # optional |
49
|
|
|
|
|
|
|
#pod enabled => $enabled, # default: 1 |
50
|
|
|
|
|
|
|
#pod }); |
51
|
|
|
|
|
|
|
#pod |
52
|
|
|
|
|
|
|
#pod Piper::Process->new( |
53
|
|
|
|
|
|
|
#pod $label => { |
54
|
|
|
|
|
|
|
#pod handler => $handler, |
55
|
|
|
|
|
|
|
#pod batch_size => $num, |
56
|
|
|
|
|
|
|
#pod allow => $allow, |
57
|
|
|
|
|
|
|
#pod enabled => $enabled, |
58
|
|
|
|
|
|
|
#pod } |
59
|
|
|
|
|
|
|
#pod ); |
60
|
|
|
|
|
|
|
#pod |
61
|
|
|
|
|
|
|
#pod Piper::Process->new($label => $handler); |
62
|
|
|
|
|
|
|
#pod |
63
|
|
|
|
|
|
|
#pod =cut |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
around BUILDARGS => sub { |
66
|
|
|
|
|
|
|
my ($orig, $self, @args) = @_; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
croak 'ERROR: Too many arguments to constructor of '.__PACKAGE__ |
69
|
|
|
|
|
|
|
if @args > 2; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
croak 'ERROR: Last argument must be a CODE ref or HASH ref' |
72
|
|
|
|
|
|
|
unless (ref $args[-1] eq 'CODE') or (ref $args[-1] eq 'HASH'); |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
my %hash; |
75
|
|
|
|
|
|
|
if (ref $args[-1] eq 'CODE') { |
76
|
|
|
|
|
|
|
$hash{handler} = pop @args; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
else { |
79
|
|
|
|
|
|
|
%hash = %{pop @args}; |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
if (@args) { |
83
|
|
|
|
|
|
|
croak 'ERROR: Labels may not be a reference' if ref $args[0]; |
84
|
|
|
|
|
|
|
$hash{label} = shift @args; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
$hash{config} = $CONFIG if defined $CONFIG; |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
return $self->$orig(%hash); |
90
|
|
|
|
|
|
|
}; |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
#pod =head1 ATTRIBUTES |
93
|
|
|
|
|
|
|
#pod |
94
|
|
|
|
|
|
|
#pod =head2 allow |
95
|
|
|
|
|
|
|
#pod |
96
|
|
|
|
|
|
|
#pod An optional coderef used to subset the items which are I to be processed by the segment. |
97
|
|
|
|
|
|
|
#pod |
98
|
|
|
|
|
|
|
#pod The coderef runs on each item attempting to queue to the segment. If it returns true, the item is queued. Otherwise, the item skips the segment and proceeds to the next adjacent segment. |
99
|
|
|
|
|
|
|
#pod |
100
|
|
|
|
|
|
|
#pod Each item is localized to C<$_>, and is also passed in as the first argument. These example C subroutines are equivalent: |
101
|
|
|
|
|
|
|
#pod |
102
|
|
|
|
|
|
|
#pod # This segment only accepts digit inputs |
103
|
|
|
|
|
|
|
#pod sub { /^\d+$/ } |
104
|
|
|
|
|
|
|
#pod sub { $_ =~ /^\d+$/ } |
105
|
|
|
|
|
|
|
#pod sub { $_[0] =~ /^\d+$/ } |
106
|
|
|
|
|
|
|
#pod |
107
|
|
|
|
|
|
|
#pod =head2 batch_size |
108
|
|
|
|
|
|
|
#pod |
109
|
|
|
|
|
|
|
#pod The number of items to process at a time for the segment. Once initialized, a segment inherits the C of its parent(s) if not provided. |
110
|
|
|
|
|
|
|
#pod |
111
|
|
|
|
|
|
|
#pod =head2 enabled |
112
|
|
|
|
|
|
|
#pod |
113
|
|
|
|
|
|
|
#pod Boolean indicating that the segment is enabled and can accept items for processing. Defaults to true. |
114
|
|
|
|
|
|
|
#pod |
115
|
|
|
|
|
|
|
#pod =head2 handler |
116
|
|
|
|
|
|
|
#pod |
117
|
|
|
|
|
|
|
#pod The data-processing subroutine for this segment. |
118
|
|
|
|
|
|
|
#pod |
119
|
|
|
|
|
|
|
#pod The arguments provided to the handler are as follows: |
120
|
|
|
|
|
|
|
#pod |
121
|
|
|
|
|
|
|
#pod $instance - the instance corresponding to the segment |
122
|
|
|
|
|
|
|
#pod $batch - an arrayref of items to process |
123
|
|
|
|
|
|
|
#pod @args - the init arguments (if any) provided |
124
|
|
|
|
|
|
|
#pod at the initialization of the pipeline |
125
|
|
|
|
|
|
|
#pod |
126
|
|
|
|
|
|
|
#pod Via the provided C<$instance> object (L), the handler has several options for sending data to other pipes or processes in the pipeline: |
127
|
|
|
|
|
|
|
#pod |
128
|
|
|
|
|
|
|
#pod $instance->eject(@data) |
129
|
|
|
|
|
|
|
#pod $instance->emit(@data) |
130
|
|
|
|
|
|
|
#pod $instance->inject(@data) |
131
|
|
|
|
|
|
|
#pod $instance->injectAfter($location, @data) |
132
|
|
|
|
|
|
|
#pod $instance->injectAt($location, @data) |
133
|
|
|
|
|
|
|
#pod $instance->recycle(@data) |
134
|
|
|
|
|
|
|
#pod |
135
|
|
|
|
|
|
|
#pod See L or L for an explanation of these methods. |
136
|
|
|
|
|
|
|
#pod |
137
|
|
|
|
|
|
|
#pod Example handler: |
138
|
|
|
|
|
|
|
#pod |
139
|
|
|
|
|
|
|
#pod sub { |
140
|
|
|
|
|
|
|
#pod my ($instance, $batch) = @_; |
141
|
|
|
|
|
|
|
#pod $instance->emit(map { ... } @$batch); |
142
|
|
|
|
|
|
|
#pod } |
143
|
|
|
|
|
|
|
#pod |
144
|
|
|
|
|
|
|
#pod =cut |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
has handler => ( |
147
|
|
|
|
|
|
|
is => 'ro', |
148
|
|
|
|
|
|
|
isa => CodeRef, |
149
|
|
|
|
|
|
|
required => 1, |
150
|
|
|
|
|
|
|
); |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
#pod =head2 id |
153
|
|
|
|
|
|
|
#pod |
154
|
|
|
|
|
|
|
#pod A globally unique ID for the segment. This is primarily useful for debugging only. |
155
|
|
|
|
|
|
|
#pod |
156
|
|
|
|
|
|
|
#pod =head2 label |
157
|
|
|
|
|
|
|
#pod |
158
|
|
|
|
|
|
|
#pod A label for this segment. If no label is provided, the segment's C will be used. |
159
|
|
|
|
|
|
|
#pod |
160
|
|
|
|
|
|
|
#pod Labels are necessary if any handlers wish to use the C or C methods. Otherwise, labels are primarily useful for logging and/or debugging. |
161
|
|
|
|
|
|
|
#pod |
162
|
|
|
|
|
|
|
#pod Stringification of a L object is overloaded to return its label: |
163
|
|
|
|
|
|
|
#pod |
164
|
|
|
|
|
|
|
#pod my $process = Piper::Process->new($label => sub {...}); |
165
|
|
|
|
|
|
|
#pod |
166
|
|
|
|
|
|
|
#pod $process->label; # $label |
167
|
|
|
|
|
|
|
#pod "$process"; # $label |
168
|
|
|
|
|
|
|
#pod |
169
|
|
|
|
|
|
|
#pod =head1 METHODS |
170
|
|
|
|
|
|
|
#pod |
171
|
|
|
|
|
|
|
#pod =head2 has_allow |
172
|
|
|
|
|
|
|
#pod |
173
|
|
|
|
|
|
|
#pod A boolean indicating whether or not an C attribute exists for this segment. |
174
|
|
|
|
|
|
|
#pod |
175
|
|
|
|
|
|
|
#pod =head2 has_batch_size |
176
|
|
|
|
|
|
|
#pod |
177
|
|
|
|
|
|
|
#pod A boolean indicating whether the segment has an assigned C. |
178
|
|
|
|
|
|
|
#pod |
179
|
|
|
|
|
|
|
#pod =head2 init |
180
|
|
|
|
|
|
|
#pod |
181
|
|
|
|
|
|
|
#pod Returns a L object for this segment. |
182
|
|
|
|
|
|
|
#pod |
183
|
|
|
|
|
|
|
#pod =cut |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
sub init { |
186
|
|
|
|
|
|
|
my ($self) = @_; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
return Piper::Instance->new( |
189
|
|
|
|
|
|
|
segment => $self, |
190
|
|
|
|
|
|
|
); |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
1; |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
__END__ |