Index: trunk/Nebulous-Server/lib/Nebulous/Server.pm
===================================================================
--- trunk/Nebulous-Server/lib/Nebulous/Server.pm	(revision 18389)
+++ trunk/Nebulous-Server/lib/Nebulous/Server.pm	(revision 18400)
@@ -1,5 +1,5 @@
 # Copyright (c) 2004-2008  Joshua Hoblitt
 #
-# $Id: Server.pm,v 1.78 2008-07-01 00:28:06 jhoblitt Exp $
+# $Id: Server.pm,v 1.79 2008-07-02 03:40:10 jhoblitt Exp $
 
 package Nebulous::Server;
@@ -320,5 +320,6 @@
             type        => SCALAR,
             callbacks   => {
-                'is valid object key' => sub { $self->_is_valid_object_key($_[0]) },
+                'is valid object key'
+                    => sub { $self->_is_valid_object_key($_[0]) },
             },
         },
@@ -336,4 +337,12 @@
     );
 
+    # if a volume name is explicity specified then we should make the
+    # replication onto that volume (even if there is alread an instance on that
+    # volume) if at all possible and throw an error if we can not.
+    # if a volume name IS NOT specified then we should make the replication
+    # onto any (hopefully the best) volume that DOES NOT already have an
+    # instance on it.  If all avilable volume already have an instance on them
+    # then we should throw an error 
+
     my $log = $self->log;
     my $sql = $self->sql;
@@ -353,5 +362,12 @@
     }
         
-    my ($vol_id, $vol_host, $vol_path, $vol_xattr) = $self->_get_storage_volume($vol_name);
+    my ($vol_id, $vol_host, $vol_path, $vol_xattr);
+    if (defined $vol_name) {
+        ($vol_id, $vol_host, $vol_path, $vol_xattr)
+            = $self->_get_storage_volume($vol_name);
+    } else {
+        ($vol_id, $vol_host, $vol_path, $vol_xattr)
+            = $self->_get_replication_volume($key);
+    }
 
     my $uri;
@@ -359,4 +375,5 @@
         my $so_id;
         {
+            # verify that at least one instance is currently available
             my $query = $db->prepare_cached( $sql->get_object_instances );
             my $rows = $query->execute($key, 1);
@@ -382,5 +399,5 @@
             ($ins_id) = $query->fetchrow_array;
             # XXX finish seems to be required when using LAST_INSERT_ID() or we
-            # get a warning about the stmt handling still be active the next
+            # get a warning about the stmt handling still being active the next
             # time LAST_INSERT_ID() is invoked
             $query->finish;
@@ -1197,4 +1214,53 @@
 
 
+sub _get_replication_volume
+{
+    my $self = shift;
+
+    my $log = $self->log;
+    my $sql = $self->sql;
+    my $db  =$self->db;
+
+    no warnings qw( uninitialized );
+    $log->debug( "entered - @_" );
+    use warnings;
+
+    my $key = shift;
+
+    my $volume;
+    ($volume, $key) = parse_neb_key($key);
+
+    my ($vol_id, $vol_host, $vol_path, $xattr);
+    eval {
+        my $rows;
+        my $query = $db->prepare_cached( $sql->get_replication_volume_for_ext_id );
+        # ext_id, %free, avaiable, allocate
+        $rows = $query->execute($key, 0.95, 1, 1);
+        # XXX destinguish between non-existant and unaviable
+        unless ($rows > 0) {
+            $query->finish;
+            $log->logdie("can't find a suitable storage volume to replicate $key too");
+        }
+        # when matching by name we shouldn't ever match more than once
+        if ($rows > 1) {
+            $query->finish;
+            $log->logdie("affected row count is $rows instead of 1");
+        }
+
+        my $free;
+        ($vol_id, $vol_host, $vol_path, $xattr, $free) = $query->fetchrow_array;
+        $query->finish;
+    };
+    $log->logdie("database error: $@") if $@;
+
+    $log->logdie("failed to find a suitable volume" )
+        unless defined $vol_id and defined $vol_path;
+
+    $log->debug( "leaving" );
+
+    return ($vol_id, $vol_host, $vol_path, $xattr);
+}
+
+
 sub _is_valid_object_key
 {
