File Coverage

blib/lib/MogileFS/Host.pm
Criterion Covered Total %
statement 53 78 67.9
branch 4 10 40.0
condition 9 43 20.9
subroutine 22 32 68.7
pod 0 21 0.0
total 88 184 47.8


line stmt bran cond sub pod time code
1             package MogileFS::Host;
2 21     21   122 use strict;
  21         51  
  21         712  
3 21     21   111 use warnings;
  21         47  
  21         1742  
4 21     21   135 use MogileFS::Util qw(throw);
  21         43  
  21         1399  
5 21     21   131 use Net::Netmask;
  21         44  
  21         2599  
6 21     21   144 use Carp qw(croak);
  21         52  
  21         1014  
7 21     21   13076 use MogileFS::Connection::Mogstored;
  21         65  
  21         686  
8 21     21   13670 use MogileFS::Connection::HTTP;
  21         97  
  21         1384  
9 21     21   17722 use MogileFS::ConnectionPool;
  21         90  
  21         50326  
10             our $http_pool;
11              
12             =head1
13              
14             MogileFS::Host - host class
15              
16             =cut
17              
18             # Centralized here instead of three places.
19             my @observed_fields = qw/observed_state/;
20             my @fields = (qw/hostid hostname hostip status http_port http_get_port altip altmask/,
21             @observed_fields);
22              
23             # TODO: Validate a few things: state, observed state.
24             sub new_from_args {
25 69     69 0 979 my ($class, $args, $dev_factory) = @_;
26 69         447 my $self = bless {
27             dev_factory => $dev_factory,
28 69         79 %{$args},
29             }, $class;
30              
31 69 50 33     318 $self->{mask} = ($self->{altip} && $self->{altmask}) ?
32             Net::Netmask->new2($self->{altmask}) : undef;
33              
34 69         267 return $self;
35             }
36              
37             sub valid_state {
38 0     0 0 0 my ($class, $state) = @_;
39 0   0     0 return $state && $state =~ /\A(?:alive|dead|down)\z/;
40             }
41              
42             # Instance methods:
43              
44 198     198 0 1982 sub id { $_[0]{hostid} }
45 68     68 0 211 sub name { $_[0]{hostname} }
46 0     0 0 0 sub hostname { $_[0]{hostname} }
47 0     0 0 0 sub hostip { $_[0]{hostip} }
48 52     52 0 247 sub status { $_[0]{status} }
49 14     14 0 97 sub http_port { $_[0]{http_port} }
50              
51             sub http_get_port {
52 1   33 1 0 11 return $_[0]->{http_get_port} || $_[0]->{http_port};
53             }
54              
55             sub ip {
56 15     15 0 33 my $self = shift;
57 15 50 33     361 if ($self->{mask} && $self->{altip} &&
      0        
      33        
58             ($MogileFS::REQ_altzone || ($MogileFS::REQ_client_ip &&
59             $self->{mask}->match($MogileFS::REQ_client_ip)))) {
60 0         0 return $self->{altip};
61             } else {
62 15         639 return $self->{hostip};
63             }
64             }
65              
66             sub fields {
67 0     0 0 0 my $self = shift;
68 0 0       0 my @tofetch = @_ ? @_ : @fields;
69 0         0 return { map { $_ => $self->{$_} } @tofetch };
  0         0  
70             }
71              
72             sub observed_fields {
73 0     0 0 0 return $_[0]->fields(@observed_fields);
74             }
75              
76             sub alive {
77 52     52 0 115 return $_[0]->status eq 'alive';
78             }
79              
80             sub observed_reachable {
81 52     52 0 64 my $self = shift;
82 52   33     381 return $self->{observed_state} && $self->{observed_state} eq 'reachable';
83             }
84              
85             sub observed_unreachable {
86 0     0 0 0 my $self = shift;
87 0   0     0 return $self->{observed_state} && $self->{observed_state} eq 'unreachable';
88             }
89              
90             # returns/creates a MogileFS::Connection::Mogstored object to the
91             # host's mogstored management/side-channel port (which starts
92             # unconnected, and only connects when you ask it to, with its sock
93             # method)
94             sub mogstored_conn {
95 0     0 0 0 my $self = shift;
96 0   0     0 return $self->{mogstored_conn} ||=
97             MogileFS::Connection::Mogstored->new($self->ip, $self->sidechannel_port);
98             }
99              
100             sub sidechannel_port {
101             # TODO: let this be configurable per-host? currently it's configured
102             # once for all machines.
103 0     0 0 0 MogileFS->config("mogstored_stream_port");
104             }
105              
106             # starts an HTTP request on the given $port with $method to $path
107             # Calls cb with an HTTP::Response object when done
108             sub _http_conn {
109 15     15   64 my ($self, $port, $method, $path, $opts, $cb) = @_;
110 15         52 _init_pools();
111              
112             $http_pool->start($opts->{ip} || $self->ip, $port, sub {
113 16     16   123 $_[0]->start($method, $path, $opts, $cb);
114 15   33     158 });
115             }
116              
117             # Returns a ready, blocking HTTP connection
118             # This is only used by replicate
119             sub http_conn_get {
120 0     0 0 0 my ($self, $opts) = @_;
121 0   0     0 my $ip = $opts->{ip} || $self->ip;
122 0   0     0 my $port = $opts->{port} || $self->http_port;
123              
124 0         0 _init_pools();
125 0         0 my $conn = $http_pool->conn_get($ip, $port);
126 0 0       0 $conn->sock->blocking(1) if $conn;
127 0         0 return $conn;
128             }
129              
130             # Returns a blocking HTTP connection back to the pool.
131             # This is the inverse of http_conn_get, and should be called when
132             # done using a connection (iff the connection is really still alive)
133             # (and makes it non-blocking for future use)
134             # This is only used by replicate.
135             sub http_conn_put {
136 0     0 0 0 my ($self, $conn) = @_;
137 0         0 $conn->sock->blocking(0);
138 0         0 $http_pool->conn_put($conn);
139             }
140              
141             sub http_get {
142 1     1 0 37 my ($self, $method, $path, $opts, $cb) = @_;
143 1   50     11 $opts ||= {};
144 1         5 $self->_http_conn($self->http_get_port, $method, $path, $opts, $cb);
145             }
146              
147             sub http {
148 14     14 0 142008 my ($self, $method, $path, $opts, $cb) = @_;
149 14   50     238 $opts ||= {};
150 14   33     182 my $port = delete $opts->{port} || $self->http_port;
151 14         106 $self->_http_conn($port, $method, $path, $opts, $cb);
152             }
153              
154             # FIXME - make these customizable
155             sub _init_pools {
156 16 100   16   81 return if $http_pool;
157              
158 1         12 $http_pool = MogileFS::ConnectionPool->new("MogileFS::Connection::HTTP");
159             }
160              
161             1;