1 package OpenSRF::UnixServer;
2 use strict; use warnings;
4 use OpenSRF::EX qw(:try);
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; }
74 if( ! $data or ! defined( $data ) or $data eq "" ) {
75 close($self->{server}->{client});
76 $logger->debug("Unix child received empty data from socket", ERROR);
82 if( ! close( $self->{server}->{client} ) ) {
83 $logger->debug( "Error closing Unix socket: $!", ERROR );
87 my $app = $self->app();
88 $logger->transport( "UnixServer for $app received $data", INTERNAL );
90 my $app_session = OpenSRF::Transport->handler( $self->app(), $data );
92 if(!ref($app_session)) {
93 $logger->transport( "Did not receive AppSession from transport handler, returning...", WARN );
98 if($app_session->stateless and $app_session->state != $app_session->CONNECTED()){
99 $logger->debug("Exiting keepalive for stateless session / orig = $orig");
100 $app_session->kill_me;
106 my $client = OpenSRF::Utils::SettingsClient->new();
107 my $keepalive = $client->config_value("apps", $self->app(), "keepalive");
110 while( $app_session and
111 $app_session->state and
112 $app_session->state != $app_session->DISCONNECTED() and
113 $app_session->find( $app_session->session_id ) ) {
117 $logger->debug( "UnixServer calling queue_wait $keepalive", INTERNAL );
118 $app_session->queue_wait( $keepalive );
119 $logger->debug( "after queue wait $keepalive", INTERNAL );
122 if( ($after - $before) >= $keepalive ) {
124 my $res = OpenSRF::DomainObject::oilsConnectStatus->new(
125 status => "Disconnected on timeout",
126 statusCode => STATUS_TIMEOUT);
127 $app_session->status($res);
128 $app_session->state( $app_session->DISCONNECTED() );
135 while( $app_session && $app_session->queue_wait(0) ) {
136 $logger->debug( "Looping on zombies " . $x++ , DEBUG);
139 $logger->debug( "Timed out, disconnected, or auth failed", INFO );
140 $app_session->kill_me if ($app_session);
151 my $app = $self->app();
153 $0 = "OpenSRF master [$app]";
155 my $client = OpenSRF::Utils::SettingsClient->new();
156 $logger->transport("Max Req: " . $client->config_value("apps", $app, "unix_config", "max_requests" ), INFO );
158 my $min_servers = $client->config_value("apps", $app, "unix_config", "min_children" );
159 my $max_servers = $client->config_value("apps", $app, "unix_config", "max_children" );
160 my $min_spare = $client->config_value("apps", $app, "unix_config", "min_spare_children" );
161 my $max_spare = $client->config_value("apps", $app, "unix_config", "max_spare_children" );
162 my $max_requests = $client->config_value("apps", $app, "unix_config", "max_requests" );
163 my $log_file = join("/", $client->config_value("dirs", "log"),
164 $client->config_value("apps", $app, "unix_config", "unix_log" ));
165 my $port = join("/", $client->config_value("dirs", "sock"),
166 $client->config_value("apps", $app, "unix_config", "unix_sock" ));
167 my $pid_file = join("/", $client->config_value("dirs", "pid"),
168 $client->config_value("apps", $app, "unix_config", "unix_pid" ));
170 my $file = "/tmp/" . time . rand( $$ ) . "_$$";
171 my $file_string = "min_servers $min_servers\nmax_servers $max_servers\n" .
172 "min_spare_servers $min_spare\nmax_spare_servers $max_spare\n" .
173 "max_requests $max_requests\nlog_file $log_file\nproto unix\n" .
174 "port $port\npid_file $pid_file\nlog_level 3\n";
176 open F, "> $file" or die "Can't open $file : $!";
177 print F $file_string;
180 $self->run( 'conf_file' => $file );
187 my $app = $self->app;
190 OpenSRF::System->bootstrap_client( client_name => "system_client" );
192 $logger->debug( "Setting application implementaion for $app", DEBUG );
193 my $client = OpenSRF::Utils::SettingsClient->new();
194 my $imp = $client->config_value("apps", $app, "implementation");
195 OpenSRF::Application::server_class($app);
196 OpenSRF::Application->application_implementation( $imp );
197 JSON->register_class_hint( name => $imp, hint => $app, type => "hash" );
198 OpenSRF::Application->application_implementation->initialize()
199 if (OpenSRF::Application->application_implementation->can('initialize'));
201 if( $client->config_value("server_type") !~ /fork/i ) {
202 $self->child_init_hook();
205 my $con = OpenSRF::Transport::PeerHandle->retrieve;
210 return OpenSRF::Application->application_implementation;
213 sub child_finish_hook {
215 OpenSRF::AppSession->kill_client_session_cache;
218 sub child_init_hook {
220 $0 =~ s/master/drone/g;
222 if ($ENV{OPENSRF_PROFILE}) {
225 eval "use Devel::Profiler output_file => '/tmp/profiler_$file.out', buffer_size => 0;";
227 $logger->debug("Could not load Devel::Profiler: $@",ERROR);
229 $0 .= ' [PROFILING]';
230 $logger->debug("Running under Devel::Profiler", INFO);
236 # $logger->transport(
237 # "Creating PeerHandle from UnixServer child_init_hook", INTERNAL );
238 OpenSRF::Transport::PeerHandle->construct( $self->app() );
239 $logger->transport( "PeerHandle Created from UnixServer child_init_hook", INTERNAL );
241 OpenSRF::Application->application_implementation->child_init
242 if (OpenSRF::Application->application_implementation->can('child_init'));
243 return OpenSRF::Transport::PeerHandle->retrieve;