fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2010-09-08 07:57 am

[dw-free] investigate LJ::Blob, remove?

[commit: http://hg.dwscoalition.org/dw-free/rev/f12012566efe]

http://bugs.dwscoalition.org/show_bug.cgi?id=1711

Remove no longer used classes; dev servers and small installations can use
the DB (easy to setup). Bigger installations should use mogilefs.

Patch by [personal profile] kareila.

Files modified:
  • bin/upgrading/migrate-userpics.pl
  • cgi-bin/Apache/LiveJournal.pm
  • cgi-bin/BlobClient.pm
  • cgi-bin/BlobClient/Local.pm
  • cgi-bin/BlobClient/Remote.pm
  • cgi-bin/LJ/Blob.pm
  • cgi-bin/LJ/ConfCheck/General.pm
  • cgi-bin/LJ/Userpic.pm
  • cgi-bin/modperl_subs.pl
  • t/userpics.t
--------------------------------------------------------------------------------
diff -r b0e5dbe30bbf -r f12012566efe bin/upgrading/migrate-userpics.pl
--- a/bin/upgrading/migrate-userpics.pl	Wed Sep 08 15:46:13 2010 +0800
+++ b/bin/upgrading/migrate-userpics.pl	Wed Sep 08 15:57:21 2010 +0800
@@ -15,7 +15,6 @@ use strict;
 use strict;
 use lib "$ENV{LJHOME}/cgi-bin";
 require 'ljlib.pl';
-use LJ::Blob;
 use LJ::User;
 use Getopt::Long;
 use IPC::Open3;
@@ -231,14 +230,10 @@ sub handle_userid {
 
         my $format = { G => 'gif', J => 'jpg', P => 'png' }->{$fmt};
 
-        # if the picture is from the blobserver
         my $data;
-        if ( $loc eq 'blob' ) {
-
-            $data = LJ::Blob::get($u, "userpic", $format, $picid);
 
         # no target?  then it's in the database
-        } elsif ( ! defined $loc ) {
+        unless ( defined $loc ) {
 
             ($data) = $dbcm->selectrow_array(
                 'SELECT imagedata FROM userpicblob2 WHERE userid = ? AND picid = ?',
diff -r b0e5dbe30bbf -r f12012566efe cgi-bin/Apache/LiveJournal.pm
--- a/cgi-bin/Apache/LiveJournal.pm	Wed Sep 08 15:46:13 2010 +0800
+++ b/cgi-bin/Apache/LiveJournal.pm	Wed Sep 08 15:57:21 2010 +0800
@@ -24,7 +24,6 @@ use Apache2::Const qw/ :common REDIRECT 
 
 # needed to call S2::set_domain() so early:
 use LJ::S2;
-use LJ::Blob;
 use Apache::LiveJournal::Interface::Blogger;
 use Apache::LiveJournal::Interface::AtomAPI;
 use Apache::LiveJournal::Interface::ElsewhereInfo;
@@ -1196,26 +1195,6 @@ sub userpic_content
         return OK;
     }
 
-    # dversion < 7 reproxy file path
-    if ( !$LJ::REPROXY_DISABLE{userpics} &&
-         exists $LJ::PERLBAL_ROOT{userpics} &&
-         $r->headers_in->{'X-Proxy-Capabilities'} &&
-         $r->headers_in->{'X-Proxy-Capabilities'} =~ m{\breproxy-file\b}i )
-    {
-        # Get the blobroot and load the pic hash
-        my $root = $LJ::PERLBAL_ROOT{userpics};
-
-        # Now ask the blob lib for the path to send to the reproxy
-        eval { LJ::Blob->can("autouse"); };
-        my $fmt = $MimeTypeMapd6{ $pic->{fmt} };
-        my $path = LJ::Blob::get_rel_path( $root, $u, "userpic", $fmt, $picid );
-
-        $r->headers_out->{'X-REPROXY-FILE'} = $path;
-        $send_headers->();
-
-        return OK;
-    }
-
     # try to get it from disk if in disk-cache mode
     if ($disk_cache) {
         if (-s $r->finfo) {
@@ -1240,18 +1219,10 @@ sub userpic_content
     unless ($data) {
         $lastmod = $pic->{'picdate'};
 
-        if ($LJ::USERPIC_BLOBSERVER) {
-            eval { LJ::Blob->can("autouse"); };
-            my $fmt = $MimeTypeMapd6{ $pic->{fmt} };
-            $data = LJ::Blob::get($u, "userpic", $fmt, $picid);
-        }
-
-        unless ($data) {
-            my $dbb = LJ::get_cluster_reader($u);
-            return SERVER_ERROR unless $dbb;
-            $data = $dbb->selectrow_array("SELECT imagedata FROM userpicblob2 WHERE ".
-                                          "userid=$pic->{'userid'} AND picid=$picid");
-        }
+        my $dbb = LJ::get_cluster_reader( $u );
+        return SERVER_ERROR unless $dbb;
+        $data = $dbb->selectrow_array( "SELECT imagedata FROM userpicblob2 WHERE " .
+                                       "userid=$pic->{userid} AND picid=$picid" );
     }
 
     return NOT_FOUND unless $data;
diff -r b0e5dbe30bbf -r f12012566efe cgi-bin/BlobClient.pm
--- a/cgi-bin/BlobClient.pm	Wed Sep 08 15:46:13 2010 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-#!/usr/bin/perl
-# This code was forked from the LiveJournal project owned and operated
-# by Live Journal, Inc. The code has been modified and expanded by
-# Dreamwidth Studios, LLC. These files were originally licensed under
-# the terms of the license supplied by Live Journal, Inc, which can
-# currently be found at:
-#
-# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
-#
-# In accordance with the original license, this code and all its
-# modifications are provided under the GNU General Public License.
-# A copy of that license can be found in the LICENSE file included as
-# part of this distribution.
-
-# vim:ts=4 sw=4 et:
-
-use strict;
-
-use BlobClient::Local;
-
-# Note: BlobClient::Remote is now deprecated, in favor of MogileFS.
-
-package BlobClient;
-
-sub new {
-    my ($class, $args) = @_;
-    my $self = {};
-    $self->{path} = $args->{path};
-    $self->{path} =~ s!/$!!;
-    $self->{backup_path} = $args->{backup_path};
-    $self->{backup_path} =~ s!/$!!;
-    bless $self, ref $class || $class;
-    return $self;
-}
-
-sub _make_path {
-    my ($cid, $uid, $domain, $fmt, $bid) = @_;
-    die "bogus domain" unless $domain =~ /^\w{1,40}$/;
-    die "bogus format" unless $fmt =~ /^\w{1,10}$/;
-
-    sprintf("%07d", $uid) =~ /^(\d+)(\d\d\d)(\d\d\d)$/;
-    my ($uid1, $uid2, $uid3) = ($1, $2, $3);
-
-    sprintf("%04d", $bid) =~ /^(\d+)(\d\d\d)$/;
-    my ($bid1, $bid2) = ($1, $2);
-    return join('/', int($cid), $uid1, $uid2, $uid3, $domain, $bid1, $bid2) . ".$fmt";
-}
-
-sub make_path {
-    my $self = shift;
-    return $self->{path} . '/' . _make_path(@_);
-}
-
-sub make_backup_path {
-    my $self = shift;
-    my $path = $self->{backup_path};
-    return undef unless $path; # if no backup_path, just return undef
-    return $path . '/' . _make_path(@_);
-}
-
-# derived classes will override this.
-sub is_dead {
-    return 0;
-}
-
-1;
diff -r b0e5dbe30bbf -r f12012566efe cgi-bin/BlobClient/Local.pm
--- a/cgi-bin/BlobClient/Local.pm	Wed Sep 08 15:46:13 2010 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-#!/usr/bin/perl
-# This code was forked from the LiveJournal project owned and operated
-# by Live Journal, Inc. The code has been modified and expanded by
-# Dreamwidth Studios, LLC. These files were originally licensed under
-# the terms of the license supplied by Live Journal, Inc, which can
-# currently be found at:
-#
-# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
-#
-# In accordance with the original license, this code and all its
-# modifications are provided under the GNU General Public License.
-# A copy of that license can be found in the LICENSE file included as
-# part of this distribution.
-
-# 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;
diff -r b0e5dbe30bbf -r f12012566efe cgi-bin/BlobClient/Remote.pm
--- a/cgi-bin/BlobClient/Remote.pm	Wed Sep 08 15:46:13 2010 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-#!/usr/bin/perl
-# This code was forked from the LiveJournal project owned and operated
-# by Live Journal, Inc. The code has been modified and expanded by
-# Dreamwidth Studios, LLC. These files were originally licensed under
-# the terms of the license supplied by Live Journal, Inc, which can
-# currently be found at:
-#
-# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
-#
-# In accordance with the original license, this code and all its
-# modifications are provided under the GNU General Public License.
-# A copy of that license can be found in the LICENSE file included as
-# part of this distribution.
-
-# 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;
diff -r b0e5dbe30bbf -r f12012566efe cgi-bin/LJ/Blob.pm
--- a/cgi-bin/LJ/Blob.pm	Wed Sep 08 15:46:13 2010 +0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-# This code was forked from the LiveJournal project owned and operated
-# by Live Journal, Inc. The code has been modified and expanded by
-# Dreamwidth Studios, LLC. These files were originally licensed under
-# the terms of the license supplied by Live Journal, Inc, which can
-# currently be found at:
-#
-# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
-#
-# In accordance with the original license, this code and all its
-# modifications are provided under the GNU General Public License.
-# A copy of that license can be found in the LICENSE file included as
-# part of this distribution.
-#
-# Wrapper around BlobClient.
-
-package LJ::Blob;
-use strict;
-use BlobClient;
-use BlobClient::Local;
-
-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/) {
-        die "BlobClient::Remote support is now removed in favor of MogileFS.";
-    } 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 LJ::isu( $u );
-    return $u->{blob_clusterid} if $u->{blob_clusterid};
-
-    return $u->prop( "blob_clusterid" )
-        or 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 {
-    shift @_ unless LJ::isu($_[0]);  # let it be called as class method (LJ::Blob->get_disk_usage($u,...))
-    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;
diff -r b0e5dbe30bbf -r f12012566efe cgi-bin/LJ/ConfCheck/General.pm
--- a/cgi-bin/LJ/ConfCheck/General.pm	Wed Sep 08 15:46:13 2010 +0800
+++ b/cgi-bin/LJ/ConfCheck/General.pm	Wed Sep 08 15:57:21 2010 +0800
@@ -442,9 +442,6 @@ add_conf('$FRONTPAGE_JOURNAL',
 add_conf('$FRONTPAGE_JOURNAL',
          type => '',
          des => "");
-add_conf('%PERLBAL_ROOT',
-         type => '',
-         des => "");
 add_conf('@DINSERTD_HOSTS',
          type => '',
          des => "");
@@ -695,7 +692,6 @@ my %bools = (
              'USE_ACCT_CODES' => "Make joining the site require an 'invite code'.  Note that this code might've bitrotted, so perhaps it should be kept off.",
              'USER_VHOSTS' => "Let (at least some) users get *.\$USER_DOMAIN URLs.  They'll also need the 'userdomain' cap.",
              'USER_EMAIL' => "Let (at least some) users get email aliases on the site.  They'll also need the 'useremail' cap.  See also \$USER_DOMAIN",
-             'USERPIC_BLOBSERVER' => "Store userpics on the 'blobserver'.  This is old.  MogileFS is the future.  You might want to use this option, though, for development, as blobserver in local-filesystem-mode is easy to setup.",
              'TRACK_URL_ACTIVE' => "record in memcached what URL a given host/pid is working on",
              'TRUST_X_HEADERS' => "LiveJournal should trust the upstream's X-Forwarded-For and similar headers.  Default is off (for direct connection to the net).  If behind your own reverse proxies, you should enable this.",
              'UNICODE' => "Unicode support is enabled.  The default has been 'on' for ages, and turning it off is nowadays not recommended or even known to be working/reliable.  Keep it enabled.",
diff -r b0e5dbe30bbf -r f12012566efe cgi-bin/LJ/Userpic.pm
--- a/cgi-bin/LJ/Userpic.pm	Wed Sep 08 15:46:13 2010 +0800
+++ b/cgi-bin/LJ/Userpic.pm	Wed Sep 08 15:57:21 2010 +0800
@@ -452,21 +452,13 @@ sub imagedata {
         return $$data;
     }
 
-    # check blobserver
-    my $data;
-    if ($LJ::USERPIC_BLOBSERVER) {
-        my $fmt = $self->extension;
-        $data = LJ::Blob::get( $u, "userpic", $fmt, $self->picid );
-        return $data if $data;
-    }
-
     # check userpicblob2 table
     my $dbb = LJ::get_cluster_reader($u)
         or return undef;
 
-    $data = $dbb->selectrow_array( "SELECT imagedata FROM userpicblob2 WHERE ".
-                                   "userid=? AND picid=?", undef, $self->userid,
-                                   $self->picid );
+    my $data = $dbb->selectrow_array( "SELECT imagedata FROM userpicblob2 WHERE ".
+                                      "userid=? AND picid=?", undef, $self->userid,
+                                      $self->picid );
     return $data ? $data : undef;
 }
 
@@ -603,12 +595,7 @@ sub create {
 
     my $base64 = Digest::MD5::md5_base64($$dataref);
 
-    my $target;
-    if ( $LJ::USERPIC_MOGILEFS ) {
-        $target = 'mogile';
-    } elsif ( $LJ::USERPIC_BLOBSERVER ) {
-        $target = 'blob';
-    }
+    my $target = $LJ::USERPIC_MOGILEFS ? 'mogile' : undef;
 
     my $dbh = LJ::get_db_writer();
 
@@ -643,9 +630,7 @@ sub create {
         return $err->(@_);
     };
 
-    ### insert the blob
-    $target ||= ''; # avoid warnings FIXME should this be set before the INSERT call?
-    if ($target eq 'mogile' && !$dberr) {
+    if ( $target && $target eq 'mogile' && !$dberr ) {
         my $fh = LJ::mogclient()->new_file($u->mogfs_userpic_key($picid), 'userpics');
         if (defined $fh) {
             $fh->print($$dataref);
@@ -656,18 +641,13 @@ sub create {
             push @errors, $clean_err->("Unable to contact storage server.  Your picture has not been saved.");
         }
 
-        # even in the non-LJ::Blob case we use the userblob table as a means
+        # even for mogile we use the userblob table as a means
         # to track the number and size of user blob assets
         my $dmid = LJ::get_blob_domainid('userpic');
         $u->do("INSERT INTO userblob (journalid, domain, blobid, length) ".
                "VALUES (?, ?, ?, ?)", undef, $u->{userid}, $dmid, $picid, $size);
 
-    } elsif ($target eq 'blob' && !$dberr) {
-        my $et;
-        my $fmt = lc($filetype);
-        my $rv = LJ::Blob::put($u, "userpic", $fmt, $picid, $$dataref, \$et);
-        push @errors, $clean_err->("Error saving to media server: $et") unless $rv;
-    } elsif (!$dberr) {
+    } elsif ( !$dberr ) {  # use userpicblob2 table in database
         my $dbcm = LJ::get_cluster_master($u);
         return $err->($BML::ML{'error.nodb'}) unless $dbcm;
         $u->do("INSERT INTO userpicblob2 (userid, picid, imagedata) " .
@@ -941,11 +921,10 @@ sub delete {
         my $location = $self->location; # avoid warnings FIXME
         if (defined $location and $location eq 'mogile') {
             LJ::mogclient()->delete($u->mogfs_userpic_key($picid));
-        } elsif ($LJ::USERPIC_BLOBSERVER &&
-                 LJ::Blob::delete($u, "userpic", $self->extension, $picid)) {
-        } elsif ($u->do("DELETE FROM userpicblob2 WHERE ".
-                        "userid=? AND picid=?", undef,
-                        $u->{userid}, $picid) > 0) {
+        } else {
+            $u->do( "DELETE FROM userpicblob2 WHERE ".
+                    "userid=? AND picid=?", undef,
+                    $u->userid, $picid );
         }
     };
 
diff -r b0e5dbe30bbf -r f12012566efe cgi-bin/modperl_subs.pl
--- a/cgi-bin/modperl_subs.pl	Wed Sep 08 15:46:13 2010 +0800
+++ b/cgi-bin/modperl_subs.pl	Wed Sep 08 15:57:21 2010 +0800
@@ -42,7 +42,6 @@ use POSIX ();
 use POSIX ();
 
 use LJ::Hooks;
-use LJ::Blob;
 use LJ::Faq;
 use DW::BusinessRules::InviteCodes;
 use DW::BusinessRules::InviteCodeRequests;
diff -r b0e5dbe30bbf -r f12012566efe t/userpics.t
--- a/t/userpics.t	Wed Sep 08 15:46:13 2010 +0800
+++ b/t/userpics.t	Wed Sep 08 15:57:21 2010 +0800
@@ -6,7 +6,6 @@ require 'ljlib.pl';
 require 'ljlib.pl';
 use LJ::Userpic;
 use LJ::Test;
-use LJ::Blob;
 use FindBin qw($Bin);
 use Digest::MD5;
 chdir "$Bin/data/userpics" or die "Failed to chdir to t/data/userpics";
--------------------------------------------------------------------------------