
=head1 NAME

GSI::DBI::Connection - GSI DBI connection management class

=head1 DERIVED FROM

L<DBI>

=head1 DESCRIPTION

This class provides a GSI view to the standard perl DBI class.  Rather
than passing driver specific parameters to the DBI B<connect()> method,
the B<connect()> method provided by this derived class allows connections
to be specified as abstract names mapped by the L<GSI::DBI::DBValues>
interface. 

=head1 SEE ALSO

=over 4

=item *

L<DBI>

=item *

L<GSI::DBI::DBValues>

=back

=head1 AUTHOR

Steve Sapovits

=cut

#use strict;
use vars qw(@ISA @EXPORT $VERSION);
use Exporter;

$VERSION = 1.00;
@ISA = qw(Exporter);

@EXPORT = qw(connect disconnect);

package GSI::DBI::Connection;
@ISA = qw(DBI);

use DBI;
use GSI::DBI::DBValues;

my $shared_dbs = {};
my $dbh_index = {};

sub connect 
{
    my $class = shift;
    my $name = shift;
    my $db_opts = shift;
    my $opts = shift;
    my $this;
    my $super;
    my $db_name;
    my $user;
    my $password;
    my $share_key;
    my $share_entry;

    $class->init_rootclass;

    if (defined($name))
    {
        ($db_name, $user, $password) = get_db_values($name);
    }
    else
    {
        $db_name = 'DBI:' . $ENV{'DBI_DRIVER'} . ':' . $ENV{'DBI_DSN'};
        $user = $ENV{'DBI_USER'};
        $password = $ENV{'DBI_PASS'};
    }

    $share_key = $user . '.' . $password . '@' . $db_name;

    if ( $opts->{NO_SHARE} || 
         !defined($share_entry = $shared_dbs->{$share_key}) )
    {
        # Get a connection to the database.
        $this = $class->SUPER::connect($db_name, $user, $password, $db_opts);

        if ( defined($this) && !$opts->{NO_SHARE} )
        {
            $share_entry = {DBH => $this, SHARED_COUNT => 1};
            $shared_dbs->{$share_key} = $share_entry; 
            $dbh_index->{$this} = $share_key;
        }
    }
    else
    {
        $this = $share_entry->{DBH};
        ++$share_entry->{SHARED_COUNT};
    }

    return $this;
}


package GSI::DBI::Connection::db;
@ISA = qw(DBI::db);

sub disconnect
{
    my $this = shift;
    my $key;
    my $share_entry;
    my $status;

    if ( !defined($key = $dbh_index->{$this})         ||
         !defined($share_entry = $shared_dbs->{$key}) ||
         (--$share_entry->{SHARED_COUNT} <= 0) )
    {
        $status = $this->SUPER::disconnect();
        delete($dbh_index->{$this}) if (defined($key));
        delete($shared_dbs->{$key}) if (defined($share_entry));
    }
    else
    {
        $status = 1;
    }

    return $status;
}

package GSI::DBI::Connection::st;
@ISA = qw(DBI::st);

1;

