Author: timbo
Date: Wed Apr 25 08:57:06 2007
New Revision: 9451

Modified:
   dbi/trunk/Changes
   dbi/trunk/DBI.pm
   dbi/trunk/goferperf.pl
   dbi/trunk/lib/DBD/Gofer.pm
   dbi/trunk/lib/DBD/Gofer/Transport/Base.pm
   dbi/trunk/lib/DBD/Gofer/Transport/pipeone.pm
   dbi/trunk/lib/DBI/DBD.pm
   dbi/trunk/lib/DBI/Gofer/Execute.pm
   dbi/trunk/lib/DBI/Gofer/Request.pm
   dbi/trunk/lib/DBI/Gofer/Response.pm
   dbi/trunk/test.pl

Log:
Partial work on retry mechanism for gofer.
Added flags field to response, with GOf_RESPONSE_EXECUTED set if 
$dbh->{Executed}
so if the flags not set then the client knows it can safely retry.
Removed dbh_wantarray from request by moving it into dbh_method_call.


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Wed Apr 25 08:57:06 2007
@@ -6,8 +6,6 @@
 
 =cut
 
-http://buildd.debian.org/fetch.cgi?&pkg=libdbi-perl&ver=1.54-1&arch=m68k&stamp=1174636818&file=log
-
 Policy principle:
     Designed to influence behaviour of unaltered programs
     ie go_* attributes take precidence over policy

Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm    (original)
+++ dbi/trunk/DBI.pm    Wed Apr 25 08:57:06 2007
@@ -3082,7 +3082,7 @@
 Returns a state code in the standard SQLSTATE five character format.
 Note that the specific success code C<00000> is translated to any empty string
 (false). If the driver does not support SQLSTATE (and most don't),
-then state will return C<S1000> (General Error) for all errors.
+then state() will return C<S1000> (General Error) for all errors.
 
 The driver is free to return any value via C<state>, e.g., warning
 codes, even if it has not declared an error by returning a true value
@@ -3090,7 +3090,7 @@
 
 The state() method should not be used to test for errors, use err()
 for that, because drivers may return a 'success with information' or
-warning state code via errstr() for methods that have not 'failed'.
+warning state code via state() for methods that have not 'failed'.
 
 =item C<set_err>
 

Modified: dbi/trunk/goferperf.pl
==============================================================================
--- dbi/trunk/goferperf.pl      (original)
+++ dbi/trunk/goferperf.pl      Wed Apr 25 08:57:06 2007
@@ -14,7 +14,7 @@
 
 GetOptions(
     'c|count=i' => \(my $opt_count = 100),
-    'dsn=s'     => \(my $opt_dsn   = "dbi:NullP:"),
+    'dsn=s'     => \(my $opt_dsn),
     'timeout=i' => \(my $opt_timeout = 10),
     'p|policy=s' => \(my $opt_policy = "pedantic,classic,rush"),
 ) or exit 1;
@@ -38,6 +38,7 @@
 
 my %trials = (
     null       => {},
+    null_ha    => { DBI => "DBIx::HA" },
     pipeone    => { perl=>$perl, timeout=>$opt_timeout },
     stream     => { perl=>$perl, timeout=>$opt_timeout },
     stream_ssh => ($can_ssh)
@@ -80,19 +81,23 @@
 sub run_tests {
     my ($transport, $trans_attr, $policy_name) = @_;
 
-    my $test_run_tag = "Testing $transport transport with $policy_name policy";
+    my $connect_attr = delete $trans_attr->{connect_attr} || {};
+    my $DBI = delete $trans_attr->{DBI} || "DBI";
+    _load_class($DBI) if $DBI ne "DBI";
+
+    my $test_run_tag = "Testing $transport transport with $policy_name policy 
@{[ %$connect_attr ]}";
     print "\n$test_run_tag\n";
 
-    my $dsn = $opt_dsn;
+    my $dsn = $opt_dsn || $trans_attr->{dsn} || "dbi:NullP:";
     if ($policy_name ne 'no') {
         my $driver_dsn = "transport=$transport;policy=$policy_name";
         $driver_dsn .= join ";", '', map { "$_=$trans_attr->{$_}" } keys 
%$trans_attr
             if %$trans_attr;
-        $dsn = "dbi:Gofer:$driver_dsn;dsn=$opt_dsn";
+        $dsn = "dbi:Gofer:$driver_dsn;dsn=$dsn";
     }
     print " $dsn\n";
 
-    my $dbh = DBI->connect($dsn, undef, undef, { RaiseError => 1 } );
+    my $dbh = $DBI->connect($dsn, undef, undef, { %$connect_attr, RaiseError 
=> 1 } );
 
     $dbh->do("DROP TABLE IF EXISTS fruit");
     $dbh->do("CREATE TABLE fruit (dKey INT, dVal VARCHAR(10))");

Modified: dbi/trunk/lib/DBD/Gofer.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer.pm  (original)
+++ dbi/trunk/lib/DBD/Gofer.pm  Wed Apr 25 08:57:06 2007
@@ -251,7 +251,7 @@
         # $method and @args left in @_
 
         my $request = $dbh->{go_request};
-        $request->init_request([EMAIL PROTECTED], wantarray);
+        $request->init_request([ wantarray, @_ ]);
         ++$dbh->{go_request_count};
 
         my $go_policy = $dbh->{go_policy};
@@ -506,7 +506,7 @@
 
         my ($sth, $sth_inner) = DBI::_new_sth($dbh, {
             Statement => $statement,
-            go_prepare_call => [ $go_prepare, $statement, $attr ],
+            go_prepare_call => [ 0, $go_prepare, $statement, $attr ],
             # go_method_calls => [], # autovivs if needed
             go_request => $dbh->{go_request},
             go_transport => $dbh->{go_transport},
@@ -567,7 +567,7 @@
         ++$dbh->{go_request_count};
 
         my $request = $sth->{go_request};
-        $request->init_request($sth->{go_prepare_call}, undef);
+        $request->init_request($sth->{go_prepare_call});
         $request->sth_method_calls(delete $sth->{go_method_calls})
             if $sth->{go_method_calls};
         $request->sth_result_attr({}); # (currently) also indicates this is an 
sth request

Modified: dbi/trunk/lib/DBD/Gofer/Transport/Base.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Transport/Base.pm   (original)
+++ dbi/trunk/lib/DBD/Gofer/Transport/Base.pm   Wed Apr 25 08:57:06 2007
@@ -26,27 +26,34 @@
 
 sub transmit_request {
     my ($self, $request) = @_;
-
     my $to = $self->go_timeout;
-    local $SIG{ALRM} = sub { die "TIMEOUT\n" } if $to;
 
-    my $info = eval {
-        local $SIG{PIPE} = sub {
-            my $extra = ($! eq "Broken pipe") ? "" : " ($!)";
-            die "Unable to send request: Broken pipe$extra\n";
+    my $transmit_sub = sub {
+        local $SIG{ALRM} = sub { die "TIMEOUT\n" } if $to;
+
+        my $info = eval {
+            local $SIG{PIPE} = sub {
+                my $extra = ($! eq "Broken pipe") ? "" : " ($!)";
+                die "Unable to send request: Broken pipe$extra\n";
+            };
+            alarm($to) if $to;
+            $self->transmit_request_by_transport($request);
         };
-        alarm($to) if $to;
-        $self->transmit_request_by_transport($request);
+        alarm(0) if $to;
+
+        if ($@) {
+            return $self->transport_timedout("transmit_request", $to)
+                if $@ eq "TIMEOUT\n";
+            return DBI::Gofer::Response->new({ err => 1, errstr => $@ });
+        }
+
+        return undef;
     };
-    alarm(0) if $to;
 
-    if ($@) {
-        return $self->transport_timedout("transmit_request", $to)
-            if $@ eq "TIMEOUT\n";
-        return DBI::Gofer::Response->new({ err => 1, errstr => $@ });
-    }
+    my $response = $transmit_sub->();
 
-    return undef;
+    return $response unless wantarray;
+    return ($response, $transmit_sub);
 }
 
 

Modified: dbi/trunk/lib/DBD/Gofer/Transport/pipeone.pm
==============================================================================
--- dbi/trunk/lib/DBD/Gofer/Transport/pipeone.pm        (original)
+++ dbi/trunk/lib/DBD/Gofer/Transport/pipeone.pm        Wed Apr 25 08:57:06 2007
@@ -132,7 +132,7 @@
         for my $fh (@readable) {
             local $_;
             my $actions = $fh_actions->{$fh} || die "panic: no action for $fh";
-            my $rv = sysread($fh, $_='', 512 * 32);
+            my $rv = sysread($fh, $_='', 1024*31);  # to fit in 32KB slab
             unless ($rv) {              # error (undef) or end of file (0)
                 my $action;
                 unless (defined $rv) {  # was an error

Modified: dbi/trunk/lib/DBI/DBD.pm
==============================================================================
--- dbi/trunk/lib/DBI/DBD.pm    (original)
+++ dbi/trunk/lib/DBI/DBD.pm    Wed Apr 25 08:57:06 2007
@@ -1273,7 +1273,7 @@
 
     /* Adjust NUM_OF_FIELDS - which also adjusts the row buffer size */
     DBIc_NUM_FIELDS(imp_sth) = 0; /* for DBI <= 1.53 */
-    DBIS->set_attr_k(sth, sv_2mortal(newSVpvn("NUM_OF_FIELDS",13)), 0,
+    DBIc_STATE(imp_xxh)->set_attr_k(sth, 
sv_2mortal(newSVpvn("NUM_OF_FIELDS",13)), 0,
         sv_2mortal(newSViv(mysql_num_fields(imp_sth->result)))
     );
 

Modified: dbi/trunk/lib/DBI/Gofer/Execute.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Execute.pm  (original)
+++ dbi/trunk/lib/DBI/Gofer/Execute.pm  Wed Apr 25 08:57:06 2007
@@ -23,6 +23,9 @@
 
 our $local_log = $ENV{DBI_GOFER_LOCAL_LOG}; # do extra logging to stderr
 
+our $current_dbh;   # the dbh we're using for this request
+
+
 # set trace for server-side gofer
 # Could use DBI_TRACE env var when it's an unrelated separate process
 # but using DBI_GOFER_TRACE makes testing easier for subprocesses (eg stream)
@@ -165,6 +168,10 @@
         # RaiseError must be enabled
         RaiseError => 1,
 
+        # reset Executed flag (of the cached handle) so we can use it to tell
+        # if errors happened before the main part of the request was executed
+        Executed => 0,
+
         # ensure this connect_cached doesn't have the same args as the client
         # because that causes subtle issues if in the same process (ie 
transport=null)
        # include pid to avoid problems with forking (ie null transport in 
mod_perl)
@@ -178,6 +185,7 @@
     }
 
     #$dbh->trace(0);
+    $current_dbh = $dbh;
     return $dbh;
 }
 
@@ -189,7 +197,7 @@
 
 
 sub new_response_with_err {
-    my ($self, $rv, $eval_error) = @_;
+    my ($self, $rv, $eval_error, $h) = @_;
     # capture err+errstr etc and merge in $eval_error ($@)
 
     my ($err, $errstr, $state) = ($DBI::err, $DBI::errstr, $DBI::state);
@@ -203,11 +211,15 @@
         $errstr = ($errstr) ? "$errstr; $eval_error" : $eval_error;
     }
 
+    my $flags;
+    $flags |= GOf_RESPONSE_EXECUTED if $h && $h->{Executed};
+
     my $response = DBI::Gofer::Response->new({
         rv     => $rv,
         err    => $err,
         errstr => $errstr,
         state  => $state,
+        flags  => $flags,
     });
 
     return $response;
@@ -238,7 +250,8 @@
             ? $self->execute_sth_request($request)
             : $self->execute_dbh_request($request);
     };
-    $response ||= $self->new_response_with_err(undef, $@);
+    $response ||= $self->new_response_with_err(undef, $@, $current_dbh);
+    undef $current_dbh;
 
     $response->warnings([EMAIL PROTECTED]) if @warnings;
     DBI->trace_msg("<----- execute_request\n");
@@ -254,14 +267,15 @@
     my $rv_ref = eval {
         $dbh = $self->_connect($request);
         my $args = $request->dbh_method_call; # [ 'method_name', @args ]
-        my $meth = shift @$args;
+        my $wantarray = shift @$args;
+        my $meth      = shift @$args;
         $stats->{method_calls_dbh}->{$meth}++;
-        my @rv = ($request->dbh_wantarray)
+        my @rv = ($wantarray)
             ?        $dbh->$meth(@$args)
             : scalar $dbh->$meth(@$args);
         [EMAIL PROTECTED];
     } || [];
-    my $response = $self->new_response_with_err($rv_ref, $@);
+    my $response = $self->new_response_with_err($rv_ref, $@, $dbh);
 
     return $response if not $dbh;
 
@@ -342,7 +356,8 @@
     my $rv = eval {
         $dbh = $self->_connect($request);
 
-        my $args = $request->dbh_method_call; # [ 'method_name', @args ]
+        my $args = $request->dbh_method_call; # [ wantarray, 'method_name', 
@args ]
+        shift @$args; # discard wantarray
         my $meth = shift @$args;
         $stats->{method_calls_sth}->{$meth}++;
         $sth = $dbh->$meth(@$args);
@@ -364,7 +379,7 @@
 
         $last;
     };
-    my $response = $self->new_response_with_err($rv, $@);
+    my $response = $self->new_response_with_err($rv, $@, $dbh);
 
     return $response if not $dbh;
 

Modified: dbi/trunk/lib/DBI/Gofer/Request.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Request.pm  (original)
+++ dbi/trunk/lib/DBI/Gofer/Request.pm  Wed Apr 25 08:57:06 2007
@@ -20,7 +20,6 @@
     version
     dbh_connect_call
     dbh_method_call
-    dbh_wantarray
     dbh_attributes
     dbh_last_insert_id_args
     sth_method_calls
@@ -46,10 +45,9 @@
 }
 
 sub init_request {
-    my ($self, $method_and_args, $wantarray) = @_;
+    my ($self, $method_and_args) = @_;
     $self->reset;
     $self->dbh_method_call($method_and_args);
-    $self->dbh_wantarray($wantarray);
 }
 
 sub summary_as_text {

Modified: dbi/trunk/lib/DBI/Gofer/Response.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Response.pm (original)
+++ dbi/trunk/lib/DBI/Gofer/Response.pm Wed Apr 25 08:57:06 2007
@@ -12,16 +12,22 @@
 use Carp;
 use DBI qw(neat neat_list);
 
-use base qw(DBI::Util::_accessor);
+use base qw(DBI::Util::_accessor Exporter);
 
 our $VERSION = sprintf("0.%06d", q$Revision$ =~ /(\d+)/o);
 
+use constant GOf_RESPONSE_EXECUTED => 0x0001;
+
+our @EXPORT = qw(GOf_RESPONSE_EXECUTED);
+
+
 __PACKAGE__->mk_accessors(qw(
     version
     rv
     err
     errstr
     state
+    flags
     last_insert_id
     dbh_attributes
     sth_resultsets
@@ -90,6 +96,8 @@
     my @s = sprintf("\trv=%s", (ref $rv) ? "[".neat_list($rv)."]" : neat($rv));
     $s[-1] .= sprintf(", err=%s, errstr=%s", $err, neat($errstr))
         if defined $err;
+    $s[-1] .= sprintf(",  flags=0x%x", $self->{flags})
+        if defined $self->{flags};
 
     push @s, "last_insert_id=%s", $self->last_insert_id
         if defined $self->last_insert_id;

Modified: dbi/trunk/test.pl
==============================================================================
--- dbi/trunk/test.pl   (original)
+++ dbi/trunk/test.pl   Wed Apr 25 08:57:06 2007
@@ -102,6 +102,7 @@
     my $null_dbh = DBI->connect('dbi:NullP:','','');
     my $null_sth = $null_dbh->prepare('');     # create one to warm up
     $count = 20_000;
+    $count /= 10 if $ENV{DBI_AUTOPROXY};
     my $i = $count;
     my $t1 = new Benchmark;
     $null_dbh->prepare('') while $i--;

Reply via email to