File Coverage

blib/lib/Apache/TS/AdminClient.pm
Criterion Covered Total %
statement 24 82 29.2
branch 0 42 0.0
condition 0 15 0.0
subroutine 8 14 57.1
pod 0 4 0.0
total 32 157 20.3


line stmt bran cond sub pod time code
1             #
2             # Licensed to the Apache Software Foundation (ASF) under one
3             # or more contributor license agreements. See the NOTICE file
4             # distributed with this work for additional information
5             # regarding copyright ownership. The ASF licenses this file
6             # to you under the Apache License, Version 2.0 (the
7             # "License"); you may not use this file except in compliance
8             # with the License. You may obtain a copy of the License at
9             #
10             # http://www.apache.org/licenses/LICENSE-2.0
11             #
12             # Unless required by applicable law or agreed to in writing, software
13             # distributed under the License is distributed on an "AS IS" BASIS,
14             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15             # See the License for the specific language governing permissions and
16             # limitations under the License.
17              
18             package Apache::TS::AdminClient;
19             $VERSION = '0.02';
20              
21 1     1   85847 use warnings;
  1         3  
  1         98  
22 1     1   7 use strict;
  1         3  
  1         52  
23              
24             require 5.006;
25              
26 1     1   7 use Carp;
  1         206  
  1         579  
27 1     1   3350 use IO::Socket::UNIX;
  1         183184  
  1         9  
28 1     1   20551 use IO::Select;
  1         2005  
  1         109  
29              
30             use constant {
31 1         377 TS_FILE_READ => 0,
32             TS_FILE_WRITE => 1,
33             TS_RECORD_SET => 2,
34             TS_RECORD_GET => 3,
35             TS_PROXY_STATE_GET => 4,
36             TS_PROXY_STATE_SET => 5,
37             TS_RECONFIGURE => 6,
38             TS_RESTART => 7,
39             TS_BOUNCE => 8,
40             TS_EVENT_RESOLVE => 9,
41             TS_EVENT_GET_MLT => 10,
42             TS_EVENT_ACTIVE => 11,
43             TS_EVENT_REG_CALLBACK => 12,
44             TS_EVENT_UNREG_CALLBACK => 13,
45             TS_EVENT_NOTIFY => 14,
46             TS_SNAPSHOT_TAKE => 15,
47             TS_SNAPSHOT_RESTORE => 16,
48             TS_SNAPSHOT_REMOVE => 17,
49             TS_SNAPSHOT_GET_MLT => 18,
50             TS_DIAGS => 19,
51             TS_STATS_RESET => 20,
52             TS_ENCRYPT_TO_FILE => 21
53 1     1   9 };
  1         3  
54              
55             # We treat both REC_INT and REC_COUNTER the same here
56             use constant {
57 1         105 TS_REC_INT => 0,
58             TS_REC_COUNTER => 0,
59             TS_REC_FLOAT => 2,
60             TS_REC_STRING => 3
61 1     1   6 };
  1         2  
62              
63             use constant {
64 1         1126 TS_ERR_OKAY => 0,
65             TS_ERR_READ_FILE => 1,
66             TS_ERR_WRITE_FILE => 2,
67             TS_ERR_PARSE_CONFIG_RULE => 3,
68             TS_ERR_INVALID_CONFIG_RULE => 4,
69             TS_ERR_NET_ESTABLISH => 5,
70             TS_ERR_NET_READ => 6,
71             TS_ERR_NET_WRITE => 7,
72             TS_ERR_NET_EOF => 8,
73             TS_ERR_NET_TIMEOUT => 9,
74             TS_ERR_SYS_CALL => 10,
75             TS_ERR_PARAMS => 11,
76             TS_ERR_FAIL => 12
77 1     1   6 };
  1         2  
