diff --git a/Makefile b/Makefile
index d6f1e8ad..ab556dd2 100644
--- a/Makefile
+++ b/Makefile
@@ -66,6 +66,7 @@ CGIDIR = ${LIBEXECDIR}/mxq/cgi
########################################################################
MXQ_MYSQL_DEFAULT_FILE = ${SYSCONFDIR}/mxq/mysql.cnf
+MXQ_MYSQL_RO_DEFAULT_FILE = ${SYSCONFDIR}/mxq/mysql_ro.cnf
MXQ_MYSQL_DEFAULT_GROUP_CLIENT = mxqclient
MXQ_MYSQL_DEFAULT_GROUP_SERVER = mxqd
MXQ_MYSQL_DEFAULT_GROUP_DEVELOPMENT = mxqdevel
@@ -158,6 +159,7 @@ sed-rules = -e 's,@PREFIX@,${PREFIX},g' \
-e 's,@DATADIR@,${DATADIR},g' \
-e 's,@MXQ_VERSION@,${MXQ_VERSION},g' \
-e 's,@MXQ_MYSQL_DEFAULT_FILE@,${MXQ_MYSQL_DEFAULT_FILE},g' \
+ -e 's,@MXQ_MYSQL_RO_DEFAULT_FILE@,${MXQ_MYSQL_RO_DEFAULT_FILE},g' \
-e 's,@CGIDIR@,${CGIDIR},g' \
-e 's,@HTTP_USER@,${HTTP_USER},g' \
-e 's,@HTTP_GROUP@,${HTTP_GROUP},g' \
diff --git a/web/pages/mxq/mxq.in b/web/pages/mxq/mxq.in
index d35021f8..f188b33f 100755
--- a/web/pages/mxq/mxq.in
+++ b/web/pages/mxq/mxq.in
@@ -10,8 +10,11 @@ our %GROUP_STATUS_NAME; # ( 0=>'OK',...)
our %JOB_STATUS_NAME;
our %DAEMON_STATUS_NAME;
our $dbh;
+our $hostconfig;
our $q;
+our $LIMIT=100000; # max rows
+
sub STYLE {
return <<'EOF';
EOF
}
sub HEAD {
- return <<'EOF'.STYLE().<<'EOF';
-
-
-
-
-
-
-
-EOF
-
-EOF
+ return "\n\n".STYLE()."\n";
}
sub my_url {
@@ -73,10 +48,22 @@ sub my_url {
return $uri;
}
+sub hostconfig_init {
+ open my $in,'<','/etc/hostconfig' or die "/etc/hostconfig: $!\n";
+ while (<$in>) {
+ s/#.*//;
+ chomp;
+ my ($host,$attr,$value)=split ' ',$_,3;
+ $host or next;
+ $attr or next;
+ $attr eq 'mxqd' and $hostconfig->{$host}=1;
+ }
+}
+
sub db_init {
- open my $test,"<@MXQ_MYSQL_DEFAULT_FILE@" or die "@MXQ_MYSQL_DEFAULT_FILE@: $!\n";
- $dbh= DBI->connect('DBI:mysql:mysql_read_default_file=@MXQ_MYSQL_DEFAULT_FILE@',undef,undef, { RaiseError => 1, AutoCommit => 1 });
+ open my $test,"<@MXQ_MYSQL_RO_DEFAULT_FILE@" or die "@MXQ_MYSQL_RO_DEFAULT_FILE@: $!\n";
+ $dbh= DBI->connect('DBI:mysql:mysql_read_default_file=@MXQ_MYSQL_RO_DEFAULT_FILE@',undef,undef, { RaiseError => 1, AutoCommit => 1 });
# mxq_group.h
register_group_status(
OK => 0,
@@ -137,10 +124,73 @@ sub daemon_status { return get_status(\%DAEMON_STATUS_NAME,@_) }
sub humanSeconds {
my ($seconds)=@_;
- $seconds<60 and return sprintf ('%2d s',$seconds);
- $seconds<3600 and return sprintf ('%2d m %2d s',$seconds/60,$seconds%60);
- $seconds<86400 and return sprintf ('%2d h %2d m',$seconds/3600,$seconds%3600/60);
- return sprintf('%2d d %2d h',$seconds/86400,$seconds%86400/3600);
+ $seconds<60 and return sprintf ('%2ds',$seconds);
+ $seconds<3600 and return sprintf ('%2dm %2ds',$seconds/60,$seconds%60);
+ $seconds<86400 and return sprintf ('%2dh %2dm',$seconds/3600,$seconds%3600/60);
+ return sprintf('%2dd %2dh',$seconds/86400,$seconds%86400/3600);
+}
+
+sub size {
+ my $s = shift;
+ my $n = shift;
+ defined($n) or $n=1;
+ $s == 0 and return '0 B';
+
+ my @T=();
+ for (my $f = 4; $f >= 0; $f--) {
+ my $t = int($s/(1000**$f));
+ push @T, ($t > 0) ? $t : 0; # TB/GB/MB/Kb/B
+ $s -= $t*(1000**$f);
+ }
+ my @L;
+ for my $x ('TB','GB','MB','kB','B') {
+ my $y = shift @T;
+ if ($y != 0) {
+ if (defined($n)) {
+ $n--;
+ last if ($n < 0);
+ }
+ push @L,"$y $x";
+ }
+ }
+ return join(' ',@L);
+}
+
+sub days {
+ my $s = shift;
+ my $n = shift;
+
+ if ($s == 0) {
+ return '0 secs';
+ }
+ my @T=();
+ my $t = int($s/(60*60*24));
+ push @T, ($t > 0) ? $t : 0; # days
+ $s -= $t*(60*60*24);
+
+ $t = int($s/(60*60));
+ push @T, ($t > 0) ? $t : 0; # hrs
+ $s -= $t*(60*60);
+
+ $t = int($s/(60));
+ push @T, ($t > 0) ? $t : 0; # min
+ $s -= $t*60;
+
+ $t = int($s);
+ push @T, ($t > 0) ? $t : 0; # sec
+
+ my @L;
+ for my $x ('days','hrs','min','secs') {
+ my $y = shift @T;
+ if ($y != 0) {
+ if (defined($n)) {
+ $n--;
+ last if ($n < 0);
+ }
+ push @L,"$y $x";
+ }
+ }
+ return join(' ',@L);
}
sub split_cmd {
@@ -149,6 +199,21 @@ sub split_cmd {
return $in;
}
+sub colorize {
+ my ($color,$html) = @_;
+ return $html if ($html eq "0"); # zeros remain black
+ return "$html ";
+}
+
+sub colorize_status {
+ my ($status)=@_;
+ return colorize("green", $status) if $status =~ m/FINISHED/;
+ return colorize("orange",$status) if $status =~ m/RUNNING/;
+ return colorize("blue", $status) if $status =~ m/INQ/;
+ return colorize("red", $status) if $status =~ m/KILL|FAIL/;
+ return $status;
+}
+
sub DataDumper {
use Data::Dumper;
$Data::Dumper::Indent=0;
@@ -170,6 +235,7 @@ sub job_table_pending {
$out.=$q->Tr($q->th(\@cols));
+ my $cnt=0;
while (my $row=$sth->fetchrow_arrayref()) {
my ($job_id,$user_name,$date_submit,$job_threads)=@$row;
@@ -179,8 +245,12 @@ sub job_table_pending {
$q->td($date_submit),
$q->td({class=>'number'},$job_threads),
);
+ ++$cnt == $LIMIT and last;
}
$out.='';
+ if ($cnt==$LIMIT) {
+ $out.=$q->p($q->em("(truncated after $LIMIT rows)"));
+ }
}
sub job_table_running {
@@ -215,35 +285,165 @@ sub job_table_running {
sub job_table_of_group {
- my ($group_id)=@_;
+ my ($group_id,$job_status_filter)=@_;
my $out;
- my @cols=qw(job_id job_status date_submit date_start host_hostname host_pid);
-
- my $sth=$dbh->prepare('SELECT '.join(',',@cols).' FROM mxq_job,mxq_group WHERE mxq_job.group_id=mxq_group.group_id AND mxq_job.group_id=? ORDER BY job_id DESC');
+ my @scols=qw(job_id job_status qtime rtime host_hostname host_pid);
+
+ my $jobfilter = defined($job_status_filter) ? "AND mxq_job.job_status=$job_status_filter" : '';
+
+ my $sth=$dbh->prepare(<<"__EOF__");
+ SELECT
+ job_id,
+ job_status,
+ date_submit,
+ date_start,
+ date_end,
+ host_hostname,
+ host_pid,
+ timestampdiff(SECOND,date_submit,date_start),
+ timestampdiff(SECOND,date_submit,now()),
+ timestampdiff(SECOND,date_start,date_end),
+ timestampdiff(SECOND,date_start,now()),
+ UNIX_TIMESTAMP(date_submit) as ds
+ FROM mxq_job,mxq_group
+ WHERE mxq_job.group_id=mxq_group.group_id AND mxq_job.group_id=?
+ $jobfilter
+ ORDER BY job_id DESC
+__EOF__
$sth->execute($group_id);
$out.='';
- $out.=$q->Tr($q->th(\@cols));
+ $out.=$q->Tr($q->th(\@scols));
+ my $lds;
+ my $col=1;
+ my $cnt=0;
while (my $row=$sth->fetchrow_arrayref()) {
- my ($job_id,$job_status,$date_submit,$date_start,$host_hostname,$host_pid)=@$row;
+ my ($job_id,$job_status,$date_submit,$date_start,$date_end,$host_hostname,$host_pid,
+ $qtime,$qtime_now,$rtime,$rtime_now,$ds)=@$row;
+
+ if (defined($qtime)) {
+ $qtime = humanSeconds($qtime);
+ } else {
+ $qtime = colorize("gray",humanSeconds($qtime_now));
+ }
+
+ if (defined($rtime)) {
+ $rtime = humanSeconds($rtime);
+ } else {
+ $rtime = colorize("gray",humanSeconds($rtime_now));
+ }
+ my $date_info = "submit: $date_submit\nstart: $date_start\nend: $date_end";
+
+ if (defined $lds && abs($lds-$ds)>10) {
+ $col = 1-$col;
+ $out.=$q->Tr($q->td(' '));
+ }
+ $lds=$ds;
$out.=$q->Tr(
+ {class=>'bg'.$col},
$q->td({class=>'number'},$q->a({href=>selfurl("/job/$job_id")},$job_id)),
- $q->td(job_status($job_status)),
- $q->td($date_submit),
- $q->td($date_start),
+ $q->td(colorize_status(job_status($job_status))),
+ $q->td("$qtime "),
+ $q->td("$rtime "),
$q->td($host_hostname),
$q->td({class=>'number'},$host_pid),
);
+ ++$cnt == $LIMIT and last;
}
$out.='
';
+ if ($cnt==$LIMIT) {
+ $out.=$q->p($q->em("(truncated after $LIMIT rows)"));
+ }
+}
+
+sub job_status_filter_buttons {
+ my $group_id = shift;
+ my @r=();
+ push @r,$q->a({href=>selfurl("/group/$group_id")},'ALL');
+ for my $js ( 0, 200, 1000, 750, 400 ) {
+ push @r,$q->a({href=>selfurl("/group/$group_id/$js")},job_status($js));
+ }
+ return ''.join(' | ',@r).'
';
+}
+
+sub group_details_raw {
+ my ($o)=@_;
+
+ my $group_name=escapeHTML($o->{'group_name'});
+ my $job_command=escapeHTML($o->{'job_command'});
+ my $group_status_text=group_status($o->{'group_status'});
+
+ return <<"__EOF__"
+
+group_name : $group_name
+group_status : $group_status_text
+group_flags : $o->{group_flags}
+group_priority : $o->{group_priority}
+
+user_uid : $o->{user_uid}
+user_name : $o->{user_name}
+user_gid : $o->{user_gid}
+user_group : $o->{user_group}
+
+job_command : $job_command
+job_threads : $o->{job_threads}
+job_memory : $o->{job_memory} MiB
+job_time : $o->{job_time} minutes
+
+job_max_per_node : $o->{job_max_per_node}
+
+group_jobs : $o->{group_jobs}
+group_jobs_inq : $o->{group_jobs_inq}
+group_jobs_running : $o->{group_jobs_running}
+group_jobs_finished : $o->{group_jobs_finished}
+group_jobs_failed : $o->{group_jobs_failed}
+group_jobs_cancelled : $o->{group_jobs_cancelled}
+group_jobs_unknown : $o->{group_jobs_unknown}
+group_jobs_restarted : $o->{group_jobs_restarted}
+
+group_slots_running: : $o->{group_slots_running}
+
+group_mtime : $o->{group_mtime}
+
+group_date_end : $o->{group_date_end}
+
+stats_max_sumrss : $o->{stats_max_sumrss} kiB
+stats_max_maxrss : $o->{stats_max_maxrss}
+stats_max_utime_sec : $o->{stats_max_utime_sec}
+stats_max_stime_sec : $o->{stats_max_stime_sec}
+stats_max_real_sec : $o->{stats_max_real_sec}
+
+stats_total_utime_sec : $o->{stats_total_utime_sec}
+stats_total_stime_sec : $o->{stats_total_stime_sec}
+stats_total_real_sec : $o->{stats_total_real_sec}
+stats_total_wait_sec : $o->{stats_total_wait_sec}
+
+stats_wait_sec : $o->{stats_wait_sec}
+stats_run_sec : $o->{stats_run_sec}
+stats_idle_sec : $o->{stats_idle_sec}
+
+stats_total_utime_sec_finished : $o->{stats_total_utime_sec_finished}
+stats_total_stime_sec_finished : $o->{stats_total_stime_sec_finished}
+stats_total_real_sec_finished : $o->{stats_total_real_sec_finished}
+stats_total_wait_sec_finished : $o->{stats_total_wait_sec_finished}
+
+__EOF__
+}
+
+sub group_details_raw_by_group_id {
+ my ($group_id)=@_;
+ my $sth=$dbh->prepare('SELECT * FROM mxq_group WHERE group_id=? LIMIT 1',undef);
+ $sth->execute($group_id);
+ my $o=$sth->fetchrow_hashref('NAME_lc');
+ return group_details_raw($o);
}
-sub group_detail {
+sub group_details {
my ($group_id)=@_;
$dbh or db_init();
@@ -253,79 +453,45 @@ sub group_detail {
$sth->execute($group_id);
my %o=%{$sth->fetchrow_hashref('NAME_lc')};
- $out.=h2("Group Detail group_id $o{group_id}");
-
my $group_status_text=group_status($o{'group_status'});
my $group_name=escapeHTML($o{group_name});
my $job_command=escapeHTML($o{job_command});
- $out.=<<"EOF";
+ $out.=<<"__EOF__";
+Summary
-group_name : $group_name
-group_status : $group_status_text
-group_flags : $o{group_flags}
-group_priority : $o{group_priority}
+$o{user_name} submitted
-user_uid : $o{user_uid}
-user_name : $o{user_name}
-user_gid : $o{user_gid}
-user_group : $o{user_group}
+ $job_command
+
+in group "$group_name", the group status is $group_status_text.
-job_command : $job_command
-job_threads : $o{job_threads}
-job_memory : $o{job_memory} MiB
-job_time : $o{job_time} minutes
-
-job_max_per_node : $o{job_max_per_node}
-
-group_jobs : $o{group_jobs}
-group_jobs_inq : $o{group_jobs_inq}
-group_jobs_running : $o{group_jobs_running}
-group_jobs_finished : $o{group_jobs_finished}
-group_jobs_failed : $o{group_jobs_failed}
-group_jobs_cancelled : $o{group_jobs_cancelled}
-group_jobs_unknown : $o{group_jobs_unknown}
-group_jobs_restarted : $o{group_jobs_restarted}
-
-group_slots_running: : $o{group_slots_running}
-
-group_mtime : $o{group_mtime}
-
-group_date_end : $o{group_date_end}
-
-stats_max_sumrss : $o{stats_max_sumrss} kiB
-stats_max_maxrss : $o{stats_max_maxrss}
-stats_max_utime_sec : $o{stats_max_utime_sec}
-stats_max_stime_sec : $o{stats_max_stime_sec}
-stats_max_real_sec : $o{stats_max_real_sec}
-
-stats_total_utime_sec : $o{stats_total_utime_sec}
-stats_total_stime_sec : $o{stats_total_stime_sec}
-stats_total_real_sec : $o{stats_total_real_sec}
-stats_total_wait_sec : $o{stats_total_wait_sec}
-
-stats_wait_sec : $o{stats_wait_sec}
-stats_run_sec : $o{stats_run_sec}
-stats_idle_sec : $o{stats_idle_sec}
-
-stats_total_utime_sec_finished : $o{stats_total_utime_sec_finished}
-stats_total_stime_sec_finished : $o{stats_total_stime_sec_finished}
-stats_total_real_sec_finished : $o{stats_total_real_sec_finished}
-stats_total_wait_sec_finished : $o{stats_total_wait_sec_finished}
-EOF
+
+[show group details ...]
+
+
+[hide group details]
+
+
+__EOF__
+ $out.=group_details_raw(\%o);
+ $out.=<<'__EOF__';
+
+__EOF__
- return $out;
+ return $out;
}
sub group {
- my ($group_id)=@_;
+ my ($group_id,$job_status_filter)=@_;
my $out=h1('MXQ Group '.$group_id);
- $out.=group_detail($group_id);
- $out.=h2('Jobs of this group').job_table_of_group($group_id);
+ $out.=group_details($group_id);
+ my $what = defined($job_status_filter) ? job_status($job_status_filter) . ' jobs' : 'Jobs';
+ $out.=h2($what . ' of this group ').job_status_filter_buttons($group_id).job_table_of_group($group_id,$job_status_filter);
return $out;
}
@@ -341,8 +507,6 @@ sub job {
$sth->execute($job_id);
my %o=%{$sth->fetchrow_hashref('NAME_lc')};
- $out.=group_detail($o{group_id});
-
my $job_status_text=job_status($o{'job_status'});
my $job_umask_text=sprintf('%03O',$o{job_umask});
my $link_group_id=a({href=>selfurl("/group/$o{group_id}")},$o{group_id});
@@ -356,8 +520,6 @@ sub job {
defined $_ or $_='<null>' for values %o;
- $out.=h2("Job Details $o{job_id}");
-
$out.=<<"EOF";
job_status : $job_status_text
@@ -411,12 +573,15 @@ stats_nvcsw : $o{stats_nvcsw}
stats_nivcsw : $o{stats_nivcsw}
EOF
+
+ $out .= "group details ";
+ $out.=group_details_raw_by_group_id($o{group_id});
return $out;
}
sub group_table {
- my ($sql_clause,$sql_binds)=@_;
+ my ($sql_clause,$sql_binds,$days)=@_;
$sql_clause||='true';
@@ -426,8 +591,10 @@ sub group_table {
$out .= 'Active Groups ';
@cols=qw(
- group_id group_name job_threads user_name
- group_mtime
+ group_id group_name job_threads
+ job_memory
+ job_time
+ user_name
group_status
group_jobs
group_jobs_inq group_jobs_running
@@ -435,12 +602,20 @@ sub group_table {
);
@head=qw(
- group_id group_name threads user_name
- group_mtime
- group_status
+ group id
+ group name
+ req. threads
+ req. memory
+ req. runtime
+ user name
+ group status
jobs
- inq running
- finished failed cancelled unknown
+ inq
+ running
+ finished
+ failed
+ cancelled
+ unknown
);
my $sth=$dbh->prepare('SELECT '.join(',',@cols).' FROM mxq_group WHERE '.$sql_clause.' AND (group_jobs_running>0 OR group_jobs_inq>0) ORDER BY group_id DESC');
@@ -449,7 +624,9 @@ sub group_table {
$out.='';
$out.=$q->Tr($q->th(\@head));
while (my $row=$sth->fetchrow_arrayref()) {
- my ($group_id,$group_name,$job_threads,$user_name,$group_mtime,$group_status,
+ my ($group_id,$group_name,$job_threads,
+ $job_memory,$job_time,
+ $user_name,$group_status,
$group_jobs,$group_jobs_inq,$group_jobs_running,$group_jobs_finished,$group_jobs_failed,$group_jobs_cancelled,$group_jobs_unknown
)=@$row;
@@ -457,45 +634,66 @@ sub group_table {
$q->td({class=>'number'},$q->a({href=>selfurl("/group/$group_id")},$group_id)),
$q->td($group_name),
$q->td({class=>'number'},$job_threads),
+ $q->td({class=>'number'},size($job_memory*1000**2)),
+ $q->td({class=>'number'},days($job_time*60)),
$q->td($q->a({href=>my_url('groups',{user_name=>$user_name})},$user_name)),
- $q->td($group_mtime),
$q->td(group_status($group_status)),
$q->td({class=>'number'},$group_jobs),
- $q->td({class=>'number'},$group_jobs_inq),
- $q->td({class=>'number'},$group_jobs_running),
- $q->td({class=>'number'},$group_jobs_finished),
- $q->td({class=>'number'},$group_jobs_failed),
- $q->td({class=>'number'},$group_jobs_cancelled),
- $q->td({class=>'number'},$group_jobs_unknown)
+ $q->td({class=>'number'},colorize("blue",$group_jobs_inq)),
+ $q->td({class=>'number'},colorize("orange",$group_jobs_running)),
+ $q->td({class=>'number'},colorize("green",$group_jobs_finished)),
+ $q->td({class=>'number'},colorize("red",$group_jobs_failed)),
+ $q->td({class=>'number'},colorize("red",$group_jobs_cancelled)),
+ $q->td({class=>'number'},colorize("red",$group_jobs_unknown))
);
}
$out.='
';
- $out .= 'Finished Groups (last 7 days) ';
+ $out .= "Finished Groups (last $days days) ";
@cols=qw(
- group_id group_name job_threads user_name
- group_date_end
+ group_id group_name job_threads
+ job_memory
+ stats_max_sumrss
+ job_time
+ stats_run_sec
+ stats_idle_sec
+ user_name
group_status
group_jobs
group_jobs_finished group_jobs_failed group_jobs_cancelled group_jobs_unknown
);
@head=qw(
- group_id group_name threads user_name
- date_end
- group_status
+ group id
+ group name
+ req. threads
+ req. memory
+ used memory
+ req. runtime
+ used runtime
+ user name
+ group status
jobs
- finished failed cancelled unknown
+ fin
+ fail
+ canc
+ unkn
);
- $sth=$dbh->prepare('SELECT '.join(',',@cols).' FROM mxq_group WHERE '.$sql_clause.' AND (group_jobs_running=0 AND group_jobs_inq=0) AND group_mtime >= DATE_SUB(NOW(),INTERVAL 7 DAY) ORDER BY group_id DESC');
- $sth->execute(@$sql_binds);
+ $sth=$dbh->prepare('SELECT '.join(',',@cols).' FROM mxq_group WHERE '.$sql_clause.' AND (group_jobs_running=0 AND group_jobs_inq=0) AND group_mtime >= DATE_SUB(NOW(),INTERVAL ? DAY) ORDER BY group_id DESC');
+ $sth->execute(@$sql_binds,$days);
$out.='';
$out.=$q->Tr($q->th(\@head));
while (my $row=$sth->fetchrow_arrayref()) {
- my ($group_id,$group_name,$job_threads,$user_name,$group_date_end,$group_status,
+ my ($group_id,$group_name,$job_threads,
+ $job_memory,
+ $stats_max_sumrss,
+ $job_time,
+ $stats_run_sec,
+ $stats_idle_sec,
+ $user_name,$group_status,
$group_jobs,$group_jobs_finished,$group_jobs_failed,$group_jobs_cancelled,$group_jobs_unknown
)=@$row;
@@ -503,14 +701,17 @@ sub group_table {
$q->td({class=>'number'},$q->a({href=>selfurl("/group/$group_id")},$group_id)),
$q->td($group_name),
$q->td({class=>'number'},$job_threads),
+ $q->td({class=>'number'},size($job_memory*1000**2)),
+ $q->td({class=>'number'},size($stats_max_sumrss*1000)),
+ $q->td({class=>'number'},humanSeconds($job_time*60)),
+ $q->td({class=>'number'},humanSeconds($stats_run_sec+$stats_idle_sec,2)),
$q->td($q->a({href=>my_url('groups',{user_name=>$user_name})},$user_name)),
- $q->td($group_date_end),
$q->td(group_status($group_status)),
$q->td({class=>'number'},$group_jobs),
- $q->td({class=>'number'},$group_jobs_finished),
- $q->td({class=>'number'},$group_jobs_failed),
- $q->td({class=>'number'},$group_jobs_cancelled),
- $q->td({class=>'number'},$group_jobs_unknown)
+ $q->td({class=>'number'},colorize("green",$group_jobs_finished)),
+ $q->td({class=>'number'},colorize("red",$group_jobs_failed)),
+ $q->td({class=>'number'},colorize("red",$group_jobs_cancelled)),
+ $q->td({class=>'number'},colorize("red",$group_jobs_unknown))
);
}
$out.='
';
@@ -522,16 +723,24 @@ sub groups {
my @sql_clauses;
my @sql_binds;
+ my $user_name_info='';
if ($q->param('user_name')) {
push @sql_clauses,'user_name = ?';
push @sql_binds,$q->param('user_name');
+ $user_name_info=' submitted by '. $q->param('user_name');
+ }
+ my $days = 7;
+ if ($q->param('days')) {
+ if ( $q->param('days') =~ /^\d+$/ ) {
+ $days = $q->param('days');
+ }
}
- my $out=h1('MXQ Groups');
+ my $out=h1("MXQ Groups$user_name_info");
$dbh or db_init();
- $out.=group_table(join('AND',@sql_clauses),\@sql_binds);
+ $out.=group_table(join('AND',@sql_clauses),\@sql_binds,$days);
return $out;
}
@@ -543,6 +752,8 @@ sub active_jobs() {
sub server() {
$dbh or db_init();
+ $hostconfig or hostconfig_init();
+ my $dead_hosts = $hostconfig;
my $out=h1('MXQ Servers');
my @cols=qw(
@@ -569,9 +780,9 @@ sub server() {
# 'boot_id',
# 'pid_starttime',
'pid',
- 'slots available',
- 'memory available',
- 'max runtime (minutes)',
+ 'slots',
+ 'memory',
+ 'time min',
# 'time',
'slotmem_soft available',
# 'slotmem_hard',
@@ -584,7 +795,7 @@ sub server() {
# 'stop',
]));
-
+ my %S;
while (my $row=$sth->fetchrow_arrayref()) {
my (
$daemon_id,$daemon_name,$status,$hostname,$mxq_version,$boot_id,$pid_starttime,
@@ -596,6 +807,14 @@ sub server() {
) = @$row;
$hostname =~s/\.molgen\.mpg\.de$//;
+ $S{daemon_slots} += $daemon_slots;
+ $S{daemon_slots_dist}->{$daemon_slots}++;
+ $S{daemon_slots_running} += $daemon_slots_running;
+ $S{daemon_memory_sum} += $daemon_memory;
+ $S{daemon_memory_used_sum} += $daemon_memory_used;
+ $S{servers}++;
+
+ delete($dead_hosts->{$hostname});
$out.=$q->Tr(
$q->td({class=>'number'},$daemon_id),
@@ -605,21 +824,32 @@ sub server() {
$q->td($mxq_version),
# $q->td($boot_id),
# $q->td($pid_starttime),
- $q->td($daemon_pid),
+ $q->td({class=>'number'},$daemon_pid),
$q->td({class=>'number'},$daemon_slots),
- $q->td({class=>'number'},$daemon_memory),
- $q->td({class=>'number'},$daemon_maxtime),
- $q->td({class=>'number'},$daemon_memory_limit_slot_soft),
+ $q->td({class=>'number'},size($daemon_memory*1000000)),
+ $q->td({class=>'number'},$daemon_maxtime ? $daemon_maxtime : ''),
+ $q->td({class=>'number'},size($daemon_memory_limit_slot_soft*1000000)),
# $q->td({class=>'number'},$daemon_memory_limit_slot_hard),
$q->td({class=>'number'},$daemon_jobs_running),
$q->td({class=>'number'},$daemon_slots_running),
$q->td({class=>'number'},$daemon_threads_running),
- $q->td({class=>'number'},$daemon_memory_used),
+ $q->td({class=>'number'},size($daemon_memory_used*1000000)),
# $q->td($mtime),
# $q->td($daemon_start),
# $q->td($daemon_stop),
);
}
+ map {
+ $out.=$q->Tr( $q->td(0),$q->td('-'),$q->td('no mxqd'),$q->td($_),$q->td(' '),$q->td(' '),$q->td(' '),$q->td(' '),$q->td(' '),$q->td(' '),$q->td(' '),$q->td(' '),$q->td(' '),$q->td(' '),);
+ } keys %{$dead_hosts};
+
+ $out.=$q->Tr($q->td({colspan=>14},' '));
+ my $dist = join(', ',map {"$S{daemon_slots_dist}->{$_}x$_"} sort {$b <=> $a} keys %{$S{daemon_slots_dist}});
+ $out.=$q->Tr(
+ $q->td({class=>'center', colspan=>3},$S{servers}.' servers'),$q->td($dist),
+ $q->td({class=>'center', colspan=>3},$S{daemon_slots}.' cores'),$q->td({class=>'number'},size($S{daemon_memory_sum}*1000**2)),$q->td(' '),$q->td(' '),$q->td(' '),
+ $q->td({class=>'number'},$S{daemon_slots_running}),$q->td(' '),$q->td({class=>'number'},size($S{daemon_memory_used_sum}*1000**2)),);
+
$out.='';
return $out;
}
@@ -629,12 +859,12 @@ sub selfurl {
return $q->url().$path_info;
}
-sub top {
- return $q->ul(
- $q->li(a({href=>selfurl('/groups')},'groups')),
- $q->li(a({href=>selfurl('/active_jobs')},'active_jobs')),
- $q->li(a({href=>selfurl('/server')},'server')),
- );
+sub top_menu {
+ return '';
}
$q=new CGI;
@@ -649,17 +879,19 @@ my $path_info=$q->path_info()||'';
$path_info=~s/\/$//;
if ($path_info eq '') {
- print header().HEAD().top();
+ print header().HEAD().top_menu().groups();
} elsif ($path_info eq '/server') {
- print header().HEAD().server();
+ print header().HEAD().top_menu().server();
} elsif ($path_info eq '/groups') {
- print header().HEAD().groups();
+ print header().HEAD().top_menu().groups();
} elsif ($path_info eq '/active_jobs') {
- print header().HEAD().active_jobs();
+ print header().HEAD().top_menu().active_jobs();
} elsif ($path_info =~ /\/group\/(\d+)$/) {
- print header().HEAD().group($1);
+ print header().HEAD().top_menu().group($1);
+} elsif ($path_info =~ /\/group\/(\d+)\/(\d+)$/) {
+ print header().HEAD().top_menu().group($1,$2);
} elsif ($path_info =~ /\/job\/(\d+)$/) {
- print header().HEAD().job($1);
+ print header().HEAD().top_menu().job($1);
} else {
- print header(-status => 404).HEAD().'not found ';
+ print header(-status => 404).HEAD().top_menu().'not found ';
}