http://qs321.pair.com?node_id=266334

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I am wondering if it is possible to scope an entire namespace. I have an application I am trying to use under mod_perl. One of the objects dynamically require/do's a file that containes serialized data. This data is then used by assigning from the name space to an objects instance data. This happens like so:


eval "require './data_to_import.dat'" if -f './data_to_import.dat'; $self->{imported_data} = $foo_name_space::data unless $@;

This works great until it's tried under mod_perl. Data is being shared and is showing up where it's not supposed to. Now I can't redesign the whole application, but the speed boost of mod_perl is too enticing to say 'forget it'. Is there a way to do something along the lines of the following (I am aware this doesn't work):

{ local *foo_name_spane::data; eval "require './data_to_import.dat'"; + $self->{imported_data} = $foo_name_space::data unless $@; }

Replies are listed 'Best First'.
Re: scoped namespace?
by sauoq (Abbot) on Jun 16, 2003 at 23:36 UTC
    use Symbol qw( delete_package ); delete_package( $foo_name_space );

    Update: (As webfiend asked for elaboration...) Symbol is a module. It comes with perl. Read perldoc Symbol for more information. Of course, this doesn't have anything to do with "scoping" of any kind... but it should get the job done. ;-)

    -sauoq
    "My two cents aren't worth a dime.";
    

      Thanks. This looks like it's exactly what I was looking for. Is this lexically scoped in such a way that if it happens in a method, the foo_name_space that is require'd in can't be seen by another mod_perl process?

      Also, to clarify, here is a small example using Symbol as suggested:

      #!/usr/bin/perl use strict; use warnings; use Symbol qw( delete_package ); + eval { do './foo_name_space.dat'; print "within eval: ",$foo_name_space::data,"\n" if $foo_name_space: +:data; delete_package('foo_name_space'); }; if( $@ ){ print "Oops [$!]","\n"; } if($foo_name_space::data){ print "outside eval: ",$foo_name_space::data,"\n" }else{ print "no such namespace\n"; }
Re: scoped namespace?
by BrowserUk (Patriarch) on Jun 17, 2003 at 00:02 UTC

    Your question is a bit sketchy on the details of what you doing. In particular, what you mean by showing up where it's not supposed to, but I think that you might be able to use package scoping to achieve you aim.

    package foo_name_space; eval "require './data_to_import.dat'"; package main; ## or your module name $self->{imported_data} = $foo_name_space::data unless $@; }

    I think that would get you part way to your goal at least. Any vars created would be in the 'other' package space, and so isolated from your code.

    This would probably work well if any vars created were overwritten with the new data each time the code was invoked, but if new variables are created each time, then the old ones would persist and you would have a memory leak which wouldn't bode well in a mod_perl environment.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


      The dumped data is filled into a file that has a package declaration at the top that is pretty uniform across all the dumps.

      There are hundreds of these dumps (serialized data) across a directory structure.

      Certain parts of this directory structure are made available to certain users of this web app (similar to Unix filesystem access rules).

      Thus, the data contained in these dumps are pertinant to the group the user is a member of. Since this data is stored in a uniform namespace (the package delcaration that is the same across all the dump files), the data shows up (due to mod_perls persistance) even though the object falls out of scope. So a few refreshes from one session might accidentally show the data from another session (this seems to be the case in a low percentage of views, say one in ten).

        (this seems to be the case in a low percentage of views, say one in ten)

        Let me guess... you start 10 server processes... right?

        Try starting just a single server and see if that doesn't raise your 1 in 10 to a hundred percent. ;-)

        I think you should certainly be doing this another way (say, encapsulating the data in an object rather than using a package's whole namespace, for instance.) But, I understand you are already entrenched and trying to make a go of what you currently have... Still, I'd consider some sweeping changes for the next revision.

        -sauoq
        "My two cents aren't worth a dime.";
        

        In the light of the further info, my suggestion does help at all.

        Given the status quo, sauoq's suggestion of Symbol::delete_package (used as early as possible) seems about the best your going to get without pretty fundemental changes to your app architecture.

        I keep wondering if you couldn't rename the uniform package statements to use some sort of hierarchal naming convention and then use that to restrict what information the user sees according to their group rights, but that sort of change is probably so extensive, that you would be better off rewriting from scratch to use a better architecture.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller


Re: scoped namespace?
by shotgunefx (Parson) on Jun 17, 2003 at 02:40 UTC
      Interesting... thanks for the pointer. Safe.pm might be another possible solution.

        Like the following...

        #!/usr/bin/perl use strict; use warnings; use Safe; my $data = Safe->new()->rdo('./data_to_import.dat');

        cp
        ----
        "Never be afraid to try something new. Remember, amateurs built the ark. Professionals built the Titanic."
        If package vars persisting across requests are the problem, why not look at mod_perl PerlRun

        -Lee

        "To be civilized is to deny one's nature."
Re: scoped namespace?
by bunnyman (Hermit) on Jun 17, 2003 at 14:37 UTC

    I think you are using the wrong approach to solve the problem. Instead of just doing eval on the file, actually parse the data and get it into whatever storage location it belongs in. As a bonus, you could do data validation and filter out code that should not get executed.

    Whenever I see the term "namespace" I think of a hash. A hash is a portable namespace, and it can be lexically scoped using my.

    Cleaning the namespace between file reads will hurt performance because only one file can be read at a time. Besides that, it sounds ugly.