Commit 45f997fd authored by Kevin Atkinson's avatar Kevin Atkinson

Updates to to Error Logging API Code.

You should start seeing much better error messages coming from my
system.  Errors coming from parse.proxy and assign (the two most
frequent sources of errors) should now be concise and to the point.
Errors coming from libosload/libreboot (the next most frequent source
of errors) should now also be much better, but not perfect.  Getting
perfect errors will likely a rework of how errors are handled in
libosload/libreboot, just adding tberror/tbwarn/tbnotice calls is not
enough.  I can do this at a latter date if necessary.

A few minor database changes.

Some changes to the API.  A few bug fixes. Lots of tberror/tbwarn/tbnotice
added to scripts.

Since assign is a C program, and at this time my API is perl only, I wrote a
second wrapper around assign, assign_wrapper2.  When assign fails errors are
now parsed in assign_wrapper2, sent to stderr and logged.  This means that
RunAssign() just returns when assign fails rather than echoing some of
assign.log output and then quiting.  The output to the activity log remains
unchanged.

Since "parse.proxy" is run from ops I couldn't use my API in it, even though
it is a perl program.  Instead I parse the errors coming form it in
parse-ns.
parent 95ec7066
...@@ -2265,6 +2265,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ ...@@ -2265,6 +2265,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/tbprerun tbsetup/tbswap tbsetup/tbend tbsetup/tbrestart \ tbsetup/tbprerun tbsetup/tbswap tbsetup/tbend tbsetup/tbrestart \
tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \ tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \ tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \
tbsetup/assign_wrapper2 \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \ tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs tbsetup/setgroups tbsetup/websetgroups \ tbsetup/savelogs tbsetup/setgroups tbsetup/websetgroups \
tbsetup/savelogs.proxy \ tbsetup/savelogs.proxy \
......
...@@ -703,6 +703,7 @@ outfiles="$outfiles Makeconf GNUmakefile \ ...@@ -703,6 +703,7 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/tbprerun tbsetup/tbswap tbsetup/tbend tbsetup/tbrestart \ tbsetup/tbprerun tbsetup/tbswap tbsetup/tbend tbsetup/tbrestart \
tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \ tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \ tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \
tbsetup/assign_wrapper2 \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \ tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs tbsetup/setgroups tbsetup/websetgroups \ tbsetup/savelogs tbsetup/setgroups tbsetup/websetgroups \
tbsetup/savelogs.proxy \ tbsetup/savelogs.proxy \
......
...@@ -922,11 +922,12 @@ CREATE TABLE log ( ...@@ -922,11 +922,12 @@ CREATE TABLE log (
invocation int(10) unsigned NOT NULL default '0', invocation int(10) unsigned NOT NULL default '0',
parent int(10) unsigned NOT NULL default '0', parent int(10) unsigned NOT NULL default '0',
script smallint(3) NOT NULL default '0', script smallint(3) NOT NULL default '0',
level smallint(2) NOT NULL default '0', level tinyint(2) NOT NULL default '0',
sublevel tinyint(2) NOT NULL default '0',
priority smallint(3) NOT NULL default '0', priority smallint(3) NOT NULL default '0',
inferred tinyint(1) NOT NULL default '0', inferred tinyint(1) NOT NULL default '0',
cause varchar(32) NOT NULL default '', cause varchar(32) NOT NULL default '',
type enum('normal','entering','exiting','thecause') NOT NULL default 'normal', type enum('normal','entering','exiting','thecause','extra','summary') NOT NULL default 'normal',
relevant tinyint(1) NOT NULL default '0', relevant tinyint(1) NOT NULL default '0',
mesg text NOT NULL, mesg text NOT NULL,
PRIMARY KEY (seq), PRIMARY KEY (seq),
...@@ -1625,9 +1626,9 @@ CREATE TABLE portmap ( ...@@ -1625,9 +1626,9 @@ CREATE TABLE portmap (
CREATE TABLE priorities ( CREATE TABLE priorities (
priority smallint(3) NOT NULL default '0', priority smallint(3) NOT NULL default '0',
name varchar(8) NOT NULL default '', priority_name varchar(8) NOT NULL default '',
PRIMARY KEY (priority), PRIMARY KEY (priority),
UNIQUE KEY name (name) UNIQUE KEY name (priority_name)
) TYPE=MyISAM; ) TYPE=MyISAM;
-- --
...@@ -1758,9 +1759,9 @@ CREATE TABLE scheduled_reloads ( ...@@ -1758,9 +1759,9 @@ CREATE TABLE scheduled_reloads (
CREATE TABLE scripts ( CREATE TABLE scripts (
script smallint(3) NOT NULL auto_increment, script smallint(3) NOT NULL auto_increment,
name varchar(24) NOT NULL default '', script_name varchar(24) NOT NULL default '',
PRIMARY KEY (script), PRIMARY KEY (script),
UNIQUE KEY id (name) UNIQUE KEY id (script_name)
) TYPE=MyISAM; ) TYPE=MyISAM;
-- --
......
...@@ -2867,7 +2867,7 @@ last_net_act,last_cpu_act,last_ext_act); ...@@ -2867,7 +2867,7 @@ last_net_act,last_cpu_act,last_ext_act);
4.16: Add new tables for the logging subsystem (libdblog) 4.16: Add new tables for the logging subsystem (libdblog)
mysql tbdb < libtblog.sql mysql tbdb < libtblog-orig.sql
4.17: Add linktest feature. 4.17: Add linktest feature.
...@@ -3021,3 +3021,16 @@ last_net_act,last_cpu_act,last_ext_act); ...@@ -3021,3 +3021,16 @@ last_net_act,last_cpu_act,last_ext_act);
notes text, notes text,
PRIMARY KEY (uid_idx) PRIMARY KEY (uid_idx)
) TYPE=MyISAM; ) TYPE=MyISAM;
4.25: Modify tables for the logging subsystem
alter table log
modify level tinyint(2) not null,
add sublevel tinyint(2) NOT NULL default 0 after level,
modify type
enum('normal','entering','exiting','thecause','extra','summary')
NOT NULL default 'normal';
alter table scripts change name script_name varchar(24) NOT NULL default '';
alter table priorities change name priority_name varchar(8) NOT NULL;
-- MYSQL TABLES used for logging subsystem
CREATE TABLE log (
seq int unsigned NOT NULL auto_increment,
stamp int unsigned NOT NULL,
pidx int NOT NULL, -- unique project id
uid int default NULL, -- numeric user id
session int unsigned NOT NULL, -- session id (1)
invocation int unsigned NOT NULL, -- invocation id - unique id for a
-- particular execution of a script (1)
parent int unsigned NOT NULL, -- invocation id of the parent script
script smallint(3) NOT NULL, -- numeric id for the script name
level smallint(2) NOT NULL , -- depth of the script in the call chain
priority smallint(3) NOT NULL, -- syslog priority
inferred tinyint(1) NOT NULL, -- 0 - log created with tblog
-- 1 - log created by catching a die or warn
-- 2 - log created with a normal print and
-- given the non-default priority
-- 3 - log created with a normal print and
-- given the default priority
cause varchar(32) NOT NULL, -- string identifying the "cause" of the error
type enum('normal','entering','exiting','thecause')
NOT NULL default 'normal',-- type of error:
-- normal: normal error generated by tblog
-- entering: auto gen when a script starts
-- exiting: auto gen when a script exists (2)
-- thecause: created by tblog_find_error
relevant tinyint(1) NOT NULL, -- if the error was considered relevent
-- by tblog_find_error
mesg text NOT NULL, -- the text of the message
PRIMARY KEY (seq),
KEY (session)
);
-- (1) These ids are equal to the sequence number of the "entering" log
-- message
-- (2) Due to a number of factors every "exiting" message in not
-- garanteed to have a 1-1 relation with the "entering" message.
-- The two major ones are
-- (1) A Fork not followed by a "exec" will most likely to cause
-- multiple exiting messages. (2) If "exec" is used the script
-- will not have an exiting message.
-- NOTE: It may be beneficial to split this table into three:
-- session pidx uid
-- invocation session parent script level
-- seq stamp [session] invocation priority inferred cause type relevant mesg
-- ...
CREATE TABLE scripts (
script smallint(3) NOT NULL auto_increment,
name varchar(24) NOT NULL default '',
PRIMARY KEY (script),
UNIQUE KEY id (name)
);
CREATE TABLE priorities (
priority smallint(3) NOT NULL,
name varchar(8) NOT NULL,
primary key (priority),
unique key (name)
);
insert into priorities values (000, 'EMERG');
insert into priorities values (100, 'ALERT');
insert into priorities values (200, 'CRIT');
insert into priorities values (300, 'ERR');
insert into priorities values (400, 'WARNING');
insert into priorities values (500, 'NOTICE');
insert into priorities values (600, 'INFO');
insert into priorities values (700, 'DEBUG');
insert into exported_tables values ('state_timeouts');
...@@ -10,7 +10,8 @@ CREATE TABLE log ( ...@@ -10,7 +10,8 @@ CREATE TABLE log (
-- particular execution of a script (1) -- particular execution of a script (1)
parent int unsigned NOT NULL, -- invocation id of the parent script parent int unsigned NOT NULL, -- invocation id of the parent script
script smallint(3) NOT NULL, -- numeric id for the script name script smallint(3) NOT NULL, -- numeric id for the script name
level smallint(2) NOT NULL , -- depth of the script in the call chain level tinyint(2) NOT NULL , -- depth of the script in the call chain
sublevel tinyint(2) NOT NULL, -- sub level
priority smallint(3) NOT NULL, -- syslog priority priority smallint(3) NOT NULL, -- syslog priority
inferred tinyint(1) NOT NULL, -- 0 - log created with tblog inferred tinyint(1) NOT NULL, -- 0 - log created with tblog
-- 1 - log created by catching a die or warn -- 1 - log created by catching a die or warn
...@@ -19,12 +20,16 @@ CREATE TABLE log ( ...@@ -19,12 +20,16 @@ CREATE TABLE log (
-- 3 - log created with a normal print and -- 3 - log created with a normal print and
-- given the default priority -- given the default priority
cause varchar(32) NOT NULL, -- string identifying the "cause" of the error cause varchar(32) NOT NULL, -- string identifying the "cause" of the error
type enum('normal','entering','exiting','thecause') type enum('normal','entering','exiting','thecause','extra','summary')
NOT NULL default 'normal',-- type of error: NOT NULL default 'normal',-- type of error:
-- normal: normal error generated by tblog -- normal: normal error generated by tblog
-- entering: auto gen when a script starts -- entering: auto gen when a script starts
-- exiting: auto gen when a script exists (2) -- exiting: auto gen when a script exists (2)
-- thecause: created by tblog_find_error -- thecause: created by tblog_find_error
-- extra: extra information to normal info
-- at a lower level
-- summary: useful summary of errors,
-- ignore all info at lower levels
relevant tinyint(1) NOT NULL, -- if the error was considered relevent relevant tinyint(1) NOT NULL, -- if the error was considered relevent
-- by tblog_find_error -- by tblog_find_error
mesg text NOT NULL, -- the text of the message mesg text NOT NULL, -- the text of the message
...@@ -49,14 +54,14 @@ CREATE TABLE log ( ...@@ -49,14 +54,14 @@ CREATE TABLE log (
CREATE TABLE scripts ( CREATE TABLE scripts (
script smallint(3) NOT NULL auto_increment, script smallint(3) NOT NULL auto_increment,
name varchar(24) NOT NULL default '', script_name varchar(24) NOT NULL default '',
PRIMARY KEY (script), PRIMARY KEY (script),
UNIQUE KEY id (name) UNIQUE KEY id (name)
); );
CREATE TABLE priorities ( CREATE TABLE priorities (
priority smallint(3) NOT NULL, priority smallint(3) NOT NULL,
name varchar(8) NOT NULL, priority_name varchar(8) NOT NULL,
primary key (priority), primary key (priority),
unique key (name) unique key (name)
); );
......
...@@ -40,7 +40,8 @@ FSBIN_STUFF = exports_setup.proxy ...@@ -40,7 +40,8 @@ FSBIN_STUFF = exports_setup.proxy
LIBEXEC_STUFF = rmproj wanlinksolve wanlinkinfo \ LIBEXEC_STUFF = rmproj wanlinksolve wanlinkinfo \
os_setup mkexpdir console_setup webnscheck webreport \ os_setup mkexpdir console_setup webnscheck webreport \
webendexp webbatchexp webpanic \ webendexp webbatchexp webpanic \
assign_wrapper assign_prepass ptopgen webnodeupdate \ assign_wrapper assign_wrapper2 \
assign_prepass ptopgen webnodeupdate \
webdelay_config webnodehistory \ webdelay_config webnodehistory \
webrmgroup webswapexp webnodecontrol webeventsys_control \ webrmgroup webswapexp webnodecontrol webeventsys_control \
webmkgroup websetgroups webmkproj webmodgroups \ webmkgroup websetgroups webmkproj webmodgroups \
......
...@@ -113,6 +113,7 @@ use libtestbed; ...@@ -113,6 +113,7 @@ use libtestbed;
use Node; use Node;
use libadminctrl; use libadminctrl;
use libtblog; use libtblog;
use libtblog qw(*SOUT *SERR);
# #
# assign_wrapper Settings # assign_wrapper Settings
...@@ -186,11 +187,9 @@ TBDebugTimeStampsOn(); ...@@ -186,11 +187,9 @@ TBDebugTimeStampsOn();
# #
# All exits happen via this function! # All exits happen via this function!
# #
sub fatal ($) sub fatal (@)
{ {
my($message) = @_; &tberror(@_);
tberror $message;
# We next go to the END block below. # We next go to the END block below.
exit($WRAPPER_FAILED); exit($WRAPPER_FAILED);
...@@ -200,7 +199,7 @@ sub fatal ($) ...@@ -200,7 +199,7 @@ sub fatal ($)
# We want warnings to cause assign_wrapper to exit abnormally. # We want warnings to cause assign_wrapper to exit abnormally.
# We will come through here no matter how we exit though. # We will come through here no matter how we exit though.
# #
$SIG{__WARN__} = sub { print STDERR $_[0];$warnings++; }; $SIG{__WARN__} = sub { tbwarn $_[0];$warnings++; };
END { END {
# Watch for getting here cause of a die()/exit() statement someplace. # Watch for getting here cause of a die()/exit() statement someplace.
...@@ -211,7 +210,7 @@ END { ...@@ -211,7 +210,7 @@ END {
} }
if ($warnings > 0) { if ($warnings > 0) {
tbwarn "$warnings.\n"; tberror "$warnings warnings.\n";
$exitcode |= $WRAPPER_FAILED; $exitcode |= $WRAPPER_FAILED;
} }
...@@ -750,7 +749,7 @@ while (1) { ...@@ -750,7 +749,7 @@ while (1) {
$precheck = 1; $precheck = 1;
my $retval = RunAssign(); my $retval = RunAssign();
if ($retval != 0) { if ($retval != 0) {
fatal("Experiment can not be run on an empty testbed. Please fix the experiment."); fatal({type=>'extra'}, "Experiment can not be run on an empty testbed. Please fix the experiment.");
} }
print("Assign succeeded on an empty testbed.\n"); print("Assign succeeded on an empty testbed.\n");
$precheck = 0; $precheck = 0;
...@@ -887,20 +886,20 @@ sub RunAssign () ...@@ -887,20 +886,20 @@ sub RunAssign ()
# the parent. # the parent.
# #
POSIX::setsid(); POSIX::setsid();
exec("nice $cmd $cmdargs > assign.log"); exec("nice assign_wrapper2 $cmd $cmdargs > assign.log");
die "Could not start assign!\n"; die "Could not start assign!\n";
} }
# Check cancel flag before continuing. # Check cancel flag before continuing.
TBGetCancelFlag($pid, $eid, \$canceled); TBGetCancelFlag($pid, $eid, \$canceled);
if ($canceled) { if ($canceled) {
print("Cancel flag set; aborting assign run!\n"); tbnotice("Cancel flag set; aborting assign run!\n");
return -1; return -1;
} }
# Check for possible full filesystem ... # Check for possible full filesystem ...
if (-z "assign.log") { if (-z "assign.log") {
print("assign.log is zero length! Stopping ...\n"); tbnotice("assign.log is zero length! Stopping ...\n");
return -1; return -1;
} }
...@@ -916,37 +915,12 @@ sub RunAssign () ...@@ -916,37 +915,12 @@ sub RunAssign ()
printdb "Reading assign results.\n"; printdb "Reading assign results.\n";
# #
# We no longer care what assign has to say when it fails! Just # We no longer care what assign has to say when it fails!
# tell the caller whether we want to keep trying or not. We still # Any relevent info was already sent to stderr so just
# send some of the goo to the output stream so that Rob can quickly # tell the caller whether we want to keep trying or not.
# deduce what what wrong.
# #
if ($assignexitcode) { if ($assignexitcode) {
my $violations = 0; close ASSIGNFP;
print "ASSIGN FAILED:\n";
while (<ASSIGNFP> !~ /^[\w\s]*precheck:$/) {}
while (<ASSIGNFP>) {
chop;
/^\w*\s*precheck:$/ && do {
next;
};
/^With ([0-9]+) violations$/ && do {
$violations = $1;
last;
};
print $_ . "\n";
}
if ($violations) {
while (<ASSIGNFP> !~ /^Violations:/) {}
while (<ASSIGNFP>) {
if (/^Nodes:/) {
last;
}
print "$_";
}
}
close(ASSIGNFP);
return (($assignexitcode == 1) ? 1 : -1); return (($assignexitcode == 1) ? 1 : -1);
} }
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
#
# Hack to get assign error messages into the database correctly. Will
# be removed once the API is ported to other languages besides perl
#
BEGIN {$FAKE_SCRIPTNAME = $ARGV[0];}
use lib "@prefix@/lib";
use libtblog;
use libtblog qw(dblog *SOUT *SERR);
use strict;
open P, join(' ', @ARGV, ' |');
my @out;
my @err;
my $obvious_error = 0;
while (<P>) {
print SOUT $_;
push @out, $_;
}
close P;
my $exitcode = $? >> 8;
#
# Now parse out relevent info and echo it to stderr. Also, pull out
# any obvious errors (prefixed with ***) and log them sepertly. The
# rest will go in te database as one big error.
#
if ($exitcode) {
my $violations = 0;
# Pull out relevent info
print SERR "ASSIGN FAILED:\n";
while ((shift @out) !~ /^[\w\s]*precheck:$/) {}
while (($_ = shift @out)) {
/^[\w\s]*precheck:$/ && do {
next;
};
/^With ([0-9]+) violations$/ && do {
$violations = $1;
last;
};
print SERR $_;
push @err, $_;
}
if ($violations) {
while ((shift @out) !~ /^Violations:/) {}
while (($_ = shift @out)) {
if (/^Nodes:/) {
last;
}
print SERR $_;
push @err, $_;
}
}
# See if there are any obvious errors
my $err = '';
while (($_ = shift @err)) {
$err .= $_;
if (/^(\s*)\*\*\*+\s*(.+)/) {
$obvious_error = 1;
my $space = $1;
my $mesg = $2;
while (@err && $err[0] =~ /^$space \s*(.+)/) {
$mesg .= "\n$1";
shift @err;
}
my $sublevel = length($space) > 0 ? 1 : 0;
if ($mesg =~ s/^warning:\s+//i) {
dblog(TBLOG_WARNING, {sublevel=>$sublevel}, $mesg);
} else {
dblog(TBLOG_ERR, {sublevel=>$sublevel}, $mesg);
}
}
}
# log all relevent output as one entry unless an obvious_error was
# already found
dblog(TBLOG_ERR, {}, $err) unless ($obvious_error);
# create a log entry that assign failed
my %parms;
$parms{sublevel} = -1;
$parms{type} = 'extra' unless $obvious_error;
dblog(TBLOG_ERR, \%parms, "Assign Failed.");
}
exit $exitcode;
...@@ -146,16 +146,14 @@ my $committed = 0; ...@@ -146,16 +146,14 @@ my $committed = 0;
# Verify user and get his DB uid. # Verify user and get his DB uid.
# #
if (! UNIX2DBUID($UID, \$dbuid)) { if (! UNIX2DBUID($UID, \$dbuid)) {
die("*** $0:\n". tbdie("You do not exist in the Emulab Database!");
" You do not exist in the Emulab Database!\n");
} }
# #
# Get email info for user. # Get email info for user.
# #
if (! UserDBInfo($dbuid, \$user_name, \$user_email)) { if (! UserDBInfo($dbuid, \$user_name, \$user_email)) {
die("*** $0:\n". tbdie("Cannot determine your name and email address.");
" Cannot determine your name and email address.\n");
} }
# #
...@@ -163,9 +161,7 @@ if (! UserDBInfo($dbuid, \$user_name, \$user_email)) { ...@@ -163,9 +161,7 @@ if (! UserDBInfo($dbuid, \$user_name, \$user_email)) {
# our time. Make sure user sees the error by exiting with 1. # our time. Make sure user sees the error by exiting with 1.
# #
if (system("$checkquota $dbuid") != 0) { if (system("$checkquota $dbuid") != 0) {
print STDERR tberror("You are over your disk quota on $CONTROL; please cleanup!");
"*** $0:\n".
" You are over your disk quota on $CONTROL; please cleanup!\n";
exit(1); exit(1);
} }
...@@ -187,14 +183,13 @@ if (!defined($description)) { ...@@ -187,14 +183,13 @@ if (!defined($description)) {
$description = "'Created by $dbuid'"; $description = "'Created by $dbuid'";
} }
if (! $swappable && (!defined($noswap_reason) || $noswap_reason eq "")) { if (! $swappable && (!defined($noswap_reason) || $noswap_reason eq "")) {
die("Must provide a reason with -S option (not swappable reason)!\n"); tbdie("Must provide a reason with -S option (not swappable reason)!");
} }
if (! $idleswap && (!defined($noidleswap_reason) || $noidleswap_reason eq "")) { if (! $idleswap && (!defined($noidleswap_reason) || $noidleswap_reason eq "")) {
die("Must provide a reason with -L option (no idleswap reason)!\n"); tbdie("Must provide a reason with -L option (no idleswap reason)!");
} }
if (!defined($tempnsfile) && !TBAdmin($dbuid)) { if (!defined($tempnsfile) && !TBAdmin($dbuid)) {
die("*** $0:\n". tbdie("Only admins can create experiments with no NS file");
" Only admins can create experiments with no NS file\n");
} }
my $nsfile = "$eid.ns"; my $nsfile = "$eid.ns";
my $repfile = "$eid.report"; my $repfile = "$eid.report";
...@@ -209,8 +204,7 @@ $noidleswap_reason = "'None Given'" ...@@ -209,8 +204,7 @@ $noidleswap_reason = "'None Given'"
# Make sure UID is allowed to create experiments in this project. # Make sure UID is allowed to create experiments in this project.
# #
if (! TBProjAccessCheck($dbuid, $pid, $gid, TB_PROJECT_CREATEEXPT)) { if (! TBProjAccessCheck($dbuid, $pid, $gid, TB_PROJECT_CREATEEXPT)) {
die("*** $0:\n". die("You do not have permission to create experiments in $pid/$gid");
" You do not have permission to create experiments in $pid/$gid\n");
} }
# #
...@@ -223,8 +217,7 @@ if (!defined($tempnsfile)) { ...@@ -223,8 +217,7 @@ if (!defined($tempnsfile)) {
} }
elsif (! -f $tempnsfile || ! -r $tempnsfile || -z $tempnsfile) { elsif (! -f $tempnsfile || ! -r $tempnsfile || -z $tempnsfile) {
# Exit so that user sees the error, not us. # Exit so that user sees the error, not us.
print STDERR "*** $0:\n". tberror("$tempnsfile does not exist or is not a readable file!");
" $tempnsfile does not exist or is not a readable file!\n";
exit(1); exit(1);
} }
...@@ -270,8 +263,7 @@ $query_result = ...@@ -270,8 +263,7 @@ $query_result =
if ($query_result->numrows) { if ($query_result->numrows) {
DBQueryWarn("unlock tables"); DBQueryWarn("unlock tables");
die("*** $0:\n". tbdie("Experiment $eid in project $pid already exists!");
" Experiment $eid in project $pid already exists!\n");
} }
# #
...@@ -298,8 +290,7 @@ foreach my $table ("experiments", "experiment_stats", "experiment_resources", ...@@ -298,8 +290,7 @@ foreach my $table ("experiments", "experiment_stats", "experiment_resources",