File Coverage

blib/lib/Siebel/Srvrmgr/Daemon.pm
Criterion Covered Total %
statement 136 179 75.9
branch 40 94 42.5
condition 9 12 75.0
subroutine 24 26 92.3
pod 8 8 100.0
total 217 319 68.0


line stmt bran cond sub pod time code
1             package Siebel::Srvrmgr::Daemon;
2              
3             =pod
4              
5             =head1 NAME
6              
7             Siebel::Srvrmgr::Daemon - super class for sessions with Siebel srvrmgr program
8              
9             =head1 SYNOPSIS
10              
11             package MyDaemon;
12              
13             extends 'Siebel::Srvrmgr::Daemon';
14              
15             =head1 DESCRIPTION
16              
17             This is a super class, and alone it does not provide any functionaly to use srvrmgr to send commands and process returned data.
18              
19             The "private" method C<_setup_commands> must be overrided by subclasses of it or commands will not be sent to C<srvrmgr>.
20              
21             Logging of this class can be enabled by using L<Siebel::Srvrmgr> logging feature.
22              
23             The logic behind this class is easy: you can submit a pair of command/action to the class. It will then connect to the server by executing C<srvrmgr>, submit the command
24             to the server and recover the output generated. The action will be executed having this output as parameter. Anything could be considered as an action, from simple
25             storing the output to even generating new commands to be executed in the server.
26              
27             A command is an instance of L<Siebel::Srvrmgr::Daemon::Command> class. Any "list" command is supported, and also C<load preferences> and C<exit>. Anything else
28             is considered dangerous and will generated an exception. Beware that you will need to have an L<Siebel::Srvrmgr::ListParser::Output> class available to be
29             able to parse the command output.
30              
31             An action can be any class but is obligatory to create a subclass of L<Siebel::Srvrmgr::Daemon::Action> base class. See the <commands>
32             attribute for details.
33              
34             Implementation details are reserved to subclasses of Siebel::Srvrmgr::Daemon: be sure to check them for real usage cenarios.
35              
36             =cut
37              
38 6     6   308507 use Moose;
  6         397364  
  6         39  
39 6     6   30063 use Siebel::Srvrmgr::Regexes qw(SIEBEL_ERROR);
  6         11  
  6         338  
40 6     6   1850 use Siebel::Srvrmgr::ListParser;
  6         17  
  6         212  
41 6     6   40 use Siebel::Srvrmgr;
  6         8  
  6         116  
42 6     6   22 use Scalar::Util qw(weaken);
  6         8  
  6         297  
43 6     6   25 use Config;
  6         9  
  6         214  
44 6     6   22 use Siebel::Srvrmgr::Types;
  6         6  
  6         99  
45 6     6   17 use Fcntl ':flock'; # import LOCK_* constants
  6         7  
  6         645  
46 6     6   26 use Config;
  6         7  
  6         114  
47 6     6   20 use Carp;
  6         7  
  6         231  
48 6     6   23 use File::Spec;
  6         5  
  6         10626  
