ljr/livejournal/cgi-bin/LJ/Blob.pm

151 lines
4.6 KiB
Perl
Executable File

# Wrapper around BlobClient.
use strict;
use lib "$ENV{'LJHOME'}/cgi-bin";
use BlobClient;
package LJ::Blob;
my %bc_cache = ();
my %bc_reader_cache = ();
my %bc_path_reader_cache = ();
# read-write (i.e. HTTP connection to BlobServer, with NetApp NFS mounted)
sub get_blobclient {
my $u = shift;
my $bcid = $u->{blob_clusterid} or die "No blob_clusterid";
return $bc_cache{$bcid} ||=
_bc_from_path($LJ::BLOBINFO{clusters}->{$bcid},
$LJ::BLOBINFO{clusters}->{"$bcid-BACKUP"});
}
# read-only access. (i.e. direct HTTP connection to NetApp)
sub get_blobclient_reader {
my $u = shift;
my $bcid = $u->{blob_clusterid} or die "No blob_clusterid";
return $bc_reader_cache{$bcid} if $bc_reader_cache{$bcid};
my $path = $LJ::BLOBINFO{clusters}->{"$bcid-GET"} ||
$LJ::BLOBINFO{clusters}->{$bcid};
my $bpath = $LJ::BLOBINFO{clusters}->{"$bcid-BACKUP"};
return $bc_reader_cache{$bcid} = _bc_from_path($path, $bpath);
}
sub _bc_from_path {
my ($path, $bpath) = @_;
if ($path =~ /^http/) {
$bpath = undef unless $bpath =~ /^http/;
return BlobClient::Remote->new({ path => $path, backup_path => $bpath });
} elsif ($path) {
return BlobClient::Local->new({ path => $path });
}
return undef;
}
# given a $u, returns that user's blob_clusterid, conditionally loading it
sub _load_bcid {
my $u = shift;
die "No user" unless $u;
return $u->{blob_clusterid} if $u->{blob_clusterid};
# if the entire system only has one blob_clusterid, use that
# without querying the database/memcache
return $u->{blob_clusterid} = $LJ::ONLY_BLOB_CLUSTERID
if defined $LJ::ONLY_BLOB_CLUSTERID;
LJ::load_user_props($u, "blob_clusterid");
return $u->{blob_clusterid} if $u->{blob_clusterid};
die "Couldn't find user $u->{user}'s blob_clusterid\n";
}
# args: u, domain, fmt, bid
# des-fmt: string file extension ("jpg", "gif", etc)
# des-bid: numeric blob id for this domain
# des-domain: string name of domain ("userpic", "phonephost", etc)
sub get {
my ($u, $domain, $fmt, $bid) = @_;
_load_bcid($u);
my $bc = get_blobclient_reader($u);
return $bc->get($u->{blob_clusterid}, $u->{userid}, $domain, $fmt, $bid);
}
# Return a path relative to the specified I<root> for the given arguments.
# args: root, u, domain, fmt, bid
# des-root: Root path
# des-fmt: string file extension ("jpg", "gif", etc)
# des-bid: numeric blob id for this domain
# des-domain: string name of domain ("userpic", "phonephost", etc)
sub get_rel_path {
my ( $root, $u, $domain, $fmt, $bid ) = @_;
my $bcid = _load_bcid( $u );
my $bc = $bc_path_reader_cache{ "$bcid:$root" } ||= new BlobClient::Local ({ path => $root });
return $bc->make_path( $bcid, $u->{userid}, $domain, $fmt, $bid );
}
sub get_stream {
my ($u, $domain, $fmt, $bid, $callback) = @_;
_load_bcid($u);
my $bc = get_blobclient_reader($u);
return $bc->get_stream($u->{blob_clusterid}, $u->{userid}, $domain, $fmt, $bid, $callback);
}
sub put {
my ($u, $domain, $fmt, $bid, $data, $errref) = @_;
_load_bcid($u);
my $bc = get_blobclient($u);
unless ($u->writer) {
$$errref = "nodb";
return 0;
}
unless ($bc->put($u->{blob_clusterid}, $u->{userid}, $domain,
$fmt, $bid, $data, $errref)) {
return 0;
}
$u->do("INSERT IGNORE INTO userblob (journalid, domain, blobid, length) ".
"VALUES (?, ?, ?, ?)", undef,
$u->{userid}, LJ::get_blob_domainid($domain),
$bid, length($data));
die "Error doing userblob accounting: " . $u->errstr if $u->err;
return 1;
}
sub delete {
my ($u, $domain, $fmt, $bid) = @_;
_load_bcid($u);
my $bc = get_blobclient($u);
return 0 unless $u->writer;
my $bdid = LJ::get_blob_domainid($domain);
return 0 unless $bc->delete($u->{blob_clusterid}, $u->{userid}, $domain,
$fmt, $bid);
$u->do("DELETE FROM userblob WHERE journalid=? AND domain=? AND blobid=?",
undef, $u->{userid}, $bdid, $bid);
die "Error doing userblob accounting: " . $u->errstr if $u->err;
return 1;
}
sub get_disk_usage {
my ($u, $domain) = @_;
my $dbcr = LJ::get_cluster_reader($u);
if ($domain) {
return $dbcr->selectrow_array("SELECT SUM(length) FROM userblob ".
"WHERE journalid=? AND domain=?", undef,
$u->{userid}, LJ::get_blob_domainid($domain));
} else {
return $dbcr->selectrow_array("SELECT SUM(length) FROM userblob ".
"WHERE journalid=?", undef, $u->{userid});
}
}
1;