Actually you'd also need to dereference the array of hashes all the way down to
a scalar....since the only way to pass hard data to another process is in a
scalar format since everything else uses a memory reference of some sort.
On 25 May 2001 12:01:39 CDT, STAFF said:
> Indeed, you are passing references ..Shouldn't your dereference when you push
> onto @results like this:
>
>
> $sth=$dbh->prepare($query);
> $sth->execute();
> while(my $hash_ref=$sth->fetchrow_hashref()){
> push(@results,%$hash_ref);
> }
>
>
> Thus making an array of hashes instead of an array of hash_references?
>
> It apparently sometimes works because your child get's to the reference before
> the Automatic garbage collection does and I don't think you can reference a
> non-shared memory object from within a shared memory object which is what you
> would be doing by passing references instead of actual results.
>
> (Correct me if I'm wrong on this, I'm not an expert on FORKing or Shared
> memory, but I have learned quite a bit about Referencing and dereferencing data
> this last week, in the Perl Developer's Guide by Ed Peschko & Michele DeWolfe,
> Osborne publishing.)
>
> On Fri, 25 May 2001 08:37:37 -0500, Mr. Sunray said:
>
> > Hi all,
> >
> > Perl 5.6 on bughat 6.2, using DBI 1.14, DBD-Oracle 1.06.
> >
> > Ok - I thought I'd try and optimize a series of sql SELECT statements by
> >
> > forking each one and storing the results in a shared memory object.
> >
> > Here's the code - I'm reading a series of sql select statements from a
> > file, fork'ing a child for each one, executing the 'fetch' within the
> > child and trying to store the results in an array for later retrieval.
> >
> > The problem seems to be with the shared memory objects. Either the
> > array of results grows each time I run the program or else I get "Can't
> > use an undefined value as an ARRAY reference at
> > /usr/local/lib/perl5/site_perl/5.6.0/IPC/Shareable.pm line 446, <GEN1>
> > chunk whatever".
> >
> > Now, I've been told that part of the problem (at least) is that I'm
> > trying
> > to store references, which probably won't work (though it seems to
> > work sometimes).
> >
> > I guess my big question is how can I use fork to speed up my queries
> > *and*
> > store the results in the parent (without using a text file)? Should I
> > be
> > looking at threads instead? Is there a *standard idiom*?
> >
> > Thanks in advance for any help.
> >
> > WARNING - be prepared to use 'ipcs' and 'ipcrm' if you want to play with
> >
> > this script! You may have stray memory objects floating around
> > afterwards.
> >
> > Be sure to run this/your program at least twice to make sure your shared
> >
> > memory objects aren't "collecting".
> >
> > #!/usr/local/bin/perl -w
> >
> > use strict;
> > use DBI;
> > use DBD::Oracle;
> > use IPC::Shareable;
> > use IO::File;
> > use POSIX qw(WNOHANG);
> >
> > use constant DB => 'myDB';
> > use constant USER => 'user';
> > use constant PASSWD => 'passwd';
> > use constant DRIVER => 'Oracle';
> >
> > #+++++++++++++++++++++++++++++++++++++++++++++
> > # File contains 4 sql SELECT statements.
> > # Use "select sysdate from dual" if you like, so long as it works.
> > #+++++++++++++++++++++++++++++++++++++++++++++
> > use constant SQLFILE => 'file.sql';
> >
> > # Child handler
> > $SIG{CHLD} = \&reapChild;
> >
> > my($dbh, $sth, @results, @allRecords);
> > my $if = IO::File->new(SQLFILE) or die "Couldn't open file: $!\n";
> >
> > #+++++++++++++++++++++++++++++++++++++++++++++++++
> > # I am not entirely sure what the proper settings for these should be.
> > # I've tried various combinations with no (or bad) luck.
> > #+++++++++++++++++++++++++++++++++++++++++++++++++
> > my $glue = 'data';
> > my %options = (create => 'yes', exclusive => 0, destroy=>1)
> > tie @allRecords, 'IPC::Shareable', $glue, { %options } or die "Tie
> > failed: $!\n";
> >
> > $/ = ""; # We're going to read each 'select' statement as an input
> > record
> > while(my $query = <$if>){
> > chomp($query);
> >
> > my $child = fork();
> > die "Can't fork: $!\n" unless defined $child;
> >
> > if($child == 0){
> >
> > # Not sure if I need 'InactiveDestroy' here or not
> > $dbh = DBI->connect(DB,USER,PASSWD,DRIVER,
> > {RaiseError=>1,PrintError=>1,InactiveDestroy=>1}
> > );
> >
> > $sth = $dbh->prepare($query);
> > $sth->execute();
> > while( my $hash_ref = $sth->fetchrow_hashref() ){
> > push(@results, $hash_ref);
> > }
> >
> > #+++++++++++++++++++++++++++++++++++++++++++++
> > # '@allRecords' should contain a reference to an array of hash
> > # reference for each select statement (thus, four total).
> > #+++++++++++++++++++++++++++++++++++++++++++++
> > push(@allRecords, \@results);
> >
> > $sth->finish();
> > $dbh->disconnect();
> > exit 0;
> > }
> > }
> >
> > close($if) or die "Unable to close input file: $!\n";
> >
> > #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > # I expect to see four array references here. When I try this, I either
> >
> > # get "Can't use undefined value as an array reference" warnings
> > # from the 'Shareable.pm' module or the list keeps growing and growing
> > # each time I run the program. What do I need to do?
> > #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > foreach my $ref(@allRecords){
> > print "Ref is: $ref\n";
> > }
> >
> > sub reapChild{ do {} while waitpid(-1, WNOHANG) > 0 }
> >
> >
> >
> >
> >
> >
>
--
Michael Wray
Network Administrator
FamilyConnect, Inc.