Subversion Repositories DevTools

Rev

Rev 5233 | Rev 5252 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5209 dpurdie 1
########################################################################
2
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
3
#
4
# Module name   : jats_lxr.pl
5
# Module type   : JATS Utility
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
5213 dpurdie 9
# Description   : Tools to maintain LXR information
5209 dpurdie 10
#
5213 dpurdie 11
# Possible imporvements
12
#       Delete files we don't want to index
13
#           .DMP,.dmp,.so,.gz,.zip,.lib,.bz,.bz2,.tbz,.jar,.deb,.exe,.a,.msb
14
#
15
#       Merge ripples package versions
16
#           Just keep one
5233 dpurdie 17
#           At the moment, simply ignore ripples in release comparisons.
5213 dpurdie 18
#
19
#       Cots packages
20
#           Use contents from dpkg_archive instead of the package
21
#
5231 dpurdie 22
#       Better Version-Aging algorithm
23
#           Currently keep the last 5
24
#           Perhaps keep one from a month ago and one from 6 months ago.
25
#
26
#       Indication back into ReleaseManager of Releases that are present
27
#
5209 dpurdie 28
# Usage         : See POD at the end of this file
29
#
30
#......................................................................#
31
 
32
require 5.008_002;
33
use strict;
34
use warnings;
35
 
36
use Pod::Usage;
37
use Getopt::Long;
38
use File::Path;
39
use FindBin;
40
use Socket;
5213 dpurdie 41
use Fcntl ':flock';
5209 dpurdie 42
 
43
use JatsError;
44
use JatsRmApi;
45
use DBI;
46
use JatsSystem;
47
use FileUtils;
48
 
49
#
50
#   Config Options
51
#
52
my $VERSION = "1.0.0";                      # Update this
53
my $opt_help = 0;
54
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
55
my $opt_createVersions = 1;
56
my $opt_index = 1;
57
my $opt_purge = 1;
58
my $opt_extract = 1;
59
my $opt_logfile = 1;
5231 dpurdie 60
my $opt_forceViews;
5211 dpurdie 61
my $opt_config;
5209 dpurdie 62
 
63
 
64
#
65
#   Globals
66
#
67
my $scriptDir;
68
my $RM_DB;
5213 dpurdie 69
my $Config;
5209 dpurdie 70
my @addressList;
71
my %ReleaseData;
72
my %Packages;
73
my $PackageStore;
74
my $ReleaseStore;
5213 dpurdie 75
my $StampTime = time;
76
my $lockFile = '/tmp/JATSLXR_LOCK';
5209 dpurdie 77
 
78
#-------------------------------------------------------------------------------
79
# Function        : Main
80
#
81
# Description     : Main entry point
82
#                   Parse user options
83
#
84
# Inputs          :
85
#
86
# Returns         :
87
#
88
 
89
my $result = GetOptions (
90
                "help:+"            => \$opt_help,              # flag, multiple use allowed
91
                "manual:3"          => \$opt_help,              # flag, multiple use allowed
92
                "verbose:+"         => \$opt_verbose,           # flag
93
                "createVersions!"   => \$opt_createVersions,
94
                "purge!"            => \$opt_purge,
95
                "index!"            => \$opt_index,
96
                "extract!"          => \$opt_extract,
5211 dpurdie 97
                "logfile!"          => \$opt_logfile,
98
                "config:s"          => \$opt_config,
5231 dpurdie 99
                "forceViews!"       => \$opt_forceViews,
5209 dpurdie 100
                );
101
 
102
#
103
#   Process help and manual options
104
#
105
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
106
pod2usage(-verbose => 1)  if ($opt_help == 2 );
107
pod2usage(-verbose => 2)  if ($opt_help > 2);
108
 
109
#
110
#   Capture all logging to a file
111
#   Could be done by the jats wrapper, but this way we can control its location
112
#
113
ErrorConfig( 'name'    => 'LXR',
114
             'verbose' => $opt_verbose );
115
 
116
#
117
#   Sanity test
118
#
119
 
120
$scriptDir = $FindBin::Bin;
121
InitFileUtils();
122
 
123
#
124
#   Read the tool configuration
5213 dpurdie 125
#   Sed with Default config
5209 dpurdie 126
#
5213 dpurdie 127
$Config->{'releaseAge'} = 0;
128
$Config->{'packageAge'} = 0;
129
$Config->{'logAge'} = 0;
130
$Config->{'verbose'} = 0;
5247 dpurdie 131
$Config->{GBE_RM_LOCATION} = $ENV{GBE_RM_LOCATION};
132
$Config->{GBE_RM_USERNAME} = $ENV{GBE_RM_USERNAME};
133
$Config->{GBE_RM_PASSWORD} = $ENV{GBE_RM_PASSWORD};
5209 dpurdie 134
readConfig();
135
 
136
#
137
#   Start logging
138
#
139
startLogFile();
140
Message ("Start of LXR. " . localtime(time) ) if $opt_logfile;
141
Message("ScriptDir: $scriptDir");
5231 dpurdie 142
DebugDumpData("Config", \$Config) if (IsVerbose(1));
5209 dpurdie 143
 
144
#
5231 dpurdie 145
#   Sanity Testing
146
#   
147
 
148
Error ("No LXR Data directory defined") unless( exists $Config->{lxrFiles});
149
Error ("No LXR Data directory found", $Config->{lxrFiles}) unless( -d $Config->{lxrFiles});
150
 
151
Error ("No LXR Install directory defined") unless( exists $Config->{lxr});
152
Error ("No LXR Install directory found",$Config->{lxr}) unless( -d $Config->{lxr});
153
 
154
Error ("No Glimpse Data directory defined") unless( exists $Config->{glimpseDir});
155
Warning ("No Glimpse Data directory found",$Config->{glimpseDir}) unless( -d $Config->{glimpseDir});
156
 
157
ErrorConfig( 'verbose' => $Config->{'verbose'} );
158
 
159
#
5213 dpurdie 160
#   Prevent multiple instances of the program running
161
#
162
#   PerlMonks say to use $0 as the lock file, but that did not work.
163
#   Perhaps the file was open in an editor
164
#   Solution: Create my own file
165
#
166
open( FW, '>',$lockFile);
167
print FW '';
168
close FW;
169
 
170
open (my $self, '<', $lockFile)    || Error("Couldn't open self: $!");
171
flock ($self, (LOCK_EX | LOCK_NB)) || Error("This script is already running");
172
 
173
#
5209 dpurdie 174
#   Check required paths exist
175
#
5213 dpurdie 176
$PackageStore = catdir($Config->{lxrFiles}, 'Packages');
177
$ReleaseStore = catdir($Config->{lxrFiles}, 'Releases');
5209 dpurdie 178
mkpath($PackageStore);
179
mkpath($ReleaseStore);
180
Error ("Package Store not found ",$PackageStore) unless( -d $PackageStore);
181
Error ("Release Store not found ",$ReleaseStore) unless( -d $ReleaseStore);
182
 
183
#
184
#   Determine the various names for this machine
185
#   Include all the IP addresses too
186
#
187
my ($canonname, $aliases, $addrtype, $length, @addrs) = gethostbyname($ENV{GBE_HOSTNAME});
188
push @addressList, $canonname ;
189
push (@addressList, $aliases) if ($aliases) ;
190
push (@addressList, $ENV{GBE_HOSTNAME});
5231 dpurdie 191
foreach (@addrs) {
5209 dpurdie 192
    push @addressList, inet_ntoa($_); 
193
}
194
Message("IpAddress: @addressList");
195
 
