blob: 3274d72c3306644621efcde81e6ebc3d540fc9eb [file] [log] [blame]
#*******************************************************************************
#* Copyright (c) 2011 Forschungszentrum Juelich GmbH.
#* All rights reserved. This program and the accompanying materials
#* are made available under the terms of the Eclipse Public License v1.0
#* which accompanies this distribution, and is available at
#* http://www.eclipse.org/legal/epl-v10.html
#*
#* Contributors:
#* Wolfgang Frings (Forschungszentrum Juelich GmbH)
#*******************************************************************************/
package LML_gen_nodedisplay;
my $VERSION='1.0';
my($debug)=0;
use strict;
use Data::Dumper;
use Time::Local;
use Time::HiRes qw ( time );
use String::Scanf;
use LML_ndtree;
use LML_gen_nodedisplay_insert_job;
sub new {
my $self = {};
my $proto = shift;
my $class = ref($proto) || $proto;
my $verbose = shift;
my $timings = shift;
printf("\t LML_gen_nodedisplay: new %s\n",ref($proto)) if($debug>=3);
$self->{VERBOSE} = $verbose;
$self->{TIMINGS} = $timings;
$self->{LMLFH} = undef;
$self->{LAYOUT} = undef;
$self->{NODEMAPPING} = undef;
$self->{NODENAMENAMASK}= "n%06d";
$self->{IDLISTREF} = undef;
bless $self, $class;
return $self;
}
sub get_ids {
my($self) = shift;
return($self->{IDLISTREF});
}
sub process {
my($self) = shift;
my $layoutref = shift;
my $filehandler_LML = shift;
my ($numids,$gid,$idlistref);
my ($schemeroot,$dataroot);
$numids=0;
$self->{LAYOUT} = $layoutref;
$self->{LMLFH} = $filehandler_LML;
$gid = $layoutref->{gid};
# internal structure
$self->{SCHEMEROOT} = $schemeroot = LML_ndtree->new();
$self->{DATAROOT} = $dataroot = LML_ndtree->new();
# determine scheme of system
$self->{SYSTEMTYPE}=$self->_get_system_type();
if($self->{SYSTEMTYPE} eq "BG/P") {
my($maxlx,$maxly,$maxlz,$maxpx,$maxpy,$maxpz)=$self->_get_system_size_bg();
if(!$self->_init_trees_bg($maxlx,$maxly,$maxlz,$maxpx,$maxpy,$maxpz)) {
print "ERROR: could not init internal data structures, system type: $self->{SYSTEMTYPE}, aborting ...\n";
return(-1);
}
} elsif($self->{SYSTEMTYPE} eq "Cluster") {
# standard one-level tree, mapping of node names
$self->_get_system_size_cluster();
if(!$self->_init_trees_cluster()) {
print "ERROR: could not init internal data structures, system type: $self->{SYSTEMTYPE}, aborting ...\n";
return(-1);
}
} else {
print "ERROR: not supported system type: $self->{SYSTEMTYPE}, aborting ...\n";
return(-1);
}
# add regular expression to each level of node display scheme for fast pattern scann of nodenames
$self->_add_regexp_to_scheme();
$idlistref=[];
print "LML_gen_nodedisplay::process: gid=$gid\n" if($self->{VERBOSE});
$idlistref=$self->_insert_run_jobs();
$self->{IDLISTREF}=$idlistref;
$numids=scalar @{$idlistref};
return($numids);
}
sub _insert_run_jobs {
my($self) = shift;
my (@idlist,$key,$ref,$inforef,$nodelist);
keys(%{$self->{LMLFH}->{DATA}->{OBJECT}}); # reset iterator
while(($key,$ref)=each(%{$self->{LMLFH}->{DATA}->{OBJECT}})) {
next if($ref->{type} ne 'job');
$inforef=$self->{LMLFH}->{DATA}->{INFODATA}->{$key};
next if($inforef->{state} ne 'Running');
$nodelist=$self->_remap_nodes($inforef->{nodelist});
$self->insert_job_into_nodedisplay($self->{SCHEMEROOT},$self->{DATAROOT},$nodelist,$key);
push(@idlist,$key);
# last; # WF
}
return(\@idlist);
}
sub get_lml_nodedisplay {
my($self) = shift;
my($ds,$rc,$id,$cid);
my $layoutref = $self->{LAYOUT};
my(@keylist,$key,$value);
$ds->{id}=$layoutref->{gid};
$ds->{title}=$layoutref->{id};
$ds->{schemeroot}=$self->{SCHEMEROOT};
$ds->{dataroot}=$self->{DATAROOT};
return($ds);
}
sub get_lml_nodedisplaylayout {
my($self) = shift;
my($ds,$rc,$id,$cid);
my $layoutref = $self->{LAYOUT};
return($layoutref);
}
sub _get_system_type {
my($self) = shift;
my $system_type = "unknown";
my($key,$ref);
keys(%{$self->{LMLFH}->{DATA}->{OBJECT}}); # reset iterator
while(($key,$ref)=each(%{$self->{LMLFH}->{DATA}->{OBJECT}})) {
if($ref->{type} eq 'system') {
$ref=$self->{LMLFH}->{DATA}->{INFODATA}->{$key};
if($ref->{type}) {
$system_type=$ref->{type};
printf("_get_system_type: type is '%s'\n",$system_type) if($self->{VERBOSE});
}
last;
}
}
return($system_type);
}
sub _add_regexp_to_scheme {
my($self) = shift;
my $schemeref=$self->{SCHEMEROOT};
my($id,@numbers,$format,$regexp, $child);
$regexp="";
foreach $child (@{$schemeref->{_childs}}) {
$self->__add_regexp_to_scheme($child,$regexp);
}
return(1);
}
sub __add_regexp_to_scheme {
my($self) = shift;
my($schemeref)=shift;
my($regexp)=shift;
my($rg,$child);
if(exists($schemeref->{ATTR}->{mask})) {
$rg=String::Scanf::format_to_re($schemeref->{ATTR}->{mask});
} else {
$rg="";
}
$schemeref->{ATTR}->{_maskreg}=$rg;
$regexp.=$rg;
$schemeref->{ATTR}->{_maskregall}=$regexp;
foreach $child (@{$schemeref->{_childs}}) {
$self->__add_regexp_to_scheme($child,$regexp);
}
return(1);
}
sub _remap_nodes {
my($self) = shift;
my($nodelist)=shift;
my($newnodelist,$spec,$node,$num,$newnode);
if($self->{NODEMAPPING}) {
foreach $spec (split(/\),?\(/,$nodelist)) {
if($spec=~/\(?([^,]+),(\d+)\)?/) {
$node=$1;$num=$2;
if(exists($self->{NODEMAPPING}->{$node})) {
$newnode=$self->{NODEMAPPING}->{$node};
$newnodelist.="," if($newnodelist);
$newnodelist.=sprintf("%s-c%02d",$newnode,$num);
} else {
print "ERROR: _remap_nodes: unknown node '$node', skipping a\n";
}
}
if($spec=~/^([^,]+)$/) {
$node=$1;
if(exists($self->{NODEMAPPING}->{$node})) {
$newnode=$self->{NODEMAPPING}->{$node};
$newnodelist.="," if($newnodelist);
$newnodelist.=sprintf("%s-c%02d",$newnode,0);
} else {
print "ERROR: _remap_nodes: unknown node '$node', skipping\n";
}
}
}
return($newnodelist);
} else {
return($nodelist);
}
}
###############################################
# Cluster related
###############################################
sub _get_system_size_cluster {
my($self) = shift;
my($indataref) = $self->{INDATA};
my($numnodes);
my ($key,$ref,$name,$ncores);
keys(%{$self->{LMLFH}->{DATA}->{OBJECT}}); # reset iterator
while(($key,$ref)=each(%{$self->{LMLFH}->{DATA}->{OBJECT}})) {
next if($ref->{type} ne 'node');
$name=$ref->{name};
$ncores=$self->{LMLFH}->{DATA}->{INFODATA}->{$key}->{ncores};
if(!defined($ncores)) {
print "_get_system_size_cluster: suspect node: $name , assuming 0 cores\n" if($self->{VERBOSE});
$ncores=0;
}
push(@{$self->{NODESIZES}->{$ncores}},$name);
}
$numnodes=0;
foreach $ncores (sort {$a <=> $b} keys %{$self->{NODESIZES}}) {
foreach $name (@{$self->{NODESIZES}->{$ncores}}) {
# register new node
if(!exists($self->{NODEMAPPING}->{$name})) {
$self->{NODEMAPPING}->{$name}=sprintf($self->{NODENAMENAMASK},$numnodes);
# print "_get_system_size_cluster: remap '$name' -> '$self->{NODEMAPPING}->{$name}'\n";
$numnodes++;
} else {
print "ERROR: _get_system_size_cluster: duplicate node '$name' -> '$self->{NODEMAPPING}->{$name}'\n";
}
}
printf("_get_system_size_cluster: found %4d nodes of size: %d\n", scalar @{$self->{NODESIZES}->{$ncores}},$ncores)
if($self->{VERBOSE});
}
printf("_get_system_size_cluster: Cluster found of size: %d\n",$numnodes) if($self->{VERBOSE});
return();
}
sub _init_trees_cluster {
my($self) = shift;
my($id,$subid,$treenode,$schemeroot,$ncores,$numnodes,$start);
$schemeroot=$self->{SCHEMEROOT};
$start=0;
foreach $ncores (sort {$a <=> $b} keys %{$self->{NODESIZES}}) {
$numnodes=scalar @{$self->{NODESIZES}->{$ncores}};
$treenode=$schemeroot;
$treenode=$treenode->new_child();
$treenode->add_attr({ tagname => 'node',
min => $start,
max => $start+$numnodes-1,
mask => $self->{NODENAMENAMASK} });
$treenode=$treenode->new_child();
$treenode->add_attr({ tagname => 'core',
min => 0,
max => $ncores,
mask => '-c%02d' });
# insert first element in data section
$treenode=$self->{DATAROOT};
$treenode=$treenode->new_child();
$treenode->add_attr({ min => $start,
max => $start+$numnodes-1,
oid => 'empty' });
$start+=$numnodes;
}
return(1);
}
###############################################
# BG/P related
###############################################
sub _get_system_size_bg {
my($self) = shift;
my($indataref) = $self->{INDATA};
my($partref,$part,$lx,$ly,$lz,$px,$py,$pz);
my($maxlx,$maxly,$maxlz,$maxpx,$maxpy,$maxpz);
my ($key,$ref);
$maxlx=$maxly=$maxlz=0;
$maxpx=$maxpy=$maxpz=0;
keys(%{$self->{LMLFH}->{DATA}->{OBJECT}}); # reset iterator
while(($key,$ref)=each(%{$self->{LMLFH}->{DATA}->{OBJECT}})) {
next if($ref->{type} ne 'partition');
next if($ref->{id}!~/^bgbp/s);
$partref=$self->{LMLFH}->{DATA}->{INFODATA}->{$key};
$part=$partref->{bgp_partitionid};
$px=$partref->{x_loc};
$py=$partref->{y_loc};
$pz=$partref->{z_loc};
$maxpx=$px if($px>$maxpx);
$maxpy=$py if($py>$maxpy);
$maxpz=$pz if($pz>$maxpz);
# currently not supported for BG/P
# data could only get from LL over LL C-API
$lx=$ly=$lz=0;
$maxlx=$lx if($lx>$maxlx);
$maxly=$ly if($ly>$maxly);
$maxlz=$lz if($lz>$maxlz);
}
printf("_get_system_size_bg: Blue Gene System found of size: %dx%dx%d (logical: %dx%dx%d)\n",
$maxpx+1,$maxpy+1,$maxpz+1,
$maxlx+1,$maxly+1,$maxlz+1,
) if($self->{VERBOSE});
return($maxlx,$maxly,$maxlz,$maxpx,$maxpy,$maxpz);
}
sub _init_trees_bg {
my($self) = shift;
my($maxlx,$maxly,$maxlz,$maxpx,$maxpy,$maxpz)=@_;
my($id,$subid,$treenode,$schemeroot,$bgsystem);
$schemeroot=$self->{SCHEMEROOT};
$treenode=$schemeroot;
$bgsystem=$treenode=$treenode->new_child();
$treenode->add_attr({ tagname => 'row',
min => 0,
max => $maxpx,
mask => 'R%01d' });
$treenode=$treenode->new_child();
$treenode->add_attr({ tagname => 'rack',
min => 0,
max => $maxpy,
mask => '%01d' });
$treenode=$treenode->new_child();
$treenode->add_attr({ tagname => 'midplane',
min => 0,
max => $maxpz,
mask => '-M%01d' });
$treenode=$treenode->new_child();
$treenode->add_attr({ tagname => 'nodecard',
min => 0,
max => 15,
mask => '-N%02d' });
$treenode=$treenode->new_child();
$treenode->add_attr({ tagname => 'computecard',
min => 4,
max => 35,
mask => '-C%02d' });
$treenode=$treenode->new_child();
$treenode->add_attr({ tagname => 'core',
min => 0,
max => 3,
mask => '-%01d' });
# insert first element in data section
$treenode=$self->{DATAROOT};
$treenode=$treenode->new_child();
$treenode->add_attr({ min => $bgsystem->{ATTR}->{min},
max => $bgsystem->{ATTR}->{max},
oid => 'empty' });
return(1);
}
1;