1 package OpenSRF::UnixServer;
2 use strict; use warnings;
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/;
11 use OpenSRF::Utils::SettingsClient;
13 use vars qw/@ISA $app/;
16 # XXX Need to add actual logging statements in the code
17 my $logger = "OpenSRF::Utils::Logger";
19 sub DESTROY { confess "Dying $$"; }
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
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.
34 sub app { return $app; }
39 my( $class, $app1 ) = @_;
41 throw OpenSRF::EX::InvalidArg( "UnixServer requires an app name to run" );
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();
57 =head2 process_request()
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.
68 while( $d = <STDIN> ) { $data .= $d; }
73 if( ! $data or ! defined( $data ) or $data eq "" ) {
74 throw OpenSRF::EX::Socket(
75 "Unix child received empty data from socket" );
78 if( ! close( $self->{server}->{client} ) ) {
79 $logger->debug( "Error closing Unix socket: $!", ERROR );
83 my $app = $self->app();
84 $logger->transport( "UnixServer for $app received $data", INTERNAL );
86 my $app_session = OpenSRF::Transport->handler( $self->app(), $data );
88 if(!ref($app_session)) {
89 $logger->transport( "Did not receive AppSession from transport handler, returning...", WARN );
94 my $client = OpenSRF::Utils::SettingsClient->new();
95 my $keepalive = $client->config_value("apps", $self->app(), "keepalive");
98 while( $app_session->state and $app_session->state != $app_session->DISCONNECTED() and
99 $app_session->find( $app_session->session_id ) ) {
103 $logger->transport( "UnixServer calling queue_wait $keepalive", INTERNAL );
104 $app_session->queue_wait( $keepalive );
105 $logger->transport( "after queue wait $keepalive", INTERNAL );
108 if( ($after - $before) >= $keepalive ) {
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() );
122 $logger->transport( "Looping on zombies " . $x++ , DEBUG);
123 last unless ( $app_session->queue_wait(0));
126 $logger->transport( "Timed out, disconnected, or auth failed", INFO );
127 $app_session->kill_me;
138 my $app = $self->app();
140 my $client = OpenSRF::Utils::SettingsClient->new();
141 $logger->transport("Max Req: " . $client->config_value("apps", $app, "unix_config", "max_requests" ), INFO );
143 my $min_servers = $client->config_value("apps", $app, "unix_config", "min_children" );
144 my $max_servers = $client->config_value("apps", $app, "unix_config", "max_children" );
145 my $min_spare = $client->config_value("apps", $app, "unix_config", "min_spare_children" );
146 my $max_spare = $client->config_value("apps", $app, "unix_config", "max_spare_children" );
147 my $max_requests = $client->config_value("apps", $app, "unix_config", "max_requests" );
148 my $log_file = join("/", $client->config_value("dirs", "log"),
149 $client->config_value("apps", $app, "unix_config", "unix_log" ));
150 my $port = join("/", $client->config_value("dirs", "sock"),
151 $client->config_value("apps", $app, "unix_config", "unix_sock" ));
152 my $pid_file = join("/", $client->config_value("dirs", "pid"),
153 $client->config_value("apps", $app, "unix_config", "unix_pid" ));
155 my $file = "/tmp/" . time . rand( $$ ) . "_$$";
156 my $file_string = "min_servers $min_servers\nmax_servers $max_servers\n" .
157 "min_spare_servers $min_spare\nmax_spare_servers $max_spare\n" .
158 "max_requests $max_requests\nlog_file $log_file\nproto unix\n" .
159 "port $port\npid_file $pid_file\nlog_level 3\n";
161 open F, "> $file" or die "Can't open $file : $!";
162 print F $file_string;
165 $self->run( 'conf_file' => $file );
171 my $app = $self->app;
174 OpenSRF::System::bootstrap_client("system_client");
176 $logger->debug( "Setting application implementaion for $app", DEBUG );
177 my $client = OpenSRF::Utils::SettingsClient->new();
178 my $imp = $client->config_value("apps", $app, "implementation");
179 OpenSRF::Application::server_class($app);
180 OpenSRF::Application->application_implementation( $imp );
181 JSON->register_class_hint( name => $imp, hint => $app, type => "hash" );
182 OpenSRF::Application->application_implementation->initialize()
183 if (OpenSRF::Application->application_implementation->can('initialize'));
185 if( $client->config_value("server_type") !~ /fork/i ) {
186 $self->child_init_hook();
189 my $con = OpenSRF::Transport::PeerHandle->retrieve;
194 return OpenSRF::Application->application_implementation;
197 sub child_finish_hook {
199 OpenSRF::AppSession->kill_client_session_cache;
202 sub child_init_hook {
209 "Creating PeerHandle from UnixServer child_init_hook", INTERNAL );
210 OpenSRF::Transport::PeerHandle->construct( $self->app() );
211 $logger->transport( "PeerHandle Created from UnixServer child_init_hook", INTERNAL );
213 OpenSRF::Application->application_implementation->child_init
214 if (OpenSRF::Application->application_implementation->can('child_init'));
215 return OpenSRF::Transport::PeerHandle->retrieve;