196
#
5247 dpurdie 197
#   Use local Database config - if provided
198
#
199
$ENV{GBE_RM_LOCATION} = $Config->{GBE_RM_LOCATION};
200
$ENV{GBE_RM_USERNAME} = $Config->{GBE_RM_USERNAME};
201
$ENV{GBE_RM_PASSWORD} = $Config->{GBE_RM_PASSWORD};
202
 
203
#
5209 dpurdie 204
#   Perform the hard work
205
#
206
getReleaseData();
5213 dpurdie 207
updateReleaseViews() if $opt_createVersions;
5209 dpurdie 208
cleanReleaseViews();
5213 dpurdie 209
rebuildLxrConfig()  if $opt_index;
5209 dpurdie 210
buildIndexes() if $opt_index;
5247 dpurdie 211
updateReleaseManager();
5209 dpurdie 212
cleanPackageStore() if $opt_purge;
213
cleanupLogFiles() if $opt_purge;
214
 
215
#
216
#   All done
217
#
5213 dpurdie 218
unlink $lockFile;
5209 dpurdie 219
Message ("End of LXR. " . localtime(time) ) if $opt_logfile;
220
exit 0;
221
 
222
#-------------------------------------------------------------------------------
5212 dpurdie 223
# Function        : extractPackages 
5209 dpurdie 224
#
5212 dpurdie 225
# Description     : Extract Packages from VCS
5209 dpurdie 226
#                   Don't extract them if they already exist
5212 dpurdie 227
#   
228
#                   Kludge: Prevent extraction from MASS_Dev_Crypto Repo
5209 dpurdie 229
#
5213 dpurdie 230
# Inputs          : $rtagid         - Release To Process
231
#                                     Conatins PackageVersion data  
5209 dpurdie 232
#
233
# Returns         : 
234
#
5212 dpurdie 235
sub extractPackages
5209 dpurdie 236
{
5213 dpurdie 237
    my ($rtagid) = @_;
238
    foreach my $pvid (keys %{$ReleaseData{$rtagid}{data}})
5209 dpurdie 239
    {
240
        my $entry = $Packages{$pvid};
241
        #DebugDumpData("Entry", \$entry);
242
        my $fullName = join('_', $entry->{name}, $entry->{ver});
243
        my $fullPath = catfile($PackageStore , $fullName);
244
        next unless defined $entry->{vcs};
245
        next if ( $entry->{vcs} ) =~ m~^UC::~;
5211 dpurdie 246
        unless (-d $fullPath ) 
247
        {
5231 dpurdie 248
            Message("Extracting: $entry->{name}, $entry->{ver}");
5209 dpurdie 249
            if ($opt_extract)
250
            {
5231 dpurdie 251
                Verbose("Extracting into: $fullPath");
252
                my $result = 'ERROR';
5212 dpurdie 253
                if ($entry->{vcs} =~ m~/MASS_Dev_Crypto/~)
5211 dpurdie 254
                {
5231 dpurdie 255
                    $result = 'SUPPRESSED';
5211 dpurdie 256
                }
257
                else
258
                {
259
                    my $rv = JatsCmd ('jats_vcsrelease', '-devmode=escrow', '-extractfiles', "-view=$fullName", "-label=$entry->{vcs}", "-root=$PackageStore", "-noprefix");
5231 dpurdie 260
                    if ($rv)
261
                    {
262
                        $result = 'ERROR';
263
                        $entry->{bad} = 1;
264
                    }
265
                    else
266
                    {
267
                        $result = 'SUCCESS';
268
                    }
5211 dpurdie 269
                }
5231 dpurdie 270
                Message("Extraction Result: $result");
5209 dpurdie 271
            }
272
        }
5211 dpurdie 273
        else
274
        {
275
            #   Package already extracted
276
            #   Ensure that it does not get aged out
277
            deleteAgeMarker($fullPath);
278
        }
5209 dpurdie 279
    }
280
}
281
 
282
#-------------------------------------------------------------------------------
5213 dpurdie 283
# Function        : updateReleaseViews 
5209 dpurdie 284
#
5213 dpurdie 285
# Description     : 
5209 dpurdie 286
#
287
# Inputs          : 
288
#
289
# Returns         : 
290
#
5213 dpurdie 291
sub updateReleaseViews
5209 dpurdie 292
{
293
    #
5213 dpurdie 294
    #   Process each known Release
5209 dpurdie 295
    #
5213 dpurdie 296
    foreach my $rtagid (sort keys \%ReleaseData)
5209 dpurdie 297
    {
5231 dpurdie 298
        Verbose("updateReleaseViews: $rtagid"); 
5213 dpurdie 299
        if ($ReleaseData{$rtagid}{release}{ACTIVE})
5212 dpurdie 300
        {
5213 dpurdie 301
            #
302
            #   Determinte last created view in this Release
303
            #
304
            my ($latestView, $latestAge) = getLatestVersion(catdir($ReleaseStore, $rtagid ));
5233 dpurdie 305
            if ( ! defined($latestView) || $latestAge > 1 || $opt_forceViews )
5209 dpurdie 306
            {
307
                #
5213 dpurdie 308
                #   If there is no latest view, then we need to create a new view
309
                #   If there is a recent view, but its older than a day then we may need
310
                #   to refresh it.
5209 dpurdie 311
                #
5213 dpurdie 312
                getReleasePakageData($rtagid);
5231 dpurdie 313
                if (checkViewDiffs($latestView,$rtagid) || $opt_forceViews)
5209 dpurdie 314
                {
5213 dpurdie 315
                    #
316
                    #   Need to create a view
317
                    #       Either one does not exist
318
                    #       Content has changed
319
                    #
320
                    createReleaseView($rtagid);
5209 dpurdie 321
                }
5213 dpurdie 322
                else
323
                {
324
                    #   No need to create a new view
325
                    #   Do need to tag it so that we don't examine it again ( for a while )
326
                    Message("No Changes to LXR View: $rtagid");
327
                    if (defined $latestView)
328
                    {
329
                        my $rv = utime $StampTime,$StampTime, $latestView; 
5231 dpurdie 330
                        Debug("Utime $rv: $latestView");
5213 dpurdie 331
                    }
332
                }
5209 dpurdie 333
            }
5213 dpurdie 334
            else
5209 dpurdie 335
            {
5213 dpurdie 336
                Message("Recent LXR View: $rtagid");
5209 dpurdie 337
            }
5213 dpurdie 338
        }
339
        else
340
        {
341
            Message("Inactive LXR View: $rtagid");
342
        }
343
    }
344
}
345
 
