Index: trunk/Nebulous/lib/Nebulous/Client.pm
===================================================================
--- trunk/Nebulous/lib/Nebulous/Client.pm	(revision 40680)
+++ trunk/Nebulous/lib/Nebulous/Client.pm	(revision 41172)
@@ -209,5 +209,5 @@
         },
     );
-
+    
     $log->debug( "entered - @_" );
 
@@ -310,4 +310,5 @@
     my $stats = $self->stat($key);
     my $instances = $stats->[6];
+
     if ((not defined $instances) or ($instances == 0)) {
         $self->set_err("can not cull - no instances");
@@ -315,8 +316,7 @@
         return;
     }
-    if ($instances < $min_copies) {
+    if ($instances <= $min_copies) {
         $self->set_err("can not cull - not enough instances");
         $log->debug("leaving");
-
         return;
     }
@@ -334,7 +334,5 @@
 
     unless (defined $locations) {
-        $self->set_err( "no instances" );
         $log->debug( "leaving" );
-
         return;
     }
@@ -351,4 +349,5 @@
 	}
     }
+
     # If we don't have two copies on one volume, see if we have two copies on a single 
     # cabinet. If so, delete the first of those copies.
@@ -362,4 +361,5 @@
 	}
     }
+
     # Fail-safe. We didn't have any duplicates (the instances are "well-mixed"), so 
     # delete the first.
