From 0e818124ab15d1d9e2b28c5bd4ea2fa90c489631 Mon Sep 17 00:00:00 2001 From: shelling Date: Tue, 29 Oct 2013 23:43:41 +0800 Subject: [PATCH 1/9] MogileFS::Worker can handle incoming cmd 'delete_device' --- lib/MogileFS/Worker/Query.pm | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/MogileFS/Worker/Query.pm b/lib/MogileFS/Worker/Query.pm index bde7f987..c6e5887e 100644 --- a/lib/MogileFS/Worker/Query.pm +++ b/lib/MogileFS/Worker/Query.pm @@ -850,6 +850,27 @@ 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}; + + # ensure device exist and match its host + my $dev = Mgd::device_factory()->get_by_id($devid); + return $self->err_line('no_device') unless $dev; + return $self->err_line('host_mismatch') unless $dev->host->hostname eq $hostname; + + # ensure no files on device + my $sto = Mgd::get_store(); + my $count = $sto->dbh->selectrow_array('SELECT COUNT(*) FROM file_on WHERE devid = ?', undef, $devid); + return $self->err_line('device_has_files') if $count; + + $sto->delete_device($devid); + + return $self->cmd_clear_cache; +} + sub cmd_create_domain { my MogileFS::Worker::Query $self = shift; my $args = shift; @@ -1778,6 +1799,7 @@ 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", '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", From 1f2d264e9eff77e36012655b8ee8214895bb5dc3 Mon Sep 17 00:00:00 2001 From: shelling Date: Wed, 30 Oct 2013 00:32:53 +0800 Subject: [PATCH 2/9] MogileFS::Store can delete device from database with correct devid and hostid --- lib/MogileFS/Store.pm | 3 ++- lib/MogileFS/Worker/Query.pm | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/MogileFS/Store.pm b/lib/MogileFS/Store.pm index c6a7cf74..6d26fd53 100644 --- a/lib/MogileFS/Store.pm +++ b/lib/MogileFS/Store.pm @@ -1236,7 +1236,8 @@ sub update_device_usage { # 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("DELETE FROM device WHERE devid = ? and hostid = ?;", undef, $devid, $hostid); } sub mark_fidid_unreachable { diff --git a/lib/MogileFS/Worker/Query.pm b/lib/MogileFS/Worker/Query.pm index c6e5887e..30111c99 100644 --- a/lib/MogileFS/Worker/Query.pm +++ b/lib/MogileFS/Worker/Query.pm @@ -866,7 +866,7 @@ sub cmd_delete_device { my $count = $sto->dbh->selectrow_array('SELECT COUNT(*) FROM file_on WHERE devid = ?', undef, $devid); return $self->err_line('device_has_files') if $count; - $sto->delete_device($devid); + $sto->delete_device($devid, $dev->host->id); return $self->cmd_clear_cache; } From 21728db52ac744da6c141f2d5ceba9f247e40b5d Mon Sep 17 00:00:00 2001 From: shelling Date: Wed, 30 Oct 2013 13:40:14 +0800 Subject: [PATCH 3/9] dbh should be hidden in Store.pm --- lib/MogileFS/Store.pm | 5 +++++ lib/MogileFS/Worker/Query.pm | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/MogileFS/Store.pm b/lib/MogileFS/Store.pm index 6d26fd53..323e7795 100644 --- a/lib/MogileFS/Store.pm +++ b/lib/MogileFS/Store.pm @@ -1240,6 +1240,11 @@ sub delete_device { return $self->dbh->do("DELETE FROM device WHERE devid = ? and hostid = ?;", undef, $devid, $hostid); } +sub file_on_device { + my ($self, $devid) = @_; + return $self->dbh->selectrow_array('SELECT COUNT(*) FROM file_on WHERE devid = ?', undef, $devid); +} + sub mark_fidid_unreachable { my ($self, $fidid) = @_; die "Your database does not support REPLACE! Reimplement mark_fidid_unreachable!" unless $self->can_replace; diff --git a/lib/MogileFS/Worker/Query.pm b/lib/MogileFS/Worker/Query.pm index 30111c99..0c789b3e 100644 --- a/lib/MogileFS/Worker/Query.pm +++ b/lib/MogileFS/Worker/Query.pm @@ -863,8 +863,7 @@ sub cmd_delete_device { # ensure no files on device my $sto = Mgd::get_store(); - my $count = $sto->dbh->selectrow_array('SELECT COUNT(*) FROM file_on WHERE devid = ?', undef, $devid); - return $self->err_line('device_has_files') if $count; + return $self->err_line('device_has_files') if $sto->file_on_device($devid); $sto->delete_device($devid, $dev->host->id); From b1d1df2ec9adcecc362c71b7c8e28b95fe2f3c21 Mon Sep 17 00:00:00 2001 From: shelling Date: Wed, 30 Oct 2013 14:48:44 +0800 Subject: [PATCH 4/9] ensure the device is marked as dead before deleting --- lib/MogileFS/Worker/Query.pm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/MogileFS/Worker/Query.pm b/lib/MogileFS/Worker/Query.pm index 0c789b3e..5875175f 100644 --- a/lib/MogileFS/Worker/Query.pm +++ b/lib/MogileFS/Worker/Query.pm @@ -856,11 +856,17 @@ sub cmd_delete_device { my $devid = $args->{devid}; my $hostname = $args->{host}; - # ensure device exist and match its host my $dev = Mgd::device_factory()->get_by_id($devid); + + # 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 device is marked as dead + return $self->err_line('device_not_dead') unless $dev->status eq "dead"; + # ensure no files on device my $sto = Mgd::get_store(); return $self->err_line('device_has_files') if $sto->file_on_device($devid); @@ -1799,6 +1805,7 @@ sub err_line { '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", '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", From 2531fda2053a5e8d9c554101c85c8099abec6dcc Mon Sep 17 00:00:00 2001 From: shelling Date: Wed, 30 Oct 2013 17:10:58 +0800 Subject: [PATCH 5/9] file_to_device returns file count will migrate to specified device --- lib/MogileFS/Store.pm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/MogileFS/Store.pm b/lib/MogileFS/Store.pm index 323e7795..748d4398 100644 --- a/lib/MogileFS/Store.pm +++ b/lib/MogileFS/Store.pm @@ -1245,6 +1245,11 @@ sub file_on_device { 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 { my ($self, $fidid) = @_; die "Your database does not support REPLACE! Reimplement mark_fidid_unreachable!" unless $self->can_replace; From 0155a1c5f420a05c47994c7b39fe6590c1970918 Mon Sep 17 00:00:00 2001 From: shelling Date: Wed, 30 Oct 2013 17:28:53 +0800 Subject: [PATCH 6/9] ensure no files is going to specified device before deleting --- lib/MogileFS/Worker/Query.pm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/MogileFS/Worker/Query.pm b/lib/MogileFS/Worker/Query.pm index 5875175f..176e74b3 100644 --- a/lib/MogileFS/Worker/Query.pm +++ b/lib/MogileFS/Worker/Query.pm @@ -871,6 +871,9 @@ sub cmd_delete_device { my $sto = Mgd::get_store(); return $self->err_line('device_has_files') if $sto->file_on_device($devid); + # ensure no files to to device + return $self->err_line('device_in_queue') if $sto->file_to_device($devid); + $sto->delete_device($devid, $dev->host->id); return $self->cmd_clear_cache; @@ -1806,6 +1809,7 @@ sub err_line { '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", From 24330352c73a697bbc8e18764b76092c130a64fc Mon Sep 17 00:00:00 2001 From: shelling Date: Wed, 30 Oct 2013 17:31:40 +0800 Subject: [PATCH 7/9] sort the order to validate the deleting of device --- lib/MogileFS/Worker/Query.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/MogileFS/Worker/Query.pm b/lib/MogileFS/Worker/Query.pm index 176e74b3..68e1e188 100644 --- a/lib/MogileFS/Worker/Query.pm +++ b/lib/MogileFS/Worker/Query.pm @@ -857,6 +857,7 @@ sub cmd_delete_device { 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; @@ -864,16 +865,15 @@ sub cmd_delete_device { # ensure device matches its host return $self->err_line('host_mismatch') unless $dev->host->hostname eq $hostname; - # ensure device is marked as dead - return $self->err_line('device_not_dead') unless $dev->status eq "dead"; - # ensure no files on device - my $sto = Mgd::get_store(); return $self->err_line('device_has_files') if $sto->file_on_device($devid); - # ensure no files to to device + # 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; From 4fe390dcac5ab1618aac99fd9f14a11858357410 Mon Sep 17 00:00:00 2001 From: shelling Date: Wed, 30 Oct 2013 18:47:15 +0800 Subject: [PATCH 8/9] mark DONE on implemented items --- lib/MogileFS/Store.pm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/MogileFS/Store.pm b/lib/MogileFS/Store.pm index 748d4398..c4930314 100644 --- a/lib/MogileFS/Store.pm +++ b/lib/MogileFS/Store.pm @@ -1227,10 +1227,10 @@ 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 +# - 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 -# - it's already been marked dead +# - it's already been marked dead (DONE)($dev->status eq "dead") # - that all trackers are likely to know this :/ # - ensure the devid can't be reused # IE; the user can't mark it dead then remove it all at once and cause their From 424cf7b99f4008a2f9dc949cbb67f18119c5e914 Mon Sep 17 00:00:00 2001 From: shelling Date: Thu, 31 Oct 2013 14:55:08 +0800 Subject: [PATCH 9/9] delete_device() keeps primary key of device to prevent reuse. just set it hostid = 0 to make it belong to no host. get_all_devices() returns devices which hostid > 0 to avoid interactions with deleted devices. --- lib/MogileFS/Store.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/MogileFS/Store.pm b/lib/MogileFS/Store.pm index c4930314..a74a2d95 100644 --- a/lib/MogileFS/Store.pm +++ b/lib/MogileFS/Store.pm @@ -1229,15 +1229,15 @@ sub update_device_usage { # This is unimplemented at the moment as we must verify: # - 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 +# - 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 :/ -# - ensure the devid can't be reused +# - 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 { my ($self, $devid, $hostid) = @_; - return $self->dbh->do("DELETE FROM device WHERE devid = ? and hostid = ?;", undef, $devid, $hostid); + return $self->dbh->do("UPDATE device SET hostid = 0 where devid = ?", undef, $devid); } sub file_on_device { @@ -1450,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;