]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/perlmods/OpenSRF/UnixServer.pm
using OO syntax
[OpenSRF.git] / src / perlmods / OpenSRF / UnixServer.pm
1 package OpenSRF::UnixServer;
2 use strict; use warnings;
3 use base qw/OpenSRF/;
4 use OpenSRF::EX;
5 use OpenSRF::Utils::Logger qw(:level);
6 use OpenSRF::Transport::PeerHandle;
7 use OpenSRF::Application;
8 use OpenSRF::AppSession;
9 use OpenSRF::DomainObject::oilsResponse qw/:status/;
10 use OpenSRF::System;
11 use OpenSRF::Utils::SettingsClient;
12 use JSON;
13 use vars qw/@ISA $app/;
14 use Carp;
15
16 # XXX Need to add actual logging statements in the code
17 my $logger = "OpenSRF::Utils::Logger";
18
19 sub DESTROY { confess "Dying $$"; }
20
21
22 =head1 What am I
23
24 All inbound messages are passed on to the UnixServer for processing.
25 We take the data, close the Unix socket, and pass the data on to our abstract
26 'process()' method.  
27
28 Our purpose is to 'multiplex' a single TCP connection into multiple 'client' connections.
29 So when you pass data down the Unix socket to us, we have been preforked and waiting
30 to disperse new data among us.
31
32 =cut
33
34 sub app { return $app; }
35
36 {
37
38         sub new {
39                 my( $class, $app1 ) = @_;
40                 if( ! $app1 ) {
41                         throw OpenSRF::EX::InvalidArg( "UnixServer requires an app name to run" );
42                 }
43                 $app = $app1;
44                 my $self = bless( {}, $class );
45 #               my $client = OpenSRF::Utils::SettingsClient->new();
46 #               if( $client->config_value("server_type") !~ /fork/i || 
47 #                               OpenSRF::Utils::Config->current->bootstrap->settings_config ) {
48 #                       warn "Calling hooks for non-prefork\n";
49 #                       $self->configure_hook();
50 #                       $self->child_init_hook();
51 #               }
52                 return $self;
53         }
54
55 }
56
57 =head2 process_request()
58
59 Takes the incoming data, closes the Unix socket and hands the data untouched 
60 to the abstract process() method.  This method is implemented in our subclasses.
61
62 =cut
63
64 sub process_request {
65
66         my $self = shift;
67         my $data; my $d;
68         while( $d = <STDIN> ) { $data .= $d; }
69
70         $0 = "$0*";
71
72
73         if( ! $data or ! defined( $data ) or $data eq "" ) {
74                 throw OpenSRF::EX::Socket(
75                                 "Unix child received empty data from socket" );
76         }
77
78         if( ! close( $self->{server}->{client} ) ) {
79                 $logger->debug( "Error closing Unix socket: $!", ERROR );
80         }
81
82
83         my $app = $self->app();
84         $logger->transport( "UnixServer for $app received $data", INTERNAL );
85
86         my $app_session = OpenSRF::Transport->handler( $self->app(), $data );
87
88         if(!ref($app_session)) {
89                 $logger->transport( "Did not receive AppSession from transport handler, returning...", WARN );
90                 $0 =~ s/\*//g;
91                 return;
92         }
93
94         my $client = OpenSRF::Utils::SettingsClient->new();
95         my $keepalive = $client->config_value("apps", $self->app(), "keepalive");
96
97         my $req_counter = 0;
98         while( $app_session->state and $app_session->state != $app_session->DISCONNECTED() and
99                         $app_session->find( $app_session->session_id ) ) {
100                 
101
102                 my $before = time;
103                 $logger->transport( "UnixServer calling queue_wait $keepalive", INTERNAL );
104                 $app_session->queue_wait( $keepalive );
105                 $logger->transport( "after queue wait $keepalive", INTERNAL );
106                 my $after = time;
107
108                 if( ($after - $before) >= $keepalive ) { 
109
110                         my $res = OpenSRF::DomainObject::oilsConnectStatus->new(
111                                                                         status => "Disconnected on timeout",
112                                                                         statusCode => STATUS_TIMEOUT);
113                         $app_session->status($res);
114                         $app_session->state( $app_session->DISCONNECTED() );
115                         last;
116                 }
117
118         }
119
120         my $x = 0;
121         while( 1 ) {
122                 $logger->transport( "Looping on zombies " . $x++ , DEBUG);
123                 last unless ( $app_session->queue_wait(0));
124         }
125
126         $logger->transport( "Timed out, disconnected, or auth failed", INFO );
127         $app_session->kill_me;
128
129         $0 =~ s/\*//g;
130
131                 
132 }
133
134
135 sub serve {
136         my( $self ) = @_;
137
138         my $app = $self->app();
139
140         $0 = "OpenSRF master ($app)";
141
142         my $client = OpenSRF::Utils::SettingsClient->new();
143         $logger->transport("Max Req: " . $client->config_value("apps", $app, "unix_config", "max_requests" ), INFO );
144
145         my $min_servers = $client->config_value("apps", $app, "unix_config", "min_children" );
146         my $max_servers = $client->config_value("apps", $app, "unix_config", "max_children" );
147         my $min_spare    =      $client->config_value("apps", $app, "unix_config", "min_spare_children" );
148         my $max_spare    = $client->config_value("apps", $app, "unix_config", "max_spare_children" );
149         my $max_requests = $client->config_value("apps", $app, "unix_config", "max_requests" );
150         my $log_file = join("/", $client->config_value("dirs", "log"),
151                                 $client->config_value("apps", $app, "unix_config", "unix_log" ));
152         my $port =      join("/", $client->config_value("dirs", "sock"),
153                                 $client->config_value("apps", $app, "unix_config", "unix_sock" ));
154         my $pid_file =  join("/", $client->config_value("dirs", "pid"),
155                                 $client->config_value("apps", $app, "unix_config", "unix_pid" ));
156
157         my $file = "/tmp/" . time . rand( $$ ) . "_$$";
158         my $file_string = "min_servers $min_servers\nmax_servers $max_servers\n" .
159                 "min_spare_servers $min_spare\nmax_spare_servers $max_spare\n" .
160                 "max_requests $max_requests\nlog_file $log_file\nproto unix\n" . 
161                 "port $port\npid_file $pid_file\nlog_level 3\n";
162
163         open F, "> $file" or die "Can't open $file : $!";
164         print F $file_string;
165         close F;
166
167         $self->run( 'conf_file' => $file );
168
169 }
170
171 sub configure_hook {
172         my $self = shift;
173         my $app = $self->app;
174
175         # boot a client
176         OpenSRF::System->bootstrap_client( client_name => "system_client" );
177
178         $logger->debug( "Setting application implementaion for $app", DEBUG );
179         my $client = OpenSRF::Utils::SettingsClient->new();
180         my $imp = $client->config_value("apps", $app, "implementation");
181         OpenSRF::Application::server_class($app);
182         OpenSRF::Application->application_implementation( $imp );
183         JSON->register_class_hint( name => $imp, hint => $app, type => "hash" );
184         OpenSRF::Application->application_implementation->initialize()
185                 if (OpenSRF::Application->application_implementation->can('initialize'));
186
187         if( $client->config_value("server_type") !~ /fork/i  ) {
188                 $self->child_init_hook();
189         }
190
191         my $con = OpenSRF::Transport::PeerHandle->retrieve;
192         if($con) {
193                 $con->disconnect;
194         }
195
196         return OpenSRF::Application->application_implementation;
197 }
198
199 sub child_finish_hook {
200         my $self = shift;
201         OpenSRF::AppSession->kill_client_session_cache;
202 }
203
204 sub child_init_hook { 
205
206         $0 =~ s/master/drone/g;
207
208         my $self = shift;
209
210 #       $logger->transport( 
211 #                       "Creating PeerHandle from UnixServer child_init_hook", INTERNAL );
212         OpenSRF::Transport::PeerHandle->construct( $self->app() );
213         $logger->transport( "PeerHandle Created from UnixServer child_init_hook", INTERNAL );
214
215         OpenSRF::Application->application_implementation->child_init
216                 if (OpenSRF::Application->application_implementation->can('child_init'));
217         return OpenSRF::Transport::PeerHandle->retrieve;
218
219 }
220
221 1;
222