346
#-------------------------------------------------------------------------------
347
# Function        : checkViewDiffs 
348
#
5233 dpurdie 349
# Description     : Check a view against package versions in the current Release. 
350
#                   Ignore ripple built packages as these only have dependent changes
5213 dpurdie 351
#
352
# Inputs          : $vdir       - View entry to process
353
#                   $rtagid     - RtagId
354
#
355
# Returns         : True, If we need to create a new view
5231 dpurdie 356
#                         No view exists
357
#                         View does not match Release Content
5213 dpurdie 358
#
359
sub checkViewDiffs
360
{
361
    my ($vdir, $rtagid) = @_;
362
 
363
    #   No entry to process, then we need to create a view
364
    return 1 if not defined $vdir;
365
 
5231 dpurdie 366
    #
367
    #   Read in the View List
368
    #
5213 dpurdie 369
    my %pkgsUsed;
5231 dpurdie 370
    my $releaseListFile = catfile($vdir, '.lxrRelease');
371
    if (open (my $rf, '<', $releaseListFile ))
5213 dpurdie 372
    {
5231 dpurdie 373
        while (my $data = <$rf>)
5213 dpurdie 374
        {
5231 dpurdie 375
            $data =~ s~\s+$~~;
5233 dpurdie 376
            $data = baseVersionNumber ($data );
5231 dpurdie 377
            $pkgsUsed{$data} = 2;
5209 dpurdie 378
        }
5231 dpurdie 379
    }
380
    else
381
    {
382
        Warning ("Cannot find Release List: $releaseListFile", $!);
383
        return 1;
384
    }
5209 dpurdie 385
 
5231 dpurdie 386
    #
387
    #   Compare the packages in the Release against those required
388
    #
389
    foreach my $pvid (keys %{$ReleaseData{$rtagid}{data}})
390
    {
391
        my $entry = $Packages{$pvid};
392
        my $fullName = join('_', $entry->{name}, $entry->{ver});
5233 dpurdie 393
        $fullName = baseVersionNumber ($fullName );
5231 dpurdie 394
        $pkgsUsed{$fullName}++;
395
    }
5213 dpurdie 396
 
5231 dpurdie 397
    my $needNewView = 0;
398
    #
399
    #   Scan the pkgUsed
400
    #   A value of 1 indicates that it is used only in the New Version
401
    #   A value of 2 indicates that it is only used on the Last Version
402
    #   A value of 3 indicates that its used in both
403
    #   Detect those that are not a 3
404
    #
405
    foreach ( keys %pkgsUsed)
406
    {
407
        if ($pkgsUsed{$_} != 3)
5209 dpurdie 408
        {
5231 dpurdie 409
            $needNewView = 1;
410
            last;
5213 dpurdie 411
        }
412
    }
5231 dpurdie 413
    Warning("Release Contents don't match: $rtagid") if $needNewView;
5213 dpurdie 414
    #DebugDumpData("pkgsUsed",\%pkgsUsed);
415
    return $needNewView;
416
}
5209 dpurdie 417
 
5213 dpurdie 418
#-------------------------------------------------------------------------------
419
# Function        : createReleaseView 
420
#
421
# Description     : Create a new view for a single Release
422
#
423
# Inputs          : $rtagid     - RtagId
424
#
425
# Returns         : 
426
#
427
sub createReleaseView
428
{
429
    my ($rtagid) = @_;
5231 dpurdie 430
    my @ReleaseList;
5213 dpurdie 431
 
432
    #
433
    #   Ensure that packages have been extracted
434
    #
435
    extractPackages($rtagid);
436
 
437
    #
438
    #   Create the actual view directory
439
    #   Its simply a bunch of symlinks back to the package store
440
    #
5231 dpurdie 441
 
442
    #
443
    #   Create directory for the new view
444
    #   Based on current date. Some tools (glimpse and ctags) can't handle spaces in paths
445
    #
446
    my $dateTag = localtime($StampTime);
447
    $dateTag =~ s~\s+~_~g;
448
 
5213 dpurdie 449
    Message("Creating LXR View: $rtagid, $dateTag");
450
    my $releaseDir = catdir($ReleaseStore, $rtagid, $dateTag);
451
    mkpath($releaseDir);
452
    if (-d $releaseDir)
453
    {
454
        foreach my $pvid (keys %{$ReleaseData{$rtagid}{data}})
455
        {
456
            my $entry = $Packages{$pvid};
457
            my $alias = join('', $entry->{name}, $entry->{ext});
458
            my $fullName = join('_', $entry->{name}, $entry->{ver});
459
            my $PackageStore = catdir($PackageStore , $fullName);
5231 dpurdie 460
            my $pkgDir = catdir($releaseDir, $alias );
461
            push @ReleaseList, $fullName;
462
            next if -l $pkgDir;
463
            next if -d $pkgDir;
5213 dpurdie 464
 
5231 dpurdie 465
            #
466
            #   
467
            #   Glimpse will not follow symlinks - which would be nice
468
            #   Clone the Package using hardlinks - still saves space
469
            #
470
            Verbose("HardLink $PackageStore, $releaseDir");
471
            my $rv = System('--NoExit', '--NoShell', 'cp','-al', $PackageStore, $pkgDir);
472
            Warning("Could not duplicate $PackageStore, $releaseDir") if $rv;
473
 
474
 
475
#           Verbose("Symlink $PackageStore, $releaseDir");
476
#           my $rv = symlink ($PackageStore, $releaseDir);
477
#           Warning("Could not link $PackageStore, $releaseDir") unless ($rv);
5209 dpurdie 478
        }
5231 dpurdie 479
 
480
        #
481
        #   Generate a list of package-vesrions in the release
482
        #   Used so that we can detect changes to the release
483
        #
484
        FileCreate(catfile($releaseDir, '.lxrRelease'), \@ReleaseList);
5209 dpurdie 485
    }
5231 dpurdie 486
    Verbose("createReleaseView - End");
5209 dpurdie 487
}
488
 
489
#-------------------------------------------------------------------------------
490
# Function        : rebuildLxrConfig 
491
#
492
# Description     : Rebuild the LXR Configuration file
493
#                   This MAY be a bit LXR version specific, but since LXR doesn't
494
#                   provide a scriptable way to update configuration
495
#
496
#                   Uses template files that have been handcrafted after taken from
5211 dpurdie 497
#                   LXR. Basically we to a text replace and a glue together
5209 dpurdie 498
#
499
#                   For each release we need
500
#                       Long Release Name
501
#                       Short Release Name
502
#                       List of Versions
503
#
504
#
505
# Inputs          : Assumes Data has been added to %ReleaseData by other subroutines
506
#
507
# Returns         : 
508
#
509
sub rebuildLxrConfig
510
{
511
    my @lxrTreeText;
5211 dpurdie 512
 
5209 dpurdie 513
    #
5211 dpurdie 514
    #   Sort Sub
515
    #   Sort ReleaseData by Project and Name
516
    #   $a and $b are special to the sort
517
    #
518
    sub ReleaseDataSort
519
    {
520
        my $rv = lc($ReleaseData{$a}{release}{Project}) cmp lc($ReleaseData{$b}{release}{Project});
521
        if ($rv == 0)
522
        {
523
            $rv = lc($ReleaseData{$a}{release}{Name}) cmp lc($ReleaseData{$b}{release}{Name});
524
        }
525
        return $rv;
526
    }
527
 
528
    #
5209 dpurdie 529
    #   Process configured releases
5212 dpurdie 530
    #   Generate in the order we wish to display the Releases
5209 dpurdie 531
    #
532
    #DebugDumpData("ReleaseData", \%ReleaseData);
5211 dpurdie 533
    foreach my $rtagid ( sort ReleaseDataSort keys %ReleaseData )
5209 dpurdie 534
    {
535
        my $entry = $ReleaseData{$rtagid};
5211 dpurdie 536
        Information("Entry: $entry->{release}{Project}, $entry->{release}{Name}, $rtagid");
5209 dpurdie 537
        $entry->{release}{VersionsString} = join( ',', map { '"' . $_ .'"'} @{$entry->{Versions}} );
538
        $entry->{release}{dbName} = genDatabaseName($rtagid);
5213 dpurdie 539
        $entry->{release}{root} = catdir($ReleaseStore, $rtagid );
5209 dpurdie 540
        #DebugDumpData("ENTRY", \$entry);
541
 
542
        my $tfileName = 'lxr.tree.template';
543
        open( my $tf, '<', $tfileName) || Error ("Cannot open $tfileName. $!");
544
        while (my $line = <$tf>)
545
        {
546
            # Chomp trailing write space
547
            $line =~ s~\s+$~~;
548
 
549
            #   Replace known bits in the template
550
            $line =~ s~\@CAPTION\@~$entry->{release}{Project}::$entry->{release}{Name}~g;
551
            $line =~ s~\@SHORT_NAME\@~$rtagid~g;
552
            $line =~ s~\@RELEASE_ROOT\@~$entry->{release}{root}~g;
553
            $line =~ s~\@VERSIONS_LIST\@~$entry->{release}{VersionsString}~g;
554
            $line =~ s~\@DBNAME\@~$entry->{release}{dbName}~g;
555
            push @lxrTreeText, $line
556
        }
557
        close $tf;
558
    }
559
 
560
    #
561
    #   Insert tree sections into the main config file template
562
    #
563
    my $hostList = join( ',', map { '\'http://' . $_ .'\''} @addressList );
564
 
565
    my $tfileName = catfile($scriptDir, 'lxr.template');
5213 dpurdie 566
    my $lxrFileName = catfile($Config->{lxr}, 'lxr.new.conf');
5209 dpurdie 567
    unlink $lxrFileName;
568
    open( my $tf, '<', $tfileName) || Error ("Cannot open $tfileName. $!");
569
    open( my $to, '>', $lxrFileName) || Error ("Cannot open $lxrFileName. $!");
570
    while (my $line = <$tf>)
571
    {
572
        # Chomp trailing write space
573
        $line =~ s~\s+$~~;
574
 
575
        #   Replace known bits in the template
576
        if ($line =~ m~\@TREE_SECTIONS\@~)
577
        {
578
            foreach (@lxrTreeText)
579
            {
580
                print $to $_, "\n";
581
            }
582
        }
583
        else
584
        {
585
            $line =~ s~\@HOSTLIST\@~$hostList~g;
586
            print $to $line, "\n";
587
        }
588
    }
589
    close $tf;
590
    close $to;
591
 
592
    #
593
    #   Install the new config files
594
    #
5213 dpurdie 595
    my $lxrLive = catfile($Config->{lxr}, 'lxr.conf');
596
    my $lxrBackup = catfile($Config->{lxr}, 'lxr.conf.bak');
5209 dpurdie 597
    unlink $lxrBackup;
598
    rename ($lxrLive, $lxrBackup) || Warning("Renaming $lxrLive, $lxrBackup", $!);
599
    rename ($lxrFileName, $lxrLive) || Warning("Renaming $lxrFileName, $lxrLive", $!);
600
 
601
    #
602
    #   Create new database tables if required
603
    #   Use a customized shell script to do the hard work
604
    #
5213 dpurdie 605
    foreach my $rtagid ( sort keys %ReleaseData )
5209 dpurdie 606
    {
607
        my $entry = $ReleaseData{$rtagid};
5213 dpurdie 608
        Verbose("Database:$entry->{release}{Name}, $entry->{release}{dbName} ");
5209 dpurdie 609
        System('--NoExit', '--NoShell', catfile($scriptDir, 'lxr.initdb.sh'), $entry->{release}{dbName});
610
    }
611
}
612
 
