File Coverage

blib/lib/Gearman/Spawner/Server.pm
Criterion Covered Total %
statement 51 57 89.4
branch 8 14 57.1
condition n/a
subroutine 13 13 100.0
pod 0 3 0.0
total 72 87 82.7


line stmt bran cond sub pod time code
1             package Gearman::Spawner::Server;
2              
3 24     24   41885 use strict;
  24         49  
  24         1052  
4 24     24   140 use warnings;
  24         38  
  24         791  
5              
6 24     24   614 use Gearman::Spawner::Process;
  24         42  
  24         512  
7 24     24   25173 use IO::Socket::INET;
  24         587445  
  24         206  
8              
9 24     24   19297 use base 'Gearman::Spawner::Process';
  24         66  
  24         16803  
10              
11             my ($ADDRESS, $INSTANCE);
12             sub address {
13 20     20 0 4887 my $class = shift;
14              
15 20 50       96 return $ADDRESS if $ADDRESS;
16 20 50       112 return $ADDRESS = $ENV{GEARMAN_SERVER} if $ENV{GEARMAN_SERVER};
17              
18 20         129 $INSTANCE = $class->create;
19 20         246 return $ADDRESS = $INSTANCE->address;
20             }
21              
22             sub create {
23 21     21 0 64 my $class = shift;
24              
25 21 50       1824 unless (eval "require Gearman::Server; 1") {
26 0         0 die "need server to run against; either set GEARMAN_SERVER or install Gearman::Server\n";
27             }
28              
29 21         236 return Gearman::Spawner::Server::Instance->new($class->fork_gearmand());
30             }
31              
32             # start up a gearmand that exits when its parent process does. returns the
33             # address of the listening server and its pid
34             sub fork_gearmand {
35 21     21 0 58 my $class = shift;
36              
37             # NB: this relies on Gearman::Spawner::Process allowing use of fork,
38             # run_periodically, exit_with_parent, and loop as class methods instead of
39             # object methods
40              
41             # get an unused port from the OS
42 21         231 my $sock = IO::Socket::INET->new(
43             Type => SOCK_STREAM,
44             Proto => 'tcp',
45             Reuse => 1,
46             LocalHost => 'localhost',
47             Listen => 1,
48             );
49              
50 21 50       24038 $sock or die "failed to request a listening socket: $!";
51              
52 21         137 my $port = $sock->sockport;
53 21         816 my $host = $sock->sockhost;
54 21         636 my $address = "$host:$port";
55 21         193 $sock->close;
56              
57 21         720 my $parent_pid = $$;
58              
59 21         68 $Gearman::Spawner::Process::CHECK_PERIOD = 0.5;
60 21         363 my $pid = $class->fork("[Gearman::Server $address] $0", 1);
61              
62 21 50       678 if ($pid) {
63             # wait until server is contactable
64 21         897 for (1 .. 50) {
65 42         1982 my $sock = IO::Socket::INET->new($address);
66 42 100       60077 return ($address, $pid) if $sock;
67 21         2152210 select undef, undef, undef, 0.1;
68             }
69 0         0 die "couldn't contact server at $host:$port: $!";
70             }
71              
72 0         0 require Gearman::Util; # Gearman::Server doesn't itself
73 0         0 my $server = Gearman::Server->new;
74 0         0 $server->create_listening_sock($port);
75              
76 0         0 $class->loop;
77             }
78              
79             package Gearman::Spawner::Server::Instance;
80              
81 24     24   163 use strict;
  24         55  
  24         898  
82 24     24   137 use warnings;
  24         47  
  24         5237  
83              
84             sub new {
85 21     21   217 my $class = shift;
86 21         133 my ($address, $pid) = @_;
87 21         2247 return bless {
88             address => $address,
89             pid => $pid,
90             me => $$,
91             }, $class;
92             }
93              
94             sub address {
95 21     21   239 my $self = shift;
96 21         760 return $self->{address};
97             }
98              
99             sub DESTROY {
100 1     1   4157 my $self = shift;
101 1 50       201 kill 'INT', $self->{pid} if $$ == $self->{me};
102             }
103              
104             1;