Index: trunk/Nebulous-Server/lib/Nebulous/Server.pm
===================================================================
--- trunk/Nebulous-Server/lib/Nebulous/Server.pm	(revision 20091)
+++ trunk/Nebulous-Server/lib/Nebulous/Server.pm	(revision 20965)
@@ -1,5 +1,5 @@
 # Copyright (c) 2004-2008  Joshua Hoblitt
 #
-# $Id: Server.pm,v 1.93 2008-10-13 20:41:17 jhoblitt Exp $
+# $Id: Server.pm,v 1.94 2008-12-12 21:13:41 jhoblitt Exp $
 
 package Nebulous::Server;
@@ -9,5 +9,5 @@
 no warnings qw( uninitialized );
 
-our $VERSION = '0.15';
+our $VERSION = '0.16';
 
 use base qw( Class::Accessor::Fast );
@@ -19,8 +19,8 @@
 use File::Spec;
 use Log::Log4perl;
+use Nebulous::Keys qw( parse_neb_key parse_neb_volume );
 use Nebulous::Server::Config;
 use Nebulous::Server::Log;
 use Nebulous::Server::SQL;
-use Nebulous::Keys qw( parse_neb_key parse_neb_volume );
 use Params::Validate qw( validate_pos SCALAR SCALARREF UNDEF );
 use URI::file;
@@ -36,5 +36,5 @@
 
     # let Nebulous::Server::Config validate our params
-    my $config = Nebulous::Server::Config->init( @_ );
+    my $config = Nebulous::Server::Config->new( @_ );
 
     # log4perl is not avaliable until we call init()
@@ -51,7 +51,4 @@
     $self->config($config);
 
-    # ask for the db handle as a means of validating the database parameters
-    $self->db;
-
     $log->debug( "leaving" );
     