613
#-------------------------------------------------------------------------------
614
# Function        : buildIndexes 
615
#
616
# Description     : Build (Generate) indexes for all versions of all releases
617
#                   that don't have an index
618
#                   
619
#                   Place a marker file in the 'version' directory when the
620
#                   index has been created
621
#
622
#                   Notes:
623
#                   The 'genxref' program needs to be run from the lxr insatll directory
624
#                   chdir to that directory for each invocation
625
#
626
#                   genxref uses DBI - and must find the proper PERL DBI and not the one
627
#                   within JATS.. Solution:
628
#                       Kill the PERL5LIB EnvVar
629
#
630
#
631
#
632
# Inputs          : 
633
#
634
# Returns         : 
635
#
636
sub buildIndexes
637
{
638
    #
639
    #   Prep envonment for calling genxref
640
    #   See notes above
641
    #
5213 dpurdie 642
    chdir ($Config->{lxr}) || Error ("Cannot chnage directory:$Config->{lxr}, $!");
5209 dpurdie 643
    delete $ENV{PERL5LIB};
644
 
645
    #
646
    #   Examine each Version in each Release
647
    #   Generate command line like:
648
    #   genxref --tree RTAGID --url http://HOSTNAME/lxr --version 'VERSION'
5213 dpurdie 649
    foreach my $rtagid ( sort keys %ReleaseData )
5209 dpurdie 650
    {
651
        my $entry = $ReleaseData{$rtagid};
652
        foreach my $version (@{$entry->{Versions}})
653
        {
5213 dpurdie 654
            my $markerFile = catfile(catdir($ReleaseStore, $rtagid ), $version, '.lxrIndexed');
5209 dpurdie 655
            unless (-f $markerFile) {
656
                Message("Must index: $rtagid, $version");
657
                my $rv = System('--NoExit', 
658
                       '--NoShell', 
5213 dpurdie 659
                       catfile($Config->{lxr}, 'genxref'),
5209 dpurdie 660
                       '--url', 'http://' . $ENV{GBE_HOSTNAME} . '/lxr',
661
                       '--tree', $rtagid,
662
                       '--version', $version
663
                       );
664
               Verbose("genxref exit: $rv");
665
               unless ($rv) {
666
                   TouchFile($markerFile);
667
               }
668
            }
669
            else
670
            {
671
                Verbose("Already indexed: $rtagid, $version");
672
            }
673
        }
674
    }
675
    #
676
    #   Restore current directory
677
    #
678
    chdir($FileUtils::CwdFull);
679
}
680
 
681
 
682
#-------------------------------------------------------------------------------
683
# Function        : cleanReleaseViews 
684
#
685
# Description     : Clean up unused Releases and Release Views
686
#                   Maintain the list of retained versions
687
#
688
#                   Two classes
689
#                   Active - Marked as having LXR support
690
#                       Retain the last 5 Versions
691
#
692
#                  InActive - Not having LXR support
693
#                       Retain for 10 days then delete all versions
694
#
695
# Inputs          : 
696
#
697
# Returns         : 
698
#
699
sub cleanReleaseViews
700
{
701
    #
702
    #   Scan Releases and delete all that are not currently configured
703
    #
704
    opendir (my $rdir, $ReleaseStore) || Error ("Cannot open directory: $ReleaseStore", $!);
705
    while (my $rdirEntry = readdir($rdir))
706
    {
707
        #   Skip hidden files and directories
708
        next if ($rdirEntry =~ m~^\.~);
709
        my $vdirName = catdir($ReleaseStore, $rdirEntry );
710
        next unless ( -d $vdirName );
5212 dpurdie 711
        unless(exists $ReleaseData{$rdirEntry} && $ReleaseData{$rdirEntry}{release}{ACTIVE} )
5209 dpurdie 712
        {
5211 dpurdie 713
            #   Release is no longer configured - age it out
5209 dpurdie 714
            #   Assume $rdirEntry is an rtag_id
5247 dpurdie 715
            $ReleaseData{$rdirEntry}{release}{LXRSTATE} = 'C';
5213 dpurdie 716
            if (processAgeMarker($vdirName, $Config->{'releaseAge'} ))
5211 dpurdie 717
            {
5247 dpurdie 718
                $ReleaseData{$rdirEntry}{release}{LXRSTATE} = 'D';
5211 dpurdie 719
                Message("Delete Release: $rdirEntry");
720
                RmDirTree($vdirName);
721
                System('--NoExit', '--NoShell', catfile($scriptDir, 'lxr.dropdb.sh'), genDatabaseName($rdirEntry));
5231 dpurdie 722
                if ( defined $Config->{glimpseDir} )
723
                {
724
                    my $glimpseData = catdir( $Config->{glimpseDir}, $rdirEntry );
725
                    RmDirTree($glimpseData);
726
                }
5211 dpurdie 727
            }
5209 dpurdie 728
        }
729
        else
730
        {
5247 dpurdie 731
            $ReleaseData{$rdirEntry}{release}{LXRSTATE} = 'I';
5211 dpurdie 732
            deleteAgeMarker($vdirName);
5209 dpurdie 733
 
734
            #   Release is configured
735
            #   Keep the last x created
736
            #   Note: Create time is a kludge
737
            #
738
            #   Process each version within the Release
739
            #
740
            my @versionData;
741
            opendir (my $vdir, $vdirName) || Warning ("Cannot open directory: $vdirName", $!);
742
            while (my $vdirEntry = readdir($vdir))
743
            {
744
                #   Skip hidden files and directories
745
                next if ($vdirEntry =~ m~^\.~);
746
                my $ldirName = catdir($vdirName, $vdirEntry );
747
                next unless ( -d $ldirName );
748
                my $data;
749
                $data->{name} = $vdirEntry; 
750
                $data->{path} = $ldirName; 
751
                $data->{ctime} = (stat $ldirName)[9];
752
                push @versionData  , $data;
753
            }
754
            close ($vdir);
755
            #DebugDumpData("versionData",\@versionData);
756
 
757
            my $keepCount = 0;
758
            foreach my $entry ( sort { $b->{ctime} <=> $a->{ctime}} @versionData )
759
            {
760
                #DebugDumpData("Entry", $entry);
761
                $keepCount++;
762
                if ($keepCount > 5)
763
                {
764
                    #   Version is no longer needed - remove it
765
                    Message("Delete Version: $rdirEntry, $entry->{name}, $entry->{ctime}");
766
                    RmDirTree($entry->{path});
767
                }
768
                else
769
                {
770
                    #   Note which versions we have
771
                    push @{$ReleaseData{$rdirEntry}{Versions}}, $entry->{name};
772
                }
773
            }
774
        }
775
    }
776
    close ($rdir);
777
}
778
 
