Hi, Over the past few months I have posted a couple of fixes in relation to how Apache::DBI handles are cleaned up. This however is the most complete fix in that it covers the following issues :-
TimeOut = 0 :
Should always ping even when multiple requests are made in
the same secondi
Setting Attributes post connection :
$dbh->{AutoCommit}=0 will convert an AutoCommit handle to non
AutoCommit so when it is next retunred it behaves incorrectly.
Other settings can be effected in the same way.
Using begin_work :
This is a tempory version of the above. The next commit resets
the handle to the default value.
I have tested this under mp1 but do not have any active setups for testing
under mp2. I have not found that this fix degrades performance but I have
not done exhautive benchmarking on multiple platforms. I would be grateful
for all feedback in relation to this patch both good and bad..
The patch is against the current CVS version.
Thank you all
Paddy
--- Changes 2003-07-20 09:03:15.000000000 +0000
+++ Changes 2003-07-21 09:02:11.000000000 +0000
@@ -1,5 +1,11 @@
Revision history for ApacheDBI.
+patch July 21, 2003
+ - Fixed issues relating to chanding handle state post connection.
+ Handles now returned in same state as original and incomplete
+ transactions rolled back before re-issuing handle so begin_work
+ should now be safe. "Patrick Mulvany" <[EMAIL PROTECTED]>
+
0.92-dev
- Avoid use of uninitialized value warning under mod_perl 2.
--- DBI.pm 2003-06-10 12:20:06.000000000 +0000
+++ DBI.cleanup.pm 2003-07-21 09:22:34.000000000 +0000
@@ -23,6 +23,8 @@
my %LastPingTime; # keeps track of last ping per data_source
my $Idx; # key of %Connected and %Rollback.
+# Check to see if we need to reset TaintIn and TaintOut
+my $TaintInOut = ($DBI::VERSION>=1.31)?1:0;
# supposed to be called in a startup script.
# stores the data_source of all connections, which are supposed to be created upon
@@ -87,11 +89,13 @@
}
# this PerlCleanupHandler is supposed to initiate a rollback after the script has
finished if AutoCommit is off.
- my $needCleanup = ($Idx =~ /AutoCommit[^\d]+0/) ? 1 : 0;
+ # however cleanup can only be determined at end of handle life as begin_work may
have been called to temporarily turn off AutoCommit.
+ #
# TODO - Fix mod_perl 2.0 here
- if(!$Rollback{$Idx} and $needCleanup and Apache->can('push_handlers')) {
+ if(!$Rollback{$Idx} and Apache->can('push_handlers')) {
print STDERR "$prefix push PerlCleanupHandler \n" if $Apache::DBI::DEBUG > 1;
Apache->push_handlers("PerlCleanupHandler", \&cleanup);
+
# make sure, that the rollback is called only once for every
# request, even if the script calls connect more than once
$Rollback{$Idx} = 1;
@@ -101,7 +105,8 @@
$PingTimeOut{$dsn} = 0 unless $PingTimeOut{$dsn};
$LastPingTime{$dsn} = 0 unless $LastPingTime{$dsn};
my $now = time;
- my $needping = (($PingTimeOut{$dsn} == 0 or $PingTimeOut{$dsn} > 0) and $now -
$LastPingTime{$dsn} > $PingTimeOut{$dsn}) ? 1 : 0;
+ # Must ping if TimeOut = 0 else base on time
+ my $needping = ($PingTimeOut{$dsn} == 0 or ($PingTimeOut{$dsn} > 0 and $now -
$LastPingTime{$dsn} > $PingTimeOut{$dsn})) ? 1 : 0;
print STDERR "$prefix need ping: ", $needping == 1 ? "yes" : "no", "\n" if
$Apache::DBI::DEBUG > 1;
$LastPingTime{$dsn} = $now;
@@ -112,6 +117,10 @@
# RaiseError being on and the handle is invalid.
if ($Connected{$Idx} and (!$needping or eval{$Connected{$Idx}->ping})) {
print STDERR "$prefix already connected to '$Idx'\n" if $Apache::DBI::DEBUG >
1;
+
+ # Force clean up of handle in case previous transaction failed to clean up
the handle
+ &reset_startup_state();
+
return (bless $Connected{$Idx}, 'Apache::DBI::db');
}
@@ -121,6 +130,9 @@
$Connected{$Idx} = $drh->connect(@args);
return undef if !$Connected{$Idx};
+ # store the parameters of the initial connection in the handle
+ set_startup_state($Connected{$Idx});
+
# return the new database handle
print STDERR "$prefix new connect to '$Idx'\n" if $Apache::DBI::DEBUG;
return (bless $Connected{$Idx}, 'Apache::DBI::db');
@@ -158,6 +170,47 @@
1;
}
+# Store the default start state of each dbh in the handle
+# Note: This uses private_Apache_DBI hash ref to store it in the handle itself
+
+sub set_startup_state {
+ foreach my $key qw{ AutoCommit Warn CompatMode InactiveDestroy
+ PrintError RaiseError HandleError
+ ShowErrorStatement TraceLevel FetchHashKeyName
+ ChopBlanks LongReadLen LongTruncOk
+ Taint Profile} {
+ $Connected{$Idx}->{private_Apache_DBI}{$key} = $Connected{$Idx}->{$key};
+ }
+ if ($TaintInOut) {
+ foreach my $key qw{ TaintIn TaintOut } {
+ $Connected{$Idx}->{private_Apache_DBI}{$key} = $Connected{$Idx}->{$key};
+ }
+ }
+ 1;
+}
+
+
+# Restore the default start state of each dbh
+
+sub reset_startup_state {
+ # Rollback current transaction if currently in one
+ $Connected{$Idx}->{Active} and !$Connected{$Idx}->{AutoCommit} and eval
{$Connected{$Idx}->rollback};
+
+ foreach my $key qw{ AutoCommit Warn CompatMode InactiveDestroy
+ PrintError RaiseError HandleError
+ ShowErrorStatement TraceLevel FetchHashKeyName
+ ChopBlanks LongReadLen LongTruncOk
+ Taint Profile } {
+ $Connected{$Idx}->{$key} = $Connected{$Idx}->{private_Apache_DBI}{$key};
+ }
+ if ($TaintInOut) {
+ foreach my $key qw{ TaintIn TaintOut } {
+ $Connected{$Idx}->{$key} = $Connected{$Idx}->{private_Apache_DBI}{$key};
+ }
+ }
+ 1;
+}
+
# This function can be called from other handlers to perform tasks on all cached
database handles.
@@ -301,8 +354,10 @@
AutoCommit is off and the script finishes without an explicit rollback, the
Apache::DBI module uses a PerlCleanupHandler to issue a rollback at the
end of every request. Note, that this CleanupHandler will only be used, if
-the initial data_source sets AutoCommit = 0. It will not be used, if AutoCommit
-will be turned off, after the connect has been done.
+the initial data_source sets AutoCommit = 0 or AutoCommit is turned off, after
+the connect has been done (ie begin_work). However, because a connection may have
+set other parameters, the handle is reset to its initial connection state before
+it is returned for a second time.
This module plugs in a menu item for Apache::Status. The menu lists the
current database connections. It should be considered incomplete because of
pgp00000.pgp
Description: PGP signature
