File Coverage

blib/lib/POEIKC/Daemon.pm
Criterion Covered Total %
statement 27 27 100.0
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 36 36 100.0


line stmt bran cond sub pod time code
1             package POEIKC::Daemon;
2              
3 1     1   6 use strict;
  1         45  
  1         175  
4              
5 1     1   30 use 5.008_001;
  1         3  
  1         56  
6              
7 1     1   6 use warnings;
  1         2  
  1         34  
8 1     1   1359 use Data::Dumper;
  1         16217  
  1         94  
9 1     1   1221 use Sys::Hostname ();
  1         1936  
  1         27  
10 1     1   1508 use Class::Inspector;
  1         4758  
  1         38  
11 1     1   898 use UNIVERSAL::require;
  1         1745  
  1         11  
12 1     1   920 use Proc::Killall;
  1         52632  
  1         77  
13 1         8 use POE qw(
14             Sugar::Args
15             Loop::IO_Poll
16             Component::IKC::Server
17             Component::IKC::Client
18 1     1   982 );
  1         74698  
19              
20             use base qw/Class::Accessor::Fast/;
21              
22             use POEIKC;
23             our $VERSION = $POEIKC::VERSION;
24             use POEIKC::Daemon::Utility;
25              
26             our @inc = @INC;
27             our %inc = %INC;
28             our $DEBUG;
29             our %opt;
30             our %connected;
31              
32             __PACKAGE__->mk_accessors(qw/pidu argv alias ikc_self_port ikc_self_name server_port server_name/);
33              
34              
35              
36             ####
37              
38             sub ikc_server_param {
39             my $self = shift;
40             $self->{ikc_server_param}->{$_[0]} = $_[1] if (@_ and $_[1]);
41             return %{$self->{ikc_server_param}};
42             }
43              
44             sub init {
45             my $class = shift || __PACKAGE__ ;
46             my $self = $class->new;
47             $DEBUG = $opt{debug};
48             $self->argv($opt{argv}) if $opt{argv};
49             $self->alias($opt{alias} || 'POEIKCd');
50              
51             if ( exists $opt{"0PROGRAM_NAME"} ) {
52             my $pn = $opt{"0PROGRAM_NAME"} || $opt{"name"} || 'poeikcd' ;
53             $0 = sprintf "%s --alias=%s --port=%s",
54             $pn, $self->alias, $opt{port} ;
55             }else{
56             if ($opt{"name"}){
57             $0 = sprintf "poeikcd --name=%s --alias=%s --port=%s",
58             $opt{"name"}, $self->alias, $opt{port} ;
59             }else{
60             $0 = sprintf "poeikcd --alias=%s --port=%s",
61             $self->alias, $opt{port} ;
62             }
63             }
64              
65              
66             $opt{name} ||= join('_'=>__PACKAGE__ =~ m/(\w+)/g);
67             $self->server_name($opt{name});
68              
69             $opt{port} ||= $ARGV[0] || 47225 ;
70             $self->server_port($opt{port});
71              
72             $self->ikc_server_param(name =>$opt{name});
73             $self->ikc_server_param(port =>$opt{port});
74             $self->ikc_server_param(verbose =>$opt{Verbose});
75             $self->ikc_server_param(processes =>$opt{Processes});
76             $self->ikc_server_param(babysit =>$opt{babysit});
77             $self->ikc_server_param(connections =>$opt{connections});
78              
79             $self->pidu(POEIKC::Daemon::Utility->_new);
80             $self->pidu->_init();
81             $self->pidu->DEBUG($DEBUG) if $DEBUG;
82             $self->pidu->inc->{org_inc}= \%inc;
83             #$self->pidu->stay(module=>'POEIKC::Daemon::Utility');
84              
85             push @{$opt{Module}}, __PACKAGE__, 'POEIKC::Daemon::Utility';
86             $self->pidu->inc->{load}->{ $_ } = [$INC{Class::Inspector->filename($_)},scalar localtime] for @{$opt{Module}};
87              
88              
89             if ($DEBUG) {
90             no warnings 'redefine';
91             *POE::Component::IKC::Responder::DEBUG = sub { 1 };
92             *POE::Component::IKC::Responder::Object::DEBUG = sub { 1 };
93             POEIKC::Daemon::Utility::_DEBUG_log(VERSION =>$VERSION);
94             POEIKC::Daemon::Utility::_DEBUG_log(load_module=>$self->pidu->inc->{load});
95             POEIKC::Daemon::Utility::_DEBUG_log(GetOptions=>\%opt);
96             POEIKC::Daemon::Utility::_DEBUG_log('@INC' =>\@INC);
97             POEIKC::Daemon::Utility::_DEBUG_log({$self->ikc_server_param});
98             }
99             return $self;
100             }
101              
102             sub daemon {
103             my $class = shift || __PACKAGE__ ;
104             %opt = @_;
105             my @startup = @{$opt{Module}} if exists $opt{Module};
106             my $self = $class->init(%opt);
107             $self->spawn();
108             if (@startup and exists $opt{startup}) {
109             $self->startup($_, $opt{startup}) for ( @startup );
110             }
111             $self->poe_run();
112             }
113              
114             sub poe_run {
115             POE::Kernel->run();
116             }
117              
118              
119             sub spawn
120             {
121             my $self = shift;
122             my %param = (
123             aliases => [ $self->server_name .'_'. Sys::Hostname::hostname],
124             $self->ikc_server_param
125             );
126              
127             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(\%param);
128              
129             POE::Component::IKC::Server->spawn(%param);
130              
131             POE::Session->create(
132             object_states => [ $self => Class::Inspector->methods(__PACKAGE__) ]
133             );
134              
135             # if ($self->argv){
136             # my ( $session_alias, $event, $args ) = @{$self->argv};
137             # my ( $session_alias, $event, $args ) = @{$self->argv};
138             # }
139              
140             return 1;
141             }
142              
143             sub startup {
144             my $self = shift;
145             my $module = shift;
146             my $startup = shift || 'spawn';
147             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log("$module->$startup()");
148             $module->$startup();
149             }
150              
151             sub _start {
152             my $poe = sweet_args ;
153             my $object = $poe->object;
154              
155             printf "%s PID:%s ... Started!! (%s)\n", $0, $$, scalar(localtime);
156              
157             my $kernel = $poe->kernel;
158              
159             $object->{start_time} = localtime;
160             $kernel->alias_set($object->alias);
161              
162             # 終了処理 を登録
163             $kernel->sig( HUP => 'sig_stop' );
164             $kernel->sig( INT => 'sig_stop' );
165             $kernel->sig( TERM => 'sig_stop' );
166             $kernel->sig( KILL => 'sig_stop' );
167              
168             $kernel->call(
169             IKC =>
170             #publish => $object->alias, Class::Inspector->methods(__PACKAGE__),
171             publish => $object->alias, [qw/
172             _stop
173             event_respond
174             execute_respond
175             function_respond
176             method_respond
177             something_respond
178             /],
179             );
180              
181             if ($DEBUG) {
182             $kernel->post(IKC=>'monitor', '*'=>{
183             register =>'debug_monitor_callback_register',
184             unregister =>'debug_monitor_callback_unregister',
185             subscribe =>'debug_monitor_callback_subscribe',
186             unsubscribe =>'debug_monitor_callback_unsubscribe',
187             shutdown =>'debug_monitor_callback_shutdown',
188             data =>'(foo)',
189             });
190             }else{
191             $kernel->post(IKC=>'monitor', '*'=>{
192             register =>'monitor_register',
193             unregister =>'monitor_unregister',
194             });
195             }
196             }
197              
198              
199             sub monitor_register
200             {
201             my $poe = sweet_args ;
202             my $object = $poe->object;
203             my $client = (@{$poe->args})[1];
204             $connected{$client}++;
205             }
206              
207             sub monitor_unregister
208             {
209             my $poe = sweet_args ;
210             my $object = $poe->object;
211             my $client = (@{$poe->args})[1];
212             delete $connected{$client} if $connected{$client};
213             }
214              
215              
216              
217              
218             sub debug_monitor_callback_register
219             {
220             my $poe = sweet_args ;
221             my $object = $poe->object;
222             my $client = (@{$poe->args})[1];
223             $connected{$client}++;
224             POEIKC::Daemon::Utility::_DEBUG_log(join " / ", map {$_ ? $_ : ''} @{$poe->args});
225             }
226              
227             sub debug_monitor_callback_unregister
228             {
229             my $poe = sweet_args ;
230             my $object = $poe->object;
231             my $client = (@{$poe->args})[1];
232             delete $connected{$client} if $connected{$client};
233             POEIKC::Daemon::Utility::_DEBUG_log(join " / ", map {$_ ? $_ : ''} @{$poe->args});
234             }
235              
236             sub debug_monitor_callback_subscribe
237             {
238             my $poe = sweet_args ;
239             POEIKC::Daemon::Utility::_DEBUG_log(join " / ", map {$_ ? $_ : ''} @{$poe->args});
240             }
241              
242             sub debug_monitor_callback_unsubscribe
243             {
244             my $poe = sweet_args ;
245             POEIKC::Daemon::Utility::_DEBUG_log(join " / ", map {$_ ? $_ : ''} @{$poe->args});
246             }
247              
248             sub debug_monitor_callback_shutdown
249             {
250             my $poe = sweet_args ;
251             POEIKC::Daemon::Utility::_DEBUG_log(join " / ", map {$_ ? $_ : ''} @{$poe->args});
252             }
253              
254              
255              
256              
257             sub sig_stop {
258             my $poe = sweet_args;
259             my $kernel = $poe->kernel;
260             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(\%connected);
261             $kernel->yield('_stop');
262             }
263              
264             sub _stop {
265             my $poe = sweet_args;
266             my $kernel = $poe->kernel;
267             $kernel->call( IKC => 'shutdown');
268             $kernel->stop();
269             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(\%connected);
270             printf "%s PID:%s ... stopped!! (%s)\n", $0, $$, scalar(localtime);
271             }
272              
273             sub shutdown {
274             my $poe = sweet_args;
275             my $kernel = $poe->kernel;
276             my $object = $poe->object;
277             $object->{shutdown_time} ||= time;
278             $object->{shutdown_cut} ||= 0;
279             if ( $object->{shutdown_cut} < 10 and keys %connected ) {
280             $object->{shutdown_cut}++;
281             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log($object->{shutdown_time});
282             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(\%connected);
283             $kernel->delay(shutdown => 0.05);
284             # $kernel->delay(shutdown => 0.0001);
285             return;
286             }
287             $kernel->call( IKC => 'shutdown');
288             $kernel->stop();
289             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log($object->{shutdown_time});
290             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(\%connected);
291             killall('KILL', $0); # SIGKILL
292             printf "%s PID:%s ... stopped!! (%s)\n", $0, $$, scalar(localtime);
293             }
294              
295              
296             sub something_respond {
297             my $poe = sweet_args;
298             my $kernel = $poe->kernel;
299             my $session = $poe->session;
300             my $object = $poe->object;
301             my ($request) = @{$poe->args};
302             my ($args, $rsvp) = @{$request};
303              
304             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log($request);
305              
306             my @something = $object->pidu->_distinguish( poe=>$poe, args => $args );
307             @something ?
308             $kernel->call($session, execute_respond => @something, $rsvp):
309              
310             $kernel->post( IKC => post => $rsvp, {poeikcd_error=>
311             'It is not discriminable. '.
312             q{"ModuleName::functionName" or "ClassName->methodName" or "AliasName eventName"}
313             });
314             }
315              
316             sub event_respond {
317             my $poe = sweet_args;
318             my $kernel = $poe->kernel;
319             my ($request) = @{$poe->args};
320             $kernel->yield(execute_respond => 'event', @{$request});
321             }
322              
323             sub method_respond {
324             my $poe = sweet_args;
325             my $kernel = $poe->kernel;
326             my ($request) = @{$poe->args};
327             $kernel->yield(execute_respond => 'method', @{$request});
328             }
329              
330             sub function_respond {
331             my $poe = sweet_args;
332             my $kernel = $poe->kernel;
333             my ($request) = @{$poe->args};
334             $kernel->yield(execute_respond => 'function', @{$request});
335             }
336              
337             sub execute_respond {
338             my $poe = sweet_args;
339             my $kernel = $poe->kernel;
340             my $object = $poe->object;
341             my ( $from, $args, $rsvp , ) = @{$poe->args};
342              
343              
344             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log($from, $args, $rsvp);
345              
346             ref $args ne 'ARRAY' and
347             return $kernel->call( IKC => post => $rsvp,
348             {poeikcd_error=>"A parameter is not an Array reference. It is ".ref $args} );
349              
350             my $module = shift @{$args};
351             my $method = shift @{$args};
352              
353             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(module => $module);
354             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(method => $method);
355             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(args => $args);
356              
357             if($from !~ /^event/ and not $object->pidu->use(module=>$module)) {
358              
359             return $kernel->call( IKC => post => $rsvp, {poeikcd_error=>$@} );
360             }
361              
362             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log(from => $from);
363              
364             if ($module eq 'POEIKC::Daemon::Utility'){
365             #$DEBUG and POEIKC::Daemon::Utility::_DEBUG_log($rsvp);
366             my @re = eval {
367             $method ?
368             $object->pidu->$method(
369             poe=>$poe, rsvp=>$rsvp, from=>$from, args=>$args
370             ) : grep {not /^\_/ and not /^[A-Z]+$/} @{Class::Inspector->methods($module)};
371             };
372             my $re = @re == 1 ? shift @re : @re ? \@re : ();
373             if (not $rsvp->{responded}) {
374             $@ ? $kernel->post( IKC => post => $rsvp, {poeikcd_error=>$@} ) :
375             $kernel->post( IKC => post => $rsvp, $re );
376             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log($re, $rsvp);
377             }else{
378             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log($re, $rsvp);
379             }
380             return;
381             }
382              
383             my @re = $object->pidu->execute(poe=>$poe, from=>$from, module=>$module, method=>$method, args=>$args);
384             my $e = $@ if $@;
385              
386             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log('error=>'=>$e);
387             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log('@re=>'=>@re);
388             my $re = @re == 1 ? shift @re : @re ? \@re : ();
389              
390             $DEBUG and POEIKC::Daemon::Utility::_DEBUG_log($module, $method, $re);
391              
392             if ($rsvp) {
393             return $e ? $kernel->post( IKC => post => $rsvp, {poeikcd_error=>$e} ) :
394             $kernel->post( IKC => post => $rsvp, $re );
395              
396             return $kernel->post( IKC => post => $rsvp, $re ) if $re;
397             }else{
398             return @re ? @re : $re || ();
399             }
400              
401             }
402              
403              
404              
405             1;
406             __END__