MogileFS-Server
view release on metacpan or search on metacpan
lib/MogileFS/Store/MySQL.pm view on Meta::CPAN
}
# --------------------------------------------------------------------------
# Database creation time things we override
# --------------------------------------------------------------------------
sub create_table {
my $self = shift;
my ($table) = @_;
my $dbh = $self->dbh;
my $errmsg =
"InnoDB backend is unavailable for use, force creation of tables " .
"by setting USE_UNSAFE_MYSQL=1 in your environment and run this " .
"command again.";
unless ($ENV{USE_UNSAFE_MYSQL}) {
my $engines = eval { $dbh->selectall_hashref("SHOW ENGINES", "Engine"); };
if ($@ && $dbh->err == 1064) {
# syntax error? for MySQL 4.0.x.
# who cares. we'll catch it below on the double-check.
} else {
die $errmsg
unless ($engines->{InnoDB} and
$engines->{InnoDB}->{Support} =~ m/^(YES|DEFAULT)$/i);
}
}
my $existed = $self->table_exists($table);
$self->SUPER::create_table(@_);
return if $ENV{USE_UNSAFE_MYSQL};
# don't alter an existing table up to InnoDB from MyISAM...
# could be costly. but on new tables, no problem...
unless ($existed) {
$dbh->do("ALTER TABLE $table ENGINE=InnoDB");
warn "DBI reported an error of: '" . $dbh->errstr . "' when trying to " .
"alter table type of $table to InnoDB\n" if $dbh->err;
}
# but in any case, let's see if it's already InnoDB or not.
my $table_status = $dbh->selectrow_hashref("SHOW TABLE STATUS LIKE '$table'");
# if not, either die or warn.
unless (($table_status->{Engine} || $table_status->{Type} || "") eq "InnoDB") {
if ($existed) {
warn "WARNING: MySQL table that isn't InnoDB: $table\n";
} else {
die "MySQL didn't change table type to InnoDB as requested.\n\n$errmsg"
}
}
}
# --------------------------------------------------------------------------
# Data-access things we override
# --------------------------------------------------------------------------
# update the device count for a given fidid
sub update_devcount_atomic {
my ($self, $fidid) = @_;
my $lockname = "mgfs:fid:$fidid";
my $lock = eval { $self->get_lock($lockname, 10) };
# Check to make sure the lock didn't timeout, then we want to bail.
return 0 if defined $lock && $lock == 0;
# Checking $@ is pointless for the time because we just want to plow ahead
# even if the get_lock trapped a recursion and threw a fatal error.
$self->update_devcount($fidid);
# Don't release the lock if we never got it.
$self->release_lock($lockname) if $lock;
return 1;
}
sub upgrade_add_host_getport {
my $self = shift;
# see if they have the get port, else update it
unless ($self->column_type("host", "http_get_port")) {
$self->dowell("ALTER TABLE host ADD COLUMN http_get_port MEDIUMINT UNSIGNED AFTER http_port");
}
}
sub upgrade_add_host_altip {
my $self = shift;
unless ($self->column_type("host", "altip")) {
$self->dowell("ALTER TABLE host ADD COLUMN altip VARCHAR(15) AFTER hostip");
$self->dowell("ALTER TABLE host ADD COLUMN altmask VARCHAR(18) AFTER altip");
$self->dowell("ALTER TABLE host ADD UNIQUE altip (altip)");
}
}
sub upgrade_add_device_asof {
my $self = shift;
unless ($self->column_type("device", "mb_asof")) {
$self->dowell("ALTER TABLE device ADD COLUMN mb_asof INT(10) UNSIGNED AFTER mb_used");
}
}
sub upgrade_add_device_weight {
my $self = shift;
unless ($self->column_type("device", "weight")) {
$self->dowell("ALTER TABLE device ADD COLUMN weight MEDIUMINT DEFAULT 100 AFTER status");
}
}
sub upgrade_add_device_readonly {
my $self = shift;
unless ($self->column_type("device", "status") =~ /readonly/) {
$self->dowell("ALTER TABLE device MODIFY COLUMN status ENUM('alive', 'dead', 'down', 'readonly')");
}
}
sub upgrade_add_device_drain {
my $self = shift;
unless ($self->column_type("device", "status") =~ /drain/) {
lib/MogileFS/Store/MySQL.pm view on Meta::CPAN
}
}
sub upgrade_modify_device_size {
my $self = shift;
for my $col ('mb_total', 'mb_used') {
if ($self->column_type("device", $col) =~ m/mediumint/i) {
$self->dowell("ALTER TABLE device MODIFY COLUMN $col INT UNSIGNED");
}
}
}
sub upgrade_add_host_readonly {
my $self = shift;
unless ($self->column_type("host", "status") =~ /\breadonly\b/) {
$self->dowell("ALTER TABLE host MODIFY COLUMN status ENUM('alive', 'dead', 'down', 'readonly')");
}
}
sub pre_daemonize_checks {
my $self = shift;
# Jay Buffington, from the mailing lists, writes:
# > > Is your DBI version at least 1.43? The Makefile.PL of DBD::mysql shows
# > > that code for last_insert_it is compiled in only if DBD::mysql is built
# > > with DBI 1.43 or newer.
#> Yes, I have 1.53.
#> jay@webdev:~$ perl -MDBI -le 'print $DBI::VERSION'
#> 1.53
#>
#> BUT I just re-installed 2.9006 while researching this and my test
#> script started working. I just reran the mogile server test suite and
#> all test passed!
#>
#> Problem solved!
#>
#> The original DBD::mysql 2.9006 was installed from a RPM. I bet that
#> it was built against a DBI older than 1.43, so it didn't support
#> LAST_INSERT_ID.
# So...
# since we don't know what version of DBI their DBD::mysql was built against,
# let's just test that last_insert_id works.
my $id = eval {
$self->register_tempfile(dmid => 99,
key => "_server_startup_test");
};
unless ($id) {
die "MySQL self-tests failed. Your DBD::mysql might've been built against an old DBI version.\n";
}
return $self->SUPER::pre_daemonize_checks();
}
sub get_keys_like_operator {
my $bool = MogileFS::Config->server_setting_cached('case_sensitive_list_keys');
return $bool ? "LIKE /*! BINARY */" : "LIKE";
}
sub update_device_usages {
my ($self, $updates, $cb) = @_;
$cb->();
my $chunk = 10000; # in case we hit max_allowed_packet size(!)
while (scalar @$updates) {
my @cur = splice(@$updates, 0, $chunk);
my @set;
foreach my $fld (qw(mb_total mb_used mb_asof)) {
my $s = "$fld = CASE devid\n";
foreach my $upd (@cur) {
my $devid = $upd->{devid};
defined($devid) or croak("devid not set\n");
my $val = $upd->{$fld};
defined($val) or croak("$fld not defined for $devid\n");
$s .= "WHEN $devid THEN $val\n";
}
$s .= "ELSE $fld END";
push @set, $s;
}
my $sql = "UPDATE device SET ". join(",\n", @set);
$self->dowell($sql);
$cb->();
}
}
1;
__END__
=head1 NAME
MogileFS::Store::MySQL - MySQL data storage for MogileFS
=head1 SEE ALSO
L<MogileFS::Store>
( run in 0.851 second using v1.01-cache-2.11-cpan-39bf76dae61 )