MogileFS-Server
view release on metacpan or search on metacpan
lib/MogileFS/Store/Postgres.pm view on Meta::CPAN
my $host = shift;
my $port = shift;
my $rootuser = shift;
my $rootpass = shift;
return $rootdbh ||= DBI->connect("DBI:Pg:dbname=postgres;host=$host;port=$port", $rootuser, $rootpass, { RaiseError => 1 })
or die "Couldn't connect to local PostgreSQL database as $rootuser";
}
sub _drop_db {
my $dbname = shift;
my $host = shift;
my $port = shift;
my $rootuser = shift;
my $rootpass = shift;
my $root_dbh = _root_dbh($host, $port, $rootuser, $rootpass);
eval {
$root_dbh->do("DROP DATABASE $dbname");
};
}
# --------------------------------------------------------------------------
# Data-access things we override
# --------------------------------------------------------------------------
# returns 1 on success, 0 on duplicate key error, dies on exception
# TODO: need a test to hit the duplicate name error condition
sub rename_file {
my ($self, $fidid, $to_key) = @_;
my $dbh = $self->dbh;
eval {
$dbh->do('UPDATE file SET dkey = ? WHERE fid=?',
undef, $to_key, $fidid);
};
if ($@ || $dbh->err) {
# first is error code for duplicates
if ($self->was_duplicate_error) {
return 0;
} else {
die $@;
}
}
$self->condthrow;
return 1;
}
# add a record of fidid existing on devid
# returns 1 on success, 0 on duplicate
sub add_fidid_to_devid {
my ($self, $fidid, $devid) = @_;
my $dbh = $self->dbh;
eval {
$dbh->do("INSERT INTO file_on (fid, devid) VALUES (?, ?)", undef, $fidid, $devid);
};
return 1 if !$@ && !$dbh->err;
return 0;
}
# update the device count for a given fidid
sub update_devcount_atomic {
my ($self, $fidid) = @_;
my $rv;
$self->dbh->begin_work;
$rv = $self->dbh->do("SELECT devcount FROM file WHERE fid=? FOR UPDATE", undef, $fidid);
$self->condthrow;
if($rv == 0) {
$self->dbh->rollback;
return 1;
}
$rv = $self->dbh->do("UPDATE file SET devcount=(SELECT COUNT(devid) FROM file_on WHERE fid=?) WHERE fid=?", undef, $fidid, $fidid);
$self->condthrow;
$self->dbh->commit;
$self->condthrow;
return $rv;
}
# enqueue a fidid for replication, from a specific deviceid (can be undef), in a given number of seconds.
sub enqueue_for_replication {
my ($self, $fidid, $from_devid, $in) = @_;
my $dbh = $self->dbh;
my $nexttry = 0;
if ($in) {
$nexttry = $self->unix_timestamp." + ${in}::int";
}
eval {
$dbh->do("INSERT INTO file_to_replicate (fid, fromdevid, nexttry) VALUES (?, ?, $nexttry)",
undef, $fidid, $from_devid);
};
}
# reschedule all deferred replication, return number rescheduled
sub replicate_now {
my ($self) = @_;
return $self->dbh->do("UPDATE file_to_replicate SET nexttry = ".$self->unix_timestamp." WHERE nexttry > ".$self->unix_timestamp);
}
sub reschedule_file_to_replicate_relative {
my ($self, $fid, $in_n_secs) = @_;
$self->dbh->do("UPDATE file_to_replicate SET nexttry = ".$self->unix_timestamp." + ?, failcount = failcount + 1 WHERE fid = ?",
undef, $in_n_secs, $fid);
}
# creates a new domain, given a domain namespace string. return the dmid on success,
# throw 'dup' on duplicate name.
sub create_domain {
my ($self, $name) = @_;
my $dbh = $self->dbh;
# get the max domain id
my $maxid = $dbh->selectrow_array('SELECT MAX(dmid) FROM domain') || 0;
my $rv = eval {
$dbh->do('INSERT INTO domain (dmid, namespace) VALUES (?, ?)',
undef, $maxid + 1, $name);
};
if ($self->was_duplicate_error) {
throw("dup");
}
( run in 2.221 seconds using v1.01-cache-2.11-cpan-437f7b0c052 )