779
#-------------------------------------------------------------------------------
780
# Function        : getLatestVersion 
781
#
782
# Description     : For a specified directory return the newest subdir
783
#
784
#                   Used to determine the most recent version
785
#
5212 dpurdie 786
# Inputs          : $vdirName - Dir to process - expecting a Release directory
5209 dpurdie 787
#
5213 dpurdie 788
# Returns         : latestName  - Patch to the latest directory
789
#                   Age (days ) - Of the named directory
5209 dpurdie 790
#
791
sub getLatestVersion
792
{
793
    my  ($vdirName) = @_;
794
    my $latestName;
795
    my $latestAge = 0;
796
 
5213 dpurdie 797
    if (-d $vdirName )
5209 dpurdie 798
    {
5213 dpurdie 799
        opendir (my $vdir, $vdirName) || Warning ("Cannot open directory: $vdirName", $!);
800
        while (my $vdirEntry = readdir($vdir))
801
        {
802
            #   Skip hidden files and directories
803
            next if ($vdirEntry =~ m~^\.~);
5209 dpurdie 804
 
5213 dpurdie 805
            my $ldirName = catdir($vdirName, $vdirEntry );
806
            next unless ( -d $ldirName );
5209 dpurdie 807
 
5213 dpurdie 808
            my $age = (stat $ldirName)[9];
809
            Verbose3("Age: $ldirName, $age");
5209 dpurdie 810
 
5213 dpurdie 811
            if  ($age > $latestAge )
812
            {
813
                $latestAge = $age;
814
                $latestName = $ldirName;
815
            }
5209 dpurdie 816
        }
5213 dpurdie 817
        close ($vdir);
818
 
819
        #   Convert to Days ago
820
        $latestAge = ($StampTime - $latestAge) / (60*60*24);
821
        #DebugDumpData("versionDataSorted",\@versionDataSorted);
822
        Verbose("Latest: $latestName, $latestAge");
5209 dpurdie 823
    }
5213 dpurdie 824
    else
825
    {
826
        Verbose("Latest: No directory found: $vdirName");
827
    }
5209 dpurdie 828
 
5213 dpurdie 829
    return $latestName, $latestAge;
5209 dpurdie 830
}
831
 
832
#-------------------------------------------------------------------------------
833
# Function        : cleanPackageStore 
834
#
5231 dpurdie 835
# Description     : Delete unused Packages from the package store
836
#                   Each View in each Release will have a .lxrRelease file that contains the
837
#                   package versions that the view needs.
5209 dpurdie 838
#
839
# Inputs          : 
840
#
841
# Returns         : 
842
#
843
sub cleanPackageStore
844
{
5231 dpurdie 845
    Verbose ("cleanPackageStore");
5209 dpurdie 846
    my %pkgsUsed;
847
    #
848
    #   Examime ALL versions in ALL Releases and build up a hash of
849
    #   Package Versions used
850
    #
851
    opendir (my $rdir, $ReleaseStore) || Error ("Cannot open directory: $ReleaseStore", $!);
852
    while (my $rdirEntry = readdir($rdir))
853
    {
854
        #   Skip hidden files and directories
855
        next if ($rdirEntry =~ m~^\.~);
856
        my $vdirName = catdir($ReleaseStore, $rdirEntry );
857
        next unless ( -d $vdirName );
858
 
859
        #
860
        #   Process each version within the Release
861
        #
862
        opendir (my $vdir, $vdirName) || Warning ("Cannot open directory: $vdirName", $!);
863
        while (my $vdirEntry = readdir($vdir))
864
        {
865
            #   Skip hidden files and directories
866
            next if ($vdirEntry =~ m~^\.~);
867
            my $ldirName = catdir($vdirName, $vdirEntry );
868
            next unless ( -d $ldirName );
869
 
870
            #
5231 dpurdie 871
            #   Read in the View List
5209 dpurdie 872
            #
5231 dpurdie 873
            my $releaseListFile = catfile($ldirName, '.lxrRelease');
874
            if (open (my $rf, '<', $releaseListFile ))
5209 dpurdie 875
            {
5231 dpurdie 876
                Verbose2("Found ", $releaseListFile);
877
                while (my $data = <$rf>)
5209 dpurdie 878
                {
5231 dpurdie 879
                    $data =~ s~\s+$~~;
880
                    $pkgsUsed{$data}++;
5209 dpurdie 881
                }
882
            }
5231 dpurdie 883
            else
884
            {
885
                Warning ("Cannot find Release List: $releaseListFile", $!);
886
            }
5209 dpurdie 887
        }
888
        close ($vdir);
889
    }
890
    close ($rdir);
891
 
892
    #
893
    #   Process the Packages directory and remove those not currently used
894
    #
895
    #
896
    #   Process each entry within the Version
897
    #
898
    opendir (my $pdir, $PackageStore) || Error ("Cannot open directory: $PackageStore", $!);
899
    while (my $pdirEntry = readdir($pdir))
900
    {
901
        #   Skip hidden files and directories
902
        next if ($pdirEntry =~ m~^\.~);
903
        my $pdirName = catdir($PackageStore, $pdirEntry );
904
        next unless ( -d $pdirName );
905
        next if (exists $pkgsUsed{$pdirEntry} );
906
 
5213 dpurdie 907
        if (processAgeMarker($pdirName, $Config->{packageAge})) 
5211 dpurdie 908
        {
909
            Message("Purge Package: $pdirEntry");
910
            RmDirTree($pdirName);
911
        }
5209 dpurdie 912
    }
913
    close ($pdir);
914
 
915
    #DebugDumpData("pkgsUsed", \%pkgsUsed);
916
}
917
 
