File Coverage

blib/lib/MCE/Core/Input/Handle.pm
Criterion Covered Total %
statement 78 134 58.2
branch 29 70 41.4
condition 5 20 25.0
subroutine 6 9 66.6
pod n/a
total 118 233 50.6


line stmt bran cond sub pod time code
1             ###############################################################################
2             ## ----------------------------------------------------------------------------
3             ## File path and Scalar reference input reader.
4             ##
5             ## This package provides the read handle method used internally by the worker
6             ## process. Distribution follows a bank-queuing model.
7             ##
8             ## There is no public API.
9             ##
10             ###############################################################################
11              
12             package MCE::Core::Input::Handle;
13              
14 13     13   1436 use strict;
  13         28  
  13         691  
15 13     13   88 use warnings;
  13         30  
  13         1818  
16              
17             our $VERSION = '1.887';
18              
19             ## Items below are folded into MCE.
20              
21             package # hide from rpm
22             MCE;
23              
24 13     13   121 no warnings qw( threads recursion uninitialized );
  13         38  
  13         22094  
25              
26             my $_que_read_size = $MCE::_que_read_size;
27             my $_que_template = $MCE::_que_template;
28              
29             ###############################################################################
30             ## ----------------------------------------------------------------------------
31             ## Worker process -- Read handle.
32             ##
33             ###############################################################################
34              
35             sub _systell {
36             # To minimize memory consumption, SEEK_CUR equals 1 on most platforms.
37             # e.g. use Fcntl qw(SEEK_CUR);
38              
39 0     0   0 sysseek($_[0], 0, 1);
40             }
41              
42             sub _worker_read_handle {
43              
44 14     14   44 my ($self, $_proc_type, $_input_data) = @_;
45              
46 14         29 @_ = ();
47              
48             _croak('MCE::_worker_read_handle: (user_func) is not specified')
49 14 50       259 unless (defined $self->{user_func});
50              
51 14 50       68 my $_is_MSWin32 = ($^O eq 'MSWin32') ? 1 : 0;
52 14         36 my $_QUE_R_SOCK = $self->{_que_r_sock};
53 14         27 my $_QUE_W_SOCK = $self->{_que_w_sock};
54 14         38 my $_chunk_size = $self->{chunk_size};
55 14         25 my $_use_slurpio = $self->{use_slurpio};
56 14         27 my $_parallel_io = $self->{parallel_io};
57 14   33     1467 my $_RS = $self->{RS} || $/;
58 14         29 my $_wuf = $self->{_wuf};
59              
60 14         46 my ($_data_size, $_next, $_chunk_id, $_offset_pos, $_IN_FILE, $_tmp_cs);
61 14         0 my ($_DAT_LOCK, $_dat_ex, $_dat_un, $_pid, $_chop_len, $_chop_str, $_p);
62              
63 14 50       68 $_pid = $INC{'threads.pm'} ? $$ .'.'. threads->tid() : $$;
64              
65             # inlined for performance
66 14         81 $_DAT_LOCK = $self->{'_mutex_'.( $self->{_wid} % 2 + 10 )};
67             $_dat_ex = sub {
68             CORE::lock($_DAT_LOCK->{_t_lock}), MCE::Util::_sock_ready($_DAT_LOCK->{_r_sock})
69 65 50   65   125 if $_is_MSWin32;
70             MCE::Util::_sysread($_DAT_LOCK->{_r_sock}, my($b), 1), $_DAT_LOCK->{ $_pid } = 1
71 65 50       901 unless $_DAT_LOCK->{ $_pid };
72 14         69 };
73             $_dat_un = sub {
74             syswrite($_DAT_LOCK->{_w_sock}, '0'), $_DAT_LOCK->{ $_pid } = 0
75 65 50   65   764 if $_DAT_LOCK->{ $_pid };
76 14         45 };
77              
78 14 50 33     67 if (length $_RS > 1 && substr($_RS, 0, 1) eq "\n") {
79 0         0 $_chop_str = substr($_RS, 1);
80 0         0 $_chop_len = length $_chop_str;
81             } else {
82 14         26 $_chop_str = '';
83 14         23 $_chop_len = 0;
84             }
85              
86             $_data_size = ($_proc_type == READ_MEMORY)
87 14 50       265 ? length ${ $_input_data } : -s $_input_data;
  0         0  
88              
89 14         43 $_chunk_id = $_offset_pos = 0;
90              
91 14 50       544 open $_IN_FILE, '<', $_input_data or die "$_input_data: $!\n";
92 14         52 binmode $_IN_FILE;
93              
94             ## -------------------------------------------------------------------------
95              
96 14     0   65 $self->{_next_jmp} = sub { goto _WORKER_READ_HANDLE__NEXT; };
  0         0  
97 14     0   47 $self->{_last_jmp} = sub { goto _WORKER_READ_HANDLE__LAST; };
  0         0  
98              
99 14         29 local $_;
100              
101             _WORKER_READ_HANDLE__NEXT:
102              
103 14         38 while (1) {
104 65 50       96 my @_recs; undef $_ if (length > MAX_GC_SIZE);
  65         351  
105              
106 65         105 $_ = '';
107              
108             ## Obtain the next chunk_id and offset position.
109 65         144 $_dat_ex->();
110 65 50       165 MCE::Util::_sock_ready($_QUE_R_SOCK) if $_is_MSWin32;
111 65         207 MCE::Util::_sysread($_QUE_R_SOCK, $_next, $_que_read_size);
112              
113 65         270 ($_chunk_id, $_offset_pos) = unpack($_que_template, $_next);
114              
115 65 100       165 if ($_offset_pos >= $_data_size) {
116 14         362 syswrite($_QUE_W_SOCK, pack($_que_template, 0, $_offset_pos));
117 14         85 $_dat_un->();
118 14         344 close $_IN_FILE; undef $_IN_FILE;
  14         78  
119 14         122 return;
120             }
121              
122 51 50 66     188 if (++$_chunk_id > 1 && $_chop_len) {
123 0         0 $_p = $_chop_len; $_ = $_chop_str;
  0         0  
124             } else {
125 51         139 $_p = 0;
126             }
127              
128             ## Read data.
129 51 50       110 if ($_chunk_size <= MAX_RECS_SIZE) { # One or many records.
130 51 50       133 local $/ = $_RS if ($/ ne $_RS);
131 51         476 seek $_IN_FILE, $_offset_pos, 0;
132              
133 51 100       144 if ($_chunk_size == 1) {
134 36 50       52 if ($_p) {
135 0         0 $_ .= <$_IN_FILE>;
136             } else {
137 36         617 $_ = <$_IN_FILE>;
138             }
139             }
140             else {
141 15 50       50 if ($_use_slurpio) {
142 0         0 for my $i (0 .. $_chunk_size - 1) {
143 0         0 $_ .= <$_IN_FILE>;
144             }
145             }
146             else {
147 15 50       30 if ($_chop_len) {
148 0 0       0 $_recs[0] = ($_chunk_id > 1) ? $_chop_str : '';
149 0         0 $_recs[0] .= <$_IN_FILE>;
150 0         0 for my $i (1 .. $_chunk_size - 1) {
151 0         0 $_recs[$i] = $_chop_str;
152 0         0 $_recs[$i] .= <$_IN_FILE>;
153 0 0       0 if (length $_recs[$i] == $_chop_len) {
154 0         0 delete $_recs[$i];
155 0         0 last;
156             }
157             }
158             }
159             else {
160 15         38 for my $i (0 .. $_chunk_size - 1) {
161 30         274 $_recs[$i] = <$_IN_FILE>;
162 30 100       92 unless (defined $_recs[$i]) {
163 3         9 delete $_recs[$i];
164 3         8 last;
165             }
166             }
167             }
168             }
169             }
170              
171 51         678 syswrite(
172             $_QUE_W_SOCK, pack($_que_template, $_chunk_id, tell $_IN_FILE)
173             );
174 51         202 $_dat_un->();
175             }
176             else { # Large chunk.
177 0 0       0 local $/ = $_RS if ($/ ne $_RS);
178              
179 0 0 0     0 if ($_parallel_io && $_RS eq $LF) {
180 0         0 syswrite(
181             $_QUE_W_SOCK,
182             pack($_que_template, $_chunk_id, $_offset_pos + $_chunk_size)
183             );
184 0         0 $_dat_un->();
185              
186 0         0 $_tmp_cs = $_chunk_size;
187 0         0 seek $_IN_FILE, $_offset_pos, 0;
188              
189 0 0       0 if ($_offset_pos) {
190 0   0     0 $_tmp_cs -= length <$_IN_FILE> || 0;
191             }
192              
193 0 0       0 if ($_proc_type == READ_FILE) {
194 0         0 sysseek($_IN_FILE, tell( $_IN_FILE ), 0);
195 0         0 sysread($_IN_FILE, $_, $_tmp_cs, $_p);
196 0         0 seek $_IN_FILE, _systell($_IN_FILE), 0;
197             }
198             else {
199 0         0 read $_IN_FILE, $_, $_tmp_cs, $_p;
200             }
201              
202 0         0 $_ .= <$_IN_FILE>;
203             }
204             else {
205 0 0       0 if ($_proc_type == READ_FILE) {
206 0         0 sysseek($_IN_FILE, $_offset_pos, 0);
207 0         0 sysread($_IN_FILE, $_, $_chunk_size, $_p);
208 0         0 seek $_IN_FILE, _systell($_IN_FILE), 0;
209             }
210             else {
211 0         0 seek $_IN_FILE, $_offset_pos, 0;
212 0         0 read $_IN_FILE, $_, $_chunk_size, $_p;
213             }
214              
215 0         0 $_ .= <$_IN_FILE>;
216              
217 0         0 syswrite(
218             $_QUE_W_SOCK, pack($_que_template, $_chunk_id, tell $_IN_FILE)
219             );
220 0         0 $_dat_un->();
221             }
222             }
223              
224             ## Call user function.
225 51 50       125 if ($_use_slurpio) {
226 0 0 0     0 if ($_chop_len && substr($_, -$_chop_len) eq $_chop_str) {
227 0         0 substr($_, -$_chop_len, $_chop_len, '');
228             }
229 0         0 local $_ = \$_;
230 0         0 $_wuf->($self, $_, $_chunk_id);
231             }
232             else {
233 51 100       94 if ($_chunk_size == 1) {
234 36 50 33     67 if ($_chop_len && substr($_, -$_chop_len) eq $_chop_str) {
235 0         0 substr($_, -$_chop_len, $_chop_len, '');
236             }
237 36         131 $_wuf->($self, [ $_ ], $_chunk_id);
238             }
239             else {
240 15 50       34 if ($_chunk_size > MAX_RECS_SIZE) {
241 0 0       0 local $/ = $_RS if ($/ ne $_RS);
242 0         0 _sync_buffer_to_array(\$_, \@_recs, $_chop_str);
243 0         0 undef $_;
244             }
245 15 50       39 if ($_chop_len) {
246 0         0 for my $i (0 .. @_recs - 1) {
247 0 0       0 if (substr($_recs[$i], -$_chop_len) eq $_chop_str) {
248 0         0 substr($_recs[$i], -$_chop_len, $_chop_len, '');
249             }
250             }
251             }
252 15         31 local $_ = \@_recs;
253 15         53 $_wuf->($self, \@_recs, $_chunk_id);
254             }
255             }
256             }
257              
258             _WORKER_READ_HANDLE__LAST:
259              
260 0           close $_IN_FILE; undef $_IN_FILE;
  0            
261              
262 0           return;
263             }
264              
265             1;
266              
267             __END__
268              
269             ###############################################################################
270             ## ----------------------------------------------------------------------------
271             ## Module usage.
272             ##
273             ###############################################################################
274              
275             =head1 NAME
276              
277             MCE::Core::Input::Handle - File path and Scalar reference input reader
278              
279             =head1 VERSION
280              
281             This document describes MCE::Core::Input::Handle version 1.887
282              
283             =head1 DESCRIPTION
284              
285             This package provides the read handle method used internally by the worker
286             process. Distribution follows a bank-queuing model.
287              
288             There is no public API.
289              
290             =head1 SEE ALSO
291              
292             The syntax for the C<input_data> option is described in L<MCE::Core>.
293              
294             =head1 AUTHOR
295              
296             Mario E. Roy, S<E<lt>marioeroy AT gmail DOT comE<gt>>
297              
298             =cut
299