Apache-DBI-Cache

 view release on metacpan or  search on metacpan

lib/Apache/DBI/Cache.pm  view on Meta::CPAN

    unless( @undef_at_cleanup ) {
      if( exists $ENV{MOD_PERL_API_VERSION} and $ENV{MOD_PERL_API_VERSION}==2 ) {
	require Apache2::RequestUtil;
	Apache2::RequestUtil->request
	    ->push_handlers(PerlCleanupHandler=>\&request_cleanup);
      } elsif( exists $INC{'Apache.pm'} and Apache->can( 'push_handlers' ) ) {
	Apache->push_handlers(PerlCleanupHandler=>\&request_cleanup);
      }
    }
    push @undef_at_cleanup, @l;
  }
  sub request_cleanup {
    $LOG->(2, "request_cleanup:");
    foreach my $v (@undef_at_cleanup) {
      $LOG->(2, "    undefining ${$v}");
      undef ${$v};
    }
    @undef_at_cleanup=();
  }
}

sub connect_on_init {
  # provide a handler which creates all connections during server startup

  # store connections
  push @ChildConnect, [@_];
}


# the connect method called from DBI::connect
our %patched_classes=('Apache::DBI::Cache'=>1);
sub connect {
  my $class = shift;
  unshift @_, $class if ref $class;
  my $drh    = shift;
  my @args   = map { defined $_ ? $_ : "" } @_;

  unless( 3 == $#args and ref $args[3] eq "HASH" ) {
    @args=(@args[0..2], {});
  }

  my ($Idx, $statIdx, $ctx);
  if( exists $plugin{$drh->{Name}} ) {
    my @l=$plugin{$drh->{Name}}->[0]->(@args);
    if( @l ) {
      my $nocache;
      ($ctx, $nocache)=splice @l, 4, 2;
      @args[0..2]=@l[0..2];
      %{$args[3]}=%{$l[3]};
      return $drh->connect(@args) if( $nocache );
    } else {
      return $drh->connect(@args);
    }
  }
  my $dsn="dbi:$drh->{Name}:$args[0]";

  my $RootClass=delete $args[3]->{RootClass};
  unless( defined $RootClass ) {
    # this is a very ugly hack
    package		# this line break should make the CPAN indexer happy
      DB;		# to get @DB::args set by caller()
    for( my $i=1; my @l=caller($i++); ) {
      if( $l[3] eq 'DBI::connect' ) {
	$RootClass=$DB::args[0] unless( $DB::args[0] eq 'DBI' );
	last;
      }
    }
  }

  $Idx    =join $DELIMITER, $drh->{Name}, $args[0], $args[1], $args[2];
  $statIdx=join $DELIMITER, $drh->{Name}, $args[0], $args[1];

  # should we default to '__undef__' or something for undef values?
  map { $Idx .= "$DELIMITER$_=" .
	  (defined $args[3]->{$_}
	   ? $args[3]->{$_}
	   : '');
      } sort keys %{$args[3]};

  if( defined $RootClass ) {
    unless( $patched_classes{$RootClass} ) {
      # this is a very ugly hack
      $patched_classes{$RootClass}=1;
      no strict 'refs';
      no warnings 'redefine';
      *{$RootClass.'::db::disconnect'}=\&Apache::DBI::Cache::db::disconnect;
      *{$RootClass.'::db::DESTROY'}=\&Apache::DBI::Cache::db::DESTROY;
    }
    $args[3]->{RootClass}=$RootClass;
  } else {
    $args[3]->{RootClass}=__PACKAGE__;
  }

  if( exists $Connected{$Idx} ) {
    while( my $dbh=shift @{$Connected{$Idx}} ) {
      local $GLOBAL_DESTROY=2;
      if( eval{$dbh->ping} ) {
	if( exists $plugin{$drh->{Name}} ) {
	  unless( $plugin{$drh->{Name}}->[1]->($dbh, @args, $ctx) ) {
	    _statop( $statIdx,
		     4, 1,	# plugin failure
		     1, -1,	# decr. free count
		     0, -1 );	# decr. handle count
	    $LOG->(2, "reusing connection to '$Idx' failed due to plugin error");
	    undef $dbh;
	    next;
	  }
	}
	_statop( $statIdx,
		 2, 1,		# incr. usage count
		 1, -1 );	# decr. free count
	$LOG->(2, "reusing connection to '$Idx'");
	$dbh->{$PRIVATE}->{disconnected}=0;
	return $dbh;
      } else {
	_statop( $statIdx,
		 3, 1,		# ping failure
		 1, -1,		# decr. free count
		 0, -1 );	# decr. handle count
	$LOG->(2, "reusing connection to '$Idx' failed due to PING failure");
	undef $dbh;
      }



( run in 2.647 seconds using v1.01-cache-2.11-cpan-98e64b0badf )