918
#-------------------------------------------------------------------------------
919
# Function        : getReleaseData 
920
#
921
# Description     : Get all the required Release Data 
922
#
923
# Inputs          :  
924
#
925
# Returns         : 
926
#
927
sub getReleaseData
928
{
929
    my ($rtagid) = @_;
930
    my (@row);
5212 dpurdie 931
    my @releaseList;
932
    my $partSql = '';
5209 dpurdie 933
 
5213 dpurdie 934
    Verbose("getReleaseData");
5209 dpurdie 935
    connectRM(\$RM_DB) unless $RM_DB;
936
 
5212 dpurdie 937
    #
938
    #   Determine list of existing Releases
939
    #   Build up a Clause for the extraction SQL
940
    #   This is used to get data for Releases that exist in the Store but may have been
941
    #   deconfigured.
942
    #
943
    if ( opendir (my $rdir, $ReleaseStore) )
944
    {
945
        while (my $rdirEntry = readdir($rdir))
946
        {
947
            #   Skip hidden files and directories
948
            next if ($rdirEntry =~ m~^\.~);
949
            my $vdirName = catdir($ReleaseStore, $rdirEntry );
950
            next unless ( -d $vdirName );
951
            push @releaseList, $rdirEntry;
952
        }
953
        close $rdir;
954
    }
5209 dpurdie 955
 
5212 dpurdie 956
    if (@releaseList)
957
    {
958
        $partSql = ' OR rt.rtag_id in (' . join(',', @releaseList ) . ')' 
959
    }
960
 
961
 
5209 dpurdie 962
    #
963
    # Determine which Releases need LXR support
964
    #
965
    my $m_sqlstr = 
5247 dpurdie 966
        "SELECT rt.rtag_id," .
967
        "  rt.proj_id," .
968
        "  p.PROJ_NAME," .
969
        "  rt.rtag_name," .
970
        "  rt.official," .
971
        "  NVL(TRUNC (SYSDATE - rt.official_stamp),0) AS OFFICIAL_STAMP_DAYS," .
972
        "  rt.lxr,".
973
        "  lxr.lxrserver" .
974
        " FROM release_manager.release_tags rt," .
975
        "  release_manager.lxr_state lxr," .
976
        "  release_manager.projects p" .
977
        " WHERE lxr.RTAG_ID(+) = rt.RTAG_ID" .
978
        " AND (rt.lxr = 'Y'" . $partSql . ")" .
979
        " AND p.PROJ_ID = rt.proj_id";
5209 dpurdie 980
 
5247 dpurdie 981
    Verbose2('$m_sqlstr',$m_sqlstr);
5209 dpurdie 982
    my $sth = $RM_DB->prepare($m_sqlstr);
983
    if ( defined($sth) )
984
    {
985
        if ( $sth->execute( ) )
986
        {
987
            if ( $sth->rows )
988
            {
989
                while ( @row = $sth->fetchrow_array )
990
                {
991
                    my $rtagid = $row[0];
992
                    my $data;
993
                    $data->{Project} = $row[2];
994
                    $data->{Name} = $row[3];
995
                    $data->{official} = substr($row[4],0,1);
996
                    $data->{official_stamp_days} = $row[5];
5212 dpurdie 997
                    $data->{lxr} = $row[6];
5247 dpurdie 998
                    $data->{lxr_state} = $row[7] || 'N';
5209 dpurdie 999
 
1000
                    #
1001
                    #   Determine if this request for an LXR release is OK
1002
                    #   Ok If the release is Open, CCB or Restricted
5212 dpurdie 1003
                    #   Ok If closed and has been closed to < 10 days
5209 dpurdie 1004
                    #
5212 dpurdie 1005
                    if ($data->{lxr} eq 'Y')
5209 dpurdie 1006
                    {
5212 dpurdie 1007
                        if (index('NRC', $data->{official}) >= 0)
1008
                        {
1009
                            $data->{ACTIVE} = 1;
1010
                        }
1011
                        elsif ($data->{official} eq 'Y' && $data->{official_stamp_days} < 10 )
1012
                        {
1013
                            $data->{ACTIVE} = 2;
1014
                        }
5209 dpurdie 1015
                    }
1016
 
1017
                    $ReleaseData{$rtagid}{release} = $data;
1018
                }
1019
            }
1020
            $sth->finish();
1021
        }
1022
    }
1023
    else
1024
    {
1025
        Error("getReleaseData:Prepare failure" );
1026
    }
1027
 
5213 dpurdie 1028
    if (IsVerbose(1))
1029
    {
1030
        DebugDumpData("ReleaseData", \%ReleaseData);
1031
    }
5212 dpurdie 1032
 
5213 dpurdie 1033
    #
1034
    #   Just a summary display for logging
1035
    #
1036
    foreach my $rtagid ( sort keys %ReleaseData)
5209 dpurdie 1037
    {
5213 dpurdie 1038
        my $state = $ReleaseData{$rtagid}{release}{ACTIVE} ? 'ACTIVE' : 'InActive';
1039
        Information("Release: RtagId $rtagid, $state");
5209 dpurdie 1040
    }
1041
}
1042
 
1043
#-------------------------------------------------------------------------------
5213 dpurdie 1044
# Function        : getReleasePakageData
5209 dpurdie 1045
#
5212 dpurdie 1046
# Description     : Get PackgeVersion information for one Release
5209 dpurdie 1047
#
1048
# Inputs          : rtagid
1049
#
1050
# Returns         : 
1051
#
5213 dpurdie 1052
sub getReleasePakageData
5209 dpurdie 1053
{
1054
    my ($rtagid) = @_;
1055
    my (@row);
1056
 
1057
    connectRM(\$RM_DB) unless $RM_DB;
1058
 
1059
 
1060
    # Get details for each package in the Release
1061
    #   Don't worry about dependent packages
1062
    #
1063
    my $m_sqlstr = "SELECT pv.PV_ID, pkg.PKG_NAME, pv.PKG_VERSION, pv.V_EXT, release_manager.PK_RMAPI.return_vcs_tag(pv.PV_ID)".
1064
                   " FROM RELEASE_MANAGER.RELEASE_CONTENT rc, RELEASE_MANAGER.PACKAGE_VERSIONS pv, RELEASE_MANAGER.PACKAGES pkg" .
1065
                   " WHERE rc.RTAG_ID = $rtagid AND rc.PV_ID = pv.PV_ID AND pv.PKG_ID = pkg.PKG_ID";
1066
    my $sth = $RM_DB->prepare($m_sqlstr);
1067
    if ( defined($sth) )
1068
    {
1069
        if ( $sth->execute( ) )
1070
        {
1071
            if ( $sth->rows )
1072
            {
1073
                while ( @row = $sth->fetchrow_array )
1074
                {
1075
                    my $data;
1076
                    my $pvid = $row[0];
1077
                    unless (exists $Packages{$pvid}) {
1078
                        $data->{pv_id} = $row[0];
1079
                        $data->{name} = $row[1];
1080
                        $data->{ver} = $row[2];
1081
                        $data->{ext} = $row[3] || '';
1082
                        $data->{vcs} = $row[4] || '';
1083
                        $Packages{$pvid} = $data;
1084
                    }
5212 dpurdie 1085
                    $ReleaseData{$rtagid}{data}{$pvid} = 1;
5209 dpurdie 1086
                }
1087
            }
1088
            $sth->finish();
1089
        }
1090
    }
1091
    else
1092
    {
5213 dpurdie 1093
        Error("getReleasePakageData:Prepare failure" );
5209 dpurdie 1094
    }
1095
}
1096
 