49              
50             my $SIG_INT = 0;
51             my $SIG_PIPE = 0;
52             my $SIG_ALARM = 0;
53              
54             $SIG{INT} = sub { $SIG_INT = 1 };
55             $SIG{PIPE} = sub { $SIG_PIPE = 1 };
56             $SIG{ALRM} = sub { $SIG_ALARM = 1 };
57              
58             # :TODO :19/08/2013 16:19:19:: enable Taint Mode
59              
60             =pod
61              
62             =head1 ATTRIBUTES
63              
64             =head2 server
65              
66             This is a string representing the servername where the instance should connect. This is a optional attribute during
67             object creation with the C<new> method.
68              
69             Beware that the C<run> method will verify if the C<server> attribute has a defined value or not: if it has, the C<run>
70             method will try to connect to the Siebel Enterprise specifying the given Siebel Server. If not, the method will try to connect
71             to the Enterprise only, not specifying which Siebel Server to connect.
72              
73             =cut
74              
75             has server => (
76             isa => 'NotNullStr',
77             is => 'rw',
78             required => 0,
79             reader => 'get_server',
80             writer => 'set_server'
81             );
82              
83             =head2 gateway
84              
85             This is a string representing the gateway where the instance should connect. This is a required attribute during
86             object creation with the C<new> method.
87              
88             =cut
89              
90             has gateway => (
91             isa => 'NotNullStr',
92             is => 'rw',
93             required => 1,
94             reader => 'get_gateway',
95             writer => 'set_gateway'
96             );
97              
98             =head2 enterprise
99              
100             This is a string representing the enterprise where the instance should connect. This is a required attribute during
101             object creation with the C<new> method.
102              
103             =cut
104              
105             has enterprise => (
106             isa => 'NotNullStr',
107             is => 'rw',
108             required => 1,
109             reader => 'get_enterprise',
110             writer => 'set_enterprise'
111             );
112              
113             =head2 user
114              
115             This is a string representing the login for authentication. This is a required attribute during
116             object creation with the C<new> method.
117              
118             =cut
119              
120             has user => (
121             isa => 'NotNullStr',
122             is => 'rw',
123             required => 1,
124             reader => 'get_user',
125             writer => 'set_user'
126             );
127              
128             =head2 password
129              
130             This is a string representing the password for authentication. This is a required attribute during
131             object creation with the C<new> method.
132              
133             =cut
134              
135             has password => (
136             isa => 'NotNullStr',
137             is => 'rw',
138             required => 1,
139             reader => 'get_password',
140             writer => 'set_password'
141             );
142              
143             =head2 commands
144              
145             An array reference containing one or more references of L<Siebel::Srvrmgr::Daemon::Commands> class.
146              
147             The commands will be executed in the exactly order as given by the indexes in the array reference (as FIFO).
148              
149             This is a required attribute during object creation with the C<new> method.
150              
151             =cut
152              
153             has commands => (
154             isa => 'ArrayRef[Siebel::Srvrmgr::Daemon::Command]',
155             is => 'rw',
156             required => 1,
157             reader => 'get_commands',
158             writer => 'set_commands',
159             trigger => sub { my $self = shift; $self->_setup_commands() }
160             );
161              
162             =pod
163              
164             =head2 bin
165              
166             An string representing the full path to the C<srvrmgr> program in the filesystem.
167              
168             This is a required attribute during object creation with the C<new> method.
169              
170             =cut
171              
172             has bin => (
173             isa => 'NotNullStr',
174             is => 'rw',
175             required => 1,
176             reader => 'get_bin',
177             writer => 'set_bin'
178             );
179              
180             =pod
181              
182             =head2 is_infinite
183              
184             An boolean defining if the interaction loop should be infinite or not.
185              
186             =cut
187              
188             has is_infinite => ( isa => 'Bool', is => 'ro', default => sub { 0 } );
189              
190             =pod
191              
192             =head2 alarm_timeout
193              
194             The an integer value that will raise an ALARM signal generated by C<alarm>. The default value is 30 seconds.
195              
196             Besides C<read_timeout>, this will raise an exception and exit the read loop from srvrmgr in cases were an output cannot be retrieved.
197              
198             This attribute will be reset every time a read can be done from the STDOUT or STDERR from srvrmgr.
199              
200             =cut
201              
202             has alarm_timeout => (
203             is => 'Int',
204             is => 'rw',
205             writer => 'set_alarm',
206             reader => 'get_alarm',
207             default => 30
208             );
209              
210             =pod
211              
212             =head2 use_perl
213              
214             A boolean attribute used mostly for testing of this class.
215              
216             If true, if will prepend the complete path of the Perl interpreter to the parameters before calling the C<srvrmgr> program (of course the "srvrmgr" must
217             be itself a Perl script).
218              
219             It defaults to false.
220              
221             =cut
222              
223             has use_perl =>
224             ( isa => 'Bool', is => 'ro', reader => 'use_perl', default => 0 );
225              
226             =head2 lang_id
227              
228             A string representing the LANG_ID parameter to connect to srvrmgr. If defaults to "ENU";
229              
230             =cut
231              
232             has lang_id => (
233             isa => 'Str',
234             is => 'rw',
235             reader => 'get_lang_id',
236             writer => 'set_lang_id',
237             default => 'ENU'
238             );
239              
240             =head2 child_runs
241              
242             An integer representing the number of times the child object was used in C<run> invocations. This is reset to zero if a new child process is created.
243              
244             =cut
245              
246             has child_runs => (
247             isa => 'Int',
248             is => 'ro',
249             reader => 'get_child_runs',
250             writer => '_set_child_runs',
251             default => 0
252             );
253              
254             =head2 maximum_retries
255              
256             The maximum times this class wil retry to launch a new process of srvrmgr if the previous one failed for any reason. This is intented to implement
257             robustness to the process.
258              
259             =cut
260              
261             has maximum_retries => (
262             isa => 'Int',
263             is => 'ro',
264             reader => 'get_max_retries',
265             writer => '_set_max_retries',
266             default => 5
267             );
268              
269             =head2 retries
270              
271             The number of retries of launching a new srvrmgr process. If this value reaches the value defined for C<maximum_retries>, the instance of Siebel::Srvrmgr::Daemon
272             will quit execution returning an error code.
273              
274             =cut
275              
276             has retries => (
277             isa => 'Int',
278             is => 'ro',
279             reader => 'get_retries',
280             writer => '_set_retries',
281             default => 0
282             );
283              
284             =head2 clear_raw
285              
286             A boolean attribute that defines if the raw data recovered from C<srvrmgr> should be kept or discarded as soon as possibly.
287              
288             Having a default value of true, it should help reducing memory usage or debugging, if set false.
289              
290             =cut
291              
292             has clear_raw => (
293             is => 'rw',
294             isa => 'Bool',
295             reader => 'clear_raw',
296             writer => 'set_clear_raw',
297             default => 1
298             );
299              
300             =head2 field_delimiter
301              
302             This is a single character attribute. It tells the Daemon class to consider a field delimiter, if such options was
303             set in the C<srvrmgr> program. If this option is used but this attribute is not set accordinly, parsing will probably
304             fail.
305              
306             Since this attribute should be defined during Daemon object instance, it is read-only.
307              
308             =cut
309              
310             has field_delimiter => ( is => 'ro', isa => 'Chr', reader => 'get_field_del' );
311              
312             =head2 has_lock
313              
314             Optional parameter.
315              
316             This is a boolean attribute (in the sense of Perl) that identifies if the L<Daemon> needs to use a lock or not. Default is false.
317              
318             Using a lock is useful to avoid two instances of the same C<Daemon> running. See also C<lock_dir> attribute.
319              
320             =cut
321              
322             has has_lock => ( is => 'ro', isa => 'Bool', default => 0 );
323              
324             =head2 lock_dir
325              
326             Optional parameter.
327              
328             This parameter is used to determine the location in the filesystem to create the lock file.
329              
330             Expects a string as parameter. The directory must be readable and writable to the user running the C<Daemon>.
331              
332             It defaults to the "home" directory of the user. The sense of "home" is the following as defined by the platform:
333              
334             This attribute is lazy and defined by the C<_define_lock_dir> "private" method.
335              
336             =over
337              
338             =item *
339              
340             Microsoft Windows: C<$ENV{HOMEDIR}>
341              
342             =item *
343              
344             UNIX-like: C<$ENV{HOME}>
345              
346             =back
347              
348             =cut
349              
350             has lock_dir => (
351             is => 'rw',
352             isa => 'Str',
353             reader => 'get_lock_dir',
354             writer => 'set_lock_dir',
355             lazy => 1,
356             builder => '_define_lock_dir'
357             );
358              
359             =pod
360              
361             =head2 cmd_stack
362              
363             This is an array reference with the stack of commands to be executed. It is maintained automatically by the class, so the attribute is read-only.
364              
365             =cut
366              
367             has cmd_stack => (
368             isa => 'ArrayRef',
369             is => 'ro',
370             writer => '_set_cmd_stack',
371             reader => 'get_cmd_stack'
372             );
373              
374             =pod
375              
376             =head1 METHODS
377              
378             =head2 get_cmd_stack
379              
380             Returns the content of the attribute C<cmd_stack>.
381              
382             =head2 get_field_del
383              
384             Getter for the C<field_delimiter> attribute.
385              
386             =head2 clear_raw
387              
388             Getter for the C<clear_raw> attribute.
389              
390             =head2 set_clear_raw
391              
392             Setter for the C<clear_raw> attribute.
393              
394             =head2 get_alarm
395              
396             Returns the content of the C<alarm_timeout> attribute.
397              
398             =head2 set_alarm
399              
400             Sets the attribute C<alarm_timeout>. Expects an integer as parameter, in seconds.
401              
402             =head2 get_child_runs
403              
404             Returns the value of the attribute C<child_runs>.
405              
406             =head2 use_perl
407              
408             Returns the content of the attribute C<use_perl>.
409              
410             =head2 get_buffer_size
411              
412             Returns the value of the attribute C<ipc_buffer_size>.
413              
414             =head2 set_buffer_size
415              
416             Sets the attribute C<ipc_buffer_size>. Expects an integer as parameter, multiple of 1024.
417              
418             =head2 get_lang_id
419              
420             Returns the value of the attribute C<lang_id>.
421              
422             =head2 set_lang_id
423              
424             Sets the attribute C<lang_id>. Expects a string as parameter.
425              
426             =head2 get_server
427              
428             Returns the content of C<server> attribute as a string.
429              
430             =head2 set_server
431              
432             Sets the attribute C<server>. Expects an string as parameter.
433              
434             =head2 get_gateway
435              
436             Returns the content of C<gateway> attribute as a string.
437              
438             =head2 set_gateway
439              
440             Sets the attribute C<gateway>. Expects a string as parameter.
441              
442             =head2 get_enterprise
443              
444             Returns the content of C<enterprise> attribute as a string.
445              
446             =head2 set_enterprise
447              
448             Sets the C<enterprise> attribute. Expects a string as parameter.
449              
450             =head2 get_user
451              
452             Returns the content of C<user> attribute as a string.
453              
454             =head2 set_user
455              
456             Sets the C<user> attribute. Expects a string as parameter.
457              
458             =head2 get_password
459              
460             Returns the content of C<password> attribute as a string.
461              
462             =head2 set_password
463              
464             Sets the C<password> attribute. Expects a string as parameter.
465              
466             =head2 get_commands
467              
468             Returns the content of the attribute C<commands>.
469              
470             =head2 set_commands
471              
472             Set the content of the attribute C<commands>. Expects an array reference as parameter.
473              
474             =head2 get_bin
475              
476             Returns the content of the C<bin> attribute.
477              
478             =head2 set_bin
479              
480             Sets the content of the C<bin> attribute. Expects a string as parameter.
481              
482             =head2 get_pid
483              
484             Returns the content of C<pid> attribute as an integer.
485              
486             =head2 is_infinite
487              
488             Returns the content of the attribute C<is_infinite>, returning true or false depending on this value.
489              
490             =head2 reset_retries
491              
492             Reset the retries of creating a new process of srvrmgr program, setting the attribute C<retries> to zero.
493              
494             =cut
495              
496             sub reset_retries {
497              
498 0     0 1 0 my $self = shift;
499              
500 0         0 $self->_set_retries(0);
501              
502 0         0 return 1;
503              
504             }
505              
506             =head2 check_cmd
507              
508             This methods expects as parameter a string representing a C<srvrmgr> command.
509              
510             The command will be checked and if considered insecure, an exception will be raised.
511              
512             Commands considered secure are:
513              
514             =over
515              
516             =item *
517              
518             load preferences
519              
520             =item *
521              
522             list <anything>
523              
524             =item *
525              
526             exit
527              
528             =item *
529              
530             set delimiter
531              
532             =back
533              
534             This method is also used internally through the C<_setup_commands> method.
535              
536             =cut
537              
538             sub check_cmd {
539              
540 46     46 1 65965 my $self = shift;
541 46         38 my $cmd = shift;
542              
543 46 50       83 confess( 'Invalid command received for execution: '
544             . Dumper( $self->get_cmd_stack() ) )
545             unless ( defined($cmd) );
546              
547 46 50 100     448 confess("Insecure command from command stack [$cmd]. Execution aborted")
      66        
      66        
548             unless ( ( $cmd =~ /^load/ )
549             or ( $cmd =~ /^list/ )
550             or ( $cmd =~ /^set\sdelimiter\s[[:graph:]]/ )
551             or ( $cmd =~ /^exit/ ) );
552              
553 36         69 return 1;
554              
555             }
556              
557             =pod
558              
559             =head2 shift_commands
560              
561             Does a C<shift> in the C<commands> attribute.
562              
563             Does not expects any parameter. Returns the C<shift>ed L<Siebel::Srvrmgr::Daemon::Command> instance or C<undef> if there is only B<one>
564             command left (which is not C<shift>ed).
565              
566             This method is useful specially if the Daemon will keep executing commands, but setup commands (like C<load preferences>) are not necessary to be executed
567             again.
568              
569             =cut
570              
571             sub shift_commands {
572              
573 4     4 1 24 my $self = shift;
574              
575 4         147 my $cmds_ref = $self->get_commands();
576              
577 4 50       8 if ( scalar( @{$cmds_ref} ) > 1 ) {
  4         13  
578              
579 4         6 my $shifted = shift( @{$cmds_ref} );
  4         7  
580 4         134 $self->set_commands($cmds_ref); # must trigger the attribute
581 4         18 return $shifted;
582              
583             }
584             else {
585              
586 0         0 return undef;
587              
588             }
589              
590             }
591              
592             =pod
593              
594             =head2 run
595              
596             This is the method used to execute commands in srvrmgr program and must be overrided by subclasses of Siebel::Srvrmgr::Daemon.
597             Subclasses should invoke L<Moose> C<super> to when doing override because this implementation will apply lock control when appropriate.
598              
599             =cut
600              
601             sub run {
602              
603 22     22 1 597 my $self = shift;
604              
605 22 100       956 if ( $self->has_lock ) {
606              
607 10         56 $self->_create_lock;
608              
609             }
610              
611             }
612              
613             =pod
614              
615             =head2 normalize_eol
616              
617             Expects an array reference as parameter.
618              
619             Changes any EOL character to LF from each index value.
620              
621             See perlport -> Issues -> Newlines for details on this.
622              
623             =cut
624              
625             sub normalize_eol {
626              
627 27     27 1 54 my $self = shift;
628 27         41 my $data_ref = shift;
629              
630 27         64 my $ref_type = ref($data_ref);
631              
632 27 50 66     162 confess 'data parameter must be an array or scalar reference'
633             unless ( ( $ref_type eq 'ARRAY' ) or ( $ref_type eq 'SCALAR' ) );
634              
635 27         137 my $c_regex = qr/\015?\012/;
636              
637 27 100       76 if ( $ref_type eq 'ARRAY' ) {
638              
639 3         15 local $/ = \012;
640              
641 3         52 foreach ( @{$data_ref} ) {
  3         13  
642              
643 1047         7023 s/$c_regex/\n/g;
644              
645             }
646              
647             }
648             else {
649              
650 24         1556 $$data_ref =~ s/$c_regex/\n/g;
651              
652             }
653              
654             }
655              
656             =pod
657              
658             =head2 create_parser
659              
660             Returns an instance of a L<Siebel::Srvrmgr::ListParser> class.
661              
662             =cut
663              
664             sub create_parser {
665              
666 20     20 1 41 my $self = shift;
667              
668 20 50       763 if ( $self->get_field_del() ) {
669              
670 0         0 return Siebel::Srvrmgr::ListParser->new(
671             {
672             clear_raw => $self->clear_raw(),
673             field_delimiter => $self->get_field_del()
674             }
675             );
676              
677             }
678             else {
679              
680 20         818 return Siebel::Srvrmgr::ListParser->new(
681             { clear_raw => $self->clear_raw() } );
682              
683             }
684              
685             }
686              
687             sub _define_params {
688              
689 5     5   56 my $self = shift;
690              
691 5         164 my @params = (
692             $self->get_bin(), '/e',
693             $self->get_enterprise(), '/g',
694             $self->get_gateway(), '/u',
695             $self->get_user(), '/p',
696             $self->get_password(), '/l',
697             $self->get_lang_id()
698              
699             );
700              
701 5 50       202 push( @params, '/s', $self->get_server() )
702             if ( defined( $self->get_server() ) );
703              
704             # :WORKAROUND:06/08/2013 21:05:32:: if a perl script will be executed (like for automated testing of this distribution)
705             # then the perl interpreter must be part of the command path to avoid calling cmd.exe in Microsoft Windows
706 5 50       140 unshift( @params, $Config{perlpath} ) if ( $self->use_perl() );
707              
708 5         5994 return \@params;
709              
710             }
711              
712             =head2 get_lock_file
713              
714             Returns the complete path to the lock file as a string.
715              
716             =cut
717              
718             sub get_lock_file {
719              
720 16     16 1 24 my $self = shift;
721              
722 16         82 my $filename = $self->blessed;
723 16         140 $filename =~ s/\:{2}/_/g;
724              
725 16         580 return File::Spec->catfile( $self->get_lock_dir, ( $filename . '.lock' ) );
726              
727             }
728              
729             our $adm_60070 = qr/^SBL-ADM-60070.*/;
730             our $adm_02043 = qr/^SBL-ADM-02043.*/;
731             our $adm_02071 = qr/^SBL-ADM-02071.*/;
732             our $adm_02049 = qr/^SBL-ADM-02049.*/;
733             our $adm_02751 = qr/^SBL-ADM-02751.*/;
734             our $siebel_error = SIEBEL_ERROR;
735              
736             sub _check_error {
737              
738 1094     1094   1023 my $self = shift;
739 1094         1292 my $content = shift;
740 1094         800 my $logger = shift;
741              
742 1094         2050 weaken($logger);
743              
744 1094 100       1698 if ( ref($content) eq 'ARRAY' ) {
745              
746 3         7 foreach my $line ( @{$content} ) {
  3         12  
747              
748             # :WORKAROUND:22-09-2014 14:02:27:: to avoid multiple methods calls, the verifications
749             # were duplicated (copy an paste)
750 3 50       50 if ( $line =~ $siebel_error ) {
751              
752             SWITCH: {
753              
754 0 0       0 if ( $line =~ $adm_60070 ) {
  0         0  
755              
756 0 0       0 $logger->warn(
757             'Trying to get additional information from next line'
758             ) if ( $logger->is_warn() );
759 0         0 return 1;
760             }
761              
762 0 0       0 if ( $line =~ $adm_02043 ) {
763 0         0 $logger->logdie('Could not find the Siebel Server');
764             }
765              
766 0 0       0 if ( $line =~ $adm_02071 ) {
767 0         0 $logger->logdie('Could not find the Siebel Enterprise');
768             }
769              
770 0 0       0 if ( $line =~ $adm_02049 ) {
771 0         0 $logger->logdie('Generic error');
772             }
773              
774 0 0       0 if ( $line =~ $adm_02751 ) {
775 0         0 $logger->logdie('Unable to open file');
776             }
777             else {
778 0         0 $logger->logdie(
779             "Unknown error [$line], aborting execution");
780             }
781              
782             }
783              
784             }
785             else {
786              
787 3 50       15 $logger->debug(
788             "Got $line. Since it doesn't look like a Siebel error, I will try to keep running"
789             ) if ( $logger->is_debug );
790              
791 3         45 $logger->warn($content);
792              
793 3         1672 return 1;
794              
795             }
796              
797             }
798              
799             }
800             else {
801              
802 1091 100       2874 if ( $content =~ $siebel_error ) {
803              
804             SWITCH: {
805              
806 1 50       3 if ( $content =~ $adm_60070 ) {
  1         6  
807              
808 0 0       0 $logger->warn(
809             'Trying to get additional information from next line')
810             if ( $logger->is_warn() );
811 0         0 return 1;
812             }
813              
814 1 50       9 if ( $content =~ $adm_02043 ) {
815 1         7 $logger->logdie('Could not find the Siebel Server');
816             }
817              
818 0 0       0 if ( $content =~ $adm_02071 ) {
819 0         0 $logger->logdie('Could not find the Siebel Enterprise');
820             }
821              
822 0 0       0 if ( $content =~ $adm_02049 ) {
823 0         0 $logger->logdie('Generic error');
824             }
825              
826 0 0       0 if ( $content =~ $adm_02751 ) {
827 0         0 $logger->logdie('Unable to open file');
828             }
829             else {
830 0         0 $logger->logdie(
831             "Unknown error [$content], aborting execution");
832             }
833              
834             }
835              
836             }
837             else {
838              
839 1090 50       1911 $logger->debug(
840             "Got $content. Since it doesn't look like a Siebel error, I will try to keep running"
841             ) if ( $logger->debug );
842              
843 1090         7459 $logger->warn($content);
844              
845 1090         299201 return 1;
846              
847             }
848              
849             }
850              
851             }
852              
853             =pod
854              
855             =head2 DEMOLISH
856              
857             This method is invoked before the object instance is destroyed. It does really few things like writting messages to the define configuration of
858             L<Log::Log4perl> logger. It will also log if ALRM, INT or PIPE signals were received.
859              
860             Subclasses may want to C<override> the method "private" C<_my_cleanup> to do their properly laundry since the definition of C<_my_cleanup> for this class
861             is just to C<return> true. C<_my_cleanup> is called with a reference of a L<Log::Log4perl::Logger> instance for usage.
862              
863             =cut
864              
865             sub DEMOLISH {
866              
867 15     15 1 23 my $self = shift;
868              
869 15         119 my $logger = Siebel::Srvrmgr->gimme_logger( ref($self) );
870 15         923 weaken($logger);
871              
872 15         49 $logger->info('Terminating daemon: preparing cleanup');
873              
874 15         152 $self->_my_cleanup($logger);
875              
876 15 100       455 if ( $self->has_lock ) {
877              
878 4         34 $self->_del_lock($logger);
879              
880             }
881              
882 15         992 $logger->info('Cleanup is finished');
883              
884 15 50       94 if ( $logger->is_warn() ) {
885              
886 15 50       101 $logger->warn('Program termination was forced by ALRM signal')
887             if ($SIG_ALARM);
888 15 50       40 $logger->warn('Program termination was forced by INT signal')
889             if ($SIG_INT);
890 15 50       34 $logger->warn('Program termination was forced by PIPE signal')
891             if ($SIG_PIPE);
892              
893             }
894              
895 15 50       34 $logger->info( ref($self) . ' says bye-bye' ) if ( $logger->is_info() );
896              
897             }
898              
899             =head1 CONSTANTS
900              
901             The following constants are available in this class:
902              
903             =over
904              
905             =item LOCK_EX
906              
907             =item LOCK_NB
908              
909             =back
910              
911             All of them from the L<Fcntl> module.
912              
913             =cut
914              
915             sub _create_lock {
916              
917 10     10   15 my $self = shift;
918              
919 10         69 my $logger = Siebel::Srvrmgr->gimme_logger( ref($self) );
920 10         314 weaken($logger);
921              
922 10         48 my $lock_file = $self->get_lock_file;
923              
924 10 100       117 if ( -e $lock_file ) {
925              
926 8 50       158 open( my $in, '<', $lock_file )
927             or $logger->logdie("Cannot read $lock_file: $!");
928 8 50       53 flock( $in, LOCK_EX | LOCK_NB )
929             or $logger->logdie("Could not get exclusive lock on $lock_file: $!");
930 8         23 local $/ = undef;
931 8         64 my $pid = <$in>;
932 8         43 close($in);
933              
934 8 100       73 $logger->logdie(
935             "Previous executing is still running (PID $pid), cannot execute")
936             if ( $pid != $$ );
937              
938             }
939             else {
940              
941 2 50       152 open( my $out, '>', $lock_file )
942             or $logger->logdie("Cannot create $lock_file: $!");
943 2 50       13 flock( $out, LOCK_EX | LOCK_NB )
944             or $logger->logdie("Could not get exclusive lock on $lock_file: $!");
945 2         26 print $out $$;
946 2         78 close($out);
947              
948             }
949              
950             }
951              
952             sub _del_lock {
953              
954 4     4   8 my $self = shift;
955 4         7 my $logger = shift;
956 4         21 my $lock_file = $self->get_lock_file;
957              
958 4 100       148 if ( -e $lock_file ) {
959              
960 2 50       182 unlink($lock_file)
961             or $logger->logdie("Could not remove $lock_file: $!");
962              
963             }
964             else {
965              
966 2         13 $logger->warn(
967             'Could not find lock file to remove before program termination');
968              
969             }
970              
971             }
972              
973             sub _my_cleanup {
974              
975 0     0   0 return 1;
976              
977             }
978              
979             sub _define_lock_dir {
980              
981 4     4   5 my $lock_dir = undef;
982            
983             CASE: {
984              
985 4 50       4 if ( $Config{osname} =~ /^linux$/i ) {
  4         57  
986              
987 4         8 $lock_dir = $ENV{HOME};
988 4         8 last CASE;
989              
990             }
991              
992 0 0       0 if ( $Config{osname} =~ /^aix$/i ) {
993              
994 0         0 $lock_dir = $ENV{HOME};
995 0         0 last CASE;
996              
997             }
998              
999 0 0       0 if ( $Config{osname} =~ /^hpux$/i ) {
1000              
1001 0         0 $lock_dir = $ENV{HOME};
1002 0         0 last CASE;
1003              
1004             }
1005              
1006 0 0       0 if ( $Config{osname} =~ /^mswin32$/i ) {
1007              
1008 0 0       0 if (defined( $ENV{HOMEDIR} ) ) {
1009            
1010 0         0 $lock_dir = $ENV{HOMEDIR};
1011            
1012             } else {
1013            
1014 0         0 $lock_dir = $ENV{USERPROFILE};
1015            
1016             }
1017            
1018 0         0 last CASE;
1019              
1020             }
1021              
1022 0 0       0 if ( $Config{osname} =~ /^solaris$/i ) {
1023              
1024 0         0 $lock_dir = $ENV{HOME};
1025 0         0 last CASE;
1026              
1027             }
1028             else {
1029              
1030 0         0 confess "don't know what to do with $Config{osname}";
1031              
1032             }
1033            
1034             }
1035            
1036 4 50       15 confess "could not defined a lock_dir for $Config{osname}" unless(defined($lock_dir));
1037            
1038 4         105 return $lock_dir;
1039              
1040             }
1041              
1042             sub _setup_commands {
1043              
1044 14     14   284 my $self = shift;
1045              
1046 14         17 foreach my $cmd ( @{ $self->get_commands } ) {
  14         480  
1047              
1048 36         1065 $self->check_cmd( $cmd->get_command() );
1049              
1050             }
1051              
1052             }
1053              
1054             =pod
1055              
1056             =head1 SEE ALSO
1057              
1058             =over
1059              
1060             =item *
1061              
1062             L<Moose>
1063              
1064             =item *
1065              
1066             L<Siebel::Srvrmgr::Daemon::ActionFactory>
1067              
1068             =item *
1069              
1070             L<Siebel::Srvrmgr::ListParser>
1071              
1072             =item *
1073              
1074             L<Siebel::Srvrmgr::Regexes>
1075              
1076             =item *
1077              
1078             L<POSIX>
1079              
1080             =item *
1081              
1082             L<Siebel::Srvrmgr::Daemon::Command>
1083              
1084             =item *
1085              
1086             L<Fcntl>
1087              
1088             =back
1089              
1090             =head1 AUTHOR
1091              
1092             Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>
1093              
1094             =head1 COPYRIGHT AND LICENSE
1095              
1096             This software is copyright (c) 2012 of Alceu Rodrigues de Freitas Junior, E<lt>arfreitas@cpan.orgE<gt>
1097              
1098             This file is part of Siebel Monitoring Tools.
1099              
1100             Siebel Monitoring Tools is free software: you can redistribute it and/or modify
1101             it under the terms of the GNU General Public License as published by
1102             the Free Software Foundation, either version 3 of the License, or
1103             (at your option) any later version.
1104              
1105             Siebel Monitoring Tools is distributed in the hope that it will be useful,
1106             but WITHOUT ANY WARRANTY; without even the implied warranty of
1107             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1108             GNU General Public License for more details.
1109              
1110             You should have received a copy of the GNU General Public License
1111             along with Siebel Monitoring Tools. If not, see <http://www.gnu.org/licenses/>.
1112              
1113             =cut
1114              
1115             __PACKAGE__->meta->make_immutable;
1116              
1117             1;
1118