File Coverage

blib/lib/Sprocket/AIO.pm
Criterion Covered Total %
statement 30 79 37.9
branch 3 20 15.0
condition 1 6 16.6
subroutine 9 19 47.3
pod 0 5 0.0
total 43 129 33.3


line stmt bran cond sub pod time code
1             package Sprocket::AIO;
2              
3 8     8   47 use Fcntl;
  8         14  
  8         3217  
4 8     8   50 use POE;
  8         13  
  8         47  
5 8     8   2825 use Carp qw( croak );
  8         17  
  8         431  
6              
7 8     8   46 use strict;
  8         12  
  8         248  
8 8     8   52 use warnings;
  8         22  
  8         664  
9              
10             our $sprocket_aio;
11            
12             BEGIN {
13 8     8   559 eval "use IO::AIO qw( poll_fileno poll_cb 2 )";
  8     8   4022  
  0         0  
  0         0  
14 8 50       41 if ( $@ ) {
15 8         1066 eval 'sub HAS_AIO () { 0 }';
16             } else {
17 0         0 eval 'sub HAS_AIO () { 1 }';
18             }
19             }
20              
21             sub import {
22 13     13   35 my ( $class, $args ) = @_;
23 13         34 my $package = caller();
24            
25 13 50 33     79 croak "Sprocket::AIO expects its arguments in a hash ref"
26             if ( $args && ref( $args ) ne 'HASH' );
27              
28 13 50       60 unless ( delete $args->{no_auto_export} ) {
29             {
30 8     8   54 no strict 'refs';
  8         23  
  8         12642  
  13         29  
31 13         26 *{ $package . '::sprocket_aio' } = \$sprocket_aio;
  13         65  
32             }
33             }
34              
35 13         370 return if ( !HAS_AIO || delete $args->{no_auto_bootstrap} );
36              
37             # bootstrap
38             # XXX I don't like this, let's find another way
39 0           eval( qq|
40             package $package;
41             use IO::AIO 2;
42             sub plugin_start_aio {
43             Sprocket::AIO->new( parent_id => shift->parent_id );
44             }
45             | );
46 0 0         croak "could not import AIO into $package : $@"
47             if ( $@ );
48            
49 0           return;
50             }
51              
52             sub new {
53 0     0 0   my $class = shift;
54 0 0         return $sprocket_aio if ( $sprocket_aio );
55            
56 0           return undef unless ( HAS_AIO );
57              
58 0   0       my $self = $sprocket_aio = bless({
59             session_id => undef,
60             watch_fork_delay => 2,
61             @_,
62             pid => $$,
63             }, ref $class || $class );
64              
65 0 0         return $self unless ( $self->{parent_id} );
66              
67 0           POE::Session->create(
68             object_states => [
69             $self => {
70             _start => '_start',
71             _stop => '_stop',
72             poll_cb => 'poll_cb',
73             watch_aio => 'watch_aio',
74             watch_fork => 'watch_fork',
75             shutdown => '_shutdown',
76             restart => '_restart',
77             },
78             ],
79             );
80              
81 0           return $self;
82             }
83              
84             sub _start {
85 0     0     my ( $self, $kernel, $session ) = @_[ OBJECT, KERNEL, SESSION ];
86            
87 0           $self->{session_id} = $session->ID();
88 0           $kernel->alias_set( "$self" );
89 0           $kernel->call( $session => 'watch_aio' );
90            
91 0 0         $kernel->delay_set( watch_fork => $self->{watch_fork_delay} )
92             if ( $self->{watch_for_fork} );
93            
94 0           $self->_log( v => 2, msg => 'AIO support module started' );
95            
96 0           return;
97             }
98              
99             sub watch_aio {
100 0     0 0   my ( $self, $kernel ) = @_[ OBJECT, KERNEL ];
101            
102             # eval here because poll_fileno isn't imported when IO::AIO isn't installed
103 0           open( my $fh, "<&=".eval "poll_fileno()" );
104             #or die "error during open in watch_aio $!";
105 0           $kernel->select_read( $fh, 'poll_cb' );
106 0           $self->{fh} = $fh;
107              
108             # save our pid for watch_fork
109 0           $self->{pid} = $$;
110            
111 0           return;
112             }
113              
114             sub watch_fork {
115 0     0 0   my ( $self, $kernel ) = @_[ OBJECT, KERNEL ];
116              
117 0 0         if ( $self->{pid} != $$ ) {
118 0           $self->_log( v => 4, msg => 'fork detected, restarting aio' );
119 0           $kernel->call( $_[SESSION] => 'restart' );
120             }
121              
122 0           $kernel->delay_set( watch_fork => $self->{watch_fork_delay} );
123             }
124              
125             sub _stop {
126 0     0     $_[ OBJECT ]->_log(v => 2, msg => 'stopped');
127             }
128              
129             sub _log {
130             # TODO replace with $sprocket->log
131 0     0     $poe_kernel->call( shift->{parent_id} => _log => ( call => ( caller(1) )[ 3 ], @_ ) );
132             }
133              
134             sub shutdown {
135 0     0 0   my $self = shift;
136 0 0         return $self->{session_id} ? $poe_kernel->call( $self->{session_id} => shutdown => @_ ) : undef;
137             }
138              
139             sub _shutdown {
140 0     0     my ( $self, $kernel ) = @_[ OBJECT, KERNEL ];
141              
142 0           $kernel->alias_remove( "$self" );
143 0           $kernel->alarm_remove_all();
144 0           $kernel->select_read( delete $self->{fh} );
145 0           $sprocket_aio = undef;
146              
147 0           return;
148             }
149              
150             sub restart {
151 0     0 0   my $self = shift;
152 0 0         return unless ( $self->{session_id} );
153 0           return $poe_kernel->call( $self->{session_id} => restart => @_ );
154             }
155              
156             sub _restart {
157 0     0     my ( $self, $kernel, $session ) = @_[ OBJECT, KERNEL, SESSION ];
158            
159 0           $kernel->select_read( delete $self->{fh} );
160 0           $kernel->call( $session, 'watch_aio' );
161              
162 0           $self->_log( v => 2, msg => 'AIO support module restarted' );
163            
164 0           return;
165             }
166              
167             1;
168              
169             __END__