1097
#-------------------------------------------------------------------------------
5247 dpurdie 1098
# Function        : updateReleaseManager 
1099
#
1100
# Description     : Feed the state of the releases back into the Release
1101
#                   manager database
1102
#                   
1103
#                   Assumes that the user has write access to ONE table
1104
#
1105
# Inputs          : 
1106
#
1107
# Returns         : 
1108
#
1109
sub updateReleaseManager
1110
{
1111
    foreach my $rtagid ( keys %ReleaseData)
1112
    {
1113
        my $rentry = $ReleaseData{$rtagid}{release}; 
1114
        Verbose3("updateReleaseManager:", $rtagid, $rentry->{lxr_state}, $rentry->{LXRSTATE});
1115
 
1116
        #
1117
        #   Only update those that have changed
1118
        #
1119
        if ($rentry->{lxr_state} ne $rentry->{LXRSTATE})
1120
        {
1121
            my $m_sqlstr;
1122
            #
1123
            #   Have just deleted the entry
1124
            #
1125
            if ($rentry->{LXRSTATE} eq 'D')
1126
            {
1127
                simpleSqlExecute('updateReleaseManager',"DELETE from release_manager.lxr_state where rtag_id = " . $rtagid);
1128
            }
1129
            elsif ($rentry->{LXRSTATE} eq 'C')
1130
            {
1131
                my $state = 'C';
1132
                simpleSqlExecute('updateReleaseManager',"begin insert into release_manager.lxr_state (rtag_id, lxrserver) values ($rtagid, '$state'); exception when dup_val_on_index then update release_manager.lxr_state set lxrserver = '$state' where  rtag_id = $rtagid; end; ");
1133
            }
1134
            elsif ($rentry->{LXRSTATE} eq 'I')
1135
            {
1136
                my $state = 'I';
1137
                simpleSqlExecute('updateReleaseManager',"begin insert into release_manager.lxr_state (rtag_id, lxrserver) values ($rtagid, '$state'); exception when dup_val_on_index then update release_manager.lxr_state set lxrserver = '$state' where  rtag_id = $rtagid; end; ");
1138
            }
1139
            else
1140
            {
1141
                Warning("updateReleaseManager. No entry for $rtagid");
1142
            }
1143
        }
1144
    }
1145
}
1146
 
1147
#-------------------------------------------------------------------------------
1148
# Function        : simpleSqlExecute 
1149
#
1150
# Description     : Perform a simple SQL statement that does not return anything
1151
#                   Used to update the RM database 
1152
#
1153
# Inputs          : $pname          - proceedure name ( for logging)
1154
#                   $m_sqlstr       - Sql to process
1155
#                    
1156
#
1157
# Returns         : 
1158
#
1159
sub simpleSqlExecute
1160
{
1161
    my ($pname,$m_sqlstr) = @_;
1162
    my (@row);
1163
 
1164
    connectRM(\$RM_DB) unless $RM_DB;
1165
 
1166
    Verbose2($pname,$m_sqlstr);
1167
    my $sth = $RM_DB->prepare($m_sqlstr);
1168
    if ( defined($sth) )
1169
    {
1170
        if ( $sth->execute( ) )
1171
        {
1172
            $sth->finish();
1173
        }
1174
        else
1175
        {
1176
            Warning("$pname.Execute failure: $m_sqlstr", $sth->errstr() );
1177
        }
1178
    }
1179
    else
1180
    {
1181
        Error("$pname:Prepare failure" );
1182
    }
1183
}
1184
 
1185
#-------------------------------------------------------------------------------
5209 dpurdie 1186
# Function        : genDatabaseName 
1187
#
1188
# Description     : Genertate the name of a database
1189
#
1190
# Inputs          : rtag_id 
1191
#
1192
# Returns         : Text Name of the database
1193
#
1194
 
1195
sub genDatabaseName
1196
{
1197
    my ($rtag_id) = @_;
1198
    return 'LXR_' . $rtag_id;
1199
}
1200
 
1201
#-------------------------------------------------------------------------------
1202
# Function        : readConfig 
1203
#
1204
# Description     : Read the basic LXR config
1205
#                   This is held in a Perl structure 
1206
#
1207
# Inputs          : None 
1208
#
1209
# Returns         : Populate Global Data
1210
#
1211
sub readConfig
1212
{
1213
    my $cfile = catfile($scriptDir,'jats_lxr.conf');
5211 dpurdie 1214
    if ($opt_config)
1215
    {
1216
        Message ("Using alternate config: $opt_config");
1217
        $cfile = $opt_config;
1218
    }
5209 dpurdie 1219
 
5213 dpurdie 1220
    #
1221
    #   Slurp in the file and evaluate it as a perl expression
1222
    #
1223
    if (open(my $CONFIG, '<', $cfile))
1224
    {
1225
        local ($/) = undef;
1226
        my $config_contents = <$CONFIG>;
1227
        $config_contents =~ m/(.*)/s;
1228
        $config_contents = $1;    #untaint it
1229
        my $config = eval("\n#line 1 \"configuration file\"\n" . $config_contents);
1230
        Error($@) if $@;
1231
        close $CONFIG;
5209 dpurdie 1232
 
5213 dpurdie 1233
        #
1234
        #   Merge read data with defaults
1235
        #
1236
        @$Config{ keys %$config } = values %$config;
1237
    }
1238
    else
1239
    {
1240
        Error("Couldn't open configuration file \"$cfile\".", $!);
1241
    }
5209 dpurdie 1242
}
1243
 
1244
#-------------------------------------------------------------------------------
1245
# Function        : startLogFile 
1246
#
1247
# Description     : Start logging to a log file
1248
#                   Generate a nice name for the log file
1249
#
1250
# Inputs          : 
1251
#
1252
# Returns         : 
1253
#
1254
sub startLogFile
1255
{
1256
    if ( $opt_logfile )
1257
    {
5213 dpurdie 1258
        if (exists $Config->{lxrLogDir})
5209 dpurdie 1259
        {
5213 dpurdie 1260
            my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($StampTime);
5209 dpurdie 1261
            my $name = sprintf("jats-lxr-%4.4d%2.2d%2.2d.%2.2d%2.2d%2.2d.log", 1900+$year, 1+$mon, $mday, $hour, $min, $sec);
5213 dpurdie 1262
            $name = catdir($Config->{lxrLogDir}, $name);
5209 dpurdie 1263
 
5213 dpurdie 1264
            mkpath($Config->{lxrLogDir}); 
1265
            if (-d $Config->{lxrLogDir} )
5209 dpurdie 1266
            {
1267
                open STDOUT, '>', $name  or die "Can't redirect STDOUT: $!";
1268
                open STDERR, ">&STDOUT"  or die "Can't dup STDOUT: $!";
1269
            }
1270
            else
1271
            {
5213 dpurdie 1272
                Warning("Can't create log dir: $Config->{lxrLogDir}. $!");
5209 dpurdie 1273
            }
1274
        }
1275
    }
1276
}
1277
 
1278
#-------------------------------------------------------------------------------
1279
# Function        : cleanupLogFiles 
1280
#
1281
# Description     : Remove old log files
1282
#
1283
# Inputs          : 
1284
#
1285
# Returns         : 
1286
#
1287
sub cleanupLogFiles
1288
{
5213 dpurdie 1289
    if (exists $Config->{lxrLogDir} && exists $Config->{logAge}  && $Config->{logAge} > 0 )
5209 dpurdie 1290
    {
5213 dpurdie 1291
        Verbose("cleanupLogFiles:$Config->{lxrLogDir}, $Config->{logAge}");
1292
        if ( opendir my $logDir, $Config->{lxrLogDir} )
5209 dpurdie 1293
        {
1294
            foreach my $fileName (readdir $logDir)
1295
            {
5213 dpurdie 1296
                my $file = catfile($Config->{lxrLogDir}, $fileName);
5209 dpurdie 1297
                next unless -f $file;
5213 dpurdie 1298
                next unless -M $file > $Config->{logAge};
5209 dpurdie 1299
                Verbose("Purge logfile: $fileName");
1300
                unlink $file;
1301
            }
1302
            closedir $logDir;
1303
        }
1304
    }
1305
}
1306
 