@@ -403,13 +403,23 @@
     eval {
         # first - strip off any inaccesible instances
+	# these are not counted in the 'removed' number
         if (not defined $self->prune($key)) {
             # use the prune() method to also determine if $key is valid
             die "invalid key: $key";
         }
-
-        # check to see if there is an instance on $vol_name that should be the
-        # sole survivor
+	
+        # check to see if there is an instance on $vol_name that
+        # should be the sole survivor.  This is a bit dangerous : what
+        # if the only instance is on an invalid volume?  what if an
+        # invalid volume is specified?
+
         if (defined $vol_name) {
             $locations = $self->find_instances($key, $vol_name);
+            if (not defined $locations) {
+                die "no instances on requested node";
+            }
+            if (scalar @$locations == 0) {
+                die "no instances on requested node";
+            }
         }
 
@@ -418,17 +428,26 @@
 
         if (defined $locations) {
-            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) {
+	    print "dev: looking for undef volume instances\n";
+	    # first delete the valid instances (except the one we own)
+            my $instances_valid = $self->find_instances($key, undef, 0); # find all valid instances
+            if (not defined $instances_valid) {
+		# there should have been at least one valid instance?
                 die "no instances";
             }
-            foreach my $victim (@$instances) {
-                next if $victim eq $locations->[0];
-                $self->delete_instance($key, $victim);
-                $removed++;
+            if (scalar @$instances_valid == 0) {
+		# there should have been at least one valid instance?
+                die "no instances";
             }
+
+	    # we have more than one instance, delete the others
+            if (scalar @$instances_valid > 1) {
+		foreach my $victim (@$instances_valid) {
+		    next if $victim eq $locations->[0];
+		    $self->delete_instance($key, $victim);
+		    $removed ++;
+		}
+	    }
+	    # the prune above should have deleted any invalid instances, so we only
+	    # need to worry about the valid instances;
         } else {
             # nuke whatever
@@ -448,5 +467,4 @@
             }
         }
-
     };
     if ($@) {
@@ -663,4 +681,17 @@
     if ($response->fault) {
         $self->set_err($response->faultstring);
+
+	## invalid object key
+        if ($response->faultstring =~ /is valid object key/) {
+            $log->debug( "leaving" );
+	    die "invalid key $key, fails 'is valid object key' test\n";
+        }
+
+	## invalid object key
+        if ($response->faultstring =~ /xattr is in user. namespace/) {
+            $log->debug( "leaving" );
+	    die "invalid xattr key $name : fails 'xattr is in user. namespace' test\n";
+        }
+
         $log->logdie("unhandled fault - ", $self->err);
     }
@@ -690,4 +721,22 @@
     if ( $response->fault ) {
         $self->set_err($response->faultstring);
+
+	## invalid object key
+        if ($response->faultstring =~ /is valid object key/) {
+            $log->debug( "leaving" );
+	    die "invalid key $key, fails 'is valid object key' test\n";
+        }
+
+	## invalid xattr key (not in user. namespace)
+        if ($response->faultstring =~ /xattr is in user. namespace/) {
+            $log->debug( "leaving" );
+	    die "xattr $name is invalid : xattr is in user. namespace\n";
+        }
+
+	## invalid xattr key
+        if ($response->faultstring =~ /user\..*? does not exist/) {
+            $log->debug( "leaving" );
+	    die "xattr key $name not found : xattr $name does not exist\n";
+        }
         $log->logdie("unhandled fault - ", $self->err);
     }
@@ -747,4 +796,23 @@
     if ( $response->fault ) {
         $self->set_err($response->faultstring);
+
+	## invalid object key
+        if ($response->faultstring =~ /is valid object key/) {
+            $log->debug( "leaving" );
+	    die "invalid key $key, fails 'is valid object key' test\n";
+        }
+
+	## invalid xattr key (not in user. namespace)
+        if ($response->faultstring =~ /xattr is in user. namespace/) {
+            $log->debug( "leaving" );
+	    die "xattr $name is invalid : xattr is in user. namespace\n";
+        }
+
+	## invalid xattr key
+        if ($response->faultstring =~ /user\..*? does not exist/) {
+            $log->debug( "leaving" );
+	    die "xattr key $name not found : xattr $name does not exist\n";
+        }
+
         $log->logdie("unhandled fault - ", $self->err);
     }
@@ -865,5 +933,5 @@
     unless(defined($params[0])) {
 	$params[0] = hostname() . ".0";
-#	print STDERR "Setting host to $params[0]\n";
+	# print STDERR "Setting host to $params[0]\n";
     }
 
@@ -871,4 +939,5 @@
     if ( $response->fault ) {
         $self->set_err($response->faultstring);
+
         # check to see if this failure is because $key doesn't exist
         if ($response->faultstring =~ /is valid object key/) {
@@ -878,4 +947,14 @@
         # key is valid but no instances are on the specified volume
         if ($response->faultstring =~ /no instances on storage volume/) {
+            $log->debug( "leaving" );
+            return;
+        }
+        # check to see if this failure is volume is unknown
+        if ($response->faultstring =~ /is not a valid volume name/) {
+            $log->debug( "leaving" );
+            return;
+        }
+        # key is valid but no instances are on the specified volume
+        if ($response->faultstring =~ /no instances available for key/) {
             $log->debug( "leaving" );
             return;
@@ -949,5 +1028,7 @@
         $self->set_err($response->faultstring);
         # check to see if this failure is because $key doesn't exist
+	my $string = $response->faultstring;
         if ($response->faultstring =~ /is valid object key/) {
+	    $self->set_err("invalid object key");
             $log->debug( "leaving" );
             return;
@@ -955,4 +1036,5 @@
         # key is valid but no instances are on the specified volume
         if ($response->faultstring =~ /no instances on storage volume/) {
+	    $self->set_err("no instances on storage volume or volume is not available");
             $log->debug( "leaving" );
             return;
@@ -972,4 +1054,5 @@
 
 
+## this is used by PS:IPP:Config nebulous functions
 sub find
 {
@@ -1014,5 +1097,4 @@
     return $path;
 }
-
 
 sub open
@@ -1124,8 +1206,8 @@
     $log->debug( "entered - @_" );
 
-
     my $locations;
     if ($invalid) {
-	$locations = $self->find_instances( $key, 'any', 'find them all');
+	# delete the invalid instances:
+	$locations = $self->find_instances( $key, 'any', 1);
     }
     else {
@@ -1315,4 +1397,8 @@
         }
 
+        if ($response->faultstring =~ /is valid object key/) {
+	    $log->logdie("parameter #1 to delete_instance did not pass the 'is valid object key' callback");
+        }
+
         $log->logdie("unhandled fault - ", $self->err);
     }
@@ -1477,4 +1563,15 @@
 }
 
+sub set_log_level
+{
+    my $self = shift;
+
+    my $log_level = shift;
+
+    $log->level($log_level);
+
+    return $self;
+}
+
 
 1;
Index: trunk/Nebulous/lib/Nebulous/Util.pm
===================================================================
--- trunk/Nebulous/lib/Nebulous/Util.pm	(revision 40680)
+++ trunk/Nebulous/lib/Nebulous/Util.pm	(revision 41172)
@@ -78,4 +78,5 @@
     # The instance file attempting to be opened should always exist as it was
     # created by the Nebulous server.
+
     my $fh;
     for (my $i = 0; $i < 60; $i++) {
@@ -160,5 +161,5 @@
         die "can not process $arg because it is not in name:value form"
             unless defined $name and defined $value;
-        die "xattr name: $name is not in to the form user.name"
+        die "xattr name: $name is not in the form user.name"
             unless $name =~ /^user\./;
         $neb->setxattr($key, $name, $value, "replace")
