Index: /trunk/Nebulous/Changes
===================================================================
--- /trunk/Nebulous/Changes	(revision 24929)
+++ /trunk/Nebulous/Changes	(revision 24930)
@@ -7,4 +7,5 @@
     - change neb-locate's output seperator to \n
     - add Nebulous::Client->prune() method
+    - add Nebulous::Client->there_can_be_only_one() method
 
 0.10
Index: /trunk/Nebulous/MANIFEST
===================================================================
--- /trunk/Nebulous/MANIFEST	(revision 24929)
+++ /trunk/Nebulous/MANIFEST	(revision 24930)
@@ -101,4 +101,5 @@
 t/69_client_prune.t
 t/70_neb-ls.t
+t/71_client_there_can_be_only_one.t
 t/90_nebclient.t
 t/TEST.PL
Index: /trunk/Nebulous/lib/Nebulous/Client.pm
===================================================================
--- /trunk/Nebulous/lib/Nebulous/Client.pm	(revision 24929)
+++ /trunk/Nebulous/lib/Nebulous/Client.pm	(revision 24930)
@@ -360,7 +360,12 @@
 
     my $locations;
+    my $removed = 0;
     eval {
         # first - strip off any inaccesible instances
-        $self->prune($key);
+        if (not defined $self->prune($key)) {
+            # use the prune() method to also determine if $key is valid
+            $removed = undef;
+            return;
+        }
 
         # check to see if there is an instance on $vol_name that should be the
@@ -375,10 +380,14 @@
                 next if $victim eq $locations->[0];
                 $self->delete_instance($key, $victim);
+                $removed++;
             }
         } else {
             # nuke whatever
-            my @stats = $self->stat($key);
-            foreach (1 .. $stats[6]) {
+            my $stats = $self->stat($key);
+            # start at one so cull() is called one less time then the # of
+            # instances
+            for (my $i = 1; $i < $stats->[6]; $i++) {
                 $self->cull($key);
+                $removed++;
             }
         }
@@ -391,5 +400,5 @@
     $log->debug("leaving");
 
-    return $locations->[0];
+    return $removed;
 }
 
Index: /trunk/Nebulous/lib/Nebulous/Client.pod
===================================================================
--- /trunk/Nebulous/lib/Nebulous/Client.pod	(revision 24929)
+++ /trunk/Nebulous/lib/Nebulous/Client.pod	(revision 24930)
@@ -35,5 +35,6 @@
     my $mounts = $neb->mounts();
     my $mode = $neb->chmod( $key, $mode );
-    my $dead = $neb->prune( $key );
+    my $n_dead = $neb->prune( $key );
+    my $n_dead = $neb->there_can_be_only_one( $key, $vol );
 
 =head1 DESCRIPTION
@@ -419,5 +420,25 @@
 =back
 
-The number of inaccessible instances removed:
+The number of instances removed.
+
+=item * there_can_be_only_one($key, $vol)
+
+Removes all but one instance of an object and automatically removes any
+inaccessible instances.
+
+=over 4
+
+=item * key
+
+The storage object key (name).
+
+=item * vol
+
+If specified, the only remaining instance will be left on this volume (if an
+instance already exists there).
+
+=back
+
+The number of avaiable instances removed.
 
 =item * mounts()
@@ -479,5 +500,5 @@
 =head1 COPYRIGHT
 
-Copyright (C) 2004-2008  Joshua Hoblitt.  All rights reserved.
+Copyright (C) 2004-2009  Joshua Hoblitt.  All rights reserved.
 
 This program is free software; you can redistribute it and/or modify it under
Index: /trunk/Nebulous/t/71_client_there_can_be_only_one.t
===================================================================
--- /trunk/Nebulous/t/71_client_there_can_be_only_one.t	(revision 24930)
+++ /trunk/Nebulous/t/71_client_there_can_be_only_one.t	(revision 24930)
@@ -0,0 +1,89 @@
+#!/usr/bin/perl
+
+# Copryight (C) 2004-2005  Joshua Hoblitt
+#
+# $Id: 56_client_find_instances.t,v 1.5 2008-09-10 23:50:26 bills Exp $
+
+use strict;
+use warnings FATAL => qw( all );
+
+use Apache::Test qw( -withtestmore );
+
+plan tests => 8;
+
+use lib qw( ./t ./lib );
+
+use Nebulous::Client;
+use Nebulous::Util qw( :standard );
+use Test::Nebulous;
+
+my $hostport = Apache::Test->config->{ 'hostport' };
+
+Test::Nebulous->setup;
+
+{
+    my $key = "foo";
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create($key);
+    $neb->replicate($key,);
+
+    is($neb->there_can_be_only_one($key), 1, "there can be only one!");
+
+    my $locations = $neb->find_instances( "foo" );
+
+    is( scalar @$locations, 1, "found 1" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $key = "foo";
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+    $neb->create($key, "node01");
+    my $uri = $neb->replicate($key, "node02");
+
+    is($neb->there_can_be_only_one($key, "node02"), 1, "there can be only one!");
+
+    my $locations = $neb->find_instances( "foo" );
+
+    is( scalar @$locations, 1, "found 1" );
+    is($locations->[0], $uri, "instance on correct volume" );
+}
+
+Test::Nebulous->setup;
+
+{
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    is( $neb->there_can_be_only_one( "foo" ), undef, "storage object does not exist" );
+}
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->there_can_be_only_one();
+};
+like( $@, qr/1 - 2 were expected/, "no params" );
+
+Test::Nebulous->setup;
+
+eval {
+    my $neb = Nebulous::Client->new(
+        proxy => "http://$hostport/nebulous",
+    );
+
+    $neb->there_can_be_only_one( "foo", 'read', 3 );
+};
+like( $@, qr/1 - 2 were expected/, "too many params" );
+
+Test::Nebulous->cleanup;
