File Coverage

blib/lib/Hardware/UPS/Perl/PID.pm
Criterion Covered Total %
statement 89 128 69.5
branch 17 44 38.6
condition 0 9 0.0
subroutine 17 20 85.0
pod 7 7 100.0
total 130 208 62.5


line stmt bran cond sub pod time code
1             package Hardware::UPS::Perl::PID;
2              
3             #==============================================================================
4             # package description:
5             #==============================================================================
6             # This package supplies a set of methods to deal with PID files. For a
7             # detailed description see the pod documentation included at the end of this
8             # file.
9             #
10             # List of public methods:
11             # -----------------------
12             # new - initializing a Hardware::UPS::Perl PID file
13             # object
14             # setLogger - setting the current logger
15             # getLogger - getting the current logger
16             # getErrorMessage - getting internal error messages
17             # delete - deleting the PID file
18             # getPID - getting the current PID
19             # getPIDFile - getting the current PID file
20             #
21             #==============================================================================
22              
23             #==============================================================================
24             # Copyright:
25             #==============================================================================
26             # Copyright (c) 2007 Christian Reile, . All
27             # rights reserved. This program is free software; you can redistribute it
28             # and/or modify it under the same terms as Perl itself.
29             #==============================================================================
30              
31             #==============================================================================
32             # Entries for Revision Control:
33             #==============================================================================
34             # Revision : $Revision: 1.9 $
35             # Author : $Author: creile $
36             # Last Modified On: $Date: 2007/04/17 19:47:48 $
37             # Status : $State: Exp $
38             #------------------------------------------------------------------------------
39             # Modifications :
40             #------------------------------------------------------------------------------
41             #
42             # $Log: PID.pm,v $
43             # Revision 1.9 2007/04/17 19:47:48 creile
44             # documentation bugfixes.
45             #
46             # Revision 1.8 2007/04/14 09:37:26 creile
47             # documentation update.
48             #
49             # Revision 1.7 2007/04/07 15:15:13 creile
50             # adaptations to "best practices" style;
51             # update of documentation.
52             #
53             # Revision 1.6 2007/03/13 17:21:49 creile
54             # options as anonymous hashes.
55             #
56             # Revision 1.5 2007/03/03 21:17:23 creile
57             # new variable $UPSERROR added;
58             # adaptations to revised Constants.pm;
59             # "return undef" replaced by "return".
60             #
61             # Revision 1.4 2007/02/25 17:07:33 creile
62             # option handling redesigned.
63             #
64             # Revision 1.3 2007/02/05 20:36:40 creile
65             # pod documentation revised.
66             #
67             # Revision 1.2 2007/02/04 14:00:39 creile
68             # public method delete() revised;
69             # logging support added;
70             # private method _open() renamed to _writePID();
71             # update of documentation.
72             #
73             # Revision 1.1 2007/02/01 10:53:21 creile
74             # initial revision.
75             #
76             #
77             #==============================================================================
78              
79             #==============================================================================
80             # module preamble:
81             #==============================================================================
82              
83 1     1   904 use strict;
  1         3  
  1         46  
84              
85             BEGIN {
86            
87 1     1   5 use vars qw($VERSION @ISA);
  1         2  
  1         97  
88              
89 1     1   24 $VERSION = sprintf( "%d.%02d", q$Revision: 1.9 $ =~ /(\d+)\.(\d+)/ );
90              
91 1         49 @ISA = qw();
92              
93             }
94              
95             #==============================================================================
96             # end of module preamble
97             #==============================================================================
98              
99             #==============================================================================
100             # packages required:
101             #------------------------------------------------------------------------------
102             #
103             # Fcntl - load the C Fcntl.h defines
104             # FileHandle - supply object methods for filehandles
105             #
106             # Hardware::UPS::Perl::Constants - importing Hardware::UPS::Perl constants
107             # Hardware::UPS::Perl::General - importing Hardware::UPS::Perl variables
108             # and functions for scripts
109             # Hardware::UPS::Perl::Logging - importing Hardware::UPS::Perl methods
110             # dealing with logfiles
111             # Hardware::UPS::Perl::Utils - importing Hardware::UPS::Perl utility
112             # functions for packages
113             #
114             #==============================================================================
115              
116 1     1   7 use Fcntl;
  1         2  
  1         339  