5211 dpurdie 1307
#-------------------------------------------------------------------------------
1308
# Function        : processAgeMarker 
1309
#
1310
# Description     : Age out directories
1311
#                   Will create age markers as required
1312
#
1313
# Inputs          : $tdir       - Target Directory
1314
#                   $age        - Configured age 
1315
#
1316
# Returns         : true        - Directory has reached age
1317
#
1318
sub processAgeMarker
1319
{
1320
    my ($tdir, $age) = @_;
1321
 
1322
    unless (-d $tdir) {
1323
        Warning ("Expected directory not found: $tdir");
1324
        return 0; 
1325
    }
5209 dpurdie 1326
 
5211 dpurdie 1327
    #   A configured age of 0 implies delete immediatly
1328
    if ($age == 0)
1329
    {
1330
        return 1;
1331
    }
1332
 
1333
    #
1334
    #   Create the file ONCE
1335
    #
1336
    my $markerfile = catfile($tdir, '.lxrAge');
1337
    unless (-f $markerfile)
1338
    {
1339
        TouchFile($markerfile);
1340
    }
1341
    else
1342
    {
5213 dpurdie 1343
        my $fileAge = -M $markerfile;
1344
        Verbose ("Age: $fileAge, $tdir");
1345
        if ($fileAge > $age)
5211 dpurdie 1346
        {
1347
            return 1
1348
        }
1349
    }
1350
    return 0;
1351
}
1352
 
1353
 
5209 dpurdie 1354
#-------------------------------------------------------------------------------
5211 dpurdie 1355
# Function        : deleteAgeMarker 
1356
#
1357
# Description     : Delete any age marker
1358
#                   Used when a (potentially) agable directory is used to remove
1359
#                   the aging marker
1360
#
1361
# Inputs          :  $tdir      - Directory
1362
#
1363
# Returns         : 
1364
#
1365
sub deleteAgeMarker
1366
{
1367
    my ($tdir) = @_;
1368
 
1369
    unless (-d $tdir) {
1370
        Warning ("Expected directory not found: $tdir");
1371
        return 0; 
1372
    }
1373
 
1374
    #
1375
    #   Use same file name as in processAgeMarker
1376
    #
1377
    my $markerfile = catfile($tdir, '.lxrAge');
1378
    unlink $markerfile;
1379
}
1380
 
5233 dpurdie 1381
#-------------------------------------------------------------------------------
1382
# Function        : baseVersionNumber 
1383
#
1384
# Description     : Remove the build number from a package-version string 
1385
#
1386
# Inputs          : Package-Version string 
1387
#
1388
# Returns         : Version String with a build # of 0
1389
#                   Will return a non-standard string, but one that can be used for comparisons
1390
#
1391
sub baseVersionNumber
1392
{
1393
    my ($version) = @_;
1394
    my $iversion = $version;
5211 dpurdie 1395
 
5233 dpurdie 1396
    #
1397
    #   Look for a patchRipple.suffix
1398
    #
1399
    if ( $version =~ m~(.*?)\.([0-9]{4,6})(\.\w+)$~ )
1400
    {
1401
        my $part1 = $1;
1402
        my $patch = $2;
1403
        my $suffix = $3;
1404
        my $build;
1405
 
1406
        if ( length( $patch) >= 4 )
1407
        {
1408
            $build = substr( $patch, -3 ,3);
1409
            $patch = substr( $patch,  0 ,length($patch)-3);
1410
 
1411
            $version = $part1 . sprintf (".%3.3d.%3.3d", $patch, 0) . $suffix;
1412
        }
1413
    }
1414
    else
1415
    {
1416
        Verbose("baseVersionNumber. Could not massge: $iversion");
1417
    }
1418
    return $version;
1419
}
1420
 
1421
 
5211 dpurdie 1422
#-------------------------------------------------------------------------------
5209 dpurdie 1423
#   Documentation
1424
#
1425
 
1426
=pod
1427
 
1428
=head1 NAME
1429
 
1430
jats_lxr - Maintain LXR Releases
1431
 
1432
=head1 SYNOPSIS
1433
 
1434
  jats jats_lxr [options]
1435
 
1436
 Options:
1437
    -help               - brief help message
1438
    -help -help         - Detailed help message
1439
    -man                - Full documentation
1440
    -[no]createVersions - Create new versions. Default:Create
1441
    -[no]extract        - Extract source code. Default:Extract
1442
    -[no]index          - Index new LXR versions. Default:Index
1443
    -[no]purge          - Purge unused packages. Default:Purge
1444
    -[no]logfile        - Capture out to a log file. Default:Log
5231 dpurdie 1445
    -[no]forceViews     - Force creation of new views. Default:NoForceView
5211 dpurdie 1446
    -config=file        - Alternate config file
5209 dpurdie 1447
 
1448
=head1 OPTIONS
1449
 
1450
=over 8
1451
 
1452
=item B<-help>
1453
 
1454
Print a brief help message and exits.
1455
 
1456
=item B<-help -help>
1457
 
1458
Print a detailed help message with an explanation for each option.
1459
 
1460
=item B<-man>
1461
 
1462
Prints the manual page and exits.
1463
 
1464
=item B<-verbose>
1465
 
1466
This option will display progress information as the program executes.
1467
 
1468
=item B<-[no]createVersions>
1469
 
1470
This option can be used to suppress the creation of new views.
1471
 
1472
=item B<-[no]extract>
1473
 
1474
This option can be used to suppress the extraction of source.
1475
 
1476
=item B<-[no]index>
1477
 
1478
This option can be used to suppress the indexing of newly created views.
1479
 
1480
=item B<-[no]purge>
1481
 
1482
This option can be used to suppress purging of packages that are no longer used by any of the LXR Trees.
1483
 
5231 dpurdie 1484
=item B<-[no]forceViews>
1485
 
1486
This option can be used to force the creation of a new View in each Release.
1487
 
5211 dpurdie 1488
=item B<-config=file>
1489
 
1490
This option can be used to override the standard config file. Used in testing.
1491
 
5209 dpurdie 1492
=back
1493
 
1494
=head1 DESCRIPTION
1495
 
1496
This program is a tool for creating and maintaining an LXR instance within the VIX Build System.
1497
 
1498
The program can:
1499
 
1500
=over 8
1501
 
1502
=item * 
1503
 
1504
Examine the Release Manager Database and determine which Releases are a part of the set to have LXR Views created.
1505
 
1506
Releases that are Open (or Restricted or in CCB Mode) or that have been closed for less than 10 days will be processed.
1507
 
1508
=item *
1509
 
1510
Examine the Release Manager Database and determine the package-versions that are a part of the LXR Release Set.
1511
 
1512
The process will only examine the contents of a Release. It will not descend the version dependency tree.
1513
 
1514
The program will then extract new package-versions into it's Package Store. Multiple LXR Tree's will share the one 
1515
instance of the extracted source code.
1516
 
1517
=item *
1518
 
1519
Create a new 'Version' for each Release.
1520
 
1521
The Version Name is based on the date-time at which the process is run.
1522
 
1523
Each Version is a symlink to the required package-version held in the Package Store.
1524
 
1525
This step can be suppressed though a command line option.
1526
 
1527
=item *
1528
 
1529
Remove unused LXR Trees (Releases no longer being processed) and unused Versions within each Tree.
1530
 
1531
Releases that are no longer eligable for processing will be retained for 10 days and then deleted. 
1532
During this time the existing versions will not be aged out.
1533
 
1534
At the moment this tool simply retains the last 5 Versions of each Release. If the tool 
1535
is run nightly then this will translate into  5 days.
1536
 
1537
=item *
1538
 
1539
Regenerate the LXR Configuration file
1540
 
1541
Create new database tables for new Releases
1542
 
1543
=item *
1544
 
1545
Run the LXR indexer for each LXR Version that has not been processed. Once processed the Version will 
1546
be tagged to prevent further indexing.
1547
 
1548
=item *
1549
 
1550
Remove unused Package-Versions from the Package Store.
1551
 
1552
=back
1553
 
1554
=cut
1555