Re: [cgiapp] Re: Apache::DBI and CGI::Application with lots of modules.
Hi, I am learning lots of new things, but still working on the problem itself. It seems to be the case that even when I am running under ./httpd -X I have trouble getting the search query to get stuck. If I do something from the mysql monitor like set an order on hold directly with a query, then the search results won't show the updated status of the order. Yet if from the web interface, I set the order on hold, then reload, the correct status is shown. If I restart apache, then the correct status shows. Thanks for your advice, I am thinking besides the general advice I have received, Apache::DB will be my next most helpfull item. Eric At 02:33 PM 10/14/02 -0400, William McKee wrote: On 14 Oct 2002 at 9:12, Eric Frazier wrote: That I am not so sure of. I will do some more investigation. It seems like the only variables that could be causing this are the result set from the query and the scalar which holds the html template. I feel like I know absolutly nothing now :( I installed Apache::DB but don't yet know what to make of it. Hey Eric, I empathize with you! Getting myself up-to-speed with mod_perl development has been a demanding task. At the moment, my apps have stabilized but I'm sure to hit another hurdle down the road. As for Apache::DB, read the mod_perl guide at perl.apache.org. The debugger is a pain to learn but has helped me to solve several problems. There is good documentation on using the debugger in the camel book as well. One trick I learned was to let the script run through once using the 'c' command. That will load all the scripts and modules into memory which will let you set breaks in your code without having to watch every line go by. Also, I noticed some folks pointing out some global variables. If you're having troubles tracking these down in your script, you can see all the variables your script has instantiated by using perl-status and looking at the Loaded Modules. Find your CGI::App module in the list and click it to get a detailed list of the arrays, functions, hashes, etc. that it loads. Good luck, William -- Lead Developer Knowmad Services Inc. || Internet Applications Database Integration http://www.knowmad.com (250) 655 - 9513 (PST Time Zone) Inquiry is fatal to certainty. -- Will Durant
Re: Apache::DBI and CGI::Application with lots of modules.
Hi, I had to read that over a few times to get it. And now I see that I do indeed have that situation, there are a number of times when I call my $holdstatus = new Holds(); from within a module that also has a new method. What I don't understand is how does my code work at all? Thanks, Eric At 07:13 PM 10/14/02 +0200, Rafiq Ismail wrote: On Mon, 14 Oct 2002, Eric Frazier wrote: That looks like voodoo code copied from a man page. If you call this as Holds-new(), you don't need that junk about ref. (And most people recommend against the new Holds syntax.) I wanted the DBH to be global since just about every sub in Holds does a query of some sort. I guess it doesn't matter either way if I do the connect in the new() vs up top outside of a sub. Boredom break: As for your dbh, stick it whereever its scope applies, however I don't like declaring globals, so I've found that if I make the dbh accessible via an object, usually together with Apache::DBI in the background, I can often do clean up stuff, such as closing the handle (incase Apache::DBI isn't in place with a particular invokation of the package), last system logging updates/inserts, or whatever the job requires in a DESTROY method. What is the problem with the my $holdcheck = new Holds() type of syntax? I never read anything about that either way. It's in the book which I think should be called, 'the guy in the silly hat book,' ie. Damien's OO book, pretty much saying that, The indirect object syntax does, however, suffer from the same type of ambiguity problems that sometime befuddles print my $cd3 = new get_classname() (@data) #Compilation Error ... parapharased type=badly Assuming you have $cd=MyPackage and: get_name $cd; This is usually equivalent to: $cd-get_name; However, let's say that you have a method in the invoking script named 'get_name', then: get_name $cd; Gets interpreted as: get_name(MyPackage) Which is not what you're after. /paraphrase - from the guy in the silly hat book -- Senior Programmer Bookings.nl -- Me::[EMAIL PROTECTED]||www.dreamthought.com Budget hosting on my 10Mbit/backbone::[EMAIL PROTECTED] (250) 655 - 9513 (PST Time Zone) Inquiry is fatal to certainty. -- Will Durant
Re: [cgiapp] Re: Apache::DBI and CGI::Application with lots of modules.
On 15 Oct 2002 at 7:12, Eric Frazier wrote: I am learning lots of new things, but still working on the problem itself. It seems to be the case that even when I am running under ./httpd -X I have trouble getting the search query to get stuck. If I do something from the mysql monitor like set an order on hold directly with a query, then the search results won't show the updated status of the order. Yet if from the web interface, I set the order on hold, then reload, the correct status is shown. If I restart apache, then the correct status shows. That sounds like trouble. The only problem I've had running httpd -X is when I compiled mod_ssl into my server. Apparently, it doesn't like to run in single processor mode (although I haven't confirmed this). Otherwise, the single processor mode should work just like multi-processor. I'd start looking into the code that checks that status. Good luck, William -- Lead Developer Knowmad Services Inc. || Internet Applications Database Integration http://www.knowmad.com
Re: Apache::DBI and CGI::Application with lots of modules.
Eric Frazier wrote: Here is the kind of thing that is driving me nuts. Please see: http://perl.apache.org/docs/general/perl_reference/perl_reference.html#Remed ies_for_Inner_Subroutines If what this says is true, then either I don't have a closure type problem, or else what is says isn't true. That documentation refers to one particular problem involving nested subs. You don't need to have nested subs to have closures, and closures may not even be the problem. You need to do some debugging. Narrow things down by verifying your assumptions one by one. Is CGI.pm really giving you the values you expect? (Some people have experienced issues with params not being reset when using CGI.pm in certain ways.) Is your SQL query being built correctly each time? Is the data that you're passing to the template correct? Throw in some warn statements. Run it in the debugger if you need to. - Perrin
Re: Apache::DBI and CGI::Application with lots of modules.
At 11:58 AM 10/14/02 -0400, Perrin Harkins wrote: Eric Frazier wrote: Here is the kind of thing that is driving me nuts. Please see: http://perl.apache.org/docs/general/perl_reference/perl_reference.html#Remed ies_for_Inner_Subroutines If what this says is true, then either I don't have a closure type problem, or else what is says isn't true. That documentation refers to one particular problem involving nested subs. You don't need to have nested subs to have closures, and closures may not even be the problem. You need to do some debugging. Narrow things down by verifying your assumptions one by one. Is CGI.pm really giving you the values you expect? (Some people have experienced issues with params not being reset when using CGI.pm in certain ways.) Is your SQL query being built correctly each time? I have checked the above, and I have lots of warns spaced around so I can watch things in the error log. Is the data that you're passing to the template correct? That I am not so sure of. I will do some more investigation. It seems like the only variables that could be causing this are the result set from the query and the scalar which holds the html template. I feel like I know absolutly nothing now :( I installed Apache::DB but don't yet know what to make of it. Thanks again, Eric Throw in some warn statements. Run it in the debugger if you need to. - Perrin (250) 655 - 9513 (PST Time Zone) Inquiry is fatal to certainty. -- Will Durant
Re: Apache::DBI and CGI::Application with lots of modules.
Perrin, I am starting to feel guilty about bugging you so much, but you are the only person to have responded, and I watch the list enough to value your advice quite a bit. sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; That looks like voodoo code copied from a man page. If you call this as Holds-new(), you don't need that junk about ref. (And most people recommend against the new Holds syntax.) my $self = { _ }; bless ($self, $class); $dbh = db_connect(); You don't seem to need this. You aren't using the database handle for anything in this sub and you aren't gaining anything by calling it here. I wanted the DBH to be global since just about every sub in Holds does a query of some sort. I guess it doesn't matter either way if I do the connect in the new() vs up top outside of a sub. What is the problem with the my $holdcheck = new Holds() type of syntax? I never read anything about that either way. sub GetProcessed { my $self = shift; This has a bug, somtimes the cached query doesn't stick around. If you lose your database connection, Apache::DBI will reconnect. Any prepared queries will be lost. You *must* prepare every time, but see below... sub db_connect { require DBI; You don't need that. You should have already loaded it in startup.pl. my $dbname = 'CS'; my ($dbuser, $dbpasswd) = ('myuser', 'mypass'); Probably should be in a config file, rather than buried in here. my $dbh = DBI-connect(DBI:mysql:$dbname, $dbuser, $dbpasswd) or die can't connect: $DBI::errstr\n; # we need these waiting for queries, so we are going to prepare them ahead of time, and yes # horror of horror they will be global. Sorry Mom I tried :( $processed_hnd = $dbh-prepare_cached(select ord_tpak_processed from orders where ord_num=?) or confess(can't get tpak processed); $status_hnd = $dbh-prepare_cached(select is_hold_set,holdstate from holds where ord_num=?) or confess(can't get hold status); #DBI-trace(2,/usr/local/apache/htdocs/out.log); return $dbh; Don't put those in globals. The prepare_cached call already stores them for the life of your database connection. Apache::DBI will keep that connection alive (in a global hash) as long as it can and reconnect if the connection is lost. If the connection does get lost, the statement handles in these globals will stop working. You do recreate them every time since you call this sub every time, but you could lose the connection between the time this sub is called and the time you use these handles. I did this, I was a little scared about calling $dbh-finish() but I did what you said, and yes life is good I don't notice a speed difference. 4. I know the way I have done these db connects is sloppy. But I can't seem to find a better way. Could I make one db_connect sub,and inherite it all though my modules? Make one sub that returns a database handle and use it from everywhere. Doesn't need to be inherited, you can just stick it in a module that all the other modules call. I have no idea why I put off doing that for so long. But that is done now as well. Hope some of that was helpful, Perrin (250) 655 - 9513 (PST Time Zone) Inquiry is fatal to certainty. -- Will Durant
Re: Apache::DBI and CGI::Application with lots of modules.
Eric Frazier wrote: I wanted the DBH to be global since just about every sub in Holds does a query of some sort. Three options: 1) Pass it to every sub 2) Make a utility sub that returns a dbh and call it from each sub. (Sounds like you already made one of these.) 3) Stuff it in $r-pnotes(), where it will get cleaned up after each request. What is the problem with the my $holdcheck = new Holds() type of syntax? I never read anything about that either way. It's been discussed quite a bit in various places. It is now documented in the perlobj man page: http://perldoc.com/perl5.8.0/pod/perlobj.html#Indirect-Object-Syntax - Perrin
Re: Apache::DBI and CGI::Application with lots of modules.
On Mon, 14 Oct 2002, Eric Frazier wrote: That looks like voodoo code copied from a man page. If you call this as Holds-new(), you don't need that junk about ref. (And most people recommend against the new Holds syntax.) I wanted the DBH to be global since just about every sub in Holds does a query of some sort. I guess it doesn't matter either way if I do the connect in the new() vs up top outside of a sub. Boredom break: As for your dbh, stick it whereever its scope applies, however I don't like declaring globals, so I've found that if I make the dbh accessible via an object, usually together with Apache::DBI in the background, I can often do clean up stuff, such as closing the handle (incase Apache::DBI isn't in place with a particular invokation of the package), last system logging updates/inserts, or whatever the job requires in a DESTROY method. What is the problem with the my $holdcheck = new Holds() type of syntax? I never read anything about that either way. It's in the book which I think should be called, 'the guy in the silly hat book,' ie. Damien's OO book, pretty much saying that, The indirect object syntax does, however, suffer from the same type of ambiguity problems that sometime befuddles print my $cd3 = new get_classname() (@data) #Compilation Error ... parapharased type=badly Assuming you have $cd=MyPackage and: get_name $cd; This is usually equivalent to: $cd-get_name; However, let's say that you have a method in the invoking script named 'get_name', then: get_name $cd; Gets interpreted as: get_name(MyPackage) Which is not what you're after. /paraphrase - from the guy in the silly hat book -- Senior Programmer Bookings.nl -- Me::[EMAIL PROTECTED]||www.dreamthought.com Budget hosting on my 10Mbit/backbone::[EMAIL PROTECTED]
Re: Apache::DBI and CGI::Application with lots of modules. (fwd)
On Mon, 14 Oct 2002, Eric Frazier wrote: That looks like voodoo code copied from a man page. If you call this as Holds-new(), you don't need that junk about ref. (And most people recommend against the new Holds syntax.) I wanted the DBH to be global since just about every sub in Holds does a query of some sort. I guess it doesn't matter either way if I do the connect in the new() vs up top outside of a sub. Boredom break: As for your dbh, stick it whereever its scope applies, however I don't like declaring globals, so I've found that if I make the dbh accessible via an object, usually together with Apache::DBI in the background, I can often do clean up stuff, such as closing the handle (incase Apache::DBI isn't in place with a particular invokation of the package), last system logging updates/inserts, or whatever the job requires in a DESTROY method. What is the problem with the my $holdcheck = new Holds() type of syntax? I never read anything about that either way. It's in the book which I think should be called, 'the guy in the silly hat book,' ie. Damien's OO book, pretty much saying that, The indirect object syntax does, however, suffer from the same type of ambiguity problems that sometime befuddles print my $cd3 = new get_classname() (@data) #Compilation Error ... parapharased type=badly Assuming you have $cd=MyPackage and: get_name $cd; This is usually equivalent to: $cd-get_name; However, let's say that you have a method in the invoking script named 'get_name', then: get_name $cd; Gets interpreted as: get_name(MyPackage) Which is not what you're after. /paraphrase - from the guy in the silly hat book -- Senior Programmer Bookings.nl -- Me::[EMAIL PROTECTED]||www.dreamthought.com Budget hosting on my 10Mbit/backbone::[EMAIL PROTECTED]
Re: [cgiapp] Re: Apache::DBI and CGI::Application with lots of modules.
On 14 Oct 2002 at 9:12, Eric Frazier wrote: That I am not so sure of. I will do some more investigation. It seems like the only variables that could be causing this are the result set from the query and the scalar which holds the html template. I feel like I know absolutly nothing now :( I installed Apache::DB but don't yet know what to make of it. Hey Eric, I empathize with you! Getting myself up-to-speed with mod_perl development has been a demanding task. At the moment, my apps have stabilized but I'm sure to hit another hurdle down the road. As for Apache::DB, read the mod_perl guide at perl.apache.org. The debugger is a pain to learn but has helped me to solve several problems. There is good documentation on using the debugger in the camel book as well. One trick I learned was to let the script run through once using the 'c' command. That will load all the scripts and modules into memory which will let you set breaks in your code without having to watch every line go by. Also, I noticed some folks pointing out some global variables. If you're having troubles tracking these down in your script, you can see all the variables your script has instantiated by using perl-status and looking at the Loaded Modules. Find your CGI::App module in the list and click it to get a detailed list of the arrays, functions, hashes, etc. that it loads. Good luck, William -- Lead Developer Knowmad Services Inc. || Internet Applications Database Integration http://www.knowmad.com
RE: Apache::DBI and CGI::Application with lots of modules.
Hey Eric -- I wanted the DBH to be global since just about every sub in Holds does a query of some sort. I guess it doesn't matter either way if I do the connect in the new() vs up top outside of a sub. CGI::Application has a facility which is intended to solve exactly this type of problem -- the param() method. The param() method allows you to stash a property (such as a $dbh) in your CGI::Application-based object which can be retrieved anywhere. I typically connect to the database in my setup() method and stash my $dbh for use later: package My::WebApp; use strict; use base qw/CGI::Application/; sub setup { my $self = shift; $self-start_mode('start'); $self-run_modes( 'start' = 'run_mode_method' ); my $dbh = $self-connect_to_database(); $self-param('DBH', $dbh); } sub run_mode_method { my $self = shift; # Get database handle my $dbh = $self-param('DBH'); my $output = ''; # ...etc return $output; } Furthermore, in order to disconnect, the teardown() method may be used: sub teardown { my $self = shift; # Get database handle my $dbh = $self-param('DBH'); $dbh-disconnect(); } Refer to the CGI::Application POD for details on teardown() and param(). Regarding connecting to the database, I also urge you to encapsulate your connection code. On my projects I always get things started by creating a Perl module which I use whenever I need a database connection: package My::DatabaseCreds; use DBI; sub new_dbh { my $dbh = DBI-connect() die (Can't connect: .$DBI::errstr) unless ($dbh); return $dbh; } (This isn't exactly the code I use -- I actually have a module which I sub-class, but you get the idea.) The benefit of creating a module is that (1) all your Perl code can use this module so that (2) should it ever have to change you can change it in one place. What is the problem with the my $holdcheck = new Holds() type of syntax? I never read anything about that either way. My guess is that Perrin was referring to your use of the indirect notation, as opposed to the arrow notation: Indirect: my $holdcheck = new Holds() Arrow: my $holdcheck = Holds-new() Many people (myself included) prefer the arrow notation. In general, the arrow notation tends to be less ambiguous, particularly when it comes to combining method calls with arguments. HTH, -Jesse- -- Jesse Erlbaum The Erlbaum Group [EMAIL PROTECTED] Phone: 212-684-6161 Fax: 212-684-6226
Re: Apache::DBI and CGI::Application with lots of modules.
Hi, Here is the kind of thing that is driving me nuts. Please see: http://perl.apache.org/docs/general/perl_reference/perl_reference.html#Remed ies_for_Inner_Subroutines If what this says is true, then either I don't have a closure type problem, or else what is says isn't true. It says that if I have this situation, I will get a warning. I am not getting any warnings, but I am getting this behaviour with my search queries getting stuck The only thing I do is again, copied from the perltoot package Searches; use strict; use Carp; use vars qw($dbh); use gentimeid; # generate time id based use Calc_Price; # get totals use warnings; # use DBIx::XHTML_Table; # maybe later use QueryPrint; #use Data::Dumper; # These searches are restricted to user level searches, there will be a admin level search for # managment reports $dbh = db_connect(); # requires a $q query object to be init. sub new { my $self = {}; my $proto = shift; my $class = ref($proto) || $proto; $self-{queryobject} = undef; $self-{isDomestic} = undef; $self-{isInternational} = undef; $self-{isShippingSame} = undef; $self-{CustIsInserted} = undef; $self-{OrderIsInserted} = undef; $self-{CustNum} = undef; $self-{OrderNum} = undef; bless ($self, $class); return $self; } sub queryobject { my $self = shift; if (_) { $self-{queryobject} = shift } return $self-{queryobject}; } Other stuff not used yet sub LookupOrder { my $self = shift; my $q = $self-{queryobject}; my $output = ''; my $hasparameter = 0; ... Build a query from CGI.pm vars passed in though queryobject ... $order_name_qu .= ORDER BY $orderby ; # the query string is here if ($hasparameter == 1) { # if something was filled in the search form my $sth = $dbh-prepare($order_name_qu) or confess(Main search failed $order_name_qu); $sth-execute() or confess(Main search failed $order_name_qu); my $headers = $sth-{'NAME'}; my rows= $sth-fetchall_arrayref(); my $resulthtml = new QueryPrint(ResultSet = rows, Action = 'customer', ColumnList = $headers); my $html = $resulthtml-SetAction(); # sets a template type in the QueryPrint module $output = $resulthtml-QueryPrint(); $sth-finish(); #warn QUERY - $order_name_qu; undef rows; undef $resulthtml; undef $order_name_qu; return $output; } else { return no query to do; } Then this is all called from my CGI::Application module sub customer_display{ my $self = shift; my $q = $self-query(); my $customersearch = new Searches(); $customersearch-queryobject($q); # set the query my $header = parse_header($self); return $header . $customersearch-LookupCustName(); } So going nuts now, where is the problem? My QueryPrint module is pretty much the same, so if this is ok, it should be as well. Thanks, Eric Are you using any modules that have subs with sub ref prototypes, like Error.pm? That can do it. All I have read says that because I am using oop modules and use strict along with use vars that should not happen. It's actually really easy to create closures. Here is a closure: my $holdtype = $q-param('holdstate'); display_holdtype(); sub display_holdtype { print holdtype: $holdtype in process $$\n; } This will always print whatever the value was the first time, no matter what you change it to later. (The first time for that process, that is.) Watch out for things like that. You should always pass params explicitly. 4. I know the way I have done these db connects is sloppy. But I can't seem to find a better way. Could I make one db_connect sub,and inherite it all though my modules? Make one sub that returns a database handle and use it from everywhere. Doesn't need to be inherited, you can just stick it in a module that all the other modules call. Hope some of that was helpful, Perrin (250) 655 - 9513 (PST Time Zone) Inquiry is fatal to certainty. -- Will Durant
Re: Apache::DBI and CGI::Application with lots of modules.
I'm just going to point out a few problems. These are not all related to your questions. package Holds; The case of Holds doesn't match the example sub you posted above. I'm assuming that was a typo. use strict; use Carp; use warnings; use QueryPrint; use vars qw($dbh $processed_hnd $status_hnd); use gentimeid; # generate time id based sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; That looks like voodoo code copied from a man page. If you call this as Holds-new(), you don't need that junk about ref. (And most people recommend against the new Holds syntax.) my $self = { _ }; bless ($self, $class); $dbh = db_connect(); You don't seem to need this. You aren't using the database handle for anything in this sub and you aren't gaining anything by calling it here. sub GetProcessed { my $self = shift; This has a bug, somtimes the cached query doesn't stick around. If you lose your database connection, Apache::DBI will reconnect. Any prepared queries will be lost. You *must* prepare every time, but see below... sub db_connect { require DBI; You don't need that. You should have already loaded it in startup.pl. my $dbname = 'CS'; my ($dbuser, $dbpasswd) = ('myuser', 'mypass'); Probably should be in a config file, rather than buried in here. my $dbh = DBI-connect(DBI:mysql:$dbname, $dbuser, $dbpasswd) or die can't connect: $DBI::errstr\n; # we need these waiting for queries, so we are going to prepare them ahead of time, and yes # horror of horror they will be global. Sorry Mom I tried :( $processed_hnd = $dbh-prepare_cached(select ord_tpak_processed from orders where ord_num=?) or confess(can't get tpak processed); $status_hnd = $dbh-prepare_cached(select is_hold_set,holdstate from holds where ord_num=?) or confess(can't get hold status); #DBI-trace(2,/usr/local/apache/htdocs/out.log); return $dbh; Don't put those in globals. The prepare_cached call already stores them for the life of your database connection. Apache::DBI will keep that connection alive (in a global hash) as long as it can and reconnect if the connection is lost. If the connection does get lost, the statement handles in these globals will stop working. You do recreate them every time since you call this sub every time, but you could lose the connection between the time this sub is called and the time you use these handles. 2. Every once in a while I get an out of memory error. You can control process growth over time in a number of ways. They are documented in the mod_perl guide. 3. My main search result page is getting cached, the closure type of problem. Are you using any modules that have subs with sub ref prototypes, like Error.pm? That can do it. All I have read says that because I am using oop modules and use strict along with use vars that should not happen. It's actually really easy to create closures. Here is a closure: my $holdtype = $q-param('holdstate'); display_holdtype(); sub display_holdtype { print holdtype: $holdtype in process $$\n; } This will always print whatever the value was the first time, no matter what you change it to later. (The first time for that process, that is.) Watch out for things like that. You should always pass params explicitly. 4. I know the way I have done these db connects is sloppy. But I can't seem to find a better way. Could I make one db_connect sub,and inherite it all though my modules? Make one sub that returns a database handle and use it from everywhere. Doesn't need to be inherited, you can just stick it in a module that all the other modules call. Hope some of that was helpful, Perrin
Apache::DBI and CGI::Application with lots of modules.
Hi, I am glad to see the list traffic has been picking up lately. It makes me have higher hope about posting this. First some background info. I have a fairly large CGI::Application module about 30 run modes that pretty much follows the example mailform module. I am also using HTML::Template within the module. I am running on, FreeBSD 4.6 1G mem mysql 4.02 with Innodb tables. A typical run mode looks like this. sub doug_holds { my $self = shift; my $q = $self-query(); my $holdtype = $q-param('holdstate'); my $holdsearch = new holds(); $holdsearch-HoldType($holdtype); # set hold type for the query my $header = parse_header($self); return $header . $holdsearch-getAllHolds(); } Of course many of other subs look like this sub customer_name_search { my $self = shift; my $index_page = $self-param('CUSTOMER_NAME_SEARCH_TMPL'); my $output=''; my $tmpl_obj = $self-load_tmpl($index_page, die_on_bad_params = 0, cache = 1, stack_debug =$debug ) or confess(could not create template); $tmpl_obj-param(base = $self-param('base')); $tmpl_obj-param(RUNMODE = 'customer_display'); $tmpl_obj-param(USER = $selected_user); my $header = parse_header($self); return $header . $tmpl_obj-output; } But that isn't relavent to my problem. In the first sub, I create a new holds instance. Each of these modules like holds work like this package Holds; use strict; use Carp; use warnings; use QueryPrint; use vars qw($dbh $processed_hnd $status_hnd); use gentimeid; # generate time id based sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; my $self = { _ }; bless ($self, $class); $dbh = db_connect(); #die $self-{OrdNum}, $self-{HoldReason}; return $self; } sub OrdNum { my $self = shift; if (_) { $self-{OrdNum} = shift } return $self-{OrdNum}; } sub GetProcessed { my $self = shift; This has a bug, somtimes the cached query doesn't stick around. $processed_hnd-execute($self-{OrdNum}) or confess (can't execute processed); my ($isprocessed) = $processed_hnd-fetchrow_array; $processed_hnd-finish(); if ($isprocessed){ $self-{ProcessStatus} = 1; return #4EEE94; }else{ $self-{ProcessStatus} = 0; return FF; } } .. sub db_connect { require DBI; my $dbname = 'CS'; my ($dbuser, $dbpasswd) = ('myuser', 'mypass'); my $dbh = DBI-connect(DBI:mysql:$dbname, $dbuser, $dbpasswd) or die can't connect: $DBI::errstr\n; # we need these waiting for queries, so we are going to prepare them ahead of time, and yes # horror of horror they will be global. Sorry Mom I tried :( $processed_hnd = $dbh-prepare_cached(select ord_tpak_processed from orders where ord_num=?) or confess(can't get tpak processed); $status_hnd = $dbh-prepare_cached(select is_hold_set,holdstate from holds where ord_num=?) or confess(can't get hold status); #DBI-trace(2,/usr/local/apache/htdocs/out.log); return $dbh; } Most of the modules just have simple subs called db_connect that don't have prepared statments sitting like this. I did this because I have to check the status of a LOT of rows and return the display fast. This seemed to work well at the time. It was defiantly faster that preparing the statement over and over. I am running under mod perl 1.x Apache 1.3x, and loading my CGI::App module and other modules from a start.pl I am using Apache::DBI and connect_on_init. So I have these problems, they all seem to be related, but how?? 1. Connections are getting lost. I get errors in the log about fetch without an execute which indicate this. Either the user sees an internal server error, or else I believe DBI will try to reconnect and the query will then succeed. But that slows things down when it happens. All I have to do to these kinds of errors is reload a page very quickly. click, click, click fast.. 2. Every once in a while I get an out of memory error. 3. My main search result page is getting cached, the closure type of problem. ***Sometimes*** All I have read says that because I am using oop modules and use strict along with use vars that should not happen. I have not gotten any this variable will not stay shared types of warnings. for this I have tried specificly undefing the display scalars, the result sets etc. I just can't seem to find out what var is causing the problem, and I can't find any examples of closures. 4. I know the way I have done these db connects is sloppy. But I can't seem to find a better way. Could I make one db_connect sub,and
Re: Apache::DBI and CGI::Application with lots of modules.
Perrin, I am going to read over this closely, thanks for all of the advice! What frustrats me about the search getting cached/closure thing is that I just don't have any global variables that have anything to do at all with the search results. I have read over and over examples with closures, recognize the example you included as one, but I still can't seem to find it in my own code. I guess I need to take a fresh look again. I did -X httpd and it is happening every time. I think part of what is getting me is I have used mod_perl for smaller things, but now it is a pretty big system. I don't seem to be able to get away with as much :) Also, I am really trying to bring my code level up a notch, but as you pointed out, there are some things I am doing that I don't really understand well enough yet. Thanks, Eric http://www.kwinternet.com/eric (250) 655 - 9513 (PST Time Zone) Inquiry is fatal to certainty. -- Will Durant