File indexing completed on 2024-04-06 12:31:48
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 BEGIN {
0015 if (! exists($ENV{PERL5LIB})) {
0016
0017 use Config; $PERLVERSION=$Config{version};
0018
0019 $LIBPATH = "/afs/cern.ch/cms/sw/slc4_ia32_gcc345/external/p5-template-toolkit/2.14/lib/site_perl/5.8.5/i386-linux-thread-multi";
0020 if ($PERLVERSION eq '5.8.0') {
0021 $LIBPATH = "/afs/cern.ch/cms/sw/slc3_ia32_gcc323/external/p5-template-toolkit/2.14/lib/site_perl/5.8.0/i386-linux-thread-multi";
0022 }
0023
0024 if ($Config{archname} =~ /64/) {
0025 $LIBPATH="/afs/cern.ch/cms/sw/slc4_amd64_gcc345/external/p5-template-toolkit/2.14/lib/site_perl/5.8.5/x86_64-linux-thread-multi";
0026 }
0027 }
0028 }
0029
0030 use Cwd;
0031 use File::Find;
0032
0033
0034 use lib $LIBPATH;
0035
0036 use Getopt::Long ();
0037 use Storable;
0038 use Time::localtime;
0039
0040 my $buildsummary={};
0041 my ($mainlogfile,$logfile,$workdir,$cmsrelease,$projectversion,$templatedir,$outputdir);
0042 my %opts;
0043 my %options =
0044 ("mainlog=s" => sub { $mainlogfile = $_[1] },
0045 "workdir=s" => sub { $workdir = $_[1] },
0046 "release=s" => sub { $projectversion = $_[1] },
0047 "templatedir=s" => sub { $templatedir = $_[1] },
0048 "outputdir=s" => sub { $outputdir = $_[1] },
0049 "debug" => sub { $debug = 1 },
0050 "help" => sub { &usage(); exit(0) } );
0051
0052 my $data={};
0053 my $dataobjs={};
0054
0055 my $pkglist=[];
0056 my $currentpackage;
0057 my $lastpkglog;
0058 my $packagedata={};
0059
0060 my $tmstruct = localtime;
0061 my $daynumber = $tmstruct->wday;
0062
0063 my $mailalertdir;
0064 my $missingpackage="";
0065 my $problem_bfs={};
0066 my $scram_warnings=0;
0067
0068 my $package_version;
0069
0070
0071 Getopt::Long::config ;
0072
0073 if (! Getopt::Long::GetOptions(\%opts, %options)) {
0074 &usage(); exit(1);
0075 } else {
0076
0077 die "ERROR: You must give a project release version (e.g. --release=CMSSW_xyz).\n", unless ($projectversion);
0078
0079 die "ERROR: You must give a working directory which points to the project log files (--workdir=/a/dir/path/tmp/<ARCH>)\n", unless ($workdir && -d $workdir);
0080 die "ERROR: You must give an output directory where package information can be written (--outputdir=/a/dir/path/XXXX).\n", unless ($outputdir);
0081 system("mkdir","-p",$outputdir), unless (-d $outputdir);
0082 $templatedir||=$ENV{LOGFILEPARSER_TEMPLATE_DIR};
0083 die "ERROR: Unable to find the templates for the log results (use --templatedir=/path/2/templates).\n", unless ($templatedir && -d $templatedir);
0084
0085
0086 $debug||=0;
0087 $mainlogfile||="";
0088
0089
0090 $mailalertdir=$ENV{MAILALERT_DIR}||$outputdir."/nightly-alerts";
0091 system("mkdir","-p",$mailalertdir), unless (-d $mailalertdir);
0092
0093
0094 $buildsummary->{CMSSW_RELEASE}="CMSSW_".$daynumber;
0095 $buildsummary->{CMSSW_VERSION}=$projectversion;
0096 $buildsummary->{CMSSW_BUILD_ARCH}=$ENV{SCRAM_ARCH} || 'slc3_ia32_gcc323';
0097 $buildsummary->{CMSSW_BUILD_HOST}=`hostname`;
0098 $buildsummary->{DAY_INDEX}=$daynumber;
0099
0100
0101
0102 $buildsummary->{N_COMPILATION_ERRORS} = 0;
0103 $buildsummary->{N_LINK_ERRORS} = 0;
0104 $buildsummary->{N_OTHER_ERRORS} = 0;
0105 $buildsummary->{TOTAL_FAILED_PACKAGES} = 0;
0106
0107
0108 my $datestring;
0109 chomp($datestring=`date +'%F'`);
0110 $buildsummary->{CMSSW_DATESTRING}=$datestring;
0111
0112 my $packagelistfromTC = &getpklistfromtc();
0113
0114
0115
0116
0117
0118 $responsibles={};
0119 my $cachefilename = "./peoplecache.db";
0120
0121 if (-f $cachefilename) {
0122
0123 print "logfile_parser: Retrieving info on developers/admins cached in $cachefilename.\n";
0124 $responsibles = retrieve($cachefilename);
0125 } else {
0126
0127 use vars ;
0128
0129 *name = *File::Find::name;
0130 *dir = *File::Find::dir;
0131 *prune = *File::Find::prune;
0132
0133 $|=1;
0134 print "logfile_parser: Traversing source tree under ".$workdir."/../../src\n";
0135
0136 File::Find::find({wanted => \&collect}, $workdir."/../../src");
0137
0138 store($responsibles,$cachefilename);
0139 print "logfile_parser: Info on developers/admins cached in $cachefilename.\n";
0140 print "logfile_parser: Collected package admin/developer info.","\n";
0141 }
0142
0143
0144 foreach my $p (sort keys %$packagelistfromTC) {
0145 chomp($p);
0146 $package_version = $packagelistfromTC->{$p};
0147
0148
0149
0150 $logfile=$workdir."/cache/log/src/$p/build.log";
0151 if (-f $logfile && -s $logfile) {
0152 open(PLOG,"< $logfile") || die "$0: Unable to read package logfile $logfile!: $!","\n";
0153 while(<PLOG>) {
0154 chomp;
0155 push(@$pkglist,$p);
0156 $currentpackage = $p;
0157 my $concatpackname = $p; $concatpackname =~ s/\///g;
0158
0159
0160
0161
0162
0163
0164 if (! exists($dataobjs->{$currentpackage})) {
0165 $dataobjs->{$currentpackage} = new PackageResults($currentpackage,$package_version,$responsibles->{$currentpackage});
0166 }
0167
0168
0169
0170 if ($_ =~ ) {
0171 $buildsummary->{N_LINK_ERRORS}++;
0172 $dataobjs->{$currentpackage}->log($_);
0173 $dataobjs->{$currentpackage}->status(2);
0174 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS (missing library \"".$1."\")");
0175
0176
0177 } elsif ($_ =~ ) {
0178 $buildsummary->{N_LINK_ERRORS}++;
0179 $dataobjs->{$currentpackage}->log($_);
0180 $dataobjs->{$currentpackage}->status(2);
0181 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS for package library");
0182 } elsif ($_ =~ ) {
0183 $buildsummary->{N_COMPILATION_ERRORS}++;
0184 $dataobjs->{$currentpackage}->log($_);
0185 $dataobjs->{$currentpackage}->status(1);
0186 $dataobjs->{$currentpackage}->error(1,"COMPILATION ERRORS for package");
0187 } elsif ($_ =~ ) {
0188 $buildsummary->{N_COMPILATION_ERRORS}++;
0189 $dataobjs->{$currentpackage}->log($_);
0190 $dataobjs->{$currentpackage}->status(1);
0191 $dataobjs->{$currentpackage}->error(1,"COMPILATION ERRORS for executable $1 in bin");
0192 } elsif ($_ =~ ) {
0193 $buildsummary->{N_LINK_ERRORS}++;
0194 $dataobjs->{$currentpackage}->log($_);
0195 $dataobjs->{$currentpackage}->status(2);
0196 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS for executable $1 in bin");
0197 } elsif ($_ =~ ) {
0198 $buildsummary->{N_LINK_ERRORS}++;
0199 $dataobjs->{$currentpackage}->log($_);
0200 $dataobjs->{$currentpackage}->status(2);
0201 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS for shared library $1 in bin");
0202 } elsif ($_ =~ ) {
0203 $buildsummary->{N_LINK_ERRORS}++;
0204 $dataobjs->{$currentpackage}->log($_);
0205 $dataobjs->{$currentpackage}->status(2);
0206 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS for shared library $1 in test/stubs");
0207 } elsif ($_ =~ ) {
0208 $buildsummary->{N_LINK_ERRORS}++;
0209 $dataobjs->{$currentpackage}->log($_);
0210 $dataobjs->{$currentpackage}->status(2);
0211 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS for shared library $1 in test");
0212 } elsif ($_ =~ ) {
0213 $buildsummary->{N_COMPILATION_ERRORS}++;
0214 $dataobjs->{$currentpackage}->log($_);
0215 $dataobjs->{$currentpackage}->status(1);
0216 $dataobjs->{$currentpackage}->error(1,"COMPILATION ERRORS for library in test/stubs");
0217 } elsif ($_ =~ ) {
0218 $buildsummary->{N_COMPILATION_ERRORS}++;
0219 $dataobjs->{$currentpackage}->log($_);
0220 $dataobjs->{$currentpackage}->status(1);
0221 $dataobjs->{$currentpackage}->error(1,"COMPILATION ERRORS for executable $1 in test");
0222 } elsif ($_ =~ ) {
0223 $buildsummary->{N_LINK_ERRORS}++;
0224 $dataobjs->{$currentpackage}->log($_);
0225 $dataobjs->{$currentpackage}->status(2);
0226 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS for shared library $1 in test");
0227 } elsif ($_ =~ ) {
0228 $buildsummary->{N_COMPILATION_ERRORS}++;
0229 $dataobjs->{$currentpackage}->log($_);
0230 $dataobjs->{$currentpackage}->status(1);
0231 $dataobjs->{$currentpackage}->error(1,"COMPILATION ERRORS for executable $1 in test");
0232 } elsif ($_ =~ ) {
0233 $buildsummary->{N_LINK_ERRORS}++;
0234 $dataobjs->{$currentpackage}->log($_);
0235 $dataobjs->{$currentpackage}->status(2);
0236 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS for executable $1 in test");
0237 } elsif ($_ =~ ) {
0238 $buildsummary->{N_OTHER_ERRORS}++;
0239 $dataobjs->{$currentpackage}->log($_);
0240 $dataobjs->{$currentpackage}->status(3);
0241 $dataobjs->{$currentpackage}->error(3,"DICTIONARY GEN ERRORS in package");
0242 } elsif ($_ =~ ) {
0243 $buildsummary->{N_COMPILATION_ERRORS}++;
0244 $dataobjs->{$currentpackage}->log($_);
0245 $dataobjs->{$currentpackage}->status(1);
0246 $dataobjs->{$currentpackage}->error(1,"COMPILATION ERRORS for SEAL PLUGIN $1 in plugins");
0247 } elsif ($_ =~ ) {
0248 $buildsummary->{N_LINK_ERRORS}++;
0249 $dataobjs->{$currentpackage}->log($_);
0250 $dataobjs->{$currentpackage}->status(2);
0251 $dataobjs->{$currentpackage}->error(2,"LINK ERRORS for SEAL PLUGIN library $1 in plugins");
0252 } elsif ($_ =~ ) {
0253 $buildsummary->{N_OTHER_ERRORS}++;
0254 $dataobjs->{$currentpackage}->log($_);
0255 $dataobjs->{$currentpackage}->status(3);
0256 $dataobjs->{$currentpackage}->error(3,"DATA FILE COPY ERROR for file in data/download.url in test");
0257 } elsif ($_ =~ ) {
0258
0259
0260 print STDERR "logfile_parser.pl: No regexps matched the line \"".$_."\"\n";
0261 } else {
0262
0263 $dataobjs->{$currentpackage}->log($_);
0264 }
0265 }
0266
0267 $buildsummary->{TOTAL_FAILED_PACKAGES}++, if ($dataobjs->{$currentpackage}->status() != 0);
0268 close(PLOG);
0269 } else {
0270 print STDERR "WARNING: Missing log file (or file is zero-length) for $p\n";
0271 }
0272 }
0273
0274
0275 if (-f $mainlogfile) {
0276
0277 open(BUILDLOG,"< $mainlogfile") || die "$0: Unable to read main logfile $mainlogfile!: $!","\n";
0278
0279 my $mainobj=new PackageResults('MAIN',$projectversion);
0280 my $cycles=0;
0281
0282 while(<BUILDLOG>) {
0283 chomp;
0284
0285
0286 if ($_ =~ ) {
0287 $cycles=1;
0288 $mainobj->status(4);
0289 $mainobj->error(4,"$1 <--> $2");
0290 } else {
0291
0292
0293 if ($_ =~ ) {
0294 $scram_warnings=1;
0295 $missingpackage=$1;
0296 }
0297
0298 if ($_ =~ && $missingpackage ne "") {
0299 if (exists($problem_bfs->{$1})) {
0300 push(@{$problem_bfs->{$1}},$missingpackage);
0301 }
0302 else {
0303 $problem_bfs->{$1} = [ $missingpackage ];
0304 }
0305 $missingpackage="";
0306 }
0307 }
0308 }
0309
0310 close(BUILDLOG);
0311
0312 if ($cycles) {
0313 $dataobjs->{'MAIN'} = $mainobj;
0314 }
0315
0316
0317 my $scramlog=$outputdir."/scram_warnings.log";
0318 open(SCRAM_WARNINGS,"> $scramlog") || die "Unable to open $scramlog for writing:$!\n";;
0319
0320 if ($scram_warnings) {
0321
0322 my ($pk, $dep);
0323 print SCRAM_WARNINGS "\n\n";
0324 while (($pk, $dep)= each %{$problem_bfs}) {
0325 print SCRAM_WARNINGS "\n-> Location $pk has incorrect dependencies (to be removed from $pk/BuildFile): \n\t",join(" ",@$dep),"\n";
0326 print SCRAM_WARNINGS "\n";
0327 }
0328 }
0329 else {
0330 print SCRAM_WARNINGS "\n No SCRAM BuildFile warnings for this build: congratulations!","\n";
0331 }
0332
0333 close(SCRAM_WARNINGS);
0334 } else {
0335 print "logfile_parser: No main log given. Skipping scanning for SCRAM messages.\n";
0336 }
0337
0338
0339 foreach my $p (sort keys %$dataobjs) {
0340
0341 my $pdata = $dataobjs->{$p};
0342
0343
0344 if ($p eq 'MAIN') {
0345
0346 if ($pdata->status() == 4) {
0347
0348 last;
0349 }
0350 } else {
0351 my $packagehtmllogfile = $pdata->subsystem()."_".$pdata->packname().".log.html";
0352
0353 if ($pdata->status()) {
0354 print "Package $p had errors.","\n", if ($debug);
0355
0356 &write_alert_mail($pdata, $templatedir);
0357 }
0358
0359
0360 &log2html($pdata, $packagehtmllogfile, $templatedir, $outputdir);
0361 }
0362 }
0363
0364
0365 $buildsummary->{summarydata} = $dataobjs;
0366
0367 &dumpmainpage($buildsummary, $templatedir, $outputdir);
0368
0369 my $npackages=scalar(keys %$responsibles);
0370 print "logfile_parser: Looked at ",$npackages," packages.","\n";
0371 print "\n";
0372 }
0373
0374
0375 sub dumpmainpage() {
0376 my ($builddata,$templatedir,$outputdir)=@_;
0377 my $summaryfiletmpl="buildsummary.html.tmpl";
0378
0379 use Template;
0380
0381
0382 my $template_config = {
0383 INCLUDE_PATH => $templatedir,
0384 EVAL_PERL => 1
0385 };
0386
0387
0388 my $template_engine = Template->new($template_config) || die $Template::ERROR, "\n";
0389 $template_engine->process($summaryfiletmpl, $builddata, $outputdir."/index.html")
0390 || die "Template error: ".$template_engine->error;
0391 }
0392
0393 sub log2html() {
0394 my ($pdata,$packagehtmllogfile,$templatedir,$outputdir)=@_;
0395 my $packagehtmllogtmpl="package.log.html.tmpl";
0396 my $tdata = { package_data => $pdata };
0397
0398 use Template;
0399
0400
0401 my $template_config = {
0402 INCLUDE_PATH => $templatedir,
0403 EVAL_PERL => 1
0404 };
0405
0406
0407 my $template_engine = Template->new($template_config) || die $Template::ERROR, "\n";
0408 $template_engine->process($packagehtmllogtmpl, $tdata, $outputdir."/".$packagehtmllogfile)
0409 || die "Template error: ".$template_engine->error;
0410 }
0411
0412 sub write_alert_mail() {
0413 my ($pdata, $templatedir)=@_;
0414
0415
0416 my $tdata = {
0417 CMSSW_RELEASE => $projectversion,
0418 PACKAGE_OBJ => $pdata
0419 };
0420
0421 use Template;
0422
0423
0424 my $template_config = {
0425 INCLUDE_PATH => $templatedir,
0426 EVAL_PERL => 1
0427 };
0428
0429
0430 foreach my $admin (split(" ",$pdata->responsibles("administrators"))) {
0431
0432
0433 $tdata->{THIS_ADMIN} = $admin;
0434
0435
0436 srand();
0437 $fileid=int(rand 99999999)+1;
0438 print "logfile_parser: Preparing mail alert (fileid=",$fileid,") for package ".$pdata->fullname(),"\n";
0439 my $mailfile = $mailalertdir."/".$fileid.".mail";
0440 my $template_engine = Template->new($template_config) || die $Template::ERROR, "\n";
0441 $template_engine->process("alert_mail_stub.tmpl", $tdata, $mailfile)
0442 || die "Template error: ".$template_engine->error;
0443 }
0444 }
0445
0446 sub collect() {
0447 my $persontype;
0448 my $persondata={ 'administrators' => [], 'developers' => []};
0449
0450 if (my ($packagename) = ($name =~ )) {
0451 open(DEVELOPERS, "$name") || die "$name: $!","\n";
0452 while(<DEVELOPERS>) {
0453 chomp;
0454
0455 next if ($_ =~ /^\
0456
0457 if ($_ =~ ) {
0458 $persontype=lc($1);
0459 }
0460
0461 if ($_ =~ ) {
0462 my $address="$1\@$2";
0463
0464
0465 if (! grep($address eq $_, @{$persondata->{$persontype}})) {
0466 push(@{$persondata->{$persontype}},$address);
0467 }
0468 }
0469 }
0470
0471
0472 close(DEVELOPERS);
0473
0474
0475 $responsibles->{$packagename}->{'all'}="";
0476 foreach my $pertype ('administrators', 'developers') {
0477
0478 $responsibles->{$packagename}->{'all'}.=" ".join(" ",@{$persondata->{$pertype}});
0479 $responsibles->{$packagename}->{$pertype}=join(" ",@{$persondata->{$pertype}});
0480 }
0481 }
0482 }
0483
0484 sub getpklistfromtc() {
0485
0486
0487
0488
0489
0490 my $wgetver = (`wget --version` =~ /^GNU Wget 1\.1.*?/);
0491 my $options = ""; $options = "--no-check-certificate", if ($wgetver == 1);
0492 my $gotpacks=0;
0493
0494 open(CMSTCQUERY,"wget $options -nv -o /dev/null -O- 'https://cmstags.cern.ch/tc/public/CreateTagList?release=$projectversion' |");
0495
0496 my %tags;
0497 while ( <CMSTCQUERY> ) {
0498 if ( $_ =~ /td/) {
0499 my @sp1=split(' ',$_,99);
0500 my $pack=$sp1[2];
0501 my $tag=$sp1[5];
0502 $tags{$pack}=$tag;
0503 $gotpacks++;
0504 }
0505 }
0506
0507 close CMSTCQUERY;
0508
0509 die "$0: No packages found in release $projectversion. Perhaps $projectversion doesn't exist?\n" if ($gotpacks == 0);
0510 return \%tags;
0511 }
0512
0513 sub usage() {
0514 my $hstring="Usage:\n\n$0 [-h] [-d] --release=<version> --workdir=<workingdir> --outputdir=<dir> [-t <DIR>]\n";
0515 $hstring.="\n";
0516 $hstring.="--mainlog | -m Location of main logfile, if you want to see SCRAM messages. Optional.\n";
0517 $hstring.="--workdir | -w The project working directory where the log files can be found.\n";
0518 $hstring.="--release | -r The project release version (e.g. CMSSW_xxxx-xx-xx).\n";
0519 $hstring.="--outputdir | -o DIR Where to write the HTML log files and summary page.\n";
0520 $hstring.="--templatedir | -t DIR Set location where templates reside if LOGFILEPARSER_TEMPLATE_DIR not set.\n";
0521 $hstring.="\n";
0522 $hstring.="--debug | -d Debug mode ON (off by default).\n";
0523 $hstring.="--help | -h Show usage information.\n";
0524 $hstring.="\n";
0525 print $hstring,"\n";
0526 }
0527
0528 package PackageResults;
0529
0530 sub new() {
0531 my $proto=shift;
0532 my $class=ref($proto) || $proto;
0533 my $self={};
0534 bless($self,$class);
0535 my ($fullname, $version,$responsibles)=@_;
0536 $self->{FULLNAME} = $fullname;
0537 $self->{VERSION} = $version;
0538 $self->{RESPONSIBLES} = $responsibles || {};
0539 $self->{LOG} = [];
0540 $self->{STATUS} = 0;
0541
0542 my ($subsystem,$packname)=split("/",$fullname);
0543 $self->{SUBSYSTEM} = $subsystem;
0544 $self->{PACKNAME} = $packname;
0545
0546 return $self;
0547 }
0548
0549 sub fullname() {
0550 my $self=shift;
0551 @_ ? $self->{FULLNAME} = shift
0552 : $self->{FULLNAME};
0553 }
0554
0555 sub packname() {
0556 my $self=shift;
0557 @_ ? $self->{PACKNAME} = shift
0558 : $self->{PACKNAME};
0559 }
0560
0561 sub subsystem() {
0562 my $self=shift;
0563 @_ ? $self->{SUBSYSTEM} = shift
0564 : $self->{SUBSYSTEM};
0565 }
0566
0567 sub version() {
0568 my $self=shift;
0569 @_ ? $self->{VERSION} = shift
0570 : $self->{VERSION};
0571 }
0572
0573 sub status() {
0574 my $self=shift;
0575 my ($status)=shift;
0576
0577
0578
0579
0580 if ($status) {
0581 if ($self->{STATUS} == 0 && $status >= 2) {
0582 $self->{STATUS} = $status;
0583 } elsif ($self->{STATUS} > 0) {
0584 } else {
0585 $self->{STATUS} = 1;
0586 }
0587 } else {
0588 return $self->{STATUS};
0589 }
0590 }
0591
0592 sub log() {
0593 my $self=shift;
0594 if (@_) {
0595 push(@{$self->{LOG}},$_[0]);
0596 } else {
0597 return join("\n",@{$self->{LOG}});
0598 }
0599 }
0600
0601 sub responsibles() {
0602 my $self=shift;
0603 my ($type)=@_;
0604 if (exists($self->{RESPONSIBLES}->{$type})) {
0605 return $self->{RESPONSIBLES}->{$type};
0606 } else {
0607 return "";
0608 }
0609 }
0610
0611 sub error() {
0612 my $self=shift;
0613 my ($type,$msg)=@_;
0614
0615 if (exists($self->{ERRORS}->{$type})) {
0616 if (exists($self->{ERRORS}->{$type}->{$msg})) {
0617 $self->{ERRORS}->{$type}->{$msg}++;
0618 } else {
0619 $self->{ERRORS}->{$type}->{$msg} = 1;
0620 }
0621 } else {
0622 $self->{ERRORS}->{$type}->{$msg} = 1;
0623 }
0624
0625 }
0626
0627 sub nErrorsByType() {
0628 my $self=shift;
0629 my ($type)=@_;
0630 my $n_errors=0;
0631
0632 if (exists($self->{ERRORS}->{$type})) {
0633 foreach my $err (keys %{$self->{ERRORS}->{$type}}) {
0634 $n_errors += $self->{ERRORS}->{$type}->{$err};
0635 }
0636 }
0637 return $n_errors;
0638 }
0639
0640 sub package_errors() {
0641 my $self=shift;
0642 my ($stat)=@_;
0643
0644 if ($stat) {
0645 if (exists($self->{ERRORS}->{$stat})) {
0646 return $self->{ERRORS}->{$stat};
0647 }
0648 } else {
0649 return $self->{ERRORS};
0650 }
0651 }