init
This commit is contained in:
114
livejournal/cgi-bin/BlobClient/Local.pm
Executable file
114
livejournal/cgi-bin/BlobClient/Local.pm
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/perl
|
||||
# vim:ts=4 sw=4 et:
|
||||
|
||||
use strict;
|
||||
package BlobClient::Local;
|
||||
|
||||
use IO::File;
|
||||
use File::Path;
|
||||
use Time::HiRes qw{gettimeofday tv_interval};
|
||||
|
||||
use constant DEBUG => 0;
|
||||
|
||||
use BlobClient;
|
||||
our @ISA = ("BlobClient");
|
||||
|
||||
sub new {
|
||||
my ($class, $args) = @_;
|
||||
my $self = $class->SUPER::new($args);
|
||||
bless $self, ref $class || $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
### Time a I<block> and send a report for the specified I<op> with the given
|
||||
### I<notes> when it finishes.
|
||||
sub report_blocking_time (&@) {
|
||||
my ( $block, $op, $notes, $host ) = ( @_ );
|
||||
|
||||
my $start = [gettimeofday()];
|
||||
my $rval = $block->();
|
||||
LJ::blocking_report( $host, "blob_$op", tv_interval($start), $notes );
|
||||
|
||||
return $rval;
|
||||
}
|
||||
|
||||
sub get {
|
||||
my ($self, $cid, $uid, $domain, $fmt, $bid) = @_;
|
||||
my $fh = new IO::File;
|
||||
local $/ = undef;
|
||||
my $path = make_path(@_);
|
||||
print STDERR "Blob::Local: requesting $path\n" if DEBUG;
|
||||
|
||||
my $data;
|
||||
report_blocking_time {
|
||||
unless (open($fh, '<', $path)) {
|
||||
return undef;
|
||||
}
|
||||
print STDERR "Blob::Local: serving $path\n" if DEBUG;
|
||||
$data = <$fh>;
|
||||
close($fh);
|
||||
} "get", $path, $self->{path};
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
sub get_stream {
|
||||
my ($self, $cid, $uid, $domain, $fmt, $bid, $callback, $errref) = @_;
|
||||
|
||||
my $fh = new IO::File;
|
||||
my $path = make_path(@_);
|
||||
|
||||
my $data;
|
||||
report_blocking_time {
|
||||
unless (open($fh, '<', $path)) {
|
||||
$$errref = "Error opening '$path'";
|
||||
return undef;
|
||||
}
|
||||
while (read($fh, $data, 1024*50)) {
|
||||
$callback->($data);
|
||||
}
|
||||
close($fh);
|
||||
} "get_stream", $path, $self->{path};
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub put {
|
||||
my ($self, $cid, $uid, $fmt, $domain, $bid, $content) = @_;
|
||||
|
||||
my $filename = make_path(@_);
|
||||
|
||||
my $dir = File::Basename::dirname($filename);
|
||||
eval { File::Path::mkpath($dir, 0, 0775); };
|
||||
return undef if $@;
|
||||
|
||||
report_blocking_time {
|
||||
my $fh = new IO::File;
|
||||
unless (open($fh, '>', $filename)) {
|
||||
return undef;
|
||||
}
|
||||
print $fh $content;
|
||||
close $fh;
|
||||
} "put", $filename, $self->{path};
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub delete {
|
||||
my ($self, $cid, $uid, $fmt, $domain, $bid) = @_;
|
||||
|
||||
my $filename = make_path(@_);
|
||||
|
||||
return 0 unless -e $filename;
|
||||
my $rval;
|
||||
report_blocking_time {
|
||||
# FIXME: rmdir up the tree
|
||||
$rval = unlink($filename);
|
||||
} "delete", $filename, $self->{path};
|
||||
|
||||
return $rval;
|
||||
}
|
||||
|
||||
sub make_path { my $self = shift; return $self->SUPER::make_path(@_); }
|
||||
|
||||
1;
|
||||
164
livejournal/cgi-bin/BlobClient/Remote.pm
Executable file
164
livejournal/cgi-bin/BlobClient/Remote.pm
Executable file
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/perl
|
||||
# vim:ts=4 sw=4 et:
|
||||
|
||||
package BlobClient::Remote;
|
||||
|
||||
use BlobClient;
|
||||
use LWP::UserAgent;
|
||||
use Time::HiRes qw{gettimeofday tv_interval};
|
||||
use vars qw(@ISA);
|
||||
@ISA = qw(BlobClient);
|
||||
|
||||
use strict;
|
||||
|
||||
use constant DEBUG => 0;
|
||||
use constant DEADTIME => 30;
|
||||
|
||||
use BlobClient;
|
||||
|
||||
### Time a I<block> and send a report for the specified I<op> with the given
|
||||
### I<notes> when it finishes.
|
||||
sub report_blocking_time (&@) {
|
||||
my ( $block, $op, $notes, $host ) = ( @_ );
|
||||
|
||||
my $start = [gettimeofday()];
|
||||
my $rval = $block->();
|
||||
LJ::blocking_report( $host, "blob_$op", tv_interval($start), $notes );
|
||||
|
||||
return $rval;
|
||||
}
|
||||
|
||||
sub new {
|
||||
my ($class, $args) = @_;
|
||||
my $self = $class->SUPER::new($args);
|
||||
|
||||
$self->{ua} = LWP::UserAgent->new(agent=>'blobclient', timeout => 4);
|
||||
|
||||
bless $self, ref $class || $class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub get {
|
||||
my ($self, $cid, $uid, $domain, $fmt, $bid, $use_backup) = @_;
|
||||
my $path = $use_backup ? make_backup_path(@_) : make_path(@_);
|
||||
return undef unless $path; # if no path, we fail
|
||||
|
||||
print STDERR "Blob::Remote requesting $path (backup path? $use_backup)\n" if DEBUG;
|
||||
my $req = HTTP::Request->new(GET => $path);
|
||||
|
||||
my $res;
|
||||
report_blocking_time {
|
||||
eval { $res = $self->{ua}->request($req); };
|
||||
} "get", $path, $self->{path};
|
||||
return $res->content if $res->is_success;
|
||||
|
||||
# two types of failure: server dead, or just a 404.
|
||||
# a 404 doesn't mean the server is necessarily bad.
|
||||
|
||||
if ($res->code == 500) {
|
||||
# server dead.
|
||||
if ($use_backup) {
|
||||
# can't reach backup server, we're really dead
|
||||
$self->{deaduntil} = time() + DEADTIME;
|
||||
} else {
|
||||
# try using a backup
|
||||
return $self->get($cid, $uid, $domain, $fmt, $bid, 1);
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub get_stream {
|
||||
my ($self, $cid, $uid, $domain, $fmt, $bid, $callback, $use_backup) = @_;
|
||||
my $path = $use_backup ? make_backup_path(@_) : make_path(@_);
|
||||
return undef unless $path; # if no path, we fail
|
||||
|
||||
my $req = HTTP::Request->new(GET => $path);
|
||||
|
||||
my $res;
|
||||
report_blocking_time {
|
||||
eval { $res = $self->{ua}->request($req, $callback, 1024*50); };
|
||||
} "get_stream", $path, $self->{path};
|
||||
|
||||
return $res->is_success if $res->is_success;
|
||||
|
||||
# must have failed
|
||||
if ($res->code == 500) {
|
||||
# server dead.
|
||||
if ($use_backup) {
|
||||
# can't reach backup server, we're really dead
|
||||
$self->{deaduntil} = time() + DEADTIME;
|
||||
} else {
|
||||
# try using a backup
|
||||
return $self->get_stream($cid, $uid, $domain, $fmt, $bid, $callback, 1);
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub put {
|
||||
my ($self, $cid, $uid, $domain, $fmt, $bid, $content, $errref, $use_backup) = @_;
|
||||
my $path = $use_backup ? make_backup_path(@_) : make_path(@_);
|
||||
return 0 unless $path; # if no path, we fail
|
||||
|
||||
my $req = HTTP::Request->new(PUT => $path);
|
||||
|
||||
$req->content($content);
|
||||
|
||||
my $res;
|
||||
report_blocking_time {
|
||||
eval { $res = $self->{ua}->request($req); };
|
||||
} "put", $path, $self->{path};
|
||||
|
||||
unless ($res->is_success) {
|
||||
if ($use_backup) {
|
||||
# total failure
|
||||
$$errref = "$path: " . $res->status_line if $errref;
|
||||
return 0;
|
||||
} else {
|
||||
# try backup
|
||||
return $self->put($cid, $uid, $domain, $fmt, $bid, $content, $errref, 1);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub delete {
|
||||
my ($self, $cid, $uid, $domain, $fmt, $bid, $use_backup) = @_;
|
||||
my $path = $use_backup ? make_backup_path(@_) : make_path(@_);
|
||||
return 0 unless $path; # if no path, we fail
|
||||
|
||||
my $req = HTTP::Request->new(DELETE => $path);
|
||||
|
||||
my $res;
|
||||
report_blocking_time {
|
||||
eval { $res = $self->{ua}->request($req); };
|
||||
} "delete", $path, $self->{path};
|
||||
|
||||
return 1 if $res && $res->code == 404;
|
||||
unless ($res->is_success) {
|
||||
if ($res->code == 500) {
|
||||
if ($use_backup) {
|
||||
# total failure!
|
||||
return 0;
|
||||
} else {
|
||||
# try again
|
||||
return $self->delete($cid, $uid, $domain, $fmt, $bid, 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub is_dead {
|
||||
my $self = shift;
|
||||
delete $self->{deaduntil} if $self->{deaduntil} <= time();
|
||||
return $self->{deaduntil} > 0;
|
||||
}
|
||||
|
||||
### [MG]: Hmmm... no-op?
|
||||
sub make_path { my $self = shift; return $self->SUPER::make_path(@_); }
|
||||
sub make_backup_path { my $self = shift; return $self->SUPER::make_backup_path(@_); }
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user