C
Chris
I am completely stupified at this problem.
Since there is way too much code to post in order to provide a good
picture of the problem, I'll provide some background which I think
accurately frames my environment and what my scripts and modules are
supposed to be doing (and actually ARE doing except for this one very
weird exception):
- Windows 2003 Server
- AS Perl v.5.8.4 Build 810
- Script path: D:\MyApp (this is made up)
- Script: D:\MyApp\myapp.pl (this is made up)
Under D:\MyApp, I have a bunch of modules I am using. A lot of the
modules are in D:\MyApp\Foo\Bar (again, made up). In Foo\Bar, I have
modules A.pm, B.pm, and C.pm. A, B and C have modules A1.pm, A2.pm,
B1.pm, B2.pm, C1.pm and C2.pm which they require on the fly. A, B, and
C are basically "traffic cops" for the A1, A2, B1, B2 modules, etc.
I have a bunch of data that is being read from a database. How the
data is handled is defined in the database and this maps directly to
these A1, A2, B1, B2 modules. So, I have some data, and I also have
"this data should be handled using A's #1 way of doing things" or
"process this using A->A1->method_blah() method" And of course A
requires A1 the first time it is needed and calls this exposed,
predefined method_blah() in A1.pm to handle this data. (Thereafter, if
I have to use A1 through A, A already knows about A1.)
A1, A2, B1, B2, etc. are require'd on the fly as they are needed
because the data in the database may or may not need each of A1, A2,
B1, B2,..., C2, etc. (As you may be able to see, this is "kind" of a
"plugin" architecture. We could have A1 thru A<n> handlers for A, and
the same for B and C, etc. We could even have a D, E, F.pm, etc. with
D1.pm thru D<n>.pm and so on...) Really important here, and this is
why I am totally baffled:
A.pm, B.pm, C.pm, as well as A1.pm, A2.pm... etc. are ALL located in
D:\MyApp\Foo\Bar.
At the beginning of D:\MyApp\myapp.pl, I have:
use strict;
use warnings qw( all );
BEGIN { unshift @INC, $ENV{MYAPP_ROOT} if $ENV{MYAPP_ROOT} }
and in my environment, I have:
D:\MyApp> set MYAPP_ROOT=D:\MyApp
SO.... With all that said, the "require" code in A.pm, B.pm, and C.pm
is really identical and this is the exact code, cut and pasted from one
of A, B or C.pm:
## Private Method: Initialize Accessor
## On demand initialization of an agent accessor.
sub __initialize_accessor {
## Get parameters.
my $self = shift;
my $ctxt = shift;
## Initialize agent accessors from the accessors registry list.
if (exists $AccessorsRegistry->{$ctxt->Accessor}) {
my $accessor = $AccessorsRegistry->{$ctxt->Accessor};
my $class = "${base_class}::$accessor";
eval qq{ require $class };
croak "Failed to initialize C Agent accessor '$accessor'! Either
the accessor hasn't been properly installed or the accessor isn't in
\@INC..." if $@;
$self->__add( $accessor => $class->new( $ctxt ) );
} else {
croak "Invalid accessor /${\ $ctxt->Accessor }/ specified.";
}
}
Essentially the "if exists" just checks to make sure that what the
database said to use is registered in a registry somewhere, and if it
is, then it requires it on the fly and adds a singleton instance of the
"accessor" (A1, A2, B1...etc.) to the class. When the module is added,
then the methods I want exposed be called through A, B or C like:
$self->$accessor->$method( <parameters-here> );
$base_class = "Foo::Bar";
$accessor = like "A1", "A2", "B1", etc.
Which means $class above would be "Foo::Bar::A1", "Foo::Bar::A2",
"Foo::Bar::B1", etc.
Here's the kicker... A.pm successfully requires A1.pm and A2.pm. B.pm
successfully requires B1.pm and B2.pm. C.pm however, does NOT require
C1.pm successfully. It says it can't find it in the @INC path!
Another direct cut and paste (with proper substitution of names):
Can't locate Foo::Bar::C1 in @INC (@INC contains: d:\MyApp C:/Pe
rl/lib C:/Perl/site/lib .) at d:/MyApp/Foo/Bar/C.pm line 152.
Again, ALL these modules are in D:\MyApp\Foo\Bar. C1.pm is DEFINITELY
in the same directory. I've quaduruple checked it. Why in the world I
can require A1.pm, A2.pm, B1 and B2, but not C1.pm I don't know. I've
tried setting MYAPP_ROOT to both D:\MyApp and D:/MyApp, but that
doesn't seem to make a difference. And again, A1, A2, B1, and B2 are
being required properly. Someone would say the __initialize_accessor()
code in C.pm *has* to be different somehow, but this is not the case.
Again I've quadruple checked this and this EXACT code works with
complete success on Perl v5.8.3 on a Windows XP workstation. But on
this Windows 2003 Server with Perl v5.8.4, it doesn't.
Another weird thing: When C.pm tries to require C1.pm and fails, the
program STOPS even though it's wrapped in an eval(). And the croak
"Error blah blah blah" if $@; directly afterwards never fires. The
program just stops right at the eval statement in the C.pm module.
When I take the eval() out and just doing a straight require, I get the
error I cut and pasted above. (It's like the eval() wrap doesn't work
either.)
It's just the craziest thing I've ever seen. The fact that my code
works FLAWLESSLY on my laptop is just stupifiying. I located some
other articles on c.l.p.m regarding require failing, but none really
seem to shed light on my issue.
Sorry for the somewhat lengthy explanation, but if I posted the actual
code it would be 20x longer, and the above accurately represents what I
am doing.
-ceo
Since there is way too much code to post in order to provide a good
picture of the problem, I'll provide some background which I think
accurately frames my environment and what my scripts and modules are
supposed to be doing (and actually ARE doing except for this one very
weird exception):
- Windows 2003 Server
- AS Perl v.5.8.4 Build 810
- Script path: D:\MyApp (this is made up)
- Script: D:\MyApp\myapp.pl (this is made up)
Under D:\MyApp, I have a bunch of modules I am using. A lot of the
modules are in D:\MyApp\Foo\Bar (again, made up). In Foo\Bar, I have
modules A.pm, B.pm, and C.pm. A, B and C have modules A1.pm, A2.pm,
B1.pm, B2.pm, C1.pm and C2.pm which they require on the fly. A, B, and
C are basically "traffic cops" for the A1, A2, B1, B2 modules, etc.
I have a bunch of data that is being read from a database. How the
data is handled is defined in the database and this maps directly to
these A1, A2, B1, B2 modules. So, I have some data, and I also have
"this data should be handled using A's #1 way of doing things" or
"process this using A->A1->method_blah() method" And of course A
requires A1 the first time it is needed and calls this exposed,
predefined method_blah() in A1.pm to handle this data. (Thereafter, if
I have to use A1 through A, A already knows about A1.)
A1, A2, B1, B2, etc. are require'd on the fly as they are needed
because the data in the database may or may not need each of A1, A2,
B1, B2,..., C2, etc. (As you may be able to see, this is "kind" of a
"plugin" architecture. We could have A1 thru A<n> handlers for A, and
the same for B and C, etc. We could even have a D, E, F.pm, etc. with
D1.pm thru D<n>.pm and so on...) Really important here, and this is
why I am totally baffled:
A.pm, B.pm, C.pm, as well as A1.pm, A2.pm... etc. are ALL located in
D:\MyApp\Foo\Bar.
At the beginning of D:\MyApp\myapp.pl, I have:
use strict;
use warnings qw( all );
BEGIN { unshift @INC, $ENV{MYAPP_ROOT} if $ENV{MYAPP_ROOT} }
and in my environment, I have:
D:\MyApp> set MYAPP_ROOT=D:\MyApp
SO.... With all that said, the "require" code in A.pm, B.pm, and C.pm
is really identical and this is the exact code, cut and pasted from one
of A, B or C.pm:
## Private Method: Initialize Accessor
## On demand initialization of an agent accessor.
sub __initialize_accessor {
## Get parameters.
my $self = shift;
my $ctxt = shift;
## Initialize agent accessors from the accessors registry list.
if (exists $AccessorsRegistry->{$ctxt->Accessor}) {
my $accessor = $AccessorsRegistry->{$ctxt->Accessor};
my $class = "${base_class}::$accessor";
eval qq{ require $class };
croak "Failed to initialize C Agent accessor '$accessor'! Either
the accessor hasn't been properly installed or the accessor isn't in
\@INC..." if $@;
$self->__add( $accessor => $class->new( $ctxt ) );
} else {
croak "Invalid accessor /${\ $ctxt->Accessor }/ specified.";
}
}
Essentially the "if exists" just checks to make sure that what the
database said to use is registered in a registry somewhere, and if it
is, then it requires it on the fly and adds a singleton instance of the
"accessor" (A1, A2, B1...etc.) to the class. When the module is added,
then the methods I want exposed be called through A, B or C like:
$self->$accessor->$method( <parameters-here> );
$base_class = "Foo::Bar";
$accessor = like "A1", "A2", "B1", etc.
Which means $class above would be "Foo::Bar::A1", "Foo::Bar::A2",
"Foo::Bar::B1", etc.
Here's the kicker... A.pm successfully requires A1.pm and A2.pm. B.pm
successfully requires B1.pm and B2.pm. C.pm however, does NOT require
C1.pm successfully. It says it can't find it in the @INC path!
Another direct cut and paste (with proper substitution of names):
Can't locate Foo::Bar::C1 in @INC (@INC contains: d:\MyApp C:/Pe
rl/lib C:/Perl/site/lib .) at d:/MyApp/Foo/Bar/C.pm line 152.
Again, ALL these modules are in D:\MyApp\Foo\Bar. C1.pm is DEFINITELY
in the same directory. I've quaduruple checked it. Why in the world I
can require A1.pm, A2.pm, B1 and B2, but not C1.pm I don't know. I've
tried setting MYAPP_ROOT to both D:\MyApp and D:/MyApp, but that
doesn't seem to make a difference. And again, A1, A2, B1, and B2 are
being required properly. Someone would say the __initialize_accessor()
code in C.pm *has* to be different somehow, but this is not the case.
Again I've quadruple checked this and this EXACT code works with
complete success on Perl v5.8.3 on a Windows XP workstation. But on
this Windows 2003 Server with Perl v5.8.4, it doesn't.
Another weird thing: When C.pm tries to require C1.pm and fails, the
program STOPS even though it's wrapped in an eval(). And the croak
"Error blah blah blah" if $@; directly afterwards never fires. The
program just stops right at the eval statement in the C.pm module.
When I take the eval() out and just doing a straight require, I get the
error I cut and pasted above. (It's like the eval() wrap doesn't work
either.)
It's just the craziest thing I've ever seen. The fact that my code
works FLAWLESSLY on my laptop is just stupifiying. I located some
other articles on c.l.p.m regarding require failing, but none really
seem to shed light on my issue.
Sorry for the somewhat lengthy explanation, but if I posted the actual
code it would be 20x longer, and the above accurately represents what I
am doing.
-ceo