]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/perlmods/OpenSRF/UnixServer.pm
added a cache flag to the settings client
[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         my $client = OpenSRF::Utils::SettingsClient->new();
141         $logger->transport("Max Req: " . $client->config_value("apps", $app, "unix_config", "max_requests" ), INFO );
142
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" ));
154
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";
160
161         open F, "> $file" or die "Can't open $file : $!";
162         print F $file_string;
163         close F;
164
165         $self->run( 'conf_file' => $file );
166
167 }
168
169 sub configure_hook {
170         my $self = shift;
171         my $app = $self->app;
172
173         # boot a client
174         OpenSRF::System::bootstrap_client("system_client");
175
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'));
184
185         if( $client->config_value("server_type") !~ /fork/i  ) {
186                 $self->child_init_hook();
187         }
188
189         my $con = OpenSRF::Transport::PeerHandle->retrieve;
190         if($con) {
191                 $con->disconnect;
192         }
193
194         return OpenSRF::Application->application_implementation;
195 }
196
197 sub child_finish_hook {
198         my $self = shift;
199         OpenSRF::AppSession->kill_client_session_cache;
200 }
201
202 sub child_init_hook { 
203
204         $0 = "$0_child";
205
206         my $self = shift;
207
208         $logger->transport( 
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 );
212
213         OpenSRF::Application->application_implementation->child_init
214                 if (OpenSRF::Application->application_implementation->can('child_init'));
215         return OpenSRF::Transport::PeerHandle->retrieve;
216
217 }
218
219 1;
220