117 1     1   7 use FileHandle;
  1         1  
  1         9  
118              
119 1         60 use Hardware::UPS::Perl::Constants qw(
120             UPSPIDFILE
121             UPSSCRIPT
122 1     1   741 );
  1         2  
123 1         155 use Hardware::UPS::Perl::General qw(
124             $UPSERROR
125 1     1   6 );
  1         1  
126 1     1   7 use Hardware::UPS::Perl::Logging;
  1         2  
  1         36  
127 1         1341 use Hardware::UPS::Perl::Utils qw(
128             error
129 1     1   6 );
  1         70  
130              
131             #==============================================================================
132             # defining user invisible package variables:
133             #------------------------------------------------------------------------------
134             #
135             #
136             #
137             #==============================================================================
138              
139              
140             #==============================================================================
141             # public methods:
142             #==============================================================================
143              
144             sub new {
145              
146             # public method to construct a PID file object
147             #
148             # parameters: $class (input) - class
149             # $options (input) - anonymous hash; options
150             #
151             # The following option keys are recognized:
152             #
153             # PIDFile ($) - string; the PID file; optional
154             # Logger ($) - Hardware::UPS::Perl::Logging object; the logger to use;
155             # optional
156              
157             # input as hidden local variables
158 1     1 1 734 my $class = shift;
159 1 50       4 my $options = @_ ? shift : {};
160              
161             # hidden local variables
162 1         3 my $self = {}; # referent to be blessed
163 1         1 my $refType; # a reference type
164             my $option; # an option
165 0         0 my $logger; # the logger object
166 0         0 my $pidFile; # the PID file
167              
168             # checking options
169 1         3 $refType = ref($options);
170 1 50       5 if ($refType ne 'HASH') {
171 0         0 error("not a hash reference -- <$refType>");
172             }
173              
174             # the logger; if we don't have one, we have to create our own with output
175             # on STDERR
176 1         3 $logger = delete $options->{Logger};
177              
178 1 50       3 if (!defined $logger) {
179 0 0       0 $logger = Hardware::UPS::Perl::Logging->new()
180             or return;
181             }
182              
183             # the name of the PID file
184 1 50       4 if (exists $options->{PIDFile}) {
185 1         2 $pidFile = delete $options->{PIDFile};
186             }
187             else {
188 0         0 $pidFile = UPSPIDFILE;
189             }
190              
191             # checking for misspelled options
192 1         2 foreach $option (keys %{$options}) {
  1         3  
193 0         0 error("option unknown -- $option");
194             }
195              
196             # blessing PID file object
197 1         3 bless $self, $class;
198              
199             # initializing
200 1         5 $self->{errorMessage} = q{};
201 1         4 $self->_setPIDFile($pidFile);
202 1         3 $self->_setPID($$);
203              
204             # initializing logging object
205 1         4 $self->setLogger($logger);
206              
207             # opening file
208             $self->_writePID($self->getPIDFile())
209 1 50       3 or do {
210 0         0 $UPSERROR = $self->getErrorMessage();
211 0         0 return;
212             };
213              
214             # returning blessed PID file object
215 1         3 return $self;
216              
217             } # end of public method "new"
218              
219             sub DESTROY {
220              
221             # the destructor will delete the PID file
222             #
223             # parameters: $self (input) - referent to a PID file object
224              
225             # input as hidden local variable
226 0     0   0 my $self = shift;
227              
228             # delete PID file
229 0         0 $self->delete();
230              
231             } # end of the destructor
232              
233             sub delete {
234              
235             # public method to delete a PID file
236             #
237             # parameters: $self (input) - referent to a PID file object
238              
239             # input as hidden local variable
240 0     0 1 0 my $self = shift;
241              
242             # hidden local variables
243 0         0 my $pid; # a PID, not necessarily ours
244             my $pidFile; # the current PID file
245              
246             # getting PID file
247 0         0 $pidFile = $self->getPIDFile();
248              
249             # deleting
250 0 0 0     0 if (defined $pidFile and $pidFile and -w $pidFile) {
      0        
251              
252             # getting PID from file
253             #
254             # defining PID file handle
255 0         0 my $pid_fh = new FileHandle $pidFile, O_RDONLY;
256              
257             # getting PID
258 0         0 chomp($pid = <$pid_fh>);
259              
260             # closing PID file
261 0         0 undef $pid_fh;
262              
263             # deleting PID file if it does exist and does belong to this process
264 0 0 0     0 if ($pid != $self->getPID() and kill(0, $pid)) {
265             # another process is not dead yet
266 0         0 $self->{errorMessage}
267             = "another instance ".UPSSCRIPT." still running .(".$pid.")";
268 0         0 return 0;
269             }
270              
271             # now we can safely delete
272 0 0       0 if (unlink($pidFile)) {
273 0         0 return 1;
274             }
275             else {
276 0         0 $self->{errorMessage} = "could not delete PID file -- $!";
277 0         0 return 0;
278             }
279              
280             }
281             else {
282              
283             # PID file unavailable
284 0         0 $self->{errorMessage} = "PID file unavailable";
285 0         0 return 0;
286              
287             }
288              
289             } # end of public method "delete"
290              
291             sub getErrorMessage {
292              
293             # public method to get the current error message
294             #
295             # parameters: $self (input) - referent to a PID file object
296              
297             # input as hidden local variable
298 0     0 1 0 my $self = shift;
299              
300             # getting the error message
301 0 0       0 if (exists $self->{errorMessage}) {
302 0         0 return $self->{errorMessage};
303             }
304             else {
305 0         0 return;
306             }
307              
308             } # end of public method "getErrorMessage"
309              
310             sub getPID {
311              
312             # public method to get the current PID
313             #
314             # parameters: $self (input) - referent to a PID file object
315              
316             # input as hidden local variable
317 2     2 1 2 my $self = shift;
318              
319             # getting PID
320 2 100       5 if (exists $self->{pid}) {
321 1         3 return $self->{pid};
322             }
323             else {
324 1         2 return;
325             }
326              
327             } # end of public method "getPID"
328              
329             sub getPIDFile {
330              
331             # public method to get the current PID file
332             #
333             # parameters: $self (input) - referent to a PID file object
334              
335             # input as hidden local variable
336 2     2 1 3 my $self = shift;
337              
338             # getting PID file currently used
339 2 100       18 if (exists $self->{file}) {
340 1         4 return $self->{file};
341             }
342             else {
343 1         3 return;
344             }
345              
346             } # end of public method "getPIDFile"
347              
348             sub getLogger {
349              
350             # public method to get the logger
351             #
352             # parameters: $self (input) - referent to an PID file object
353              
354             # input as hidden local variable
355 2     2 1 3 my $self = shift;
356              
357             # getting logger
358 2 100       6 if (exists $self->{logger}) {
359 1         3 return $self->{logger};
360             }
361             else {
362 1         2 return;
363             }
364              
365             } # end of public method "getLogger"
366              
367             sub setLogger {
368              
369             # public method to set the logger
370             #
371             # parameters: $self (input) - referent to a PID file object
372             # $logger (input) - the logging object
373              
374             # input as hidden local variables
375 1     1 1 2 my $self = shift;
376              
377 1 50       4 1 == @_ or error("usage: setLogger(LOGGER)");
378 1         1 my $logger = shift;
379              
380 1 50       4 if (defined $logger) {
381 1         1 my $loggerRefType = ref($logger);
382 1 50       4 ($loggerRefType eq 'Hardware::UPS::Perl::Logging')
383             or error("no logger -- <$loggerRefType>");
384             }
385              
386             # getting old logger
387 1         4 my $oldLogger = $self->getLogger();
388              
389             # setting logger
390 1         2 $self->{logger} = $logger;
391              
392             # returning old logger
393 1         2 return $oldLogger;
394              
395             } # end of public method "setLogger"
396              
397             #==============================================================================
398             # private methods:
399             #==============================================================================
400              
401             sub _writePID {
402              
403             # private method to write a PID file
404             #
405             # parameters: $self (input) - referent to a PID file object
406             # $pidFile (input) - the PID file
407              
408             # input as hidden local variables
409 1     1   2 my $self = shift;
410 1         7 my $pidFile = shift;
411              
412             # hidden local variables
413 1         6 my $pid_fh; # the PID file filehandle
414             my $pid; # the PID
415              
416             # getting the logger
417 1         3 my $logger = $self->getLogger();
418              
419             # checking for an existing PID file of this name
420 1 50       63 if ( -w $pidFile ) {
421              
422             # defining PID file handle
423 0 0       0 $pid_fh = new FileHandle $pidFile, O_RDONLY
424             or $logger->fatal(
425             "cannot open PID file $pidFile for reading -- $!"
426             );
427              
428             # getting PID
429 0         0 chomp($pid = <$pid_fh>);
430              
431             # closing PID file
432 0         0 undef $pid_fh;
433              
434 0 0       0 if (kill(0, $pid)) {
435             # still running
436 0         0 $logger->fatal(
437             "there is already another instance of ".UPSSCRIPT." running -- pid = ".$pid
438             );
439             }
440             else {
441             # try to remove PID file
442 0 0       0 if (!unlink($pidFile)) {
443 0         0 $logger->fatal("cannot remove PID file $pidFile -- $!");
444             }
445             }
446              
447             }
448              
449             # now defining the PID file filehandle for writing PID to PID file
450 1 50       12 $pid_fh = new FileHandle $pidFile, O_CREAT| O_WRONLY | O_EXCL, 0644
451             or $logger->fatal("cannot create PID file $pidFile -- $!");
452              
453             # writing PID to file
454 1         177 $pid = $self->getPID();
455 1 50       3 if (defined $pid) {
456 1         21 print $pid_fh "$pid\n";
457             }
458             else {
459 0         0 $self->{errorMessage} = "PID unavailable";
460 0         0 return 0;
461             }
462              
463             # closing PID file
464 1         2 undef $pid_fh;
465              
466 1         56 return 1;
467              
468             } # end of private method "_writePID"
469              
470             sub _setPID {
471              
472             # private method to set the PID
473             #
474             # parameters: $self (input) - referent to a PID file object
475             # $pid (input) - the PID
476              
477             # input as hidden local variables
478 1     1   2 my $self = shift;
479 1         3 my $pid = shift;
480              
481             # hidden local variable
482 1         2 my $oldPID; # the previous PID file
483              
484             # getting old PID
485 1         3 $oldPID = $self->getPID();
486              
487             # setting PID
488 1         3 $self->{pid} = $pid;
489              
490 1         2 return $oldPID;
491              
492             } # end of private method "_setPID"
493              
494             sub _setPIDFile {
495              
496             # private method to set the PID file
497             #
498             # parameters: $self (input) - referent to a PID file object
499             # $pidFile (input) - the PID file
500              
501             # input as hidden local variables
502 1     1   2 my $self = shift;
503 1         2 my $pidFile = shift;
504              
505             # hidden local variable
506 1         1 my $oldPIDFile; # the previous PID file
507              
508             # getting old PID file
509 1         4 $oldPIDFile = $self->getPIDFile();
510              
511             # setting PID file
512 1         2 $self->{file} = $pidFile;
513              
514 1         2 return $oldPIDFile;
515              
516             } # end of private method "_setPIDFile"
517              
518             #==============================================================================
519             # package return:
520             #==============================================================================
521             1;
522              
523             __END__