78              
79             #
80             # Constructor
81             #
82             sub new {
83 0     0 0   my ( $class, %args ) = @_;
84 0           my $self = {};
85              
86 0   0       $self->{_socket_path} = $args{socket_path} || _find_socket();
87 0           $self->{_socket} = undef;
88 0 0         croak
89             "Unable to locate socket, please pass socket_pass with the management api socket location to Apache::TS::AdminClient"
90             if ( !$self->{_socket_path} );
91 0 0 0       if ( ( !-r $self->{_socket_path} )
      0        
92             or ( !-w $self->{_socket_path} )
93             or ( !-S $self->{_socket_path} ) )
94             {
95 0           croak "Unable to open $self->{_socket_path} for reads or writes";
96              
97             # see croak in "sub open_socket()" for other source of carp errors
98             }
99              
100 0           $self->{_select} = IO::Select->new();
101 0           bless $self, $class;
102              
103 0           $self->open_socket();
104              
105 0           return $self;
106             }
107              
108             sub _find_socket {
109 0     0     my @sockets_def = (
110             '/usr/local/var/trafficserver/mgmtapisocket',
111             '/var/trafficserver/mgmtapisocket'
112             );
113 0           foreach my $socket (@sockets_def) {
114 0 0         return $socket if ( -S $socket );
115             }
116 0           return undef;
117             }
118              
119             #
120             # Destructor
121             #
122             sub DESTROY {
123 0     0     my $self = shift;
124 0           return $self->close_socket();
125             }
126              
127             #
128             # Open the socket (Unix domain)
129             #
130             sub open_socket {
131 0     0 0   my $self = shift;
132 0           my %args = @_;
133              
134 0 0         if ( defined( $self->{_socket} ) ) {
135 0 0 0       if ( $args{force} || $args{reopen} ) {
136 0           $self->close_socket();
137             }
138             else {
139 0           return undef;
140             }
141             }
142              
143 0 0         $self->{_socket} = IO::Socket::UNIX->new(
144             Type => SOCK_STREAM,
145             Peer => $self->{_socket_path}
146             ) or croak("Error opening socket - $@");
147              
148 0 0         return undef unless defined( $self->{_socket} );
149 0           $self->{_select}->add( $self->{_socket} );
150              
151 0           return $self;
152             }
153              
154             sub close_socket {
155 0     0 0   my $self = shift;
156              
157             # if socket doesn't exist, return as there's nothing to do.
158 0 0         return unless defined( $self->{_socket} );
159              
160             # gracefully close socket.
161 0           $self->{_select}->remove( $self->{_socket} );
162 0           $self->{_socket}->close();
163 0           $self->{_socket} = undef;
164              
165 0           return $self;
166             }
167              
168             #
169             # Get (read) a stat out of the local manager. Note that the assumption is
170             # that you are calling this with an existing stats "name".
171             #
172             sub get_stat {
173 0     0 0   my ( $self, $stat ) = @_;
174 0           my $res = "";
175 0           my $max_read_attempts = 25;
176              
177 0 0         return undef unless defined( $self->{_socket} );
178 0 0         return undef unless $self->{_select}->can_write(10);
179              
180             # This is a total hack for now, we need to wrap this into the proper mgmt API library.
181 0           $self->{_socket}
182             ->print( pack( "sla*", TS_RECORD_GET, length($stat) ), $stat );
183              
184 0           while ( $res eq "" ) {
185 0 0         return undef if ( $max_read_attempts-- < 0 );
186 0 0         return undef unless $self->{_select}->can_read(10);
187              
188 0           my $status = $self->{_socket}->sysread( $res, 1024 );
189 0 0 0       return undef unless defined($status) || ( $status == 0 );
190              
191             }
192 0           my @resp = unpack( "sls", $res );
193 0 0         return undef unless ( scalar(@resp) == 3 );
194              
195 0 0         if ( $resp[0] == TS_ERR_OKAY ) {
196 0 0         if ( $resp[2] < TS_REC_FLOAT ) {
    0          
    0          
197 0           @resp = unpack( "slsl", $res );
198 0 0         return undef unless ( scalar(@resp) == 4 );
199 0           return int( $resp[3] );
200             }
201             elsif ( $resp[2] == TS_REC_FLOAT ) {
202 0           @resp = unpack( "slsf", $res );
203 0 0         return undef unless ( scalar(@resp) == 4 );
204 0           return $resp[3];
205             }
206             elsif ( $resp[2] == TS_REC_STRING ) {
207 0           @resp = unpack( "slsa*", $res );
208 0 0         return undef unless ( scalar(@resp) == 4 );
209 0           return $resp[3];
210             }
211             }
212              
213 0           return undef;
214             }
215              
216             1;
217              
218             __END__