Subversion Repositories DevTools

Rev

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