[dw-free] remove legacy database tables
[commit: http://hg.dwscoalition.org/dw-free/rev/ee7de5f9dd15]
http://bugs.dwscoalition.org/show_bug.cgi?id=1710
Remove support for pre-clustering migration tables and script.
Patch by
kareila.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=1710
Remove support for pre-clustering migration tables and script.
Patch by
Files modified:
- bin/upgrading/base-data.sql
- bin/upgrading/move0cluster.pl
- bin/upgrading/update-db-general.pl
--------------------------------------------------------------------------------
diff -r 8a1034a41fe1 -r ee7de5f9dd15 bin/upgrading/base-data.sql
--- a/bin/upgrading/base-data.sql Sat Sep 05 10:51:57 2009 +0000
+++ b/bin/upgrading/base-data.sql Sat Sep 05 11:33:28 2009 +0000
@@ -928,7 +928,6 @@ REPLACE INTO schematables (des, public_b
REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Historic. Global. Stores a user\'s posts on other clusters, when either 1) that user isn\'t clustered themselves yet, or 2) we\'re doing a mass conversion (moveucluster.pl) and don\'t want to look it up.\n\r\nA maintenance task (clean_caches) moves data from here to [dbtable[talkleft]] on clusters.', '0', 'off', NULL, 'talkleft_xfp');
REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Lookup table for states, countries, languages, etc...', '1', 'replace', NULL, 'codes');
REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Stores data on valid invite codes and who has used them. The acctinvite table stores the data on why they were made.', '0', 'off', NULL, 'acctcode');
-REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Stores globally-unique itemid and talkid ID (entries and comments), for URL compatibility. These were used pre-clustering. The LJ::get_newids function uses this table to find out what journal an old global ID belongs to and maps it to its new ID.', '0', 'off', NULL, 'oldids');
REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Stores metadata for entries users mark as \"Memories\". Please see also the clustered [dbtable[memorable2]] table.', '0', 'off', NULL, 'memorable');
REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Stores per-user counters on the global (contrary to the name). These are allocated by the LJ::alloc_user_counter function. Please see also [dbtable[counter]].', '0', 'off', NULL, 'usercounter');
REPLACE INTO schematables (des, public_browsable, redist_mode, redist_where, tablename) VALUES ('Stores the documentation for the database tables.', '0', 'replace', NULL, 'schematables');
diff -r 8a1034a41fe1 -r ee7de5f9dd15 bin/upgrading/move0cluster.pl
--- a/bin/upgrading/move0cluster.pl Sat Sep 05 10:51:57 2009 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,867 +0,0 @@
-#!/usr/bin/perl
-#
-# Moves a user between clusters.
-#
-
-use strict;
-use Getopt::Long;
-
-my $opt_del = 0;
-my $opt_destdel = 0;
-my $opt_useslow = 0;
-my $opt_slowalloc = 0;
-my $opt_verbose = 1;
-my $opt_movemaster = 0;
-my $opt_prelocked = 0;
-my $opt_expungedel = 0;
-my $opt_ignorebit = 0;
-exit 1 unless GetOptions('delete' => \$opt_del,
- 'destdelete' => \$opt_destdel,
- 'useslow' => \$opt_useslow, # use slow db role for read
- 'slowalloc' => \$opt_slowalloc, # see note below
- 'verbose=i' => \$opt_verbose,
- 'movemaster|mm' => \$opt_movemaster,
- 'prelocked' => \$opt_prelocked,
- 'expungedel' => \$opt_expungedel,
- 'ignorebit' => \$opt_ignorebit,
- );
-my $optv = $opt_verbose;
-
-require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
-require "$ENV{'LJHOME'}/cgi-bin/ljcmdbuffer.pl";
-
-my $dbh = LJ::get_dbh({raw=>1}, "master");
-die "No master db available.\n" unless $dbh;
-$dbh->do("SET wait_timeout=28800");
-
-my $dbr = $dbh;
-if ($opt_useslow) {
- $dbr = LJ::get_dbh({raw=>1}, "slow");
- unless ($dbr) { die "Can't get slow db from which to read.\n"; }
-}
-
-my $user = LJ::canonical_username(shift @ARGV);
-my $dclust = shift @ARGV;
-
-# tables which are dumbly copied by sucking all into memory first.
-# use smarter mover code for anything that shouldn't all go into memory.
-# also, to use this you have to define the primary keys below
-my @manual_move = qw(loginstall ratelog sessions userproplite2
- sessions_data userbio userpicblob2 userpropblob
- modlog modblob counter
- links userblob clustertrack2);
-sub usage {
- die "Usage:\n movecluster.pl <user> <destination cluster #>\n";
-}
-
-usage() unless defined $user;
-usage() unless defined $dclust;
-
-die "Failed to get move lock.\n"
- unless ($dbh->selectrow_array("SELECT GET_LOCK('moveucluster-$user', 10)"));
-
-my $u = $dbh->selectrow_hashref("SELECT * FROM user WHERE user=?", undef, $user);
-die "Non-existent user $user.\n" unless $u;
-
-die "Can't move back to legacy cluster 0\n" unless $dclust;
-
-my $dbch = LJ::get_cluster_master({raw=>1}, $dclust);
-
-die "Undefined or down cluster \#$dclust\n" unless $dbch;
-$dbch->do("SET wait_timeout=28800");
-
-my $separate_cluster = LJ::use_diff_db("master", "cluster$dclust");
-
-$dbh->{'RaiseError'} = 1;
-$dbch->{'RaiseError'} = 1;
-
-my $sclust = $u->{'clusterid'};
-
-if ($sclust == $dclust) {
- die "User '$user' is already on cluster $dclust\n";
-}
-
-if ($sclust) {
- verify_movable_tables();
-}
-
-# original cluster db handle.
-my $dbo;
-if ($sclust) {
- $dbo = $opt_movemaster ?
- LJ::get_dbh({raw=>1}, "cluster$u->{clusterid}movemaster") :
- LJ::get_cluster_master({raw=>1}, $u);
- die "Can't get source cluster handle.\n" unless $dbo;
- $dbo->{'RaiseError'} = 1;
- $dbo->do("SET wait_timeout=28800");
-}
-
-my $userid = $u->{'userid'};
-
-# find readonly cap class, complain if not found
-my $readonly_bit = undef;
-foreach (keys %LJ::CAP) {
- if ($LJ::CAP{$_}->{'_name'} eq "_moveinprogress" &&
- $LJ::CAP{$_}->{'readonly'} == 1) {
- $readonly_bit = $_;
- last;
- }
-}
-unless (defined $readonly_bit) {
- die "Won't move user without %LJ::CAP capability class named '_moveinprogress' with readonly => 1\n";
-}
-
-# make sure a move isn't already in progress
-if ($opt_prelocked) {
- unless (($u->{'caps'}+0) & (1 << $readonly_bit)) {
- die "User '$user' should have been prelocked.\n";
- }
-} else {
- if (($u->{'caps'}+0) & (1 << $readonly_bit)) {
- die "User '$user' is already in the process of being moved? (cap bit $readonly_bit set)\n"
- unless $opt_ignorebit;
- }
-}
-
-if ($opt_expungedel && $u->is_deleted &&
- LJ::mysqldate_to_time($u->{'statusvisdate'}) < time() - 86400*31) {
-
- print "Expunging user '$u->{'user'}'\n";
- $dbh->do("INSERT INTO clustermove (userid, sclust, dclust, timestart, timedone) ".
- "VALUES (?,?,?,UNIX_TIMESTAMP(),UNIX_TIMESTAMP())", undef,
- $userid, $sclust, 0);
- LJ::update_user($userid, { clusterid => 0,
- statusvis => 'X',
- raw => "caps=caps&~(1<<$readonly_bit), statusvisdate=NOW()" });
- exit 0;
-}
-
-print "Moving '$u->{'user'}' from cluster $sclust to $dclust\n" if $optv >= 1;
-
-# mark that we're starting the move
-$dbh->do("INSERT INTO clustermove (userid, sclust, dclust, timestart) ".
- "VALUES (?,?,?,UNIX_TIMESTAMP())", undef, $userid, $sclust, $dclust);
-my $cmid = $dbh->{'mysql_insertid'};
-
-# set readonly cap bit on user
-LJ::update_user($userid, { raw => "caps=caps|(1<<$readonly_bit)" })
- unless $opt_prelocked;
-$dbh->do("SELECT RELEASE_LOCK('moveucluster-$user')");
-
-unless ($opt_prelocked) {
-# wait a bit for writes to stop if journal is somewhat active (last week update)
- my $secidle = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP()-UNIX_TIMESTAMP(timeupdate) ".
- "FROM userusage WHERE userid=$userid");
- if ($secidle) {
- sleep(2) unless $secidle > 86400*7;
- sleep(1) unless $secidle > 86400;
- }
-}
-
-# make sure slow is caught up:
-if ($opt_useslow)
-{
- my $ms = $dbh->selectrow_hashref("SHOW MASTER STATUS");
- my $loop = 1;
- while ($loop) {
- my $ss = $dbr->selectrow_hashref("SHOW SLAVE STATUS");
- $loop = 0;
- unless ($ss->{'Log_File'} gt $ms->{'File'} ||
- ($ss->{'Log_File'} eq $ms->{'File'} && $ss->{'Pos'} >= $ms->{'Position'}))
- {
- $loop = 1;
- print "Waiting for slave ($ss->{'Pos'} < $ms->{'Position'})\n";
- sleep 1;
- }
- }
-}
-
-my $last = time();
-my $stmsg = sub {
- my $msg = shift;
- my $now = time();
- return if ($now < $last + 1);
- $last = $now;
- print $msg;
-};
-
-my %bufcols = (); # db|table -> scalar "(foo, anothercol, lastcol)" or undef or ""
-my %bufrows = (); # db|table -> [ []+ ]
-my %bufdbmap = (); # scalar(DBI hashref) -> DBI hashref
-
-my $flush_buffer = sub {
- my $dbandtable = shift;
- my ($db, $table) = split(/\|/, $dbandtable);
- $db = $bufdbmap{$db};
- return unless exists $bufcols{$dbandtable};
- my $sql = "REPLACE INTO $table $bufcols{$dbandtable} VALUES ";
- $sql .= join(", ",
- map { my $r = $_;
- "(" . join(", ",
- map { $db->quote($_) } @$r) . ")" }
- @{$bufrows{$dbandtable}});
- $db->do($sql);
- delete $bufrows{$dbandtable};
- delete $bufcols{$dbandtable};
-};
-
-my $flush_all = sub {
- foreach (keys %bufcols) {
- $flush_buffer->($_);
- }
-};
-
-my $replace_into = sub {
- my $db = ref $_[0] ? shift : $dbch; # optional first arg
- my ($table, $cols, $max, @vals) = @_;
- my $dbandtable = scalar($db) . "|$table";
- $bufdbmap{$db} = $db;
- if (exists $bufcols{$dbandtable} && $bufcols{$dbandtable} ne $cols) {
- $flush_buffer->($dbandtable);
- }
- $bufcols{$dbandtable} = $cols;
- push @{$bufrows{$dbandtable}}, [ @vals ];
-
- if (scalar @{$bufrows{$dbandtable}} > $max) {
- $flush_buffer->($dbandtable);
- }
-};
-
-# assume never tried to move this user before. however, if reported crap
-# in the oldids table, we'll revert to slow alloc_id functionality,
-# where we do a round-trip to $dbh for everything and see if every id
-# has been remapped already. otherwise we do it in perl and batch
-# updates to the oldids table, which is the common/fast case.
-my $first_move = ! $opt_slowalloc;
-
-my %alloc_data;
-my %alloc_arealast;
-my $alloc_id = sub {
- my ($area, $orig) = @_;
-
- # fast version
- if ($first_move) {
- my $id = $alloc_data{$area}->{$orig} = ++$alloc_arealast{$area};
- $replace_into->($dbh, "oldids", "(area, oldid, userid, newid)", 250,
- $area, $orig, $userid, $id);
- return $id;
- }
-
- # slow version
- $dbh->{'RaiseError'} = 0;
- $dbh->do("INSERT INTO oldids (area, oldid, userid, newid) ".
- "VALUES ('$area', $orig, $userid, NULL)");
- my $id;
- if ($dbh->err) {
- $id = $dbh->selectrow_array("SELECT newid FROM oldids WHERE area='$area' AND oldid=$orig");
- } else {
- $id = $dbh->{'mysql_insertid'};
- }
- $dbh->{'RaiseError'} = 1;
- $alloc_data{$area}->{$orig} = $id;
- return $id;
-};
-
-my $bufread;
-
-if ($sclust == 0)
-{
- # do bio stuff
- {
- my $bio = $dbr->selectrow_array("SELECT bio FROM userbio WHERE userid=$userid");
- my $bytes = length($bio);
- $dbch->do("REPLACE INTO dudata (userid, area, areaid, bytes) VALUES ($userid, 'B', 0, $bytes)");
- if ($separate_cluster) {
- $bio = $dbh->quote($bio);
- $dbch->do("REPLACE INTO userbio (userid, bio) VALUES ($userid, $bio)");
- }
- }
-
- my @itemids = reverse @{$dbr->selectcol_arrayref("SELECT itemid FROM log ".
- "WHERE ownerid=$u->{'userid'} ".
- "ORDER BY ownerid, rlogtime")};
-
- $bufread = make_buffer_reader("itemid", \@itemids);
-
- my $todo = @itemids;
- my $done = 0;
- my $stime = time();
- print "Total: $todo\n";
-
- # moving time, journal item at a time, and everything recursively under it
- foreach my $itemid (@itemids) {
- movefrom0_logitem($itemid);
- $done++;
- my $percent = $done/$todo;
- my $elapsed = time() - $stime;
- my $totaltime = $elapsed * (1 / $percent);
- my $timeremain = int($totaltime - $elapsed);
- $stmsg->(sprintf "$user: copy $done/$todo (%.2f%%) +${elapsed}s -${timeremain}s\n", 100*$percent);
- }
-
- $flush_all->();
-
- # update their memories. in particular, any memories of their own
- # posts need to to be updated from the (0, globalid) to
- # (journalid, jitemid) format, to make the memory filter feature
- # work. (it checks the first 4 bytes only, not joining the
- # globalid on the clustered log table)
- print "Fixing memories.\n";
- my @fix = @{$dbh->selectall_arrayref("SELECT memid, jitemid FROM memorable WHERE ".
- "userid=$u->{'userid'} AND journalid=0")};
- foreach my $f (@fix) {
- my ($memid, $newid) = ($f->[0], $alloc_data{'L'}->{$f->[1]});
- next unless $newid;
- my ($newid2, $anum) = $dbch->selectrow_array("SELECT jitemid, anum FROM log2 ".
- "WHERE journalid=$u->{'userid'} AND ".
- "jitemid=$newid");
- if ($newid2 == $newid) {
- my $ditemid = $newid * 256 + $anum;
- print "UPDATE $memid TO $ditemid\n";
- $dbh->do("UPDATE memorable SET journalid=$u->{'userid'}, jitemid=$ditemid ".
- "WHERE memid=$memid");
- }
- }
-
- # fix polls
- print "Fixing polls.\n";
- @fix = @{$dbh->selectall_arrayref("SELECT pollid, itemid FROM poll ".
- "WHERE journalid=$u->{'userid'}")};
- foreach my $f (@fix) {
- my ($pollid, $newid) = ($f->[0], $alloc_data{'L'}->{$f->[1]});
- next unless $newid;
- my ($newid2, $anum) = $dbch->selectrow_array("SELECT jitemid, anum FROM log2 ".
- "WHERE journalid=$u->{'userid'} AND ".
- "jitemid=$newid");
- if ($newid2 == $newid) {
- my $ditemid = $newid * 256 + $anum;
- print "UPDATE $pollid TO $ditemid\n";
- $dbh->do("UPDATE poll SET itemid=$ditemid WHERE pollid=$pollid");
- }
- }
-
- # move userpics
- print "Copying over userpics.\n";
- my @pics = @{$dbr->selectcol_arrayref("SELECT picid FROM userpic WHERE ".
- "userid=$u->{'userid'}")};
- foreach my $picid (@pics) {
- print " picid\#$picid...\n";
- my $imagedata = $dbr->selectrow_array("SELECT imagedata FROM userpicblob ".
- "WHERE picid=$picid");
- $imagedata = $dbh->quote($imagedata);
- $dbch->do("REPLACE INTO userpicblob2 (userid, picid, imagedata) VALUES ".
- "($u->{'userid'}, $picid, $imagedata)");
- }
-
- $dbh->do("UPDATE userusage SET lastitemid=0 WHERE userid=$userid");
-
- my $dversion = 2;
-
- # if everything's good (nothing's died yet), then delete all from source
- if ($opt_del)
- {
- # before we start deleting, record they've moved servers.
- LJ::update_user($userid, { dversion => $dversion, clusterid => $dclust });
-
- $done = 0;
- $stime = time();
- foreach my $itemid (@itemids) {
- deletefrom0_logitem($itemid);
- $done++;
- my $percent = $done/$todo;
- my $elapsed = time() - $stime;
- my $totaltime = $elapsed * (1 / $percent);
- my $timeremain = int($totaltime - $elapsed);
- $stmsg->(sprintf "$user: delete $done/$todo (%.2f%%) +${elapsed}s -${timeremain}s\n", 100*$percent);
- }
-
- # delete bio from source, if necessary
- if ($separate_cluster) {
- $dbh->do("DELETE FROM userbio WHERE userid=$userid");
- }
-
- # delete source userpics
- print "Deleting cluster0 userpics...\n";
- foreach my $picid (@pics) {
- print " picid\#$picid...\n";
- $dbh->do("DELETE FROM userpicblob WHERE picid=$picid");
- }
-
- # unset read-only bit (marks the move is complete, also, and not aborted mid-delete)
- LJ::update_user($userid, { raw => "caps=caps&~(1<<$readonly_bit)" });
- $dbh->do("UPDATE clustermove SET sdeleted='1', timedone=UNIX_TIMESTAMP() ".
- "WHERE cmid=?", undef, $cmid);
-
- }
- else
- {
- # unset readonly and move to new cluster in one update
- LJ::update_user($userid, { dversion => $dversion, clusterid => $dclust,
- raw => "caps=caps&~(1<<$readonly_bit)" });
- $dbh->do("UPDATE clustermove SET sdeleted='0', timedone=UNIX_TIMESTAMP() ".
- "WHERE cmid=?", undef, $cmid);
- }
- exit 0;
-}
-elsif ($sclust > 0)
-{
- print "Moving away from cluster $sclust\n" if $optv;
-
- while (my $cmd = $dbo->selectrow_array("SELECT cmd FROM cmdbuffer WHERE journalid=$userid")) {
- my $dbcm = LJ::get_cluster_master($sclust);
- print "Flushing cmdbuffer for cmd: $cmd\n" if $optv > 1;
- LJ::Cmdbuffer::flush($dbh, $dbcm, $cmd, $userid);
- }
-
- my $pri_key = {
- # flush this first:
- 'cmdbuffer' => 'journalid',
-
- # this is populated as we do log/talk
- 'dudata' => 'userid',
-
- # manual
- 'loginstall' => 'userid',
- 'ratelog' => 'userid',
- 'sessions' => 'userid',
- 'sessions_data' => 'userid',
- 'userbio' => 'userid',
- 'userpicblob2' => 'userid',
- 'userproplite2' => 'userid',
- 'modlog' => 'journalid',
- 'modblob' => 'journalid',
- 'counter' => 'journalid',
- 'userblob' => 'journalid',
- 'userpropblob' => 'userid',
- 'clustertrack2' => 'userid',
-
- # log
- 'log2' => 'journalid',
- 'logsec2' => 'journalid',
- 'logprop2' => 'journalid',
- 'logtext2' => 'journalid',
-
- # talk
- 'talk2' => 'journalid',
- 'talkprop2' => 'journalid',
- 'talktext2' => 'journalid',
-
- # no primary key... move up by posttime
- 'talkleft' => 'userid',
-
- # link lists
- 'links' => 'journalid',
- };
-
- # ask the local mods if they have any tables to move
- my @local_tables;
- my $local_tables = LJ::run_hook("moveucluster_local_tables");
- if ($local_tables) {
- while (my ($tab, $key) = each %$local_tables) {
- push @local_tables, $tab;
- $pri_key->{$tab} = $key;
- }
- }
-
- my @existing_data;
- print "Checking for existing data on target cluster...\n" if $optv > 1;
- foreach my $table (sort keys %$pri_key) {
- my $pri = $pri_key->{$table};
- my $is_there = $dbch->selectrow_array("SELECT $pri FROM $table WHERE $pri=$userid LIMIT 1");
- next unless $is_there;
- if ($opt_destdel) {
- while ($dbch->do("DELETE FROM $table WHERE $pri=$userid LIMIT 500") > 0) {
- print " deleted from $table\n" if $optv;
- }
- } else {
- push @existing_data, $table;
- }
- }
- if (@existing_data) {
- die " Existing data in tables: @existing_data\n";
- }
-
- my %pendreplace; # "logprop2:(col,col)" => { 'values' => [ [a, b, c], [d, e, f] ],
- # 'bytes' => 3043, 'recs' => 35 }
- my $flush = sub {
- my $dest = shift;
- return 1 unless $pendreplace{$dest};
- my ($table, $cols) = split(/:/, $dest);
- my $vals;
- foreach my $v (@{$pendreplace{$dest}->{'values'}}) {
- $vals .= "," if $vals;
- $vals .= "(" . join(',', map { $dbch->quote($_) } @$v) . ")";
- }
- print " flushing write to $table\n" if $optv > 1;
- $dbch->do("REPLACE INTO $table $cols VALUES $vals");
- die $dbh->errstr if $dbch->err;
- delete $pendreplace{$dest};
- return 1;
- };
-
- my $write = sub {
- my $dest = shift;
- my @values = @_;
- my $new_bytes = 0; foreach (@values) { $new_bytes += length($_); }
- push @{$pendreplace{$dest}->{'values'}}, \@values;
- $pendreplace{$dest}->{'bytes'} += $new_bytes;
- $pendreplace{$dest}->{'recs'}++;
- if ($pendreplace{$dest}->{'bytes'} > 1024*500 ||
- $pendreplace{$dest}->{'recs'} > 500) { $flush->($dest); }
- };
-
- # manual moving (dumb copies)
- foreach my $table (@manual_move, @local_tables) {
- next if ($table eq "modlog" || $table eq "modblob") && $u->is_person;
- print " moving $table ...\n" if $optv > 1;
- my @cols;
- my $sth = $dbo->prepare("DESCRIBE $table");
- $sth->execute;
- my $styleidcolnum = -1;
- my $colnum = 0;
- while ($_ = $sth->fetchrow_hashref) {
- push @cols, $_->{'Field'};
- $styleidcolnum = $colnum if $_->{'Field'} eq 'styleid';
- $colnum++;
- }
- my $cols = join(',', @cols);
- my $dest = "$table:($cols)";
- my $pri = $pri_key->{$table};
- $sth = $dbo->prepare("SELECT $cols FROM $table WHERE $pri=$userid");
- $sth->execute;
- while (my @vals = $sth->fetchrow_array) {
- $write->($dest, @vals);
- }
- }
-
- # size of bio
- my $bio_size = $dbch->selectrow_array("SELECT LENGTH(bio) FROM userbio WHERE userid=$userid");
- $write->("dudata:(userid,area,areaid,bytes)", $userid, 'B', 0, $bio_size) if $bio_size;
-
- # journal items
- {
- my $maxjitem = $dbo->selectrow_array("SELECT MAX(jitemid) FROM log2 WHERE journalid=$userid");
- my $load_amt = 1000;
- my ($lo, $hi) = (1, $load_amt);
- my $sth;
- my $cols = "security,allowmask,journalid,jitemid,posterid,eventtime,logtime,compressed,anum,replycount,year,month,day,rlogtime,revttime"; # order matters. see indexes below
- while ($lo <= $maxjitem) {
- print " log ($lo - $hi, of $maxjitem)\n" if $optv > 1;
-
- # log2/logsec2
- $sth = $dbo->prepare("SELECT $cols FROM log2 ".
- "WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi");
- $sth->execute;
- while (my @vals = $sth->fetchrow_array) {
- $write->("log2:($cols)", @vals);
-
- if ($vals[0] eq "usemask") {
- $write->("logsec2:(journalid,jitemid,allowmask)",
- $userid, $vals[3], $vals[1]);
- }
- }
-
- # logprop2
- $sth = $dbo->prepare("SELECT journalid,jitemid,propid,value ".
- "FROM logprop2 WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi");
- $sth->execute;
- while (my @vals = $sth->fetchrow_array) {
- $write->("logprop2:(journalid,jitemid,propid,value)", @vals);
- }
-
- # logtext2
- $sth = $dbo->prepare("SELECT journalid,jitemid,subject,event ".
- "FROM logtext2 WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi");
- $sth->execute;
- while (my @vals = $sth->fetchrow_array) {
- my $size = length($vals[2]) + length($vals[3]);
- LJ::text_compress(\$vals[3]);
- $write->("logtext2:(journalid,jitemid,subject,event)", @vals);
- $write->("dudata:(userid,area,areaid,bytes)", $userid, 'L', $vals[1], $size);
- }
-
- $hi += $load_amt; $lo += $load_amt;
- }
- }
-
- # comments
- {
- my $maxtalkid = $dbo->selectrow_array("SELECT MAX(jtalkid) FROM talk2 WHERE journalid=$userid");
- my $load_amt = 1000;
- my ($lo, $hi) = (1, $load_amt);
- my $sth;
-
- my %cols = ('talk2' => 'journalid,jtalkid,nodetype,nodeid,parenttalkid,posterid,datepost,state',
- 'talkprop2' => 'journalid,jtalkid,tpropid,value',
- 'talktext2' => 'journalid,jtalkid,subject,body');
- while ($lo <= $maxtalkid) {
- print " talk ($lo - $hi, of $maxtalkid)\n" if $optv > 1;
- foreach my $table (keys %cols) {
- $sth = $dbo->prepare("SELECT $cols{$table} FROM $table ".
- "WHERE journalid=$userid AND jtalkid BETWEEN $lo AND $hi");
- $sth->execute;
- while (my @vals = $sth->fetchrow_array) {
- LJ::text_compress(\$vals[3]) if $table eq "talktext2";
- $write->("$table:($cols{$table})", @vals);
- }
- }
-
- $hi += $load_amt; $lo += $load_amt;
- }
- }
-
- # talkleft table.
- {
- # no primary key... delete all of target first.
- while ($dbch->do("DELETE FROM talkleft WHERE userid=$userid LIMIT 1000") > 0) {
- print " deleted from talkleft\n" if $optv > 1;
- }
-
- my $last_max = 0;
- my $cols = "userid,posttime,journalid,nodetype,nodeid,jtalkid,publicitem";
- while (defined $last_max) {
- print " talkleft: $last_max\n" if $optv > 1;
- my $sth = $dbo->prepare("SELECT $cols FROM talkleft WHERE userid=$userid ".
- "AND posttime > $last_max ORDER BY posttime LIMIT 1000");
- $sth->execute;
- undef $last_max;
- while (my @vals = $sth->fetchrow_array) {
- $write->("talkleft:($cols)", @vals);
- $last_max = $vals[1];
- }
- }
- }
-
- # flush remaining items
- foreach (keys %pendreplace) { $flush->($_); }
-
- # unset readonly and move to new cluster in one update
- LJ::update_user($userid, { clusterid => $dclust, raw => "caps=caps&~(1<<$readonly_bit)" });
- print "Moved.\n" if $optv;
-
- # delete from source cluster
- if ($opt_del) {
- print "Deleting from source cluster...\n" if $optv;
- foreach my $table (sort keys %$pri_key) {
- my $pri = $pri_key->{$table};
- while ($dbo->do("DELETE FROM $table WHERE $pri=$userid LIMIT 500") > 0) {
- print " deleted from $table\n" if $optv;
- }
- }
- } else {
- # at minimum, we delete the clustertrack2 row so it doesn't get
- # included in a future ljumover.pl query from that cluster.
- $dbo->do("DELETE FROM clustertrack2 WHERE userid=$userid");
- }
-
- $dbh->do("UPDATE clustermove SET sdeleted=?, timedone=UNIX_TIMESTAMP() ".
- "WHERE cmid=?", undef, $opt_del ? 1 : 0, $cmid);
- exit 0;
-}
-
-sub deletefrom0_logitem
-{
- my $itemid = shift;
-
- # delete all the comments
- my $talkids = $dbh->selectcol_arrayref("SELECT talkid FROM talk ".
- "WHERE nodetype='L' AND nodeid=$itemid");
-
- my $talkidin = join(",", @$talkids);
- if ($talkidin) {
- foreach my $table (qw(talktext talkprop talk)) {
- $dbh->do("DELETE FROM $table WHERE talkid IN ($talkidin)");
- }
- }
-
- $dbh->do("DELETE FROM logsec WHERE ownerid=$userid AND itemid=$itemid");
- foreach my $table (qw(logprop logtext log)) {
- $dbh->do("DELETE FROM $table WHERE itemid=$itemid");
- }
-}
-
-sub movefrom0_logitem
-{
- my $itemid = shift;
-
- my $item = $bufread->(100, "SELECT * FROM log", $itemid);
- my $itemtext = $bufread->(50, "SELECT itemid, subject, event FROM logtext", $itemid);
- return 1 unless $item && $itemtext; # however that could happen.
-
- # we need to allocate a new jitemid (journal-specific itemid) for this item now.
- my $jitemid = $alloc_id->('L', $itemid);
- unless ($jitemid) {
- die "ERROR: could not allocate a new jitemid\n";
- }
- $dbh->{'RaiseError'} = 1;
- $item->{'jitemid'} = $jitemid;
- $item->{'anum'} = int(rand(256));
-
- # copy item over:
- $replace_into->("log2", "(journalid, jitemid, posterid, eventtime, logtime, ".
- "compressed, security, allowmask, replycount, year, month, day, ".
- "rlogtime, revttime, anum)",
- 50, map { $item->{$_} } qw(ownerid jitemid posterid eventtime
- logtime compressed security allowmask replycount
- year month day rlogtime revttime anum));
-
- $replace_into->("logtext2", "(journalid, jitemid, subject, event)", 10,
- $userid, $jitemid, map { $itemtext->{$_} } qw(subject event));
-
- # add disk usage info! (this wasn't in cluster0 anywhere)
- my $bytes = length($itemtext->{'event'}) + length($itemtext->{'subject'});
- $replace_into->("dudata", "(userid, area, areaid, bytes)", 50, $userid, 'L', $jitemid, $bytes);
-
- # add the logsec item, if necessary:
- if ($item->{'security'} ne "public") {
- $replace_into->("logsec2", "(journalid, jitemid, allowmask)", 50,
- map { $item->{$_} } qw(ownerid jitemid allowmask));
- }
-
- # copy its logprop over:
- while (my $lp = $bufread->(50, "SELECT itemid, propid, value FROM logprop", $itemid)) {
- next unless $lp->{'value'};
- $replace_into->("logprop2", "(journalid, jitemid, propid, value)", 50,
- $userid, $jitemid, $lp->{'propid'}, $lp->{'value'});
- }
-
- # copy its talk shit over:
- my %newtalkids = (0 => 0); # 0 maps back to 0 still
- my $talkids = $dbr->selectcol_arrayref("SELECT talkid FROM talk ".
- "WHERE nodetype='L' AND nodeid=$itemid");
- my @talkids = sort { $a <=> $b } @$talkids;
- my $treader = make_buffer_reader("talkid", \@talkids);
- foreach my $t (@talkids) {
- movefrom0_talkitem($t, $jitemid, \%newtalkids, $item, $treader);
- }
-}
-
-sub movefrom0_talkitem
-{
- my $talkid = shift;
- my $jitemid = shift;
- my $newtalkids = shift;
- my $logitem = shift;
- my $treader = shift;
-
- my $item = $treader->(100, "SELECT *, UNIX_TIMESTAMP(datepost) AS 'datepostunix' FROM talk", $talkid);
- my $itemtext = $treader->(50, "SELECT talkid, subject, body FROM talktext", $talkid);
- return 1 unless $item && $itemtext; # however that could happen.
-
- # abort if this is a stranded entry. (shouldn't happen, anyway. even if it does, it's
- # not like we're losing data: the UI (talkread.bml) won't show it anyway)
- return unless defined $newtalkids->{$item->{'parenttalkid'}};
-
- # we need to allocate a new jitemid (journal-specific itemid) for this item now.
- my $jtalkid = $alloc_id->('T', $talkid);
- unless ($jtalkid) {
- die "ERROR: could not allocate a new jtalkid\n";
- }
- $newtalkids->{$talkid} = $jtalkid;
- $dbh->{'RaiseError'} = 1;
-
- # copy item over:
- $replace_into->("talk2", "(journalid, jtalkid, parenttalkid, nodeid, ".
- "nodetype, posterid, datepost, state)", 50,
- $userid, $jtalkid, $newtalkids->{$item->{'parenttalkid'}},
- $jitemid, 'L', map { $item->{$_} } qw(posterid datepost state));
-
-
- $replace_into->("talktext2", "(journalid, jtalkid, subject, body)",
- 20, $userid, $jtalkid, map { $itemtext->{$_} } qw(subject body));
-
- # copy its logprop over:
- while (my $lp = $treader->(50, "SELECT talkid, tpropid, value FROM talkprop", $talkid)) {
- next unless $lp->{'value'};
- $replace_into->("talkprop2", "(journalid, jtalkid, tpropid, value)", 50,
- $userid, $jtalkid, $lp->{'tpropid'}, $lp->{'value'});
- }
-
- # note that poster commented here
- if ($item->{'posterid'}) {
- my $pub = $logitem->{'security'} eq "public" ? 1 : 0;
- my ($table, $db) = ("talkleft_xfp", $dbh);
- ($table, $db) = ("talkleft", $dbch) if $userid == $item->{'posterid'};
- $replace_into->($db, $table, "(userid, posttime, journalid, nodetype, ".
- "nodeid, jtalkid, publicitem)", 50,
- $item->{'posterid'}, $item->{'datepostunix'}, $userid,
- 'L', $jitemid, $jtalkid, $pub);
- }
-}
-
-sub make_buffer_reader
-{
- my $pricol = shift;
- my $valsref = shift;
-
- my %bfd; # buffer read data. halfquery -> { 'rows' => { id => [] },
- # 'remain' => [], 'loaded' => { id => 1 } }
- return sub
- {
- my ($amt, $hq, $pid) = @_;
- if (not defined $bfd{$hq}->{'loaded'}->{$pid})
- {
- if (not exists $bfd{$hq}->{'remain'}) {
- $bfd{$hq}->{'remain'} = [ @$valsref ];
- }
-
- my @todo;
- for (1..$amt) {
- next unless @{$bfd{$hq}->{'remain'}};
- my $id = shift @{$bfd{$hq}->{'remain'}};
- push @todo, $id;
- $bfd{$hq}->{'loaded'}->{$id} = 1;
- }
-
- if (@todo) {
- my $sql = "$hq WHERE $pricol IN (" . join(",", @todo) . ")";
- my $sth = $dbr->prepare($sql);
- $sth->execute;
- while (my $r = $sth->fetchrow_hashref) {
- push @{$bfd{$hq}->{'rows'}->{$r->{$pricol}}}, $r;
- }
- }
- }
-
- return shift @{$bfd{$hq}->{'rows'}->{$pid}};
- };
-}
-
-# this function needs to die loudly if moveucluster.pl is unable to move
-# any type of table that exists on this installation
-sub verify_movable_tables {
- my %table; # tablename -> unhandled flag
-
- # first, assume everything's unhandled
- foreach my $t (@LJ::USER_TABLES, @LJ::USER_TABLES_LOCAL) {
- $table{$t} = 1;
- }
-
- # now, clear things we know how to move
- foreach my $t (qw(cmdbuffer dudata log2 logsec2 logprop2 logtext2
- talk2 talkprop2 talktext2 talkleft
- ), @manual_move) {
- delete $table{$t};
- }
-
- # local stuff
- my $local_tables = LJ::run_hook("moveucluster_local_tables");
- if ($local_tables) {
- while (my ($tab, $key) = each %$local_tables) {
- delete $table{$tab};
- }
- }
-
- # things we list as active tables but don't use yet
- delete $table{"events"};
-
- # things we don't move because it doesn't really matter
- delete $table{"captcha_session"};
-
- if (%table) {
- die "ERROR. Won't try to move user, because this mover script can't move all live tables for this user. List of tables without mover code available: \n -- " . join("\n -- ", sort keys %table), "\n";
- }
-
-}
-
-1; # return true;
diff -r 8a1034a41fe1 -r ee7de5f9dd15 bin/upgrading/update-db-general.pl
--- a/bin/upgrading/update-db-general.pl Sat Sep 05 10:51:57 2009 +0000
+++ b/bin/upgrading/update-db-general.pl Sat Sep 05 11:33:28 2009 +0000
@@ -975,6 +975,7 @@ register_tabledrop("adoptlast");
register_tabledrop("adoptlast");
register_tabledrop("urimap");
register_tabledrop("syndicated_hubbub");
+register_tabledrop("oldids");
register_tablecreate("portal", <<'EOC');
CREATE TABLE portal (
@@ -1116,22 +1117,6 @@ CREATE TABLE includetext (
INDEX (updatetime)
)
-EOC
-
-# TODO: As part of migration from LJ to DW, hard redirect everything in here,
-# then get rid of this table and of code that references it. Per discussion
-# with xb95, it's not needed anywhere.
-register_tablecreate("oldids", <<'EOC');
-CREATE TABLE oldids (
- area CHAR(1) NOT NULL,
- oldid INT UNSIGNED NOT NULL,
- UNIQUE (area, oldid),
- userid INT UNSIGNED NOT NULL,
- newid INT UNSIGNED NOT NULL AUTO_INCREMENT,
-
- PRIMARY KEY (area,userid, newid),
- INDEX (userid)
-) TYPE=MYISAM
EOC
register_tablecreate("dudata", <<'EOC');
--------------------------------------------------------------------------------
