5 use Parallel
::MPI
::Simple
;
11 'logfile' => '/dev/null',
12 'afsconfig' => '-cachedir cache.afsload.$RANK',
18 print STDERR
"Usage: $0 <testconfig.conf>\n";
21 my $conf_file = $ARGV[0];
23 my $rank = MPI_Comm_rank
(MPI_COMM_WORLD
);
24 my $size = MPI_Comm_size
(MPI_COMM_WORLD
);
27 die("We only have $size processes; we must have at least 2 for a\n".
28 "director and at least one client node\n");
31 # $rank-1, because the 'director' has rank 0, and node rank 1 is specified as
32 # "node 0" in the configuration file.
33 AFS
::Load
::Config
::load_conf
($rank-1, $conf_file, \
@steps, \
%nodeconf)
34 or die("Error parsing configuration file\n");
36 if (scalar @steps < 1) {
37 die("No steps defined in the test config; nothing to run?\n");
44 Test
::More
::plan
('tests', scalar @steps);
48 open STDOUT
, '>>', $nodeconf{'logfile'}
49 or die("Error opening logfile ".$nodeconf{'logfile'}." for stdout\n");
50 open STDERR
, '>>', $nodeconf{'logfile'}
51 or die("Error opening logfile ".$nodeconf{'logfile'}." for stderr\n");
53 print "======= Starting node ".($rank-1)." at ".scalar(localtime())."\n\n";
57 AFS
::ukernel
::uafs_Setup
("/afs") and die("uafs_Setup: $!\n");
58 AFS
::ukernel
::uafs_ParseArgs
($nodeconf{'afsconfig'}) and die("uafs_ParseArgs: $!\n");
59 AFS
::ukernel
::uafs_Run
() and die("uafs_Run: $!\n");
62 # one-index the steps, since Test::More test numbers start at 1
65 for my $step (@steps) {
70 my $name = shift @acts;
72 $name = "Step $nStep: $name";
74 $name = "Step $nStep";
78 # rank 0 is the director; for all other nodes, run the actual
79 # actions we're supposed to do
80 for my $actref (@acts) {
83 my $actstr = "unknown";
85 eval { $actstr = $act->str(); };
87 eval { @stat = $act->do(); };
91 push(@res, [-1, $nAct, $actstr, -1, "Internal error: $@"]);
93 push(@res, [int($!), $nAct, $actstr, @stat]);
98 MPI_Barrier
(MPI_COMM_WORLD
);
99 # collect results from all nodes for this step
100 @allres = MPI_Gather
(\
@res, 0, MPI_COMM_WORLD
);
106 # first array element will be for rank 0, which is the director, which
107 # will never have useful information
110 foreach my $resref (@allres) {
113 if (scalar @res == 0) {
122 diag
("node $i failed: ");
124 foreach my $failref (@res) {
125 my @fail = @
$failref;
126 diag
("\tOn action $fail[1]: $fail[2]");
127 diag
("\t\terrno: $fail[0]");
128 diag
("\t\terror code: $fail[3]");
129 if (length $fail[4] > 0) {
130 diag
("\t\terror string: $fail[4]");
141 MPI_Barrier
(MPI_COMM_WORLD
);
146 AFS
::ukernel
::uafs_Shutdown
();