Skip to content

Instantly share code, notes, and snippets.

@pyh
Created October 18, 2012 20:02
Show Gist options
  • Save pyh/3914461 to your computer and use it in GitHub Desktop.
Save pyh/3914461 to your computer and use it in GitHub Desktop.
MogileFS helper script that quickly drains selected hosts
#!/usr/bin/perl
# Efficient script to remove all files from some storage nodes
# Use with caution...
# Replicates status=="drain":
# UPDATE device SET status="drain" WHERE hostid IN(1,2,3,4) AND status="alive";
# file_to_queue:
#| fid | devid | type | nexttry | failcount | flags | arg |
#+-------+-------+------+------------+-----------+-------+--------------------------+
#| 1040 | 7 | 2 | 1350564913 | 0 | 0 | 1337,1268,1201,1333,1372 |
#| 1721 | 7 | 2 | 1350564913 | 0 | 0 | 1378,1270,1369,1238,1212 |
use warnings;
use strict;
use MogileFS::Server;
MogileFS::Config->load_config;
our $dbh = Mgd::get_store()->dbh;
my $rebal_devs = $dbh->selectcol_arrayref('SELECT devid FROM device WHERE status="drain"');
my $destination_devs = $dbh->selectcol_arrayref('SELECT devid FROM device WHERE hostid IN(23,24) AND status="alive"');
if(!@{$rebal_devs}){
print "Couldn't find anything that needs to be drained\n";
exit 1;
}
my %done_devs=();
while(1){
while( ($dbh->selectrow_array("SELECT COUNT(*) FROM file_to_queue WHERE type=2"))[0] > 15000 ) {
print "sleeping\n";
sleep 2;
}
my $dest_devs = order_dest_devs($destination_devs);
foreach my $drain_dev (@$rebal_devs){
next if $done_devs{$drain_dev};
my $fids = $dbh->selectcol_arrayref("SELECT fid FROM file_on WHERE devid=? LIMIT 140", undef, $drain_dev);
# no more files, mark device as done
if(!@$fids){
$done_devs{$drain_dev}=1;
next;
}
my $nexttry=time();
my $dest = join(",",@{$dest_devs}[0..20]);
my $retval;
eval { $retval = $dbh->do("INSERT IGNORE INTO file_to_queue (fid,devid,type,nexttry,arg) VALUES". join(",", ("(?,$drain_dev,2,$nexttry,\"$dest\")")x@$fids), undef, @$fids) };
if($@) {
if ( $@ =~ /Deadlock found when trying to get lock; try restarting transaction/ ){
print "Deadlock skipping for now\n";
}else{
die($@);
}
}
print "Queued $drain_dev: ".join(" ", @$fids)."\n";
}
}
sub order_dest_devs {
my $dest = shift;
return $dbh->selectcol_arrayref('SELECT devid FROM device WHERE devid IN('. join(',',('?')x@$dest).') AND status="alive" ORDER BY mb_used', undef, @$dest);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment