diff --git a/lib/MogileFS/Store.pm b/lib/MogileFS/Store.pm index c6a7cf74..a74a2d95 100644 --- a/lib/MogileFS/Store.pm +++ b/lib/MogileFS/Store.pm @@ -1227,16 +1227,27 @@ sub update_device_usage { } # This is unimplemented at the moment as we must verify: -# - no file_on rows exist -# - nothing in file_to_queue is going to attempt to use it -# - nothing in file_to_replicate is going to attempt to use it -# - it's already been marked dead -# - that all trackers are likely to know this :/ -# - ensure the devid can't be reused +# - no file_on rows exist (DONE)(file_on_device = 0) +# - nothing in file_to_queue is going to attempt to use it (DONE)(file_to_device = 0) +# - nothing in file_to_replicate is going to attempt to use it (SKIP)(no file on it means no file will be replicated from. "dead" means no file can go there) +# - it's already been marked dead (DONE)($dev->status eq "dead") +# - that all trackers are likely to know this :/ (SKIP)(all trackers should point to the same database to share this info) +# - ensure the devid can't be reused (DONE)(keep PRI devid, set hostid = 0) # IE; the user can't mark it dead then remove it all at once and cause their # cluster to implode. sub delete_device { - die "Unimplemented; needs further testing"; + my ($self, $devid, $hostid) = @_; + return $self->dbh->do("UPDATE device SET hostid = 0 where devid = ?", undef, $devid); +} + +sub file_on_device { + my ($self, $devid) = @_; + return $self->dbh->selectrow_array('SELECT COUNT(*) FROM file_on WHERE devid = ?', undef, $devid); +} + +sub file_to_device { + my ($self, $devid) = @_; + return $self->dbh->selectrow_array('SELECT COUNT(*) FROM file_to_queue WHERE arg like ?', undef, "%$devid%"); } sub mark_fidid_unreachable { @@ -1439,7 +1450,7 @@ sub get_all_hosts { sub get_all_devices { my ($self) = @_; my $sth = $self->dbh->prepare("SELECT /*!40000 SQL_CACHE */ devid, hostid, mb_total, " . - "mb_used, mb_asof, status, weight FROM device"); + "mb_used, mb_asof, status, weight FROM device where hostid > 0"); $self->condthrow; $sth->execute; my @return; diff --git a/lib/MogileFS/Worker/Query.pm b/lib/MogileFS/Worker/Query.pm index bde7f987..68e1e188 100644 --- a/lib/MogileFS/Worker/Query.pm +++ b/lib/MogileFS/Worker/Query.pm @@ -850,6 +850,35 @@ sub cmd_create_device { die $@; # rethrow; } +sub cmd_delete_device { + my MogileFS::Worker::Query $self = shift; + my $args = shift; + my $devid = $args->{devid}; + my $hostname = $args->{host}; + + my $dev = Mgd::device_factory()->get_by_id($devid); + my $sto = Mgd::get_store(); + + # ensure device exists + return $self->err_line('no_device') unless $dev; + + # ensure device matches its host + return $self->err_line('host_mismatch') unless $dev->host->hostname eq $hostname; + + # ensure no files on device + return $self->err_line('device_has_files') if $sto->file_on_device($devid); + + # ensure no files is going to device + return $self->err_line('device_in_queue') if $sto->file_to_device($devid); + + # ensure device is marked as dead + return $self->err_line('device_not_dead') unless $dev->status eq "dead"; + + $sto->delete_device($devid, $dev->host->id); + + return $self->cmd_clear_cache; +} + sub cmd_create_domain { my MogileFS::Worker::Query $self = shift; my $args = shift; @@ -1778,6 +1807,9 @@ sub err_line { 'class_has_files' => "Class still has files, unable to delete", 'class_not_found' => "Class not found", 'db' => "Database error", + 'device_has_files' => "Device still has files, unable to delete", + 'device_not_dead' => "Device isn't marked as dead, unable to delete", + 'device_in_queue' => "Device is in queue to receive files", 'domain_has_files' => "Domain still has files, unable to delete", 'domain_exists' => "That domain already exists", 'domain_not_empty' => "Domain still has classes, unable to delete",