Index: branches/eam_branches/ipp-20101103/Nebulous/Build.PL
===================================================================
--- branches/eam_branches/ipp-20101103/Nebulous/Build.PL	(revision 29657)
+++ branches/eam_branches/ipp-20101103/Nebulous/Build.PL	(revision 29906)
@@ -122,4 +122,5 @@
         bin/neb-touch
         bin/neb-xattr
+        bin/whichnode
     )],
 )->create_build_script;
Index: branches/eam_branches/ipp-20101103/Nebulous/bin/whichnode
===================================================================
--- branches/eam_branches/ipp-20101103/Nebulous/bin/whichnode	(revision 29906)
+++ branches/eam_branches/ipp-20101103/Nebulous/bin/whichnode	(revision 29906)
@@ -0,0 +1,82 @@
+#!/bin/env perl
+
+# This script is a temporary "solution" to allow a client to determine whether
+# what volumes contain instances of a nebulous storage object regardless 
+# of whether or not the volume is currently available.
+# Used by cleanup and update processing
+
+
+use strict;
+use warnings;
+use DBI;
+use PS::IPP::Config 1.01 qw( :standard );
+
+use Getopt::Long qw( GetOptions :config auto_help auto_version gnu_getopt );
+use Pod::Usage qw( pod2usage );
+
+use Nebulous::Key qw(parse_neb_key);
+
+my $dbname = "nebulous";
+my $dbserver = "ippdb00";
+my $verbose;
+
+GetOptions(
+    'verbose'        => \$verbose,  # Print to stdout
+) or pod2usage( 2 );
+
+pod2usage( -msg => "filename required", -exitval => 2 ) if ! @ARGV;
+
+
+my $ipprc =  PS::IPP::Config->new();
+my $dbh = getDBHandle();
+
+my $query = "SELECT  volume.name AS volname, uri, mountedvol.*"
+    . " FROM storage_object JOIN instance USING(so_id)"
+    . " JOIN volume using(vol_id)"
+    . " LEFT JOIN mountedvol USING(vol_id)  WHERE ext_id = ?";
+my $stmt = $dbh->prepare($query);
+
+my $errors = 0;
+foreach my $in_key (@ARGV) {
+    my $key_object = parse_neb_key($in_key);
+
+    die "$in_key is not a valid nebulous path\n" if !$key_object;
+
+    my $key = $key_object->path;
+
+    print STDERR "$key\n" if $verbose;
+
+    $stmt->execute($key);
+    my $num_instances = 0;
+    my $num_available = 0;
+    while ( my $instance= $stmt->fetchrow_hashref() ) {
+        my $volname = $instance->{volname};
+        my $uri = $instance->{uri};
+        $num_instances++;
+        if ($instance->{available}) {
+            $num_available++;
+            print "$volname available\n";
+        } else {
+            print "$volname not available\n";
+            $errors++;
+        }
+    }
+}
+
+exit 0;
+
+sub getDBHandle {
+    my $dbuser = metadataLookupStr($ipprc->{_siteConfig}, "DBUSER");
+    my $dbpassword = metadataLookupStr($ipprc->{_siteConfig}, "DBPASSWORD");
+
+    die "database configuration set up" unless defined($dbserver) and defined($dbuser)
+        and defined($dbpassword) and defined($dbname);
+
+    my $dsn = "DBI:mysql:host=$dbserver;database=$dbname";
+
+    my $dbh = DBI->connect($dsn, $dbuser, $dbpassword) 
+        or die "Cannot connect to database.\n";
+
+    return $dbh;
+}
+
Index: branches/eam_branches/ipp-20101103/Nebulous/lib/Nebulous/Client.pm
===================================================================
--- branches/eam_branches/ipp-20101103/Nebulous/lib/Nebulous/Client.pm	(revision 29657)
+++ branches/eam_branches/ipp-20101103/Nebulous/lib/Nebulous/Client.pm	(revision 29906)
@@ -379,5 +379,5 @@
         {
             # volume
-            type        => SCALAR,
+            type        => SCALAR|UNDEF,
             optional    => 1,
         },
@@ -401,8 +401,15 @@
         }
 
+        # set the number of user copies to 1 to prevent replication
+        $self->setxattr($key, 'user.copies', 1, 'replace');
+
         if (defined $locations) {
-            my $instances = $self->find_instances($key);
-            if (scalar @$instances < 2) {
-                die "not enough instances";
+            my $instances = $self->find_instances($key, undef, 'find them all');
+            if (scalar @$instances == 1) {
+                # only one instance nothing to do
+                return 0;
+            }
+            if (scalar @$instances == 0) {
+                die "no instances";
             }
             foreach my $victim (@$instances) {
@@ -416,6 +423,10 @@
             # start at one so cull() is called one less time then the # of
             # instances
-            if ($stats->[6] < 2) {
-                die "not enough instances";
+            if ($stats->[6] ==  1) {
+                # only one instance nothing to do
+                return 0;
+            }
+            if ($stats->[6] == 0) {
+                die "no instances";
             }
             for (my $i = 1; $i < $stats->[6]; $i++) {
@@ -439,4 +450,37 @@
 }
 
+sub storage_object_exists
+{
+    my $self = shift;
+
+    # HI!
+
+    my ($key) = validate_pos(@_,
+        {
+            type => SCALAR,
+        },
+    );
+
+    $log->debug( "entered - @_" );
+
+    my $found = 0;
+    eval {
+        my $objects = $self->find_objects($key);
+        if  ($objects) {
+            $found = (scalar @$objects) > 0;
+        }
+    };
+    if ($@) {
+        if ($@ =~ qr/invalid key/) {
+            $self->set_err($@);
+            return;
+        }
+        $log->logdie($@);
+    }
+
+    $log->debug("leaving");
+
+    return $found;
+}
 
 sub lock
