File Coverage

blib/lib/AnyEvent/Task/Server.pm
Criterion Covered Total %
statement 53 71 74.6
branch 9 16 56.2
condition 3 4 75.0
subroutine 12 16 75.0
pod 0 4 0.0
total 77 111 69.3


line stmt bran cond sub pod time code
1             package AnyEvent::Task::Server;
2              
3 29     29   499642 use common::sense;
  29         43  
  29         140  
4              
5 29     29   2876 use AnyEvent;
  29         7431  
  29         585  
6 29     29   987 use AnyEvent::Util;
  29         16861  
  29         1370  
7 29     29   15536 use AnyEvent::Socket;
  29         309626  
  29         2959  
8              
9 29     29   12543 use AnyEvent::Task::Util;
  29         50  
  29         761  
10 29     29   10692 use AnyEvent::Task::Server::Worker;
  29         62  
  29         20116  
11              
12              
13             sub new {
14 14     14 0 222 my ($class, %arg) = @_;
15 14         47 my $self = {};
16 14         76 bless $self, $class;
17              
18              
19 14         370 $self->{all_done_cv} = AE::cv;
20 14         2194 $self->{children} = {};
21              
22              
23 14   100 0   414 $self->{setup} = $arg{setup} || sub {};
24 14   50 0   267 $self->{checkout_done} = $arg{checkout_done} || sub {};
25 14 100       125 $self->{hung_worker_timeout} = exists $arg{hung_worker_timeout} ? $arg{hung_worker_timeout} : (60*5);
26              
27              
28 14 50       73 if ($arg{listen}) {
29 14         51 $self->{listen} = $arg{listen};
30              
31 14         60 my $host = $self->{listen}->[0];
32 14         54 my $service = $self->{listen}->[1];
33              
34             $self->{server_guard} = tcp_server $host, $service, sub {
35 34     34   3884968 my ($fh) = @_;
36 34         250 $self->handle_new_connection($fh);
37 14         276 };
38             } else {
39 0         0 die "unspecified listen path";
40             }
41              
42              
43 14 50       4393 if (exists $arg{interface}) {
44 14         35 my $interface = $arg{interface};
45              
46 14 100       75 if (ref $interface eq 'CODE') {
    50          
47 10         36 $self->{interface} = $interface;
48             } elsif (ref $interface eq 'HASH') {
49             $self->{interface} = sub {
50 0     0   0 my $method = shift;
51 0         0 $interface->{$method}->(@_);
52 4         33 };
53             } else {
54 0         0 die "interface must be a sub or a hash";
55             }
56             } else {
57 0         0 die "unspecified interface";
58             }
59              
60              
61 14         134 return $self;
62             }
63              
64              
65             sub fork_task_server {
66 28     28 0 352 my (@args) = @_;
67              
68 28 50       76 if (wantarray) {
69             return AnyEvent::Task::Util::fork_anyevent_subprocess(sub {
70 0     0   0 AnyEvent::Task::Server->new(@args)->run;
71 0         0 });
72             } else {
73             AnyEvent::Task::Util::fork_anyevent_subprocess(sub {
74 14     14   310 AnyEvent::Task::Server->new(@args)->run;
75 0         0 return undef;
76 28         184 });
77              
78 14         738 return undef;
79             }
80             }
81              
82              
83              
84              
85             sub handle_new_connection {
86 34     34 0 71 my ($self, $fh) = @_;
87              
88 34         408 my ($monitor_fh1, $monitor_fh2) = AnyEvent::Util::portable_socketpair;
89              
90 34         26088 my $rv = fork;
91              
92 34 50       1257 if ($rv) {
    0          
93 34         940 close($fh);
94 34         411 close($monitor_fh2);
95              
96 34         3914 $self->{children}->{$rv} = {
97             monitor_fh => $monitor_fh1,
98             };
99             } elsif ($rv == 0) {
100 0         0 close($monitor_fh1);
101              
102             ## Don't want keep-alive pipes of other workers open in this worker
103 0         0 foreach my $child (keys %{$self->{children}}) {
  0         0  
104 0         0 close($self->{children}->{$child}->{monitor_fh});
105             }
106              
107 0         0 AnyEvent::Task::Server::Worker::handle_worker($self, $fh, $monitor_fh2);
108 0         0 die "handle_worker should never return";
109             } else {
110 0         0 close($fh);
111 0         0 close($monitor_fh1);
112 0         0 close($monitor_fh2);
113 0         0 die "fork failed: $!";
114             }
115             }
116              
117              
118             sub run {
119 14     14 0 31 my ($self) = @_;
120              
121 14         204 $self->{all_done_cv}->recv;
122             }
123              
124              
125             1;