@@ -62,10 +59,5 @@
 sub db
 {
-    my $self = shift;
-
-    if (@_) {
-        $self->{db} = $_[0];
-        return $self;
-    }
+    my ($self, $key) = @_;
 
     my $log     = $self->log;
@@ -73,11 +65,24 @@
     my $config  = $self->config;
 
+    my $db_index = 0;
+    if (defined $key) {
+        # hash the key to select the correct database instance
+        $db_index = unpack("%20h", sha1_hex("$key")) % $config->n_db;
+    }
+
+    # lookup to see if we have a stored dbh for this database
+    my $dbh = $self->{dbs}[$db_index];
     # if the dbh is still alive, return it
-    if (defined $self->{db} and $self->{db}->ping) {
+    if (defined $dbh and $dbh->ping) {
         $log->debug("db handle is still alive");
-        return $self->{db};
+        return $dbh;
     }
     # otherwise create a new connection
     $log->debug("db handle is dead/unopened");
+
+    # lookup database info
+    my $db_config = $config->db($db_index);
+    die "can't find database configuration info for database # $db_index"
+        unless $db_config;
 
     # if we're running under mod_perl & Apache::DBI is loaded we want to
@@ -86,10 +91,9 @@
     # processes and the database might have gone away on us.  Apache::DBI will
     # take care of getting a valid dbh back.
-    my $db;
-    eval {
-        $db = DBI->connect_cached(
-            $config->dsn,
-            $config->dbuser,
-            $config->dbpasswd,
+    eval {
+        $dbh = DBI->connect_cached(
+            $db_config->dsn,
+            $db_config->dbuser,
+            $db_config->dbpasswd,
             {
                 RaiseError => 1,
@@ -99,18 +103,18 @@
         );
 
-        $db->do( $sql->set_transaction_model );
-        $log->debug( "connected to database: ", sub { $db->data_sources; } );
-        $db->commit;
+        $dbh->do( $sql->set_transaction_model );
+        $log->debug( "connected to database: ", sub { $dbh->data_sources; } );
+        $dbh->commit;
         $log->debug("commit");
     };
     if ( $@ ) {
-        $db->rollback if $db;
+        $dbh->rollback if $dbh;
         $log->debug("rollback");
         $log->logdie( "database error: $@" );
     }
 
-    $self->{db} = $db;
-
-    return $db;
+    $self->{dbs}[$db_index] = $dbh;
+
+    return $dbh;
 }
 
@@ -139,5 +143,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug( "entered - @_" );
@@ -150,5 +154,5 @@
     # to check it after parsing the key
     if (defined $vol_name
-        and not $self->_is_valid_volume_name($key->volume)) {
+        and not $self->_is_valid_volume_name($key, $key->volume)) {
         if ($key->soft_volume) {
             $log->warn( "$vol_name is not a known volume name" );
@@ -160,5 +164,5 @@
         
     my ($vol_id, $vol_host, $vol_path, $vol_xattr)
-        = $self->_get_storage_volume($vol_name, $key->soft_volume);
+        = $self->_get_storage_volume($key, $vol_name, $key->soft_volume);
 
     my $uri;
@@ -261,5 +265,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug("entered - @_");
@@ -296,91 +300,157 @@
 
 
-sub swap_objects
-{
-    my $self = shift;
-
-    my ($key1, $key2) = validate_pos(@_,
-        {
-            type        => SCALAR,
-            callbacks   => {
-                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
-            },
-        },
-        {
-            type        => SCALAR,
-            callbacks   => {
-                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
-            },
-        },
-    );
-
-    my $log = $self->log;
-    my $sql = $self->sql;
-    my $db  =$self->db;
-
-    $log->debug("entered - @_");
-
-    # ignore volumes
-    $key1 = parse_neb_key($key1);
-    $key2 = parse_neb_key($key2);
-
-    # order of operations for the swap:
-    # key1 -> key1.swap
-    # key2 -> key1
-    # key1.swap -> key2
-
-    eval {
-        {
-            # key1 -> key1.swap
-            my $query = $db->prepare_cached($sql->rename_object); 
-            # this SQL statment takes the new key name as the first param
-            my $rows = $query->execute($key1->path . ".swap", $key1->path);
-
-            # if we affected more then one row something very bad has happened.
-            unless ($rows == 1) {
-                $query->finish;
-                $log->logdie("affected row count is $rows instead of 1");
-            }
-        }
-
-        {
-            # key2 -> key1
-            my $query = $db->prepare_cached($sql->rename_object); 
-            # this SQL statment takes the new key name as the first param
-            my $rows = $query->execute($key1->path, $key2->path);
-
-            # if we affected more then one row something very bad has happened.
-            unless ($rows == 1) {
-                $query->finish;
-                $log->logdie("affected row count is $rows instead of 1");
-            }
-        }
-
-        {
-            # key1.swap -> key2
-            my $query = $db->prepare_cached($sql->rename_object); 
-            # this SQL statment takes the new key name as the first param
-            my $rows = $query->execute($key2->path, $key1->path . ".swap");
-
-            # if we affected more then one row something very bad has happened.
-            unless ($rows == 1) {
-                $query->finish;
-                $log->logdie("affected row count is $rows instead of 1");
-            }
-        }
-
-        $db->commit;
-        $log->debug("commit");
-    };
-    if ($@) {
-        $db->rollback;
-        $log->debug("rollback");
-        $log->logdie("database error: $@");
-    }
-
-    $log->debug("leaving");
-
-    return 1;
-}
+# sub swap_objects
+# {
+#     my $self = shift;
+# 
+#     my ($key1, $key2) = validate_pos(@_,
+#         {
+#             type        => SCALAR,
+#             callbacks   => {
+#                 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+#             },
+#         },
+#         {
+#             type        => SCALAR,
+#             callbacks   => {
+#                 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+#             },
+#         },
+#     );
+# 
+#     my $log  = $self->log;
+#     my $sql  = $self->sql;
+#     my $dbh1 = $self->db($key1);
+#     my $dbh2 = $self->db($key2);
+# 
+#     $log->debug("entered - @_");
+# 
+#     # ignore volumes
+#     $key1 = parse_neb_key($key1);
+#     $key2 = parse_neb_key($key2);
+# 
+#     # order of operations for the swap with a single db is:
+#     # key1 -> key1.swap
+#     # key2 -> key1
+#     # key1.swap -> key2
+# 
+#     # XXX this cmp will only work if ->db() returns the same exact (cached) dbh
+#     if ($dbh1 == $dbh2) {
+#         my $dbh = $dbh1;
+#         eval {
+#             {
+#                 # key1 -> key1.swap
+#                 my $query = $dbh->prepare_cached($sql->rename_object); 
+#                 # this SQL statment takes the new key name as the first param
+#                 my $rows = $query->execute($key1->path . ".swap", $key1->path);
+# 
+#                 # if we affected more then one row something very bad has happened.
+#                 unless ($rows == 1) {
+#                     $query->finish;
+#                     $log->logdie("affected row count is $rows instead of 1");
+#                 }
+#             }
+# 
+#             {
+#                 # key2 -> key1
+#                 my $query = $dbh->prepare_cached($sql->rename_object); 
+#                 # this SQL statment takes the new key name as the first param
+#                 my $rows = $query->execute($key1->path, $key2->path);
+# 
+#                 # if we affected more then one row something very bad has happened.
+#                 unless ($rows == 1) {
+#                     $query->finish;
+#                     $log->logdie("affected row count is $rows instead of 1");
+#                 }
+#             }
+# 
+#             {
+#                 # key1.swap -> key2
+#                 my $query = $dbh->prepare_cached($sql->rename_object); 
+#                 # this SQL statment takes the new key name as the first param
+#                 my $rows = $query->execute($key2->path, $key1->path . ".swap");
+# 
+#                 # if we affected more then one row something very bad has happened.
+#                 unless ($rows == 1) {
+#                     $query->finish;
+#                     $log->logdie("affected row count is $rows instead of 1");
+#                 }
+#             }
+# 
+#             $dbn->commit;
+#             $log->debug("commit");
+#         };
+#         if ($@) {
+#             $dbh->rollback;
+#             $log->debug("rollback");
+#             $log->logdie("database error: $@");
+#         }
+#     }
+# 
+#     # order of operations for the swap between two dbs is:
+#     # key1 start transaction
+#     # key1 -> read all instances
+#     # key1 -> remove all instances
+#     # key2 start transaction
+#     # key2 -> read all instances
+#     # key2 -> remove all instances
+#     # key1 -> insert key 2 instances
+#     # key2 -> insert key 1 instances
+#     # key1,2 commit
+# 
+#     eval {
+#         {
+#             # key1 -> read all instances
+#             my $query = $dbh->prepare_cached($sql->rename_object); 
+#             # this SQL statment takes the new key name as the first param
+#             my $rows = $query->execute($key1->path . ".swap", $key1->path);
+# 
+#             # if we affected more then one row something very bad has happened.
+#             unless ($rows == 1) {
+#                 $query->finish;
+#                 $log->logdie("affected row count is $rows instead of 1");
+#             }
+#         }
+# 
+#         {
+#             # key2 -> key1
+#             my $query = $db->prepare_cached($sql->rename_object); 
+#             # this SQL statment takes the new key name as the first param
+#             my $rows = $query->execute($key1->path, $key2->path);
+# 
+#             # if we affected more then one row something very bad has happened.
+#             unless ($rows == 1) {
+#                 $query->finish;
+#                 $log->logdie("affected row count is $rows instead of 1");
+#             }
+#         }
+# 
+#         {
+#             # key1.swap -> key2
+#             my $query = $db->prepare_cached($sql->rename_object); 
+#             # this SQL statment takes the new key name as the first param
+#             my $rows = $query->execute($key2->path, $key1->path . ".swap");
+# 
+#             # if we affected more then one row something very bad has happened.
+#             unless ($rows == 1) {
+#                 $query->finish;
+#                 $log->logdie("affected row count is $rows instead of 1");
+#             }
+#         }
+# 
+#         $db->commit;
+#         $log->debug("commit");
+#     };
+#         if ($@) {
+#             $db->rollback;
+#             $log->debug("rollback");
+#             $log->logdie("database error: $@");
+#         }
+# 
+# 
+#     $log->debug("leaving");
+# 
+#     return 1;
+# }
 
 
@@ -420,5 +490,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug("entered - @_");
@@ -429,5 +499,5 @@
 
     if (defined $vol_name
-        and not $self->_is_valid_volume_name($key->volume)) {
+        and not $self->_is_valid_volume_name($key, $key->volume)) {
         if ($key->soft_volume) {
             $log->warn( "$vol_name is not a known volume name" );
@@ -441,5 +511,5 @@
     if (defined $vol_name) {
         ($vol_id, $vol_host, $vol_path, $vol_xattr)
-            = $self->_get_storage_volume($vol_name);
+            = $self->_get_storage_volume($key, $vol_name);
     } else {
         ($vol_id, $vol_host, $vol_path, $vol_xattr)
@@ -534,5 +604,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug( "entered - @_" );
@@ -637,5 +707,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug( "entered - @_" );
@@ -749,5 +819,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug("entered - @_");
@@ -816,5 +886,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug("entered - @_");
@@ -869,5 +939,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug("entered - @_");
@@ -912,5 +982,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug("entered - @_");
@@ -947,7 +1017,9 @@
 sub find_objects
 {
-    my $self = shift;
-
-    my ( $pattern ) = validate_pos( @_,
+    # XXX: this will only search one db
+
+    my $self = shift;
+
+    my ($pattern) = validate_pos( @_,
         {
             type        => SCALAR,
@@ -958,5 +1030,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db;
 
     $log->debug( "entered - @_" );
@@ -1016,5 +1088,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug("entered - @_");
@@ -1027,5 +1099,5 @@
     # to check it after parsing the key
     if (defined $vol_name
-        and not $self->_is_valid_volume_name($key->volume)) {
+        and not $self->_is_valid_volume_name($key, $key->volume)) {
         if ($key->soft_volume) {
             $log->warn( "$vol_name is not a known volume name" );
@@ -1087,5 +1159,11 @@
     my $self = shift;
 
-    my ( $uri ) = validate_pos( @_,
+    my ($key, $uri) = validate_pos( @_,
+        {
+            type        => SCALAR,
+            callbacks   => {
+                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+            },
+        },
         {
             type => SCALAR|SCALARREF,
@@ -1095,5 +1173,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug( "entered - @_" );
@@ -1182,5 +1260,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $log->debug("entered - @_");
@@ -1211,4 +1289,5 @@
 sub mounts
 {
+    # XXX: this will only pull the mounts from one db
     my $self = shift;
 
@@ -1217,5 +1296,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db;
 
     $log->debug("entered - @_");
@@ -1246,13 +1325,13 @@
     my $self = shift;
 
-    my $log = $self->log;
-    my $sql = $self->sql;
-    my $db  = $self->db;
+    my ($key, $name, $soft_volume) = @_;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  = $self->db($key);
 
     no warnings qw( uninitialized );
     $log->debug( "entered - @_" );
     use warnings;
-
-    my ($name, $soft_volume) = @_;
 
     my ($vol_id, $vol_host, $vol_path, $xattr);
@@ -1271,5 +1350,5 @@
                 # find it, fall back to any volume
                 if ($soft_volume) {
-                    ($vol_id, $vol_host, $vol_path, $xattr) = $self->_get_storage_volume;
+                    ($vol_id, $vol_host, $vol_path, $xattr) = $self->_get_storage_volume($key);
                     return; # this just returns out of the eval not from the subroutine
                 }
@@ -1311,7 +1390,9 @@
     my $self = shift;
 
-    my $log = $self->log;
-    my $sql = $self->sql;
-    my $db  =$self->db;
+    my $key = shift;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  = $self->db($key);
 
     no warnings qw( uninitialized );
@@ -1319,5 +1400,4 @@
     use warnings;
 
-    my $key = shift;
 
     $key = parse_neb_key($key);
@@ -1361,5 +1441,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+    my $db  = $self->db($key);
 
     $key = parse_neb_key($key);
@@ -1388,9 +1468,9 @@
 sub _is_valid_volume_name
 {
-    my ($self, $vol_name) = @_;
-
-    my $log = $self->log;
-    my $sql = $self->sql;
-    my $db  =$self->db;
+    my ($self, $key, $vol_name) = @_;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  = $self->db($key);
 
     my $volume_info = parse_neb_volume($vol_name);
@@ -1429,5 +1509,5 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  = $self->db;
+    my $db  = $self->db($key);
 
     my $uri;
@@ -1558,11 +1638,11 @@
     my $log = $self->log;
     my $sql = $self->sql;
-    my $db  =$self->db;
+#    my $db  = $self->db;
 
     $log->debug( "entered" );
 
-    $self->db->disconnect;        
-
-    $log->debug( "disconnected from database: ", sub { $db->data_sources; } );
+#    $self->db->disconnect;        
+
+#    $log->debug( "disconnected from database: ", sub { $db->data_sources; } );
 
     $log->debug( "leaving" );
