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;
12 use Time::HiRes qw(time);
14 use vars qw/@ISA $app/;
17 # XXX Need to add actual logging statements in the code
18 my $logger = "OpenSRF::Utils::Logger";
20 sub DESTROY { confess "Dying $$"; }
25 All inbound messages are passed on to the UnixServer for processing.
26 We take the data, close the Unix socket, and pass the data on to our abstract
29 Our purpose is to 'multiplex' a single TCP connection into multiple 'client' connections.
30 So when you pass data down the Unix socket to us, we have been preforked and waiting
31 to disperse new data among us.
35 sub app { return $app; }
40 my( $class, $app1 ) = @_;
42 throw OpenSRF::EX::InvalidArg( "UnixServer requires an app name to run" );
45 my $self = bless( {}, $class );
46 # my $client = OpenSRF::Utils::SettingsClient->new();
47 # if( $client->config_value("server_type") !~ /fork/i ||
48 # OpenSRF::Utils::Config->current->bootstrap->settings_config ) {
49 # warn "Calling hooks for non-prefork\n";
50 # $self->configure_hook();
51 # $self->child_init_hook();
58 =head2 process_request()
60 Takes the incoming data, closes the Unix socket and hands the data untouched
61 to the abstract process() method. This method is implemented in our subclasses.
69 while( $d = <STDIN> ) { $data .= $d; }
75 if( ! $data or ! defined( $data ) or $data eq "" ) {
76 close($self->{server}->{client});
77 $logger->debug("Unix child received empty data from socket", ERROR);
83 if( ! close( $self->{server}->{client} ) ) {
84 $logger->debug( "Error closing Unix socket: $!", ERROR );
88 my $app = $self->app();
89 $logger->transport( "UnixServer for $app received $data", INTERNAL );
91 my $app_session = OpenSRF::Transport->handler( $self->app(), $data );
93 if(!ref($app_session)) {
94 $logger->transport( "Did not receive AppSession from transport handler, returning...", WARN );
99 if($app_session->stateless and $app_session->state != $app_session->CONNECTED()){
100 $logger->debug("Exiting keepalive for stateless session / orig = $orig");
101 $app_session->kill_me;
107 my $client = OpenSRF::Utils::SettingsClient->new();
108 my $keepalive = $client->config_value("apps", $self->app(), "keepalive");
111 while( $app_session and
112 $app_session->state and
113 $app_session->state != $app_session->DISCONNECTED() and
114 $app_session->find( $app_session->session_id ) ) {
118 $logger->debug( "UnixServer calling queue_wait $keepalive", INTERNAL );
119 $app_session->queue_wait( $keepalive );
120 $logger->debug( "after queue wait $keepalive", INTERNAL );
123 if( ($after - $before) >= $keepalive ) {
125 my $res = OpenSRF::DomainObject::oilsConnectStatus->new(
126 status => "Disconnected on timeout",
127 statusCode => STATUS_TIMEOUT);
128 $app_session->status($res);
129 $app_session->state( $app_session->DISCONNECTED() );
136 while( $app_session && $app_session->queue_wait(0) ) {
137 $logger->debug( "Looping on zombies " . $x++ , DEBUG);
140 $logger->debug( "Timed out, disconnected, or auth failed", INFO );
141 $app_session->kill_me if ($app_session);
152 my $app = $self->app();
154 $0 = "OpenSRF master [$app]";
156 system("rm -f /tmp/opensrf_unix_$app*");
158 my $client = OpenSRF::Utils::SettingsClient->new();
159 $logger->transport("Max Req: " . $client->config_value("apps", $app, "unix_config", "max_requests" ), INFO );
161 my $min_servers = $client->config_value("apps", $app, "unix_config", "min_children" );
162 my $max_servers = $client->config_value("apps", $app, "unix_config", "max_children" );
163 my $min_spare = $client->config_value("apps", $app, "unix_config", "min_spare_children" );
164 my $max_spare = $client->config_value("apps", $app, "unix_config", "max_spare_children" );
165 my $max_requests = $client->config_value("apps", $app, "unix_config", "max_requests" );
166 my $log_file = join("/", $client->config_value("dirs", "log"),
167 $client->config_value("apps", $app, "unix_config", "unix_log" ));
168 my $port = join("/", $client->config_value("dirs", "sock"),
169 $client->config_value("apps", $app, "unix_config", "unix_sock" ));
170 my $pid_file = join("/", $client->config_value("dirs", "pid"),
171 $client->config_value("apps", $app, "unix_config", "unix_pid" ));
173 my $file = "/tmp/" . "opensrf_unix_$app"."_" . time . rand( $$ ) . "_$$";
174 my $file_string = "min_servers $min_servers\nmax_servers $max_servers\n" .
175 "min_spare_servers $min_spare\nmax_spare_servers $max_spare\n" .
176 "max_requests $max_requests\nlog_file $log_file\nproto unix\n" .
177 "port $port\npid_file $pid_file\nlog_level 3\n";
179 open F, "> $file" or die "Can't open $file : $!";
180 print F $file_string;
183 $self->run( 'conf_file' => $file );
190 my $app = $self->app;
193 OpenSRF::System->bootstrap_client( client_name => "system_client" );
195 $logger->debug( "Setting application implementaion for $app", DEBUG );
196 my $client = OpenSRF::Utils::SettingsClient->new();
197 my $imp = $client->config_value("apps", $app, "implementation");
198 OpenSRF::Application::server_class($app);
199 OpenSRF::Application->application_implementation( $imp );
200 JSON->register_class_hint( name => $imp, hint => $app, type => "hash" );
201 OpenSRF::Application->application_implementation->initialize()
202 if (OpenSRF::Application->application_implementation->can('initialize'));
204 if( $client->config_value("server_type") !~ /fork/i ) {
205 $self->child_init_hook();
208 my $con = OpenSRF::Transport::PeerHandle->retrieve;
213 return OpenSRF::Application->application_implementation;
216 sub child_finish_hook {
218 OpenSRF::AppSession->kill_client_session_cache;
221 sub child_init_hook {
223 $0 =~ s/master/drone/g;
225 if ($ENV{OPENSRF_PROFILE}) {
228 eval "use Devel::Profiler output_file => '/tmp/profiler_$file.out', buffer_size => 0;";
230 $logger->debug("Could not load Devel::Profiler: $@",ERROR);
232 $0 .= ' [PROFILING]';
233 $logger->debug("Running under Devel::Profiler", INFO);
239 # $logger->transport(
240 # "Creating PeerHandle from UnixServer child_init_hook", INTERNAL );
241 OpenSRF::Transport::PeerHandle->construct( $self->app() );
242 $logger->transport( "PeerHandle Created from UnixServer child_init_hook", INTERNAL );
244 OpenSRF::Application->application_implementation->child_init
245 if (OpenSRF::Application->application_implementation->can('child_init'));
246 return OpenSRF::Transport::PeerHandle->retrieve;