File Coverage

lib/IOMux/Handler/Write.pm
Criterion Covered Total %
statement 50 95 52.6
branch 8 42 19.0
condition 1 11 9.0
subroutine 15 22 68.1
pod 10 11 90.9
total 84 181 46.4


line stmt bran cond sub pod time code
1             # Copyrights 2011 by Mark Overmeer.
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 1.07.
5 8     8   804 use warnings;
  8         13  
  8         243  
6 8     8   45 use strict;
  8         15  
  8         341  
7              
8             package IOMux::Handler::Write;
9 8     8   42 use vars '$VERSION';
  8         15  
  8         361  
10             $VERSION = '0.12';
11              
12 8     8   44 use base 'IOMux::Handler';
  8         14  
  8         2354  
13              
14 8     8   52 use Log::Report 'iomux';
  8         16  
  8         70  
15 8     8   3140 use Fcntl;
  8         14  
  8         3060  
16 8     8   51 use POSIX 'errno_h';
  8         21  
  8         86  
17 8     8   4301 use File::Spec ();;
  8         23  
  8         195  
18 8     8   46 use File::Basename 'basename';
  8         23  
  8         581  
19              
20 8     8   54 use constant PIPE_BUF_SIZE => 4096;
  8         16  
  8         8325  
21              
22              
23             sub init($)
24 8     8 0 19 { my ($self, $args) = @_;
25 8         232 $self->SUPER::init($args);
26 8   50     138 $self->{IMHW_write_size} = $args->{write_size} || 4096;
27 8         20 $self;
28             }
29              
30             #-------------------
31              
32             sub writeSize(;$)
33 0     0 1 0 { my $self = shift;
34 0 0       0 @_ ? $self->{IMHW_write_size} = shift : $self->{IMHW_write_size};
35             }
36              
37             #-----------------------
38              
39             sub print(@)
40 6     6 1 2180 { my $self = shift;
41 0         0 $self->write( !ref $_[0] ? (@_>1 ? \join('',@_) : \shift)
42 6 50       53 : ref $_[0] eq 'ARRAY' ? \join('',@{$_[0]}) : $_[0] );
    0          
    50          
43             }
44              
45              
46             sub say(@)
47 0     0 1 0 { my $self = shift;
48 0         0 $self->write
49             ( !ref $_[0] ? \join('',@_, "\n")
50 0 0       0 : ref $_[0] eq 'ARRAY' ? \join('',@{$_[0]}, "\n")
    0          
51             : $_[0]."\n"
52             );
53             }
54              
55              
56             sub printf($@)
57 0     0 1 0 { my $self = shift;
58 0         0 $self->write(\sprintf(@_));
59             }
60              
61              
62             sub write($;$)
63 12     12 1 78 { my ($self, $blob, $more) = @_;
64              
65 12 50       50 if(exists $self->{IMHW_outbuf})
66 0         0 { ${$self->{IMHW_outbuf}} .= $$blob;
  0         0  
67 0         0 $self->{IMHW_more} = $more;
68 0         0 return;
69             }
70              
71 12         48 my $bytes_written = syswrite $self->fh, $$blob, $self->{IMHW_write_size};
72 12 50       70 if(!defined $bytes_written)
73 0 0 0     0 { return if $!==EWOULDBLOCK || $!==EINTR;
74 0         0 warning __x"write to {name} failed: {err}"
75             , name => $self->name, err => $!;
76 0         0 $self->close;
77             return
78 0         0 }
79              
80 12 50       55 if($bytes_written==length $$blob)
81             { # we got rit of all at once. Cheap!
82 12 50       26 $more->($self) if $more;
83 12 50       32 $self->{IMHW_is_closing}->($self)
84             if $self->{IMHW_is_closing};
85 12         33 return;
86             }
87              
88 0         0 substr($$blob, 0, $bytes_written) = '';
89 0         0 $self->{IMHW_outbuf} = $blob;
90 0         0 $self->{IMHW_more} = $more;
91 0         0 $self->fdset(1, 0, 1, 0);
92             }
93              
94              
95             #-------------------------
96              
97             sub mux_init($)
98 7     7 1 269 { my ($self, $mux) = @_;
99 7         129 $self->SUPER::mux_init($mux);
100 7         457 $self->fdset(1, 0, 1, 0);
101             }
102              
103             sub mux_write_flagged()
104 0     0 1 0 { my $self = shift;
105 0         0 my $outbuf = $self->{IMHW_outbuf};
106 0 0       0 unless($outbuf)
107 0         0 { $outbuf = $self->{IMHW_outbuf} = $self->mux_outbuffer_empty;
108 0 0       0 unless(defined $outbuf)
109             { # nothing can be produced on call, so we don't need the
110             # empty-write signals on the moment (enabled at next write)
111 0         0 $self->fdset(0, 0, 1, 0);
112 0         0 return;
113             }
114 0 0       0 unless(length $$outbuf)
115             { # retry at next interval
116 0         0 delete $self->{IMHW_outbuf};
117 0         0 return;
118             }
119             }
120              
121 0         0 my $bytes_written = syswrite $self->fh, $$outbuf, $self->{IMHW_write_size};
122 0 0       0 if(!defined $bytes_written)
    0          
123             { # should happen, but we're kind
124 0 0 0     0 return if $! == EWOULDBLOCK || $! == EINTR || $! == EAGAIN;
      0        
125 0         0 warning __x"write to {name} failed: {err}"
126             , name => $self->name, err => $!;
127 0         0 $self->close;
128             }
129             elsif($bytes_written==length $$outbuf)
130 0         0 { delete $self->{IMHW_outbuf} }
131 0         0 else { substr($$outbuf, 0, $bytes_written) = '' }
132             }
133              
134              
135             sub mux_outbuffer_empty()
136 0     0 1 0 { my $self = shift;
137 0         0 my $more = delete $self->{IMHW_more};
138 0 0       0 return $more->() if defined $more;
139              
140 0         0 $self->fdset(0, 0, 1, 0);
141 0 0       0 $self->{IMHW_is_closing}->($self)
142             if $self->{IMHW_is_closing};
143             }
144              
145              
146 0     0 1 0 sub mux_output_waiting() { exists shift->{IMHW_outbuf} }
147              
148             # Closing write handlers is a little complex: it should be delayed
149             # until the write buffer is empty.
150              
151             sub close(;$)
152 10     10 1 862 { my ($self, $cb) = @_;
153 10 50       34 if($self->{IMHW_outbuf})
154             { # delay closing until write buffer is empty
155 0     0   0 $self->{IMHW_is_closing} = sub { $self->SUPER::close($cb)};
  0         0  
156             }
157             else
158             { # can close immediately
159 10         86 $self->SUPER::close($cb);
160             }
161             }
162              
163             1;