<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2654.45">
<TITLE>RE: [Kc] dynamically loading and unloading perl packages</TITLE>
</HEAD>
<BODY>

<P><FONT SIZE=2>John Reinke wrote:</FONT>
<BR><FONT SIZE=2>&gt; </FONT>
<BR><FONT SIZE=2>&gt; I've got a challenge that I just haven't been able to</FONT>
<BR><FONT SIZE=2>&gt; find a solution for. I'll describe the feature I need</FONT>
<BR><FONT SIZE=2>&gt; to add to the application, in case I'm headed in the</FONT>
<BR><FONT SIZE=2>&gt; wrong direction.</FONT>
<BR><FONT SIZE=2>&gt; </FONT>
<BR><FONT SIZE=2>&gt; I have a script which runs constantly, watching another </FONT>
<BR><FONT SIZE=2>&gt; application. It has certain tasks it performs, and</FONT>
<BR><FONT SIZE=2>&gt; occasionally needs to add and/or subtract from the list</FONT>
<BR><FONT SIZE=2>&gt; of tasks it performs through checking to see if a</FONT>
<BR><FONT SIZE=2>&gt; config file has changed.</FONT>
<BR><FONT SIZE=2>&gt; </FONT>
<BR><FONT SIZE=2>&gt; Here's the tricky part: the tasks are performed by</FONT>
<BR><FONT SIZE=2>&gt; custom perl packages that are not known until the</FONT>
<BR><FONT SIZE=2>&gt; config file is read. This means that the main program</FONT>
<BR><FONT SIZE=2>&gt; needs to be able to dynamically load/initialize or unload</FONT>
<BR><FONT SIZE=2>&gt; packages according to changes made to the config file</FONT>
<BR><FONT SIZE=2>&gt; since the last time it was read.</FONT>
</P>

<P><FONT SIZE=2>Are you sure? I would think giving each package intialize and/or cleanup routines and a little code organization would be sufficient.</FONT></P>

<P><FONT SIZE=2>But TIMTOWTDI...</FONT>
</P>

<P><FONT SIZE=2>Reloading packages is as simple as:</FONT>
</P>

<P><FONT SIZE=2>&nbsp; do '/path/to/package';</FONT>
</P>

<P><FONT SIZE=2>But what's already in memory remains. So you'd have to make sure you have explicit default value assignments for all variables. And follow the same type of advice given to apache mod_perl programmers to otherwise make sure you don't have any package state from a previous request carry over to the next one.</FONT></P>
<BR>

<P><FONT SIZE=2>Removing a package from memory is considerably more difficult... you might try:</FONT>
</P>

<P><FONT SIZE=2>&nbsp; _pkg_clear('Foo::Bar');</FONT>
<BR><FONT SIZE=2>&nbsp; sub _pkg_clear ($) {</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; no strict 'refs';</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; my ($package) = shift;</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; my $stash = *{$package . '::'}{HASH};</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; foreach my $name (keys %$stash) {</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $name = join('::', $package, $name);</FONT>
<BR><FONT SIZE=2>&nbsp; #&nbsp;&nbsp;&nbsp; print &quot;undef $name\n&quot;;</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undef $$name;</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undef @$name;</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undef %$name;</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undef &amp;$name;</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undef *$name;</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; }</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; undef %{$package . '::'};</FONT>
<BR><FONT SIZE=2>&nbsp; }</FONT>
</P>

<P><FONT SIZE=2>But that's more of a shotgun than a recipe for reliable behaviour. It doesn't do much for detecting and removing circular references, or handling object destruction ordering issues and class clean-up code. And it'll any slots in the package namespace typeglobs I've failed to account for: like IO, FORMAT, etc.</FONT></P>

<P><FONT SIZE=2>If all the code you're using is stuff you wrote yourself... then perhaps through a little discipline you might be able to use the above. But the more complex your perl and reliance on tricky CPAN modules particularly OO-Perl, the less confident I'd be about taking the shotgun approach.</FONT></P>
<BR>

<P><FONT SIZE=2>&gt; I've not been able to figure out how to dynamically</FONT>
<BR><FONT SIZE=2>&gt; load or unload packages within a global scope. The</FONT>
<BR><FONT SIZE=2>&gt; closest I've been able to find is DynaLoader, which</FONT>
<BR><FONT SIZE=2>&gt; allows dynamically loading C libs into a perl program.</FONT>
<BR><FONT SIZE=2>&gt; </FONT>
<BR><FONT SIZE=2>&gt; This seems like something that should be easy in perl,</FONT>
<BR><FONT SIZE=2>&gt; but I've not been able to figure it out.</FONT>
</P>

<P><FONT SIZE=2>If you want some well thought out ideas on building a system that has various components which must support being initiated, suspended, resumed, terminated, and reconfigured at runtime... I'd recommend doing a little reading on the component configurator pattern.</FONT></P>

<P><FONT SIZE=2><A HREF="http://wendtstud1.hpi.uni-potsdam.de/SCAP/documents/ComponentConf.pdf" TARGET="_blank">http://wendtstud1.hpi.uni-potsdam.de/SCAP/documents/ComponentConf.pdf</A></FONT>
<BR><FONT SIZE=2><A HREF="http://www.tml.hut.fi/Studies/Tik-109.450/2001/Presentations/ComponentConfigurator.pdf" TARGET="_blank">http://www.tml.hut.fi/Studies/Tik-109.450/2001/Presentations/ComponentConfigurator.pdf</A></FONT>
</P>

<P><FONT SIZE=2>--</FONT>
<BR><FONT SIZE=2>Garrett Goebel</FONT>
<BR><FONT SIZE=2>IS Development Specialist</FONT>
</P>

<P><FONT SIZE=2>ScriptPro&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Direct: 913.403.5261</FONT>
<BR><FONT SIZE=2>5828 Reeds Road&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Main: 913.384.1008</FONT>
<BR><FONT SIZE=2>Mission, KS 66202&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Fax: 913.384.2180</FONT>
<BR><FONT SIZE=2>www.scriptpro.com&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; garrett at scriptpro dot com</FONT>
</P>
<BR>
<BR>

</BODY>
</HTML>