ljr/livejournal/htdocs/admin/dbadmin.bml

201 lines
6.7 KiB
Plaintext
Executable File

<html>
<head><title>DB Admin - <?sitename?></title>
<style>
p, td { font-size: 9pt; font-family: sans-serif; }
input { font-size: 8pt; font-family: sans-serif; }
</style>
</head>
<body bgcolor='#000000' text='#ffffff' link='#eeeeee' vlink='#eeeeee'>
<?_code
use strict;
use vars qw(%FORM);
my $dbh = LJ::get_db_writer();
my $remote = LJ::get_remote($dbh);
return"<b>Error:</b> You don't have access to administer databases."
unless (LJ::check_priv($dbh, $remote, "siteadmin", "dbweightview"));
my $can_save = LJ::check_priv($dbh, $remote, "siteadmin", "dbweightchange");
my $view = $FORM{'view'} eq "role" ? "role" : "host";
my %dbinfo; # dbid
my %slaves; # dbid
my $sth;
$sth = $dbh->prepare("SELECT dbid, name, fdsn, masterid FROM dbinfo");
$sth->execute;
while ($_ = $sth->fetchrow_hashref) {
next unless $_->{'dbid'};
$dbinfo{$_->{'dbid'}} = $_;
push @{$slaves{$_->{'masterid'}}}, $_->{'dbid'};
}
my %weights;
my %role;
my %roletweight;
$sth = $dbh->prepare("SELECT dbid, role, norm, curr FROM dbweights");
$sth->execute;
while ($_ = $sth->fetchrow_hashref) {
next unless defined $dbinfo{$_->{'dbid'}};
$weights{$_->{'dbid'}}->{$_->{'role'}} = $_;
push @{$role{$_->{'role'}}}, $_->{'dbid'};
$roletweight{$_->{'role'}} += $_->{'curr'};
}
my $ret;
my $p = sub { $ret .= shift; };
my $status;
if ($can_save && defined $FORM{'action:save'}) {
return "<b>Error:</b> Not a POST request." unless LJ::did_post();
my $curr_changed = 0;
foreach my $k (keys %FORM) {
next unless $k =~ /^set-(\d+)-(\w+?)-(\w+)$/;
my ($sid, $role, $what) = ($1, $2, $3);
next unless $what eq "norm" or $what eq "curr";
next unless defined $weights{$sid};
next unless defined $weights{$sid}->{$role};
my $val = $FORM{$k}+0;
my $old = $weights{$sid}->{$role}->{$what};
next if $val == $old;
$dbh->do("UPDATE dbweights SET $what=$val WHERE ".
"dbid=$sid AND role='$role'");
$weights{$sid}->{$role}->{$what} = $val;
if ($what eq "curr") {
$curr_changed = 1;
$roletweight{$role} += $val - $old;
}
}
if ($curr_changed) {
if ($LJ::DBCONFIG_WRITE_CONFIG) {
my $good = 1;
my $newcfg = "# auto-generated config from /admin/dbadmin.bml. changes will be overwritten!\n";
$newcfg .= "%LJ::DBINFO = (\n";
foreach my $id (sort keys %dbinfo) {
next unless $id > 0;
my $dbinf = $dbinfo{$id};
my $name = $dbinf->{'name'};
if ($dbinf->{'masterid'} == 0) { $name = "master"; }
$newcfg .= "\t'$name' => {\n";
$newcfg .= "\t\t'_fdsn' => \"$dbinf->{fdsn}\",\n";
$newcfg .= "\t\t'role' => {\n";
foreach my $role (sort keys %{$weights{$id} || {}}) {
$newcfg .= "\t\t\t'$role' => $weights{$id}->{$role}->{'curr'},\n";
}
$newcfg .= "\t\t},\n";
$newcfg .= "\t},\n";
}
$newcfg .= ");\n";
$newcfg .= "\$LJ::DBINFO{'master'}->{'role'}->{'master'} = 1;\n";
$newcfg .= "1;\n";
if (open(CFG, ">$ENV{'LJHOME'}/cgi-bin/dbconfig.pl")) {
print CFG $newcfg;
close CFG;
open (TCH, ">>$ENV{'LJHOME'}/cgi-bin/ljconfig.pl");
close TCH;
}
$status .= "<p>Wrote config.</p>";
} else {
my $newserial = LJ::procnotify_add("DBI::Role::reload");
$status .= "<p>New Serial: $newserial</p>\n";
}
}
}
my $single = sub {
my $role = shift;
return @{$role{$role}} == 1;
};
my $slaveroleperc = sub {
my $sid = shift;
my $role = shift;
return sprintf("%0.1f%%", 100*$weights{$sid}->{$role}->{'curr'}/($roletweight{$role}||1));
};
my $dumpslaves = sub
{
my $mid = shift;
my $depth = shift;
my $rec = shift;
return unless $slaves{$mid};
my $indent = "&nbsp;" x ($depth*5);
foreach my $sid (sort { $#{$slaves{$a}} <=> $#{$slaves{$b}} } @{$slaves{$mid}}) {
my $db = $dbinfo{$sid};
$p->("<tr bgcolor='#404070'><td colspan='4'><b>$indent$db->{'name'}</b> ($sid)</td></tr>");
foreach my $role (sort keys %{$weights{$sid}}) {
my $r = $weights{$sid}->{$role};
my $col;
if ($r->{'norm'} != $r->{'curr'}) {
$col = "bgcolor='#800000'";
}
$p->("<tr valign='bottom' $col><td>$indent$role</td>");
$p->("<td align='center'><input size='3' name='set-$sid-$role-norm' value='$r->{'norm'}'></td>");
$p->("<td align='center'><input size='3' name='set-$sid-$role-curr' value='$r->{'curr'}'></td>");
$p->("<td>" . $slaveroleperc->($sid, $role) . "</td>");
$p->("</tr>");
}
$rec->($sid, $depth+1, $rec);
}
};
my $dumprole = sub
{
my $role = shift;
return if $single->($role);
$p->("<tr bgcolor='#404070'><td colspan='4'><b>$role</b></td></tr>");
foreach my $sid (sort { $weights{$b}->{$role}->{'curr'} <=> $weights{$a}->{$role}->{'curr'} } @{$role{$role}})
{
my $r = $weights{$sid}->{$role};
my $col;
$col = "bgcolor='#800000'" if $r->{'norm'} != $r->{'curr'};
$p->("<tr valign='bottom' $col><td>$dbinfo{$sid}->{'name'}</td>");
$p->("<td align='center'><input size='3' name='set-$sid-$role-norm' value='$r->{'norm'}'></td>");
$p->("<td align='center'><input size='3' name='set-$sid-$role-curr' value='$r->{'curr'}'></td>");
$p->("<td>" . $slaveroleperc->($sid, $role) . "</td>");
$p->("</tr>");
}
};
$p->('<form method="post" action="dbadmin.bml">');
$p->("<input type='hidden' name='view' value='$view'>");
$p->('<table cellpadding="1" border="0" bgcolor="#606060">');
my $hr = "<b>Host</b> / <a href='dbadmin.bml?view=role'>Role</a>";
if ($view eq "role") {
$hr = "<a href='dbadmin.bml?view=host'>Host</a> / <b>Role</b>";
}
$p->("<tr bgcolor='#404040'><td>$hr</td><td><b>Norm</b></td><td><b>Curr</b></td><td>%</td></tr>");
if ($view eq "role") {
foreach my $role (sort keys %role) {
$dumprole->($role);
}
} else {
$dumpslaves->(0, 0, $dumpslaves); # root
}
if ($can_save) {
$p->('<tr><td colspan="4" align="center" bgcolor="#404040"><input type="submit" name="action:refresh" value="Refresh"> ');
$p->('<input type="submit" name="action:save" value="Save"></td></tr>');
}
$p->('</table>');
$p->('</form>');
$p->($status);
return $ret;
_code?>
</body>
</html>