|
From: Gordon M. <gm...@gm...> - 2003-06-03 15:33:33
|
I noticed that the Log4perl was pretty much a singleton pattern a while
back, so my object's constructor looks like this:
our %BE = (
logger => "",
ConfigFile => "/etc/lb_lutab",
# List of all BE objects
ALL => [ ],
);
# tri-natured: function, class method, or object method
sub _classobj {
my $objclass = shift || __PACKAGE__;
my $class = ref($objclass) || $objclass;
no strict "refs"; # to convert sym ref to real one
return \%$class;
}
for my $datum (keys %{ _classobj() } ) {
# turn off strict refs so that we can register a method
# in the symbol table
no strict "refs";
*$datum = sub {
use strict "refs";
my $self = shift->_classobj();
$self->{$datum} = shift if @_;
return $self->{$datum};
}
}
# Constructor
sub new {
my ($caller,%arg) = @_;
my $caller_is_obj = ref($caller);
my $class = $caller_is_obj || $caller;
my ($logger);
unless (BE->logger) {
Log::Log4perl::init_and_watch('/usr/LBBE/bootdiskmanager/bin/log.conf',10);
my $logger = Log::Log4perl->get_logger('BE');
BE->logger($logger);
}
$logger = Log::Log4perl->get_logger('BE');
my $instance = {
_name => $arg{name} || # Name of this BE
undef,
... Other members of the object ...
_logger => undef,
};
# Save a copy of BE->logger here so the reference to the logger can
survive
# for use inside DESTROY
$instance->{_logger} = $logger;
# Append this to the Class list of all BEs
my ($all) = BE->ALL();
push @{$all}, $instance;
BE->ALL($all);
bless $instance, $class;
}
Note the following:
If this is the first BE object in the system, then we have to explicitly
create the logger (singleton) and tuck it away. I also put a reference
to it in my object's instance, so all of my objects have individual
references to the logger.
Thus, the logger should stay around until the very last BE object calls
it's DESTROY method. This doesn't seem to be the case, as when the last
BE object enters DESTROY, $self->{_logger} has the value "undef". Not
good.
On Tue, 2003-06-03 at 11:47, Mike Schilli wrote:
> On Tue, 3 Jun 2003, Gordon Marler wrote:
>
> > I've been using Log::Log4perl for several months now, with great success
> > - great job!
>
> Thanks! :)
>
> > I've designed my Perl object to contain a reference to a Log::Log4perl
> > object, and this seems to work for all methods in the object except
> > DESTROY. Here's an example of what my DESTROY method looks like (the
> > name of my object and it's package is "BE"):
> >
> > sub DESTROY {
> > my ($self) = @_;
> > my ($logger) = Log::Log4perl->get_logger("BE");
> > $logger->info("Entering DESTROY method for " . __PACKAGE__ . "\n");
> > }
>
> Hmm ... I'm not quite sure how you're storing references to Log::Logp4erl
> objects in your object -- there's really no "Log::Log4perl objects".
>
> Typically, you call
>
> use Log::Log4perl;
> Log::Log4perl->init(...);
>
> at the beginning of your program and then, within your class code,
> you use
>
> package MyClass;
>
> use Log::Log4perl;
>
> sub method {
> my ($logger) = Log::Log4perl->get_logger("BE");
> $logger->info("message");
> }
>
> There's really no "Log::Log4perl objects" -- instead, Log4perl uses
> a singleton mechanism for its loggers.
>
> You didn't submit your class' constructor method, so I can only speculate:
> the problem might be related to storing this "Log::Log4perl reference".
> Instead, just initialize Log::Log4perl once at the start of the main (!)
> program and call the loggers in your custom class like shown above, that
> should fix the problem.
>
> Hope that helps!
>
> -- Mike
>
> Mike Schilli
> log...@pe...
> http://perlmeister.com
> http://log4perl.sourceforge.net
--
Gordon Marler <gm